mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-10-29 04:22:24 -05:00
[feature] scheduled statuses (#4274)
An implementation of [`scheduled_statuses`](https://docs.joinmastodon.org/methods/scheduled_statuses/). Will fix #1006. this is heavily WIP and I need to reorganize some of the code, working on this made me somehow familiar with the codebase and led to my other recent contributions i told some fops on fedi i'd work on this so i have no choice but to complete it 🤷♀️ btw iirc my avatar presents me working on this branch Signed-off-by: nicole mikołajczyk <git@mkljczk.pl> Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4274 Co-authored-by: nicole mikołajczyk <git@mkljczk.pl> Co-committed-by: nicole mikołajczyk <git@mkljczk.pl>
This commit is contained in:
parent
cead741c16
commit
660cf2c94c
46 changed files with 2354 additions and 68 deletions
|
|
@ -131,6 +131,9 @@ type Configuration struct {
|
|||
StatusesPollOptionMaxChars int `name:"statuses-poll-option-max-chars" usage:"Max amount of characters for a poll option"`
|
||||
StatusesMediaMaxFiles int `name:"statuses-media-max-files" usage:"Maximum number of media files/attachments per status"`
|
||||
|
||||
ScheduledStatusesMaxTotal int `name:"scheduled-statuses-max-total" usage:"Maximum number of scheduled statuses per user"`
|
||||
ScheduledStatusesMaxDaily int `name:"scheduled-statuses-max-daily" usage:"Maximum number of scheduled statuses per user for a single day"`
|
||||
|
||||
LetsEncryptEnabled bool `name:"letsencrypt-enabled" usage:"Enable letsencrypt TLS certs for this server. If set to true, then cert dir also needs to be set (or take the default)."`
|
||||
LetsEncryptPort int `name:"letsencrypt-port" usage:"Port to listen on for letsencrypt certificate challenges. Must not be the same as the GtS webserver/API port."`
|
||||
LetsEncryptCertDir string `name:"letsencrypt-cert-dir" usage:"Directory to store acquired letsencrypt certificates."`
|
||||
|
|
@ -252,6 +255,7 @@ type CacheConfiguration struct {
|
|||
PollVoteMemRatio float64 `name:"poll-vote-mem-ratio"`
|
||||
PollVoteIDsMemRatio float64 `name:"poll-vote-ids-mem-ratio"`
|
||||
ReportMemRatio float64 `name:"report-mem-ratio"`
|
||||
ScheduledStatusMemRatio float64 `name:"scheduled-status-mem-ratio"`
|
||||
SinBinStatusMemRatio float64 `name:"sin-bin-status-mem-ratio"`
|
||||
StatusMemRatio float64 `name:"status-mem-ratio"`
|
||||
StatusBookmarkMemRatio float64 `name:"status-bookmark-mem-ratio"`
|
||||
|
|
|
|||
|
|
@ -105,6 +105,9 @@ var Defaults = Configuration{
|
|||
StatusesPollOptionMaxChars: 50,
|
||||
StatusesMediaMaxFiles: 6,
|
||||
|
||||
ScheduledStatusesMaxTotal: 300,
|
||||
ScheduledStatusesMaxDaily: 25,
|
||||
|
||||
LetsEncryptEnabled: false,
|
||||
LetsEncryptPort: 80,
|
||||
LetsEncryptCertDir: "/gotosocial/storage/certs",
|
||||
|
|
@ -217,6 +220,7 @@ var Defaults = Configuration{
|
|||
PollVoteMemRatio: 2,
|
||||
PollVoteIDsMemRatio: 2,
|
||||
ReportMemRatio: 1,
|
||||
ScheduledStatusMemRatio: 4,
|
||||
SinBinStatusMemRatio: 0.5,
|
||||
StatusMemRatio: 5,
|
||||
StatusBookmarkMemRatio: 0.5,
|
||||
|
|
|
|||
|
|
@ -99,6 +99,8 @@ const (
|
|||
StatusesPollMaxOptionsFlag = "statuses-poll-max-options"
|
||||
StatusesPollOptionMaxCharsFlag = "statuses-poll-option-max-chars"
|
||||
StatusesMediaMaxFilesFlag = "statuses-media-max-files"
|
||||
ScheduledStatusesMaxTotalFlag = "scheduled-statuses-max-total"
|
||||
ScheduledStatusesMaxDailyFlag = "scheduled-statuses-max-daily"
|
||||
LetsEncryptEnabledFlag = "letsencrypt-enabled"
|
||||
LetsEncryptPortFlag = "letsencrypt-port"
|
||||
LetsEncryptCertDirFlag = "letsencrypt-cert-dir"
|
||||
|
|
@ -194,6 +196,7 @@ const (
|
|||
CachePollVoteMemRatioFlag = "cache-poll-vote-mem-ratio"
|
||||
CachePollVoteIDsMemRatioFlag = "cache-poll-vote-ids-mem-ratio"
|
||||
CacheReportMemRatioFlag = "cache-report-mem-ratio"
|
||||
CacheScheduledStatusMemRatioFlag = "cache-scheduled-status-mem-ratio"
|
||||
CacheSinBinStatusMemRatioFlag = "cache-sin-bin-status-mem-ratio"
|
||||
CacheStatusMemRatioFlag = "cache-status-mem-ratio"
|
||||
CacheStatusBookmarkMemRatioFlag = "cache-status-bookmark-mem-ratio"
|
||||
|
|
@ -296,6 +299,8 @@ func (cfg *Configuration) RegisterFlags(flags *pflag.FlagSet) {
|
|||
flags.Int("statuses-poll-max-options", cfg.StatusesPollMaxOptions, "Max amount of options permitted on a poll")
|
||||
flags.Int("statuses-poll-option-max-chars", cfg.StatusesPollOptionMaxChars, "Max amount of characters for a poll option")
|
||||
flags.Int("statuses-media-max-files", cfg.StatusesMediaMaxFiles, "Maximum number of media files/attachments per status")
|
||||
flags.Int("scheduled-statuses-max-total", cfg.ScheduledStatusesMaxTotal, "Maximum number of scheduled statuses per user")
|
||||
flags.Int("scheduled-statuses-max-daily", cfg.ScheduledStatusesMaxDaily, "Maximum number of scheduled statuses per user for a single day")
|
||||
flags.Bool("letsencrypt-enabled", cfg.LetsEncryptEnabled, "Enable letsencrypt TLS certs for this server. If set to true, then cert dir also needs to be set (or take the default).")
|
||||
flags.Int("letsencrypt-port", cfg.LetsEncryptPort, "Port to listen on for letsencrypt certificate challenges. Must not be the same as the GtS webserver/API port.")
|
||||
flags.String("letsencrypt-cert-dir", cfg.LetsEncryptCertDir, "Directory to store acquired letsencrypt certificates.")
|
||||
|
|
@ -391,6 +396,7 @@ func (cfg *Configuration) RegisterFlags(flags *pflag.FlagSet) {
|
|||
flags.Float64("cache-poll-vote-mem-ratio", cfg.Cache.PollVoteMemRatio, "")
|
||||
flags.Float64("cache-poll-vote-ids-mem-ratio", cfg.Cache.PollVoteIDsMemRatio, "")
|
||||
flags.Float64("cache-report-mem-ratio", cfg.Cache.ReportMemRatio, "")
|
||||
flags.Float64("cache-scheduled-status-mem-ratio", cfg.Cache.ScheduledStatusMemRatio, "")
|
||||
flags.Float64("cache-sin-bin-status-mem-ratio", cfg.Cache.SinBinStatusMemRatio, "")
|
||||
flags.Float64("cache-status-mem-ratio", cfg.Cache.StatusMemRatio, "")
|
||||
flags.Float64("cache-status-bookmark-mem-ratio", cfg.Cache.StatusBookmarkMemRatio, "")
|
||||
|
|
@ -414,7 +420,7 @@ func (cfg *Configuration) RegisterFlags(flags *pflag.FlagSet) {
|
|||
}
|
||||
|
||||
func (cfg *Configuration) MarshalMap() map[string]any {
|
||||
cfgmap := make(map[string]any, 194)
|
||||
cfgmap := make(map[string]any, 197)
|
||||
cfgmap["log-level"] = cfg.LogLevel
|
||||
cfgmap["log-format"] = cfg.LogFormat
|
||||
cfgmap["log-timestamp-format"] = cfg.LogTimestampFormat
|
||||
|
|
@ -485,6 +491,8 @@ func (cfg *Configuration) MarshalMap() map[string]any {
|
|||
cfgmap["statuses-poll-max-options"] = cfg.StatusesPollMaxOptions
|
||||
cfgmap["statuses-poll-option-max-chars"] = cfg.StatusesPollOptionMaxChars
|
||||
cfgmap["statuses-media-max-files"] = cfg.StatusesMediaMaxFiles
|
||||
cfgmap["scheduled-statuses-max-total"] = cfg.ScheduledStatusesMaxTotal
|
||||
cfgmap["scheduled-statuses-max-daily"] = cfg.ScheduledStatusesMaxDaily
|
||||
cfgmap["letsencrypt-enabled"] = cfg.LetsEncryptEnabled
|
||||
cfgmap["letsencrypt-port"] = cfg.LetsEncryptPort
|
||||
cfgmap["letsencrypt-cert-dir"] = cfg.LetsEncryptCertDir
|
||||
|
|
@ -580,6 +588,7 @@ func (cfg *Configuration) MarshalMap() map[string]any {
|
|||
cfgmap["cache-poll-vote-mem-ratio"] = cfg.Cache.PollVoteMemRatio
|
||||
cfgmap["cache-poll-vote-ids-mem-ratio"] = cfg.Cache.PollVoteIDsMemRatio
|
||||
cfgmap["cache-report-mem-ratio"] = cfg.Cache.ReportMemRatio
|
||||
cfgmap["cache-scheduled-status-mem-ratio"] = cfg.Cache.ScheduledStatusMemRatio
|
||||
cfgmap["cache-sin-bin-status-mem-ratio"] = cfg.Cache.SinBinStatusMemRatio
|
||||
cfgmap["cache-status-mem-ratio"] = cfg.Cache.StatusMemRatio
|
||||
cfgmap["cache-status-bookmark-mem-ratio"] = cfg.Cache.StatusBookmarkMemRatio
|
||||
|
|
@ -1186,6 +1195,22 @@ func (cfg *Configuration) UnmarshalMap(cfgmap map[string]any) error {
|
|||
}
|
||||
}
|
||||
|
||||
if ival, ok := cfgmap["scheduled-statuses-max-total"]; ok {
|
||||
var err error
|
||||
cfg.ScheduledStatusesMaxTotal, err = cast.ToIntE(ival)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error casting %#v -> int for 'scheduled-statuses-max-total': %w", ival, err)
|
||||
}
|
||||
}
|
||||
|
||||
if ival, ok := cfgmap["scheduled-statuses-max-daily"]; ok {
|
||||
var err error
|
||||
cfg.ScheduledStatusesMaxDaily, err = cast.ToIntE(ival)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error casting %#v -> int for 'scheduled-statuses-max-daily': %w", ival, err)
|
||||
}
|
||||
}
|
||||
|
||||
if ival, ok := cfgmap["letsencrypt-enabled"]; ok {
|
||||
var err error
|
||||
cfg.LetsEncryptEnabled, err = cast.ToBoolE(ival)
|
||||
|
|
@ -1972,6 +1997,14 @@ func (cfg *Configuration) UnmarshalMap(cfgmap map[string]any) error {
|
|||
}
|
||||
}
|
||||
|
||||
if ival, ok := cfgmap["cache-scheduled-status-mem-ratio"]; ok {
|
||||
var err error
|
||||
cfg.Cache.ScheduledStatusMemRatio, err = cast.ToFloat64E(ival)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error casting %#v -> float64 for 'cache-scheduled-status-mem-ratio': %w", ival, err)
|
||||
}
|
||||
}
|
||||
|
||||
if ival, ok := cfgmap["cache-sin-bin-status-mem-ratio"]; ok {
|
||||
var err error
|
||||
cfg.Cache.SinBinStatusMemRatio, err = cast.ToFloat64E(ival)
|
||||
|
|
@ -3753,6 +3786,50 @@ func GetStatusesMediaMaxFiles() int { return global.GetStatusesMediaMaxFiles() }
|
|||
// SetStatusesMediaMaxFiles safely sets the value for global configuration 'StatusesMediaMaxFiles' field
|
||||
func SetStatusesMediaMaxFiles(v int) { global.SetStatusesMediaMaxFiles(v) }
|
||||
|
||||
// GetScheduledStatusesMaxTotal safely fetches the Configuration value for state's 'ScheduledStatusesMaxTotal' field
|
||||
func (st *ConfigState) GetScheduledStatusesMaxTotal() (v int) {
|
||||
st.mutex.RLock()
|
||||
v = st.config.ScheduledStatusesMaxTotal
|
||||
st.mutex.RUnlock()
|
||||
return
|
||||
}
|
||||
|
||||
// SetScheduledStatusesMaxTotal safely sets the Configuration value for state's 'ScheduledStatusesMaxTotal' field
|
||||
func (st *ConfigState) SetScheduledStatusesMaxTotal(v int) {
|
||||
st.mutex.Lock()
|
||||
defer st.mutex.Unlock()
|
||||
st.config.ScheduledStatusesMaxTotal = v
|
||||
st.reloadToViper()
|
||||
}
|
||||
|
||||
// GetScheduledStatusesMaxTotal safely fetches the value for global configuration 'ScheduledStatusesMaxTotal' field
|
||||
func GetScheduledStatusesMaxTotal() int { return global.GetScheduledStatusesMaxTotal() }
|
||||
|
||||
// SetScheduledStatusesMaxTotal safely sets the value for global configuration 'ScheduledStatusesMaxTotal' field
|
||||
func SetScheduledStatusesMaxTotal(v int) { global.SetScheduledStatusesMaxTotal(v) }
|
||||
|
||||
// GetScheduledStatusesMaxDaily safely fetches the Configuration value for state's 'ScheduledStatusesMaxDaily' field
|
||||
func (st *ConfigState) GetScheduledStatusesMaxDaily() (v int) {
|
||||
st.mutex.RLock()
|
||||
v = st.config.ScheduledStatusesMaxDaily
|
||||
st.mutex.RUnlock()
|
||||
return
|
||||
}
|
||||
|
||||
// SetScheduledStatusesMaxDaily safely sets the Configuration value for state's 'ScheduledStatusesMaxDaily' field
|
||||
func (st *ConfigState) SetScheduledStatusesMaxDaily(v int) {
|
||||
st.mutex.Lock()
|
||||
defer st.mutex.Unlock()
|
||||
st.config.ScheduledStatusesMaxDaily = v
|
||||
st.reloadToViper()
|
||||
}
|
||||
|
||||
// GetScheduledStatusesMaxDaily safely fetches the value for global configuration 'ScheduledStatusesMaxDaily' field
|
||||
func GetScheduledStatusesMaxDaily() int { return global.GetScheduledStatusesMaxDaily() }
|
||||
|
||||
// SetScheduledStatusesMaxDaily safely sets the value for global configuration 'ScheduledStatusesMaxDaily' field
|
||||
func SetScheduledStatusesMaxDaily(v int) { global.SetScheduledStatusesMaxDaily(v) }
|
||||
|
||||
// GetLetsEncryptEnabled safely fetches the Configuration value for state's 'LetsEncryptEnabled' field
|
||||
func (st *ConfigState) GetLetsEncryptEnabled() (v bool) {
|
||||
st.mutex.RLock()
|
||||
|
|
@ -5859,6 +5936,28 @@ func GetCacheReportMemRatio() float64 { return global.GetCacheReportMemRatio() }
|
|||
// SetCacheReportMemRatio safely sets the value for global configuration 'Cache.ReportMemRatio' field
|
||||
func SetCacheReportMemRatio(v float64) { global.SetCacheReportMemRatio(v) }
|
||||
|
||||
// GetCacheScheduledStatusMemRatio safely fetches the Configuration value for state's 'Cache.ScheduledStatusMemRatio' field
|
||||
func (st *ConfigState) GetCacheScheduledStatusMemRatio() (v float64) {
|
||||
st.mutex.RLock()
|
||||
v = st.config.Cache.ScheduledStatusMemRatio
|
||||
st.mutex.RUnlock()
|
||||
return
|
||||
}
|
||||
|
||||
// SetCacheScheduledStatusMemRatio safely sets the Configuration value for state's 'Cache.ScheduledStatusMemRatio' field
|
||||
func (st *ConfigState) SetCacheScheduledStatusMemRatio(v float64) {
|
||||
st.mutex.Lock()
|
||||
defer st.mutex.Unlock()
|
||||
st.config.Cache.ScheduledStatusMemRatio = v
|
||||
st.reloadToViper()
|
||||
}
|
||||
|
||||
// GetCacheScheduledStatusMemRatio safely fetches the value for global configuration 'Cache.ScheduledStatusMemRatio' field
|
||||
func GetCacheScheduledStatusMemRatio() float64 { return global.GetCacheScheduledStatusMemRatio() }
|
||||
|
||||
// SetCacheScheduledStatusMemRatio safely sets the value for global configuration 'Cache.ScheduledStatusMemRatio' field
|
||||
func SetCacheScheduledStatusMemRatio(v float64) { global.SetCacheScheduledStatusMemRatio(v) }
|
||||
|
||||
// GetCacheSinBinStatusMemRatio safely fetches the Configuration value for state's 'Cache.SinBinStatusMemRatio' field
|
||||
func (st *ConfigState) GetCacheSinBinStatusMemRatio() (v float64) {
|
||||
st.mutex.RLock()
|
||||
|
|
@ -6545,6 +6644,7 @@ func (st *ConfigState) GetTotalOfMemRatios() (total float64) {
|
|||
total += st.config.Cache.PollVoteMemRatio
|
||||
total += st.config.Cache.PollVoteIDsMemRatio
|
||||
total += st.config.Cache.ReportMemRatio
|
||||
total += st.config.Cache.ScheduledStatusMemRatio
|
||||
total += st.config.Cache.SinBinStatusMemRatio
|
||||
total += st.config.Cache.StatusMemRatio
|
||||
total += st.config.Cache.StatusBookmarkMemRatio
|
||||
|
|
@ -7328,6 +7428,17 @@ func flattenConfigMap(cfgmap map[string]any) {
|
|||
}
|
||||
}
|
||||
|
||||
for _, key := range [][]string{
|
||||
{"cache", "scheduled-status-mem-ratio"},
|
||||
} {
|
||||
ival, ok := mapGet(cfgmap, key...)
|
||||
if ok {
|
||||
cfgmap["cache-scheduled-status-mem-ratio"] = ival
|
||||
nestedKeys[key[0]] = struct{}{}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for _, key := range [][]string{
|
||||
{"cache", "sin-bin-status-mem-ratio"},
|
||||
} {
|
||||
|
|
|
|||
2
internal/config/testdata/test.json
vendored
2
internal/config/testdata/test.json
vendored
|
|
@ -49,6 +49,8 @@
|
|||
"statuses-media-max-files": 6,
|
||||
"statuses-poll-max-options": 6,
|
||||
"statuses-poll-option-max-chars": 50,
|
||||
"scheduled-statuses-max-total": 300,
|
||||
"scheduled-statuses-max-daily": 25,
|
||||
"storage-backend": "local",
|
||||
"storage-local-base-path": "/gotosocial/storage",
|
||||
"trusted-proxies": [
|
||||
|
|
|
|||
10
internal/config/testdata/test.yaml
vendored
10
internal/config/testdata/test.yaml
vendored
|
|
@ -243,6 +243,16 @@ statuses-poll-option-max-chars: 50
|
|||
# Default: 6
|
||||
statuses-media-max-files: 6
|
||||
|
||||
# Int. Maximum number of statuses a user can schedule at time.
|
||||
# Examples: [300]
|
||||
# Default: 300
|
||||
scheduled-statuses-max-total: 300
|
||||
|
||||
# Int. Maximum number of statuses a user can schedule for a single day.
|
||||
# Examples: [25]
|
||||
# Default: 25
|
||||
scheduled-statuses-max-daily: 25
|
||||
|
||||
##############################
|
||||
##### LETSENCRYPT CONFIG #####
|
||||
##############################
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue