diff --git a/cmd/gotosocial/action/server/server.go b/cmd/gotosocial/action/server/server.go
index ee327c0c5..e695e0789 100644
--- a/cmd/gotosocial/action/server/server.go
+++ b/cmd/gotosocial/action/server/server.go
@@ -150,10 +150,7 @@ var Start action.GTSAction = func(ctx context.Context) error {
}
// build web module
- webModule, err := web.New(processor)
- if err != nil {
- return fmt.Errorf("error creating web module: %s", err)
- }
+ webModule := web.New(processor)
// build client api modules
authModule := auth.New(dbService, idp, processor)
diff --git a/cmd/gotosocial/action/testrig/testrig.go b/cmd/gotosocial/action/testrig/testrig.go
index 739358f99..02eb96063 100644
--- a/cmd/gotosocial/action/testrig/testrig.go
+++ b/cmd/gotosocial/action/testrig/testrig.go
@@ -108,10 +108,7 @@ var Start action.GTSAction = func(ctx context.Context) error {
}
// build web module
- webModule, err := web.New(processor)
- if err != nil {
- return fmt.Errorf("error creating web module: %s", err)
- }
+ webModule := web.New(processor)
// build client api modules
authModule := auth.New(dbService, idp, processor)
diff --git a/internal/api/client/followrequest/get_test.go b/internal/api/client/followrequest/get_test.go
index 2af9c7744..adf55c8b6 100644
--- a/internal/api/client/followrequest/get_test.go
+++ b/internal/api/client/followrequest/get_test.go
@@ -70,7 +70,7 @@ func (suite *GetTestSuite) TestGet() {
b, err := ioutil.ReadAll(result.Body)
assert.NoError(suite.T(), err)
- suite.Equal(`[{"id":"01FHMQX3GAABWSM0S2VZEC2SWC","username":"some_user","acct":"some_user@example.org","display_name":"some user","locked":true,"bot":false,"created_at":"2020-08-10T12:13:28.000Z","note":"i'm a real son of a gun","url":"http://example.org/@some_user","avatar":"","avatar_static":"","header":"","header_static":"","followers_count":0,"following_count":0,"statuses_count":0,"last_status_at":"","emojis":[],"fields":[]}]`, string(b))
+ suite.Equal(`[{"id":"01FHMQX3GAABWSM0S2VZEC2SWC","username":"some_user","acct":"some_user@example.org","display_name":"some user","locked":true,"bot":false,"created_at":"2020-08-10T12:13:28.000Z","note":"i'm a real son of a gun","url":"http://example.org/@some_user","avatar":"","avatar_static":"","header":"http://localhost:8080/assets/default_header.png","header_static":"http://localhost:8080/assets/default_header.png","followers_count":0,"following_count":0,"statuses_count":0,"last_status_at":"","emojis":[],"fields":[]}]`, string(b))
}
func TestGetTestSuite(t *testing.T) {
diff --git a/internal/api/client/instance/instancepatch_test.go b/internal/api/client/instance/instancepatch_test.go
index c44f8d093..4ecf0d62c 100644
--- a/internal/api/client/instance/instancepatch_test.go
+++ b/internal/api/client/instance/instancepatch_test.go
@@ -63,7 +63,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch1() {
b, err := io.ReadAll(result.Body)
suite.NoError(err)
- suite.Equal(`{"uri":"http://localhost:8080","account_domain":"localhost:8080","title":"Example Instance","description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","short_description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","email":"someone@example.org","version":"0.0.0-testrig","registrations":true,"approval_required":true,"invites_enabled":false,"configuration":{"statuses":{"max_characters":5000,"max_media_attachments":6,"characters_reserved_per_url":999},"media_attachments":{"supported_mime_types":["image/jpeg","image/gif","image/png"],"image_size_limit":10485760,"image_matrix_limit":16777216,"video_size_limit":41943040,"video_frame_rate_limit":60,"video_matrix_limit":16777216},"polls":{"max_options":6,"max_characters_per_option":50,"min_expiration":300,"max_expiration":2629746}},"urls":{"streaming_api":"wss://localhost:8080"},"stats":{"domain_count":2,"status_count":16,"user_count":4},"thumbnail":"http://localhost:8080/assets/logo.png","contact_account":{"id":"01F8MH17FWEB39HZJ76B6VXSKF","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"created_at":"2022-05-17T13:10:59.000Z","note":"","url":"http://localhost:8080/@admin","avatar":"","avatar_static":"","header":"","header_static":"","followers_count":1,"following_count":1,"statuses_count":4,"last_status_at":"2021-10-20T10:41:37.000Z","emojis":[],"fields":[]},"max_toot_chars":5000}`, string(b))
+ suite.Equal(`{"uri":"http://localhost:8080","account_domain":"localhost:8080","title":"Example Instance","description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","short_description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","email":"someone@example.org","version":"0.0.0-testrig","registrations":true,"approval_required":true,"invites_enabled":false,"configuration":{"statuses":{"max_characters":5000,"max_media_attachments":6,"characters_reserved_per_url":999},"media_attachments":{"supported_mime_types":["image/jpeg","image/gif","image/png"],"image_size_limit":10485760,"image_matrix_limit":16777216,"video_size_limit":41943040,"video_frame_rate_limit":60,"video_matrix_limit":16777216},"polls":{"max_options":6,"max_characters_per_option":50,"min_expiration":300,"max_expiration":2629746}},"urls":{"streaming_api":"wss://localhost:8080"},"stats":{"domain_count":2,"status_count":16,"user_count":4},"thumbnail":"http://localhost:8080/assets/logo.png","contact_account":{"id":"01F8MH17FWEB39HZJ76B6VXSKF","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"created_at":"2022-05-17T13:10:59.000Z","note":"","url":"http://localhost:8080/@admin","avatar":"","avatar_static":"","header":"http://localhost:8080/assets/default_header.png","header_static":"http://localhost:8080/assets/default_header.png","followers_count":1,"following_count":1,"statuses_count":4,"last_status_at":"2021-10-20T10:41:37.000Z","emojis":[],"fields":[]},"max_toot_chars":5000}`, string(b))
}
func (suite *InstancePatchTestSuite) TestInstancePatch2() {
@@ -93,7 +93,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch2() {
b, err := io.ReadAll(result.Body)
suite.NoError(err)
- suite.Equal(`{"uri":"http://localhost:8080","account_domain":"localhost:8080","title":"Geoff's Instance","description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","short_description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","email":"admin@example.org","version":"0.0.0-testrig","registrations":true,"approval_required":true,"invites_enabled":false,"configuration":{"statuses":{"max_characters":5000,"max_media_attachments":6,"characters_reserved_per_url":999},"media_attachments":{"supported_mime_types":["image/jpeg","image/gif","image/png"],"image_size_limit":10485760,"image_matrix_limit":16777216,"video_size_limit":41943040,"video_frame_rate_limit":60,"video_matrix_limit":16777216},"polls":{"max_options":6,"max_characters_per_option":50,"min_expiration":300,"max_expiration":2629746}},"urls":{"streaming_api":"wss://localhost:8080"},"stats":{"domain_count":2,"status_count":16,"user_count":4},"thumbnail":"http://localhost:8080/assets/logo.png","contact_account":{"id":"01F8MH17FWEB39HZJ76B6VXSKF","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"created_at":"2022-05-17T13:10:59.000Z","note":"","url":"http://localhost:8080/@admin","avatar":"","avatar_static":"","header":"","header_static":"","followers_count":1,"following_count":1,"statuses_count":4,"last_status_at":"2021-10-20T10:41:37.000Z","emojis":[],"fields":[]},"max_toot_chars":5000}`, string(b))
+ suite.Equal(`{"uri":"http://localhost:8080","account_domain":"localhost:8080","title":"Geoff's Instance","description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","short_description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","email":"admin@example.org","version":"0.0.0-testrig","registrations":true,"approval_required":true,"invites_enabled":false,"configuration":{"statuses":{"max_characters":5000,"max_media_attachments":6,"characters_reserved_per_url":999},"media_attachments":{"supported_mime_types":["image/jpeg","image/gif","image/png"],"image_size_limit":10485760,"image_matrix_limit":16777216,"video_size_limit":41943040,"video_frame_rate_limit":60,"video_matrix_limit":16777216},"polls":{"max_options":6,"max_characters_per_option":50,"min_expiration":300,"max_expiration":2629746}},"urls":{"streaming_api":"wss://localhost:8080"},"stats":{"domain_count":2,"status_count":16,"user_count":4},"thumbnail":"http://localhost:8080/assets/logo.png","contact_account":{"id":"01F8MH17FWEB39HZJ76B6VXSKF","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"created_at":"2022-05-17T13:10:59.000Z","note":"","url":"http://localhost:8080/@admin","avatar":"","avatar_static":"","header":"http://localhost:8080/assets/default_header.png","header_static":"http://localhost:8080/assets/default_header.png","followers_count":1,"following_count":1,"statuses_count":4,"last_status_at":"2021-10-20T10:41:37.000Z","emojis":[],"fields":[]},"max_toot_chars":5000}`, string(b))
}
func (suite *InstancePatchTestSuite) TestInstancePatch3() {
@@ -123,7 +123,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch3() {
b, err := io.ReadAll(result.Body)
suite.NoError(err)
- suite.Equal(`{"uri":"http://localhost:8080","account_domain":"localhost:8080","title":"GoToSocial Testrig Instance","description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","short_description":"\u003cp\u003eThis is some html, which is \u003cem\u003eallowed\u003c/em\u003e in short descriptions.\u003c/p\u003e","email":"admin@example.org","version":"0.0.0-testrig","registrations":true,"approval_required":true,"invites_enabled":false,"configuration":{"statuses":{"max_characters":5000,"max_media_attachments":6,"characters_reserved_per_url":999},"media_attachments":{"supported_mime_types":["image/jpeg","image/gif","image/png"],"image_size_limit":10485760,"image_matrix_limit":16777216,"video_size_limit":41943040,"video_frame_rate_limit":60,"video_matrix_limit":16777216},"polls":{"max_options":6,"max_characters_per_option":50,"min_expiration":300,"max_expiration":2629746}},"urls":{"streaming_api":"wss://localhost:8080"},"stats":{"domain_count":2,"status_count":16,"user_count":4},"thumbnail":"http://localhost:8080/assets/logo.png","contact_account":{"id":"01F8MH17FWEB39HZJ76B6VXSKF","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"created_at":"2022-05-17T13:10:59.000Z","note":"","url":"http://localhost:8080/@admin","avatar":"","avatar_static":"","header":"","header_static":"","followers_count":1,"following_count":1,"statuses_count":4,"last_status_at":"2021-10-20T10:41:37.000Z","emojis":[],"fields":[]},"max_toot_chars":5000}`, string(b))
+ suite.Equal(`{"uri":"http://localhost:8080","account_domain":"localhost:8080","title":"GoToSocial Testrig Instance","description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","short_description":"\u003cp\u003eThis is some html, which is \u003cem\u003eallowed\u003c/em\u003e in short descriptions.\u003c/p\u003e","email":"admin@example.org","version":"0.0.0-testrig","registrations":true,"approval_required":true,"invites_enabled":false,"configuration":{"statuses":{"max_characters":5000,"max_media_attachments":6,"characters_reserved_per_url":999},"media_attachments":{"supported_mime_types":["image/jpeg","image/gif","image/png"],"image_size_limit":10485760,"image_matrix_limit":16777216,"video_size_limit":41943040,"video_frame_rate_limit":60,"video_matrix_limit":16777216},"polls":{"max_options":6,"max_characters_per_option":50,"min_expiration":300,"max_expiration":2629746}},"urls":{"streaming_api":"wss://localhost:8080"},"stats":{"domain_count":2,"status_count":16,"user_count":4},"thumbnail":"http://localhost:8080/assets/logo.png","contact_account":{"id":"01F8MH17FWEB39HZJ76B6VXSKF","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"created_at":"2022-05-17T13:10:59.000Z","note":"","url":"http://localhost:8080/@admin","avatar":"","avatar_static":"","header":"http://localhost:8080/assets/default_header.png","header_static":"http://localhost:8080/assets/default_header.png","followers_count":1,"following_count":1,"statuses_count":4,"last_status_at":"2021-10-20T10:41:37.000Z","emojis":[],"fields":[]},"max_toot_chars":5000}`, string(b))
}
func (suite *InstancePatchTestSuite) TestInstancePatch4() {
@@ -214,7 +214,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch6() {
b, err := io.ReadAll(result.Body)
suite.NoError(err)
- suite.Equal(`{"uri":"http://localhost:8080","account_domain":"localhost:8080","title":"GoToSocial Testrig Instance","description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","short_description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","email":"","version":"0.0.0-testrig","registrations":true,"approval_required":true,"invites_enabled":false,"configuration":{"statuses":{"max_characters":5000,"max_media_attachments":6,"characters_reserved_per_url":999},"media_attachments":{"supported_mime_types":["image/jpeg","image/gif","image/png"],"image_size_limit":10485760,"image_matrix_limit":16777216,"video_size_limit":41943040,"video_frame_rate_limit":60,"video_matrix_limit":16777216},"polls":{"max_options":6,"max_characters_per_option":50,"min_expiration":300,"max_expiration":2629746}},"urls":{"streaming_api":"wss://localhost:8080"},"stats":{"domain_count":2,"status_count":16,"user_count":4},"thumbnail":"http://localhost:8080/assets/logo.png","contact_account":{"id":"01F8MH17FWEB39HZJ76B6VXSKF","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"created_at":"2022-05-17T13:10:59.000Z","note":"","url":"http://localhost:8080/@admin","avatar":"","avatar_static":"","header":"","header_static":"","followers_count":1,"following_count":1,"statuses_count":4,"last_status_at":"2021-10-20T10:41:37.000Z","emojis":[],"fields":[]},"max_toot_chars":5000}`, string(b))
+ suite.Equal(`{"uri":"http://localhost:8080","account_domain":"localhost:8080","title":"GoToSocial Testrig Instance","description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","short_description":"\u003cp\u003eThis is the GoToSocial testrig. It doesn't federate or anything.\u003c/p\u003e\u003cp\u003eWhen the testrig is shut down, all data on it will be deleted.\u003c/p\u003e\u003cp\u003eDon't use this in production!\u003c/p\u003e","email":"","version":"0.0.0-testrig","registrations":true,"approval_required":true,"invites_enabled":false,"configuration":{"statuses":{"max_characters":5000,"max_media_attachments":6,"characters_reserved_per_url":999},"media_attachments":{"supported_mime_types":["image/jpeg","image/gif","image/png"],"image_size_limit":10485760,"image_matrix_limit":16777216,"video_size_limit":41943040,"video_frame_rate_limit":60,"video_matrix_limit":16777216},"polls":{"max_options":6,"max_characters_per_option":50,"min_expiration":300,"max_expiration":2629746}},"urls":{"streaming_api":"wss://localhost:8080"},"stats":{"domain_count":2,"status_count":16,"user_count":4},"thumbnail":"http://localhost:8080/assets/logo.png","contact_account":{"id":"01F8MH17FWEB39HZJ76B6VXSKF","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"created_at":"2022-05-17T13:10:59.000Z","note":"","url":"http://localhost:8080/@admin","avatar":"","avatar_static":"","header":"http://localhost:8080/assets/default_header.png","header_static":"http://localhost:8080/assets/default_header.png","followers_count":1,"following_count":1,"statuses_count":4,"last_status_at":"2021-10-20T10:41:37.000Z","emojis":[],"fields":[]},"max_toot_chars":5000}`, string(b))
}
func (suite *InstancePatchTestSuite) TestInstancePatch7() {
diff --git a/internal/config/validate.go b/internal/config/validate.go
index b68cb2c62..064eae07a 100644
--- a/internal/config/validate.go
+++ b/internal/config/validate.go
@@ -62,6 +62,11 @@ func Validate() error {
errs = append(errs, fmt.Errorf("%s must be set to either http or https, provided value was %s", ProtocolFlag(), proto))
}
+ webAssetsBaseDir := GetWebAssetBaseDir()
+ if webAssetsBaseDir == "" {
+ errs = append(errs, fmt.Errorf("%s must be set", WebAssetBaseDirFlag()))
+ }
+
if len(errs) > 0 {
errStrings := []string{}
for _, err := range errs {
diff --git a/internal/config/validate_test.go b/internal/config/validate_test.go
index 6b832de36..c3a998a4a 100644
--- a/internal/config/validate_test.go
+++ b/internal/config/validate_test.go
@@ -103,6 +103,15 @@ func (suite *ConfigValidateTestSuite) TestValidateConfigNoProtocol() {
suite.EqualError(err, "protocol must be set")
}
+func (suite *ConfigValidateTestSuite) TestValidateConfigNoWebAssetBaseDir() {
+ testrig.InitTestConfig()
+
+ config.SetWebAssetBaseDir("")
+
+ err := config.Validate()
+ suite.EqualError(err, "web-asset-base-dir must be set")
+}
+
func (suite *ConfigValidateTestSuite) TestValidateConfigNoProtocolOrHost() {
testrig.InitTestConfig()
diff --git a/internal/processing/streaming/notification_test.go b/internal/processing/streaming/notification_test.go
index 960d9408d..0017dac04 100644
--- a/internal/processing/streaming/notification_test.go
+++ b/internal/processing/streaming/notification_test.go
@@ -52,7 +52,7 @@ func (suite *NotificationTestSuite) TestStreamNotification() {
suite.NoError(err)
msg := <-openStream.Messages
- suite.Equal(`{"id":"01FH57SJCMDWQGEAJ0X08CE3WV","type":"follow","created_at":"2021-10-04T08:52:36.000Z","account":{"id":"01F8MH5ZK5VRH73AKHQM6Y9VNX","username":"foss_satan","acct":"foss_satan@fossbros-anonymous.io","display_name":"big gerald","locked":false,"bot":false,"created_at":"2021-09-26T10:52:36.000Z","note":"i post about like, i dunno, stuff, or whatever!!!!","url":"http://fossbros-anonymous.io/@foss_satan","avatar":"","avatar_static":"","header":"","header_static":"","followers_count":0,"following_count":0,"statuses_count":1,"last_status_at":"2021-09-20T10:40:37.000Z","emojis":[],"fields":[]}}`, msg.Payload)
+ suite.Equal(`{"id":"01FH57SJCMDWQGEAJ0X08CE3WV","type":"follow","created_at":"2021-10-04T08:52:36.000Z","account":{"id":"01F8MH5ZK5VRH73AKHQM6Y9VNX","username":"foss_satan","acct":"foss_satan@fossbros-anonymous.io","display_name":"big gerald","locked":false,"bot":false,"created_at":"2021-09-26T10:52:36.000Z","note":"i post about like, i dunno, stuff, or whatever!!!!","url":"http://fossbros-anonymous.io/@foss_satan","avatar":"","avatar_static":"","header":"http://localhost:8080/assets/default_header.png","header_static":"http://localhost:8080/assets/default_header.png","followers_count":0,"following_count":0,"statuses_count":1,"last_status_at":"2021-09-20T10:40:37.000Z","emojis":[],"fields":[]}}`, msg.Payload)
}
func TestNotificationTestSuite(t *testing.T) {
diff --git a/internal/typeutils/converter.go b/internal/typeutils/converter.go
index 6996599ae..3effb9388 100644
--- a/internal/typeutils/converter.go
+++ b/internal/typeutils/converter.go
@@ -21,6 +21,7 @@ package typeutils
import (
"context"
"net/url"
+ "sync"
"github.com/superseriousbusiness/activity/streams/vocab"
"github.com/superseriousbusiness/gotosocial/internal/ap"
@@ -195,10 +196,15 @@ type TypeConverter interface {
}
type converter struct {
- db db.DB
+ db db.DB
+ defaultAvatars []string
+ randAvatars sync.Map
}
// NewConverter returns a new Converter
func NewConverter(db db.DB) TypeConverter {
- return &converter{db: db}
+ return &converter{
+ db: db,
+ defaultAvatars: populateDefaultAvatars(),
+ }
}
diff --git a/internal/typeutils/defaulticons.go b/internal/typeutils/defaulticons.go
new file mode 100644
index 000000000..b2a9858af
--- /dev/null
+++ b/internal/typeutils/defaulticons.go
@@ -0,0 +1,138 @@
+/*
+ GoToSocial
+ Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+
+package typeutils
+
+import (
+ "io/ioutil"
+ "math/rand"
+ "path/filepath"
+ "strings"
+
+ apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
+ "github.com/superseriousbusiness/gotosocial/internal/config"
+ "github.com/superseriousbusiness/gotosocial/internal/log"
+)
+
+const defaultHeaderPath = "/assets/default_header.png"
+
+// populateDefaultAvatars returns a slice of standard avatars found
+// in the path [web-assets-base-dir]/default_avatars. The slice
+// entries correspond to the relative url via which they can be
+// retrieved from the server.
+//
+// So for example, an avatar called default.jpeg would be returned
+// in the slice as "/assets/default_avatars/default.jpeg".
+func populateDefaultAvatars() (defaultAvatars []string) {
+ webAssetsAbsFilePath, err := filepath.Abs(config.GetWebAssetBaseDir())
+ if err != nil {
+ log.Panicf("populateDefaultAvatars: error getting abs path for web assets: %s", err)
+ }
+
+ defaultAvatarsAbsFilePath := filepath.Join(webAssetsAbsFilePath, "default_avatars")
+ defaultAvatarFiles, err := ioutil.ReadDir(defaultAvatarsAbsFilePath)
+ if err != nil {
+ log.Warnf("populateDefaultAvatars: error reading default avatars at %s: %s", defaultAvatarsAbsFilePath, err)
+ return
+ }
+
+ for _, f := range defaultAvatarFiles {
+ // ignore directories
+ if f.IsDir() {
+ continue
+ }
+
+ // ignore files bigger than 50kb
+ if f.Size() > 50000 {
+ continue
+ }
+
+ // get the name of the file, eg avatar.jpeg
+ fileName := f.Name()
+
+ // get just the .jpeg, for example, from avatar.jpeg
+ extensionWithDot := filepath.Ext(fileName)
+
+ // remove the leading . to just get, eg, jpeg
+ extension := strings.TrimPrefix(extensionWithDot, ".")
+
+ // take only files with simple extensions
+ // that we know will work OK as avatars
+ switch strings.ToLower(extension) {
+ case "jpeg", "jpg", "gif", "png":
+ avatarURL := config.GetProtocol() + "://" + config.GetHost() + "/assets/default_avatars/" + fileName
+ defaultAvatars = append(defaultAvatars, avatarURL)
+ default:
+ continue
+ }
+ }
+
+ return
+}
+
+// ensureAvatar ensures that the given account has a value set
+// for the avatar URL.
+//
+// If no value is set, an avatar will be selected at random from
+// the available default avatars. This selection is 'sticky', so
+// the same account will get the same result on subsequent calls.
+//
+// If a value for the avatar URL is already set, this function is
+// a no-op.
+//
+// If there are no default avatars available, this function is a
+// no-op.
+func (c *converter) ensureAvatar(account *apimodel.Account) {
+ if (account.Avatar != "" && account.AvatarStatic != "") || len(c.defaultAvatars) == 0 {
+ return
+ }
+
+ var avatar string
+ if avatarI, ok := c.randAvatars.Load(account.ID); ok {
+ // we already have a default avatar stored for this account
+ avatar, ok = avatarI.(string)
+ if !ok {
+ panic("avatarI was not a string")
+ }
+ } else {
+ // select + store a default avatar for this account at random
+ randomIndex := rand.Intn(len(c.defaultAvatars)) //nolint:gosec
+ avatar = c.defaultAvatars[randomIndex]
+ c.randAvatars.Store(account.ID, avatar)
+ }
+
+ account.Avatar = avatar
+ account.AvatarStatic = avatar
+}
+
+// EnsureAvatar ensures that the given account has a value set
+// for the header URL.
+//
+// If no value is set, the default header will be set.
+//
+// If a value for the header URL is already set, this function is
+// a no-op.
+func (c *converter) ensureHeader(account *apimodel.Account) {
+ if account.Header != "" && account.HeaderStatic != "" {
+ return
+ }
+
+ h := config.GetProtocol() + "://" + config.GetHost() + defaultHeaderPath
+ account.Header = h
+ account.HeaderStatic = h
+}
diff --git a/internal/typeutils/internaltofrontend.go b/internal/typeutils/internaltofrontend.go
index 6ccbed340..0243e4732 100644
--- a/internal/typeutils/internaltofrontend.go
+++ b/internal/typeutils/internaltofrontend.go
@@ -190,6 +190,9 @@ func (c *converter) AccountToAPIAccountPublic(ctx context.Context, a *gtsmodel.A
Suspended: suspended,
}
+ c.ensureAvatar(accountFrontend)
+ c.ensureHeader(accountFrontend)
+
return accountFrontend, nil
}
diff --git a/internal/typeutils/internaltofrontend_test.go b/internal/typeutils/internaltofrontend_test.go
index 648c90fba..dc92260e1 100644
--- a/internal/typeutils/internaltofrontend_test.go
+++ b/internal/typeutils/internaltofrontend_test.go
@@ -63,7 +63,7 @@ func (suite *InternalToFrontendTestSuite) TestStatusToFrontend() {
b, err := json.Marshal(apiStatus)
suite.NoError(err)
- suite.Equal(`{"id":"01F8MH75CBF9JFX4ZAD54N0W0R","created_at":"2021-10-20T11:36:45.000Z","in_reply_to_id":null,"in_reply_to_account_id":null,"sensitive":false,"spoiler_text":"","visibility":"public","language":"en","uri":"http://localhost:8080/users/admin/statuses/01F8MH75CBF9JFX4ZAD54N0W0R","url":"http://localhost:8080/@admin/statuses/01F8MH75CBF9JFX4ZAD54N0W0R","replies_count":0,"reblogs_count":0,"favourites_count":1,"favourited":true,"reblogged":false,"muted":false,"bookmarked":false,"pinned":false,"content":"hello world! #welcome ! first post on the instance :rainbow: !","reblog":null,"application":{"name":"superseriousbusiness","website":"https://superserious.business"},"account":{"id":"01F8MH17FWEB39HZJ76B6VXSKF","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"created_at":"2022-05-17T13:10:59.000Z","note":"","url":"http://localhost:8080/@admin","avatar":"","avatar_static":"","header":"","header_static":"","followers_count":1,"following_count":1,"statuses_count":4,"last_status_at":"2021-10-20T10:41:37.000Z","emojis":[],"fields":[]},"media_attachments":[{"id":"01F8MH6NEM8D7527KZAECTCR76","type":"image","url":"http://localhost:8080/fileserver/01F8MH17FWEB39HZJ76B6VXSKF/attachment/original/01F8MH6NEM8D7527KZAECTCR76.jpeg","text_url":"http://localhost:8080/fileserver/01F8MH17FWEB39HZJ76B6VXSKF/attachment/original/01F8MH6NEM8D7527KZAECTCR76.jpeg","preview_url":"http://localhost:8080/fileserver/01F8MH17FWEB39HZJ76B6VXSKF/attachment/small/01F8MH6NEM8D7527KZAECTCR76.jpeg","remote_url":null,"preview_remote_url":null,"meta":{"original":{"width":1200,"height":630,"size":"1200x630","aspect":1.9047619},"small":{"width":256,"height":134,"size":"256x134","aspect":1.9104477},"focus":{"x":0,"y":0}},"description":"Black and white image of some 50's style text saying: Welcome On Board","blurhash":"LNJRdVM{00Rj%Mayt7j[4nWBofRj"}],"mentions":[],"tags":[{"name":"welcome","url":"http://localhost:8080/tags/welcome"}],"emojis":[{"shortcode":"rainbow","url":"http://localhost:8080/fileserver/01F8MH17FWEB39HZJ76B6VXSKF/emoji/original/01F8MH9H8E4VG3KDYJR9EGPXCQ.png","static_url":"http://localhost:8080/fileserver/01F8MH17FWEB39HZJ76B6VXSKF/emoji/static/01F8MH9H8E4VG3KDYJR9EGPXCQ.png","visible_in_picker":true}],"card":null,"poll":null}`, string(b))
+ suite.Equal(`{"id":"01F8MH75CBF9JFX4ZAD54N0W0R","created_at":"2021-10-20T11:36:45.000Z","in_reply_to_id":null,"in_reply_to_account_id":null,"sensitive":false,"spoiler_text":"","visibility":"public","language":"en","uri":"http://localhost:8080/users/admin/statuses/01F8MH75CBF9JFX4ZAD54N0W0R","url":"http://localhost:8080/@admin/statuses/01F8MH75CBF9JFX4ZAD54N0W0R","replies_count":0,"reblogs_count":0,"favourites_count":1,"favourited":true,"reblogged":false,"muted":false,"bookmarked":false,"pinned":false,"content":"hello world! #welcome ! first post on the instance :rainbow: !","reblog":null,"application":{"name":"superseriousbusiness","website":"https://superserious.business"},"account":{"id":"01F8MH17FWEB39HZJ76B6VXSKF","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"created_at":"2022-05-17T13:10:59.000Z","note":"","url":"http://localhost:8080/@admin","avatar":"","avatar_static":"","header":"http://localhost:8080/assets/default_header.png","header_static":"http://localhost:8080/assets/default_header.png","followers_count":1,"following_count":1,"statuses_count":4,"last_status_at":"2021-10-20T10:41:37.000Z","emojis":[],"fields":[]},"media_attachments":[{"id":"01F8MH6NEM8D7527KZAECTCR76","type":"image","url":"http://localhost:8080/fileserver/01F8MH17FWEB39HZJ76B6VXSKF/attachment/original/01F8MH6NEM8D7527KZAECTCR76.jpeg","text_url":"http://localhost:8080/fileserver/01F8MH17FWEB39HZJ76B6VXSKF/attachment/original/01F8MH6NEM8D7527KZAECTCR76.jpeg","preview_url":"http://localhost:8080/fileserver/01F8MH17FWEB39HZJ76B6VXSKF/attachment/small/01F8MH6NEM8D7527KZAECTCR76.jpeg","remote_url":null,"preview_remote_url":null,"meta":{"original":{"width":1200,"height":630,"size":"1200x630","aspect":1.9047619},"small":{"width":256,"height":134,"size":"256x134","aspect":1.9104477},"focus":{"x":0,"y":0}},"description":"Black and white image of some 50's style text saying: Welcome On Board","blurhash":"LNJRdVM{00Rj%Mayt7j[4nWBofRj"}],"mentions":[],"tags":[{"name":"welcome","url":"http://localhost:8080/tags/welcome"}],"emojis":[{"shortcode":"rainbow","url":"http://localhost:8080/fileserver/01F8MH17FWEB39HZJ76B6VXSKF/emoji/original/01F8MH9H8E4VG3KDYJR9EGPXCQ.png","static_url":"http://localhost:8080/fileserver/01F8MH17FWEB39HZJ76B6VXSKF/emoji/static/01F8MH9H8E4VG3KDYJR9EGPXCQ.png","visible_in_picker":true}],"card":null,"poll":null}`, string(b))
}
func (suite *InternalToFrontendTestSuite) TestInstanceToFrontend() {
@@ -108,7 +108,7 @@ func (suite *InternalToFrontendTestSuite) TestInstanceToFrontendWithAdminAccount
b, err := json.Marshal(apiInstance)
suite.NoError(err)
- suite.Equal(`{"uri":"https://example.org","title":"example instance","description":"a much longer description","short_description":"a little description","email":"someone@example.org","version":"software-from-hell 0.666","registrations":false,"approval_required":false,"invites_enabled":false,"thumbnail":"","contact_account":{"id":"01FHMQX3GAABWSM0S2VZEC2SWC","username":"some_user","acct":"some_user@example.org","display_name":"some user","locked":true,"bot":false,"created_at":"2020-08-10T12:13:28.000Z","note":"i'm a real son of a gun","url":"http://example.org/@some_user","avatar":"","avatar_static":"","header":"","header_static":"","followers_count":0,"following_count":0,"statuses_count":0,"last_status_at":"","emojis":[],"fields":[]},"max_toot_chars":0}`, string(b))
+ suite.Equal(`{"uri":"https://example.org","title":"example instance","description":"a much longer description","short_description":"a little description","email":"someone@example.org","version":"software-from-hell 0.666","registrations":false,"approval_required":false,"invites_enabled":false,"thumbnail":"","contact_account":{"id":"01FHMQX3GAABWSM0S2VZEC2SWC","username":"some_user","acct":"some_user@example.org","display_name":"some user","locked":true,"bot":false,"created_at":"2020-08-10T12:13:28.000Z","note":"i'm a real son of a gun","url":"http://example.org/@some_user","avatar":"","avatar_static":"","header":"http://localhost:8080/assets/default_header.png","header_static":"http://localhost:8080/assets/default_header.png","followers_count":0,"following_count":0,"statuses_count":0,"last_status_at":"","emojis":[],"fields":[]},"max_toot_chars":0}`, string(b))
}
func TestInternalToFrontendTestSuite(t *testing.T) {
diff --git a/internal/web/assets.go b/internal/web/assets.go
index f67f38363..397870862 100644
--- a/internal/web/assets.go
+++ b/internal/web/assets.go
@@ -20,9 +20,12 @@ package web
import (
"net/http"
+ "path/filepath"
"strings"
"github.com/gin-gonic/gin"
+ "github.com/superseriousbusiness/gotosocial/internal/config"
+ "github.com/superseriousbusiness/gotosocial/internal/log"
)
type fileSystem struct {
@@ -49,7 +52,12 @@ func (fs fileSystem) Open(path string) (http.File, error) {
}
func (m *Module) mountAssetsFilesystem(group *gin.RouterGroup) {
- fs := fileSystem{http.Dir(m.webAssetsAbsFilePath)}
+ webAssetsAbsFilePath, err := filepath.Abs(config.GetWebAssetBaseDir())
+ if err != nil {
+ log.Panicf("mountAssetsFilesystem: error getting absolute path of assets dir: %s", err)
+ }
+
+ fs := fileSystem{http.Dir(webAssetsAbsFilePath)}
// use the cache middleware on all handlers in this group
group.Use(m.cacheControlMiddleware(fs))
diff --git a/internal/web/assetscache.go b/internal/web/assetscache.go
index 57a0ade0b..fccc95993 100644
--- a/internal/web/assetscache.go
+++ b/internal/web/assetscache.go
@@ -114,7 +114,7 @@ func (m *Module) cacheControlMiddleware(fs http.FileSystem) gin.HandlerFunc {
if !strings.HasPrefix(upath, "/") {
upath = "/" + upath
}
- assetFilePath := strings.TrimPrefix(path.Clean(upath), assetsPath)
+ assetFilePath := strings.TrimPrefix(path.Clean(upath), assetsPathPrefix)
// either fetch etag from ttlcache or generate it
eTag, err := m.getAssetETag(assetFilePath, fs)
diff --git a/internal/web/panels.go b/internal/web/panels.go
index dafd0abc7..fdec87a33 100644
--- a/internal/web/panels.go
+++ b/internal/web/panels.go
@@ -38,15 +38,15 @@ func (m *Module) UserPanelHandler(c *gin.Context) {
c.HTML(http.StatusOK, "frontend.tmpl", gin.H{
"instance": instance,
"stylesheets": []string{
- assetsPath + "/Fork-Awesome/css/fork-awesome.min.css",
- assetsPath + "/dist/_colors.css",
- assetsPath + "/dist/base.css",
- assetsPath + "/dist/panels-base.css",
- assetsPath + "/dist/panels-user-style.css",
+ assetsPathPrefix + "/Fork-Awesome/css/fork-awesome.min.css",
+ assetsPathPrefix + "/dist/_colors.css",
+ assetsPathPrefix + "/dist/base.css",
+ assetsPathPrefix + "/dist/panels-base.css",
+ assetsPathPrefix + "/dist/panels-user-style.css",
},
"javascript": []string{
- assetsPath + "/dist/bundle.js",
- assetsPath + "/dist/user-panel.js",
+ assetsPathPrefix + "/dist/bundle.js",
+ assetsPathPrefix + "/dist/user-panel.js",
},
})
}
@@ -63,15 +63,15 @@ func (m *Module) AdminPanelHandler(c *gin.Context) {
c.HTML(http.StatusOK, "frontend.tmpl", gin.H{
"instance": instance,
"stylesheets": []string{
- assetsPath + "/Fork-Awesome/css/fork-awesome.min.css",
- assetsPath + "/dist/_colors.css",
- assetsPath + "/dist/base.css",
- assetsPath + "/dist/panels-base.css",
- assetsPath + "/dist/panels-admin-style.css",
+ assetsPathPrefix + "/Fork-Awesome/css/fork-awesome.min.css",
+ assetsPathPrefix + "/dist/_colors.css",
+ assetsPathPrefix + "/dist/base.css",
+ assetsPathPrefix + "/dist/panels-base.css",
+ assetsPathPrefix + "/dist/panels-admin-style.css",
},
"javascript": []string{
- assetsPath + "/dist/bundle.js",
- assetsPath + "/dist/admin-panel.js",
+ assetsPathPrefix + "/dist/bundle.js",
+ assetsPathPrefix + "/dist/admin-panel.js",
},
})
}
diff --git a/internal/web/profile.go b/internal/web/profile.go
index 542c015f1..61f7c57e7 100644
--- a/internal/web/profile.go
+++ b/internal/web/profile.go
@@ -23,7 +23,6 @@ import (
"encoding/json"
"errors"
"fmt"
- "math/rand"
"net/http"
"strings"
@@ -100,21 +99,6 @@ func (m *Module) profileGETHandler(c *gin.Context) {
return
}
- // pick a random dummy avatar if this account avatar isn't set yet
- if account.Avatar == "" && len(m.defaultAvatars) > 0 {
- //nolint:gosec
- randomIndex := rand.Intn(len(m.defaultAvatars))
- dummyAvatar := m.defaultAvatars[randomIndex]
- account.Avatar = dummyAvatar
- for _, i := range statusResp.Items {
- s, ok := i.(*apimodel.Status)
- if !ok {
- panic("timelineable was not *apimodel.Status")
- }
- s.Account.Avatar = dummyAvatar
- }
- }
-
c.HTML(http.StatusOK, "profile.tmpl", gin.H{
"instance": instance,
"account": account,
diff --git a/internal/web/thread.go b/internal/web/thread.go
index d3b92bde3..3db4952c7 100644
--- a/internal/web/thread.go
+++ b/internal/web/thread.go
@@ -23,7 +23,6 @@ import (
"encoding/json"
"errors"
"fmt"
- "math/rand"
"net/http"
"strings"
@@ -36,21 +35,6 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/oauth"
)
-var randAvatars = make(map[string]string)
-
-func (m *Module) ensureAvatar(status apimodel.Status) {
- if status.Account.Avatar == "" && len(m.defaultAvatars) > 0 {
- avatar, ok := randAvatars[status.Account.ID]
- if !ok {
- //nolint:gosec
- randomIndex := rand.Intn(len(m.defaultAvatars))
- avatar = m.defaultAvatars[randomIndex]
- randAvatars[status.Account.ID] = avatar
- }
- status.Account.Avatar = avatar
- }
-}
-
func (m *Module) threadGETHandler(c *gin.Context) {
ctx := c.Request.Context()
@@ -120,16 +104,6 @@ func (m *Module) threadGETHandler(c *gin.Context) {
return
}
- m.ensureAvatar(*status)
-
- for _, status := range context.Descendants {
- m.ensureAvatar(status)
- }
-
- for _, status := range context.Ancestors {
- m.ensureAvatar(status)
- }
-
c.HTML(http.StatusOK, "thread.tmpl", gin.H{
"instance": instance,
"status": status,
diff --git a/internal/web/web.go b/internal/web/web.go
index fe270ac6c..336525938 100644
--- a/internal/web/web.go
+++ b/internal/web/web.go
@@ -20,17 +20,12 @@ package web
import (
"errors"
- "fmt"
- "io/ioutil"
"net/http"
- "path/filepath"
- "strings"
"time"
"codeberg.org/gruf/go-cache/v2"
"github.com/gin-gonic/gin"
"github.com/superseriousbusiness/gotosocial/internal/api"
- "github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
"github.com/superseriousbusiness/gotosocial/internal/processing"
"github.com/superseriousbusiness/gotosocial/internal/router"
@@ -43,7 +38,7 @@ const (
statusPath = profilePath + "/statuses/:" + statusIDKey
adminPanelPath = "/admin"
userPanelpath = "/user"
- assetsPath = "/assets"
+ assetsPathPrefix = "/assets"
tokenParam = "token"
usernameKey = "username"
@@ -52,78 +47,26 @@ const (
// Module implements the api.ClientModule interface for web pages.
type Module struct {
- processor processing.Processor
- webAssetsAbsFilePath string
- assetsETagCache cache.Cache[string, eTagCacheEntry]
- defaultAvatars []string
+ processor processing.Processor
+ assetsETagCache cache.Cache[string, eTagCacheEntry]
}
// New returns a new api.ClientModule for web pages.
-func New(processor processing.Processor) (api.ClientModule, error) {
- webAssetsBaseDir := config.GetWebAssetBaseDir()
- if webAssetsBaseDir == "" {
- return nil, fmt.Errorf("%s cannot be empty and must be a relative or absolute path", config.WebAssetBaseDirFlag())
- }
-
- webAssetsAbsFilePath, err := filepath.Abs(webAssetsBaseDir)
- if err != nil {
- return nil, fmt.Errorf("error getting absolute path of %s: %s", webAssetsBaseDir, err)
- }
-
- defaultAvatarsAbsFilePath := filepath.Join(webAssetsAbsFilePath, "default_avatars")
- defaultAvatarFiles, err := ioutil.ReadDir(defaultAvatarsAbsFilePath)
- if err != nil {
- return nil, fmt.Errorf("error reading default avatars at %s: %s", defaultAvatarsAbsFilePath, err)
- }
-
- defaultAvatars := []string{}
- for _, f := range defaultAvatarFiles {
- // ignore directories
- if f.IsDir() {
- continue
- }
-
- // ignore files bigger than 50kb
- if f.Size() > 50000 {
- continue
- }
-
- // get the name of the file, eg avatar.jpeg
- fileName := f.Name()
-
- // get just the .jpeg, for example, from avatar.jpeg
- extensionWithDot := filepath.Ext(fileName)
-
- // remove the leading . to just get, eg, jpeg
- extension := strings.TrimPrefix(extensionWithDot, ".")
-
- // take only files with simple extensions
- // that we know will work OK as avatars
- switch strings.ToLower(extension) {
- case "svg", "jpeg", "jpg", "gif", "png":
- avatar := fmt.Sprintf("%s/default_avatars/%s", assetsPath, f.Name())
- defaultAvatars = append(defaultAvatars, avatar)
- default:
- continue
- }
- }
-
+func New(processor processing.Processor) api.ClientModule {
assetsETagCache := cache.New[string, eTagCacheEntry]()
assetsETagCache.SetTTL(time.Hour, false)
assetsETagCache.Start(time.Minute)
return &Module{
- processor: processor,
- webAssetsAbsFilePath: webAssetsAbsFilePath,
- assetsETagCache: assetsETagCache,
- defaultAvatars: defaultAvatars,
- }, nil
+ processor: processor,
+ assetsETagCache: assetsETagCache,
+ }
}
// Route satisfies the RESTAPIModule interface
func (m *Module) Route(s router.Router) error {
// serve static files from assets dir at /assets
- assetsGroup := s.AttachGroup(assetsPath)
+ assetsGroup := s.AttachGroup(assetsPathPrefix)
m.mountAssetsFilesystem(assetsGroup)
s.AttachHandler(http.MethodGet, adminPanelPath, m.AdminPanelHandler)
diff --git a/web/assets/default_avatars/GoToSocial_icon1.png b/web/assets/default_avatars/GoToSocial_icon1.png
new file mode 100644
index 000000000..f8248a10c
Binary files /dev/null and b/web/assets/default_avatars/GoToSocial_icon1.png differ
diff --git a/web/assets/default_avatars/GoToSocial_icon1.svg b/web/assets/default_avatars/GoToSocial_icon1.svg
deleted file mode 100644
index 9b4e7665e..000000000
--- a/web/assets/default_avatars/GoToSocial_icon1.svg
+++ /dev/null
@@ -1,160 +0,0 @@
-
-
-
-
diff --git a/web/assets/default_avatars/GoToSocial_icon2.png b/web/assets/default_avatars/GoToSocial_icon2.png
new file mode 100644
index 000000000..718647f9a
Binary files /dev/null and b/web/assets/default_avatars/GoToSocial_icon2.png differ
diff --git a/web/assets/default_avatars/GoToSocial_icon2.svg b/web/assets/default_avatars/GoToSocial_icon2.svg
deleted file mode 100644
index cdd49ddaa..000000000
--- a/web/assets/default_avatars/GoToSocial_icon2.svg
+++ /dev/null
@@ -1,137 +0,0 @@
-
-
-
-
diff --git a/web/assets/default_avatars/GoToSocial_icon3.png b/web/assets/default_avatars/GoToSocial_icon3.png
new file mode 100644
index 000000000..9411ea3f5
Binary files /dev/null and b/web/assets/default_avatars/GoToSocial_icon3.png differ
diff --git a/web/assets/default_avatars/GoToSocial_icon3.svg b/web/assets/default_avatars/GoToSocial_icon3.svg
deleted file mode 100644
index 205e229c9..000000000
--- a/web/assets/default_avatars/GoToSocial_icon3.svg
+++ /dev/null
@@ -1,137 +0,0 @@
-
-
-
-
diff --git a/web/assets/default_avatars/GoToSocial_icon4.png b/web/assets/default_avatars/GoToSocial_icon4.png
new file mode 100644
index 000000000..56cb7bc3f
Binary files /dev/null and b/web/assets/default_avatars/GoToSocial_icon4.png differ
diff --git a/web/assets/default_avatars/GoToSocial_icon4.svg b/web/assets/default_avatars/GoToSocial_icon4.svg
deleted file mode 100644
index ec6a46212..000000000
--- a/web/assets/default_avatars/GoToSocial_icon4.svg
+++ /dev/null
@@ -1,152 +0,0 @@
-
-
-
-
diff --git a/web/assets/default_avatars/GoToSocial_icon5.png b/web/assets/default_avatars/GoToSocial_icon5.png
new file mode 100644
index 000000000..7fbef35f3
Binary files /dev/null and b/web/assets/default_avatars/GoToSocial_icon5.png differ
diff --git a/web/assets/default_avatars/GoToSocial_icon5.svg b/web/assets/default_avatars/GoToSocial_icon5.svg
deleted file mode 100644
index c505b67d7..000000000
--- a/web/assets/default_avatars/GoToSocial_icon5.svg
+++ /dev/null
@@ -1,152 +0,0 @@
-
-
-
-
diff --git a/web/assets/default_avatars/GoToSocial_icon6.png b/web/assets/default_avatars/GoToSocial_icon6.png
new file mode 100644
index 000000000..203d01887
Binary files /dev/null and b/web/assets/default_avatars/GoToSocial_icon6.png differ
diff --git a/web/assets/default_avatars/GoToSocial_icon6.svg b/web/assets/default_avatars/GoToSocial_icon6.svg
deleted file mode 100644
index 43db9cbf0..000000000
--- a/web/assets/default_avatars/GoToSocial_icon6.svg
+++ /dev/null
@@ -1,160 +0,0 @@
-
-
-
-
diff --git a/web/assets/default_header.png b/web/assets/default_header.png
new file mode 100644
index 000000000..40f0484a2
Binary files /dev/null and b/web/assets/default_header.png differ