mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-11-24 08:43:32 -06:00
[feature] Set default header and avatar for API accounts to GtS ones (#799)
* validate web-asset-base-dir * move default icons into converter * always ensure avatar + header on api accounts * update tests * add default header * don't return error from web module creation anymore * tidy a bit * use pngs for default avatars rather than svgs
This commit is contained in:
parent
4e13408fd4
commit
006c8b604b
30 changed files with 205 additions and 1039 deletions
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
138
internal/typeutils/defaulticons.go
Normal file
138
internal/typeutils/defaulticons.go
Normal file
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue