2021-11-29 21:35:21 -05:00
using System.Text ;
using Humanizer ;
2024-11-19 17:35:09 -07:00
using Myriad.Builders ;
2021-11-29 21:35:21 -05:00
using NodaTime ;
using NodaTime.Text ;
using NodaTime.TimeZones ;
using PluralKit.Core ;
namespace PluralKit.Bot ;
public class Config
{
private record PaginatedConfigItem ( string Key , string Description , string? CurrentValue , string DefaultValue ) ;
public async Task ShowConfig ( Context ctx )
{
var items = new List < PaginatedConfigItem > ( ) ;
2022-06-15 19:28:34 -04:00
var allowAutoproxy = await ctx . Repository . GetAutoproxyEnabled ( ctx . Author . Id ) ;
2021-11-29 21:35:21 -05:00
items . Add ( new (
"autoproxy account" ,
"Whether autoproxy is enabled for the current account" ,
2022-06-15 19:28:34 -04:00
EnabledDisabled ( allowAutoproxy ) ,
2021-11-29 21:35:21 -05:00
"enabled"
) ) ;
items . Add ( new (
"autoproxy timeout" ,
"If this is set, latch-mode autoproxy will not keep autoproxying after this amount of time has elapsed since the last message sent in the server" ,
ctx . Config . LatchTimeout . HasValue
? (
ctx . Config . LatchTimeout . Value ! = 0
? Duration . FromSeconds ( ctx . Config . LatchTimeout . Value ) . ToTimeSpan ( ) . Humanize ( 4 )
: "disabled"
)
: null ,
ProxyMatcher . DefaultLatchExpiryTime . ToTimeSpan ( ) . Humanize ( 4 )
) ) ;
items . Add ( new (
"timezone" ,
"The system's time zone - shows timestamps in your local time" ,
ctx . Config . UiTz ,
"UTC"
) ) ;
items . Add ( new (
"ping" ,
$"Whether other users are able to mention you via a {Emojis.Bell} reaction" ,
EnabledDisabled ( ctx . Config . PingsEnabled ) ,
"enabled"
) ) ;
2021-12-01 11:48:49 -05:00
items . Add ( new (
"private member" ,
"Whether member privacy is automatically set to private for new members" ,
EnabledDisabled ( ctx . Config . MemberDefaultPrivate ) ,
"disabled"
) ) ;
items . Add ( new (
"private group" ,
"Whether group privacy is automatically set to private for new groups" ,
EnabledDisabled ( ctx . Config . GroupDefaultPrivate ) ,
"disabled"
) ) ;
2021-12-06 04:01:42 -05:00
items . Add ( new (
"show private" ,
"Whether private information is shown to linked accounts by default" ,
ctx . Config . ShowPrivateInfo . ToString ( ) . ToLower ( ) ,
"true"
) ) ;
2021-11-29 21:35:21 -05:00
items . Add ( new (
"Member limit" ,
"The maximum number of registered members for your system" ,
ctx . Config . MemberLimitOverride ? . ToString ( ) ,
Limits . MaxMemberCount . ToString ( )
) ) ;
items . Add ( new (
"Group limit" ,
"The maximum number of registered groups for your system" ,
ctx . Config . GroupLimitOverride ? . ToString ( ) ,
Limits . MaxGroupCount . ToString ( )
) ) ;
2022-11-23 09:48:24 +01:00
items . Add ( new (
2022-11-24 21:35:14 -07:00
"Proxy case" ,
"Whether proxy tags are case sensitive" ,
2022-11-23 09:48:24 +01:00
EnabledDisabled ( ctx . Config . CaseSensitiveProxyTags ) ,
"enabled"
) ) ;
2023-03-25 23:42:47 +01:00
items . Add ( new (
"Proxy error" ,
2024-01-27 00:59:59 +00:00
"Whether to send an error message when proxying fails" ,
2023-03-25 23:42:47 +01:00
EnabledDisabled ( ctx . Config . ProxyErrorMessageEnabled ) ,
"enabled"
) ) ;
2024-04-28 15:46:06 +12:00
items . Add ( new (
"Split IDs" ,
"Whether to display 6-character IDs split with a hyphen, to ease readability" ,
EnabledDisabled ( ctx . Config . HidDisplaySplit ) ,
"disabled"
) ) ;
2024-04-28 21:05:46 +12:00
items . Add ( new (
"Capitalize IDs" ,
"Whether to display IDs as capital letters, to ease readability" ,
EnabledDisabled ( ctx . Config . HidDisplayCaps ) ,
"disabled"
) ) ;
2024-05-19 21:31:26 +09:00
items . Add ( new (
"Pad IDs" ,
"Whether to pad 5-character IDs in lists (left/right)" ,
ctx . Config . HidListPadding . ToUserString ( ) ,
"off"
) ) ;
2024-11-09 11:34:06 -07:00
items . Add ( new (
"Proxy Switch" ,
2024-12-05 18:24:20 -07:00
"Switching behavior when proxy tags are used" ,
ctx . Config . ProxySwitch . ToUserString ( ) ,
"off"
2024-11-09 11:34:06 -07:00
) ) ;
2024-10-22 03:05:32 -04:00
items . Add ( new (
"Name Format" ,
"Format string used to display a member's name https://pluralkit.me/guide/#setting-a-custom-name-format" ,
ctx . Config . NameFormat ,
ProxyMember . DefaultFormat
) ) ;
2024-11-20 16:28:42 -07:00
if ( ctx . Guild = = null )
{
items . Add ( new (
"Server Name Format" ,
"Format string used to display a member's name in the current server" ,
"only available in servers" ,
"only available in servers"
) ) ;
}
else
{
items . Add ( new (
"Server Name Format" ,
"Format string used to display a member's name in the current server" ,
( await ctx . Repository . GetSystemGuild ( ctx . Guild . Id , ctx . System . Id ) ) . NameFormat ? ? "none set" ,
"none set"
) ) ;
}
2024-11-19 17:35:09 -07:00
2021-11-29 21:35:21 -05:00
await ctx . Paginate < PaginatedConfigItem > (
items . ToAsyncEnumerable ( ) ,
items . Count ,
10 ,
"Current settings for your system" ,
ctx . System . Color ,
( eb , l ) = >
{
var description = new StringBuilder ( ) ;
foreach ( var item in l )
{
description . Append ( item . Key . AsCode ( ) ) ;
description . Append ( $" **({item.CurrentValue ?? item.DefaultValue})**" ) ;
if ( item . CurrentValue ! = null & & item . CurrentValue ! = item . DefaultValue )
description . Append ( "\ud83d\udd39" ) ;
description . AppendLine ( ) ;
description . Append ( item . Description ) ;
description . AppendLine ( ) ;
description . AppendLine ( ) ;
}
eb . Description ( description . ToString ( ) ) ;
2022-02-11 12:25:56 -05:00
// using *large* blue diamond here since it's easier to see in the small footer
2024-12-31 08:09:18 -07:00
eb . Footer ( new ( $"\U0001f537 means this setting was changed. Type `{ctx.DefaultPrefix}config <setting name> clear` to reset it to the default." ) ) ;
2022-02-11 12:25:56 -05:00
2021-11-29 21:35:21 -05:00
return Task . CompletedTask ;
}
) ;
}
2022-01-19 18:59:44 -05:00
private string EnabledDisabled ( bool value ) = > value ? "enabled" : "disabled" ;
2021-11-29 21:35:21 -05:00
2025-01-07 23:15:18 +09:00
public async Task ViewAutoproxyAccount ( Context ctx )
2021-11-29 21:35:21 -05:00
{
2022-06-15 19:28:34 -04:00
var allowAutoproxy = await ctx . Repository . GetAutoproxyEnabled ( ctx . Author . Id ) ;
2025-01-07 23:15:18 +09:00
await ctx . Reply ( $"Autoproxy is currently **{EnabledDisabled(allowAutoproxy)}** for account <@{ctx.Author.Id}>." ) ;
}
2021-11-29 21:35:21 -05:00
2025-01-21 12:36:54 +09:00
public async Task EditAutoproxyAccount ( Context ctx , bool allow )
2025-01-07 23:15:18 +09:00
{
var allowAutoproxy = await ctx . Repository . GetAutoproxyEnabled ( ctx . Author . Id ) ;
2021-11-29 21:35:21 -05:00
var statusString = EnabledDisabled ( allow ) ;
2022-06-15 19:28:34 -04:00
if ( allowAutoproxy = = allow )
2021-11-29 21:35:21 -05:00
{
await ctx . Reply ( $"{Emojis.Note} Autoproxy is already {statusString} for account <@{ctx.Author.Id}>." ) ;
return ;
}
var patch = new AccountPatch { AllowAutoproxy = allow } ;
2022-01-22 03:05:01 -05:00
await ctx . Repository . UpdateAccount ( ctx . Author . Id , patch ) ;
2021-11-29 21:35:21 -05:00
await ctx . Reply ( $"{Emojis.Success} Autoproxy {statusString} for account <@{ctx.Author.Id}>." ) ;
}
2025-01-07 23:15:18 +09:00
public async Task ViewAutoproxyTimeout ( Context ctx )
{
var timeout = ctx . Config . LatchTimeout . HasValue
? Duration . FromSeconds ( ctx . Config . LatchTimeout . Value )
: ( Duration ? ) null ;
if ( timeout = = null )
await ctx . Reply ( $"You do not have a custom autoproxy timeout duration set. The default latch timeout duration is {ProxyMatcher.DefaultLatchExpiryTime.ToTimeSpan().Humanize(4)}." ) ;
else if ( timeout = = Duration . Zero )
await ctx . Reply ( "Latch timeout is currently **disabled** for your system. Latch mode autoproxy will never time out." ) ;
else
await ctx . Reply ( $"The current latch timeout duration for your system is {timeout.Value.ToTimeSpan().Humanize(4)}." ) ;
}
2021-11-29 21:35:21 -05:00
2025-01-21 12:36:54 +09:00
public async Task DisableAutoproxyTimeout ( Context ctx )
2021-11-29 21:35:21 -05:00
{
2025-01-21 12:36:54 +09:00
await ctx . Repository . UpdateSystemConfig ( ctx . System . Id , new ( ) { LatchTimeout = ( int ) Duration . Zero . TotalSeconds } ) ;
2021-11-29 21:35:21 -05:00
2025-01-21 12:36:54 +09:00
await ctx . Reply ( $"{Emojis.Success} Latch timeout disabled. Latch mode autoproxy will never time out." ) ;
}
public async Task ResetAutoproxyTimeout ( Context ctx )
{
await ctx . Repository . UpdateSystemConfig ( ctx . System . Id , new ( ) { LatchTimeout = null } ) ;
await ctx . Reply ( $"{Emojis.Success} Latch timeout reset to default ({ProxyMatcher.DefaultLatchExpiryTime.ToTimeSpan().Humanize(4)})." ) ;
}
public async Task EditAutoproxyTimeout ( Context ctx , string timeout )
{
Duration newTimeout ;
2021-11-29 21:35:21 -05:00
Duration overflow = Duration . Zero ;
2025-01-21 12:36:54 +09:00
// todo: we should parse date in the command parser
var timeoutStr = timeout ;
var timeoutPeriod = DateUtils . ParsePeriod ( timeoutStr )
? ? throw new PKError ( $"Could not parse '{timeoutStr}' as a valid duration. Try using a syntax such as \" 3 h5m \ " (i.e. 3 hours and 5 minutes)." ) ;
if ( timeoutPeriod . TotalHours > 100000 )
2021-11-29 21:35:21 -05:00
{
2025-01-21 12:36:54 +09:00
// sanity check to prevent seconds overflow if someone types in 999999999
overflow = timeoutPeriod ;
newTimeout = Duration . Zero ;
2021-11-29 21:35:21 -05:00
}
2025-01-21 12:36:54 +09:00
else newTimeout = timeoutPeriod ;
2021-11-29 21:35:21 -05:00
2025-01-21 12:36:54 +09:00
await ctx . Repository . UpdateSystemConfig ( ctx . System . Id , new ( ) { LatchTimeout = ( int? ) newTimeout . TotalSeconds } ) ;
2021-11-29 21:35:21 -05:00
2025-01-21 12:36:54 +09:00
if ( newTimeout = = Duration . Zero & & overflow ! = Duration . Zero )
2021-11-29 21:35:21 -05:00
await ctx . Reply ( $"{Emojis.Success} Latch timeout disabled. Latch mode autoproxy will never time out. ({overflow.ToTimeSpan().Humanize(4)} is too long)" ) ;
else if ( newTimeout = = Duration . Zero )
await ctx . Reply ( $"{Emojis.Success} Latch timeout disabled. Latch mode autoproxy will never time out." ) ;
else
2025-01-21 12:36:54 +09:00
await ctx . Reply ( $"{Emojis.Success} Latch timeout set to {newTimeout.ToTimeSpan().Humanize(4)}." ) ;
2021-11-29 21:35:21 -05:00
}
public async Task SystemTimezone ( Context ctx )
{
2024-12-31 08:09:18 -07:00
if ( ctx . System = = null ) throw Errors . NoSystemError ( ctx . DefaultPrefix ) ;
2021-11-29 21:35:21 -05:00
2022-12-01 07:16:36 +00:00
if ( ctx . MatchClear ( ) )
2021-11-29 21:35:21 -05:00
{
2022-01-22 03:05:01 -05:00
await ctx . Repository . UpdateSystemConfig ( ctx . System . Id , new ( ) { UiTz = "UTC" } ) ;
2021-11-29 21:35:21 -05:00
await ctx . Reply ( $"{Emojis.Success} System time zone cleared (set to UTC)." ) ;
return ;
}
var zoneStr = ctx . RemainderOrNull ( ) ;
if ( zoneStr = = null )
{
await ctx . Reply (
2024-12-31 08:09:18 -07:00
$"Your current system time zone is set to **{ctx.Config.UiTz}**. It is currently **{SystemClock.Instance.GetCurrentInstant().FormatZoned(ctx.Config.Zone)}** in that time zone. To change your system time zone, type `{ctx.DefaultPrefix}config tz <zone>`." ) ;
2021-11-29 21:35:21 -05:00
return ;
}
var zone = await FindTimeZone ( ctx , zoneStr ) ;
if ( zone = = null ) throw Errors . InvalidTimeZone ( zoneStr ) ;
var currentTime = SystemClock . Instance . GetCurrentInstant ( ) . InZone ( zone ) ;
var msg = $"This will change the system time zone to **{zone.Id}**. The current time is **{currentTime.FormatZoned()}**. Is this correct?" ;
if ( ! await ctx . PromptYesNo ( msg , "Change Timezone" ) ) throw Errors . TimezoneChangeCancelled ;
2022-01-22 03:05:01 -05:00
await ctx . Repository . UpdateSystemConfig ( ctx . System . Id , new ( ) { UiTz = zone . Id } ) ;
2021-11-29 21:35:21 -05:00
await ctx . Reply ( $"System time zone changed to **{zone.Id}**." ) ;
}
private async Task < DateTimeZone > FindTimeZone ( Context ctx , string zoneStr )
{
// First, if we're given a flag emoji, we extract the flag emoji code from it.
zoneStr = Core . StringUtils . ExtractCountryFlag ( zoneStr ) ? ? zoneStr ;
// Then, we find all *locations* matching either the given country code or the country name.
var locations = TzdbDateTimeZoneSource . Default . Zone1970Locations ;
var matchingLocations = locations . Where ( l = > l . Countries . Any ( c = >
string . Equals ( c . Code , zoneStr , StringComparison . InvariantCultureIgnoreCase ) | |
string . Equals ( c . Name , zoneStr , StringComparison . InvariantCultureIgnoreCase ) ) ) ;
// Then, we find all (unique) time zone IDs that match.
var matchingZones = matchingLocations . Select ( l = > DateTimeZoneProviders . Tzdb . GetZoneOrNull ( l . ZoneId ) )
. Distinct ( ) . ToList ( ) ;
// If the set of matching zones is empty (ie. we didn't find anything), we try a few other things.
if ( matchingZones . Count = = 0 )
{
// First, we try to just find the time zone given directly and return that.
var givenZone = DateTimeZoneProviders . Tzdb . GetZoneOrNull ( zoneStr ) ;
if ( givenZone ! = null ) return givenZone ;
// If we didn't find anything there either, we try parsing the string as an offset, then
// find all possible zones that match that offset. For an offset like UTC+2, this doesn't *quite*
// work, since there are 57(!) matching zones (as of 2019-06-13) - but for less populated time zones
// this could work nicely.
var inputWithoutUtc = zoneStr . Replace ( "UTC" , "" ) . Replace ( "GMT" , "" ) ;
var res = OffsetPattern . CreateWithInvariantCulture ( "+H" ) . Parse ( inputWithoutUtc ) ;
if ( ! res . Success ) res = OffsetPattern . CreateWithInvariantCulture ( "+H:mm" ) . Parse ( inputWithoutUtc ) ;
// If *this* didn't parse correctly, fuck it, bail.
if ( ! res . Success ) return null ;
var offset = res . Value ;
// To try to reduce the count, we go by locations from the 1970+ database instead of just the full database
// This elides regions that have been identical since 1970, omitting small distinctions due to Ancient History(tm).
var allZones = TzdbDateTimeZoneSource . Default . Zone1970Locations . Select ( l = > l . ZoneId ) . Distinct ( ) ;
matchingZones = allZones . Select ( z = > DateTimeZoneProviders . Tzdb . GetZoneOrNull ( z ) )
. Where ( z = > z . GetUtcOffset ( SystemClock . Instance . GetCurrentInstant ( ) ) = = offset ) . ToList ( ) ;
}
// If we have a list of viable time zones, we ask the user which is correct.
// If we only have one, return that one.
if ( matchingZones . Count = = 1 )
return matchingZones . First ( ) ;
// Otherwise, prompt and return!
return await ctx . Choose ( "There were multiple matches for your time zone query. Please select the region that matches you the closest:" , matchingZones ,
z = >
{
if ( TzdbDateTimeZoneSource . Default . Aliases . Contains ( z . Id ) )
return $"**{z.Id}**, {string.Join(" , ", TzdbDateTimeZoneSource.Default.Aliases[z.Id])}" ;
return $"**{z.Id}**" ;
} ) ;
}
2021-12-01 11:48:49 -05:00
2022-01-19 18:59:44 -05:00
public async Task SystemPing ( Context ctx )
{
// note: this is here because this is also used in `pk;system ping`, which does not CheckSystem
ctx . CheckSystem ( ) ;
// todo: move all the other config settings to this format
String Response ( bool isError , bool val )
= > $"Reaction pings are {(isError ? " already " : " currently ")} **{EnabledDisabled(val)}** for your system. "
2024-12-31 08:09:18 -07:00
+ $"To {EnabledDisabled(!val)[..^1]} reaction pings, type `{ctx.DefaultPrefix}config ping {EnabledDisabled(!val)[..^1]}`." ;
2022-01-19 18:59:44 -05:00
if ( ! ctx . HasNext ( ) )
{
await ctx . Reply ( Response ( false , ctx . Config . PingsEnabled ) ) ;
return ;
}
2022-02-11 12:25:56 -05:00
var value = ctx . MatchToggle ( true ) ;
2022-01-19 18:59:44 -05:00
if ( ctx . Config . PingsEnabled = = value )
await ctx . Reply ( Response ( true , ctx . Config . PingsEnabled ) ) ;
else
{
2022-01-22 03:05:01 -05:00
await ctx . Repository . UpdateSystemConfig ( ctx . System . Id , new ( ) { PingsEnabled = value } ) ;
2022-01-19 18:59:44 -05:00
await ctx . Reply ( $"Reaction pings have now been {EnabledDisabled(value)}." ) ;
}
}
2021-12-07 01:58:05 -05:00
2021-12-01 11:48:49 -05:00
public async Task MemberDefaultPrivacy ( Context ctx )
{
if ( ! ctx . HasNext ( ) )
{
2024-12-31 08:09:18 -07:00
if ( ctx . Config . MemberDefaultPrivate ) { await ctx . Reply ( $"Newly created members will currently have their privacy settings set to private. To change this, type `{ctx.DefaultPrefix}config private member off`" ) ; }
else { await ctx . Reply ( $"Newly created members will currently have their privacy settings set to public. To automatically set new members' privacy settings to private, type `{ctx.DefaultPrefix}config private member on`" ) ; }
2021-12-01 11:48:49 -05:00
}
else
{
2022-02-11 12:25:56 -05:00
if ( ctx . MatchToggle ( false ) )
2021-12-01 11:48:49 -05:00
{
2022-01-22 03:05:01 -05:00
await ctx . Repository . UpdateSystemConfig ( ctx . System . Id , new ( ) { MemberDefaultPrivate = true } ) ;
2021-12-01 11:48:49 -05:00
await ctx . Reply ( "Newly created members will now have their privacy settings set to private." ) ;
}
2022-01-19 18:59:44 -05:00
else
2021-12-01 11:48:49 -05:00
{
2022-01-22 03:05:01 -05:00
await ctx . Repository . UpdateSystemConfig ( ctx . System . Id , new ( ) { MemberDefaultPrivate = false } ) ;
2021-12-01 11:48:49 -05:00
await ctx . Reply ( "Newly created members will now have their privacy settings set to public." ) ;
}
}
}
public async Task GroupDefaultPrivacy ( Context ctx )
{
if ( ! ctx . HasNext ( ) )
{
2024-12-31 08:09:18 -07:00
if ( ctx . Config . GroupDefaultPrivate ) { await ctx . Reply ( $"Newly created groups will currently have their privacy settings set to private. To change this, type `{ctx.DefaultPrefix}config private group off`" ) ; }
else { await ctx . Reply ( $"Newly created groups will currently have their privacy settings set to public. To automatically set new groups' privacy settings to private, type `{ctx.DefaultPrefix}config private group on`" ) ; }
2021-12-01 11:48:49 -05:00
}
else
{
2022-02-11 12:25:56 -05:00
if ( ctx . MatchToggle ( false ) )
2021-12-01 11:48:49 -05:00
{
2022-01-22 03:05:01 -05:00
await ctx . Repository . UpdateSystemConfig ( ctx . System . Id , new ( ) { GroupDefaultPrivate = true } ) ;
2021-12-01 11:48:49 -05:00
await ctx . Reply ( "Newly created groups will now have their privacy settings set to private." ) ;
}
2022-01-19 18:59:44 -05:00
else
2021-12-01 11:48:49 -05:00
{
2022-01-22 03:05:01 -05:00
await ctx . Repository . UpdateSystemConfig ( ctx . System . Id , new ( ) { GroupDefaultPrivate = false } ) ;
2021-12-01 11:48:49 -05:00
await ctx . Reply ( "Newly created groups will now have their privacy settings set to public." ) ;
}
}
}
2021-12-06 04:01:42 -05:00
public async Task ShowPrivateInfo ( Context ctx )
{
if ( ! ctx . HasNext ( ) )
{
if ( ctx . Config . ShowPrivateInfo ) await ctx . Reply ( "Private information is currently **shown** when looking up your own info. Use the `-public` flag to hide it." ) ;
else await ctx . Reply ( "Private information is currently **hidden** when looking up your own info. Use the `-private` flag to show it." ) ;
return ;
}
2022-02-11 12:25:56 -05:00
if ( ctx . MatchToggle ( true ) )
2021-12-06 04:01:42 -05:00
{
2022-01-22 03:05:01 -05:00
await ctx . Repository . UpdateSystemConfig ( ctx . System . Id , new ( ) { ShowPrivateInfo = true } ) ;
2021-12-06 04:01:42 -05:00
await ctx . Reply ( "Private information will now be **shown** when looking up your own info. Use the `-public` flag to hide it." ) ;
}
2022-01-19 18:59:44 -05:00
else
2021-12-06 04:01:42 -05:00
{
2022-01-22 03:05:01 -05:00
await ctx . Repository . UpdateSystemConfig ( ctx . System . Id , new ( ) { ShowPrivateInfo = false } ) ;
2021-12-06 04:01:42 -05:00
await ctx . Reply ( "Private information will now be **hidden** when looking up your own info. Use the `-private` flag to show it." ) ;
}
}
2022-11-23 09:48:24 +01:00
public async Task CaseSensitiveProxyTags ( Context ctx )
{
if ( ! ctx . HasNext ( ) )
{
2022-11-24 21:35:14 -07:00
if ( ctx . Config . CaseSensitiveProxyTags ) { await ctx . Reply ( "Proxy tags are currently case **sensitive**." ) ; }
else { await ctx . Reply ( "Proxy tags are currently case **insensitive**." ) ; }
2022-11-23 09:48:24 +01:00
return ;
}
if ( ctx . MatchToggle ( true ) )
{
await ctx . Repository . UpdateSystemConfig ( ctx . System . Id , new ( ) { CaseSensitiveProxyTags = true } ) ;
2022-11-24 21:35:14 -07:00
await ctx . Reply ( "Proxy tags are now case sensitive." ) ;
2022-11-23 09:48:24 +01:00
}
else
{
await ctx . Repository . UpdateSystemConfig ( ctx . System . Id , new ( ) { CaseSensitiveProxyTags = false } ) ;
2022-11-24 21:35:14 -07:00
await ctx . Reply ( "Proxy tags are now case insensitive." ) ;
2022-11-23 09:48:24 +01:00
}
}
2023-03-25 23:42:47 +01:00
public async Task ProxyErrorMessageEnabled ( Context ctx )
{
if ( ! ctx . HasNext ( ) )
{
if ( ctx . Config . ProxyErrorMessageEnabled ) { await ctx . Reply ( "Proxy error messages are currently **enabled**." ) ; }
else { await ctx . Reply ( "Proxy error messages are currently **disabled**. Messages that fail to proxy (due to message or attachment size) will not throw an error message." ) ; }
return ;
}
if ( ctx . MatchToggle ( true ) )
{
await ctx . Repository . UpdateSystemConfig ( ctx . System . Id , new ( ) { ProxyErrorMessageEnabled = true } ) ;
await ctx . Reply ( "Proxy error messages are now enabled." ) ;
}
else
{
await ctx . Repository . UpdateSystemConfig ( ctx . System . Id , new ( ) { ProxyErrorMessageEnabled = false } ) ;
await ctx . Reply ( "Proxy error messages are now disabled. Messages that fail to proxy (due to message or attachment size) will not throw an error message." ) ;
}
}
2024-04-28 15:46:06 +12:00
public async Task HidDisplaySplit ( Context ctx )
{
if ( ! ctx . HasNext ( ) )
{
var msg = $"Splitting of 6-character IDs with a hyphen is currently **{EnabledDisabled(ctx.Config.HidDisplaySplit)}**." ;
await ctx . Reply ( msg ) ;
return ;
}
2024-11-09 11:32:35 -07:00
var newVal = ctx . MatchToggle ( false ) ;
2024-04-28 15:46:06 +12:00
await ctx . Repository . UpdateSystemConfig ( ctx . System . Id , new ( ) { HidDisplaySplit = newVal } ) ;
await ctx . Reply ( $"Splitting of 6-character IDs with a hyphen is now {EnabledDisabled(newVal)}." ) ;
}
2024-04-28 21:05:46 +12:00
public async Task HidDisplayCaps ( Context ctx )
{
if ( ! ctx . HasNext ( ) )
{
var msg = $"Displaying IDs as capital letters is currently **{EnabledDisabled(ctx.Config.HidDisplayCaps)}**." ;
await ctx . Reply ( msg ) ;
return ;
}
2024-11-09 11:32:35 -07:00
var newVal = ctx . MatchToggle ( false ) ;
2024-04-28 21:05:46 +12:00
await ctx . Repository . UpdateSystemConfig ( ctx . System . Id , new ( ) { HidDisplayCaps = newVal } ) ;
await ctx . Reply ( $"Displaying IDs as capital letters is now {EnabledDisabled(newVal)}." ) ;
}
2024-05-19 21:31:26 +09:00
public async Task HidListPadding ( Context ctx )
{
if ( ! ctx . HasNext ( ) )
{
string message ;
switch ( ctx . Config . HidListPadding )
{
case SystemConfig . HidPadFormat . None : message = "Padding 5-character IDs in lists is currently disabled." ; break ;
case SystemConfig . HidPadFormat . Left : message = "5-character IDs displayed in lists will have a padding space added to the beginning." ; break ;
case SystemConfig . HidPadFormat . Right : message = "5-character IDs displayed in lists will have a padding space added to the end." ; break ;
default : throw new Exception ( "unreachable" ) ;
}
await ctx . Reply ( message ) ;
return ;
}
var badInputError = "Valid padding settings are `left`, `right`, or `off`." ;
var toggleOff = ctx . MatchToggleOrNull ( false ) ;
switch ( toggleOff )
{
case true : throw new PKError ( badInputError ) ;
case false :
{
await ctx . Repository . UpdateSystemConfig ( ctx . System . Id , new ( ) { HidListPadding = SystemConfig . HidPadFormat . None } ) ;
await ctx . Reply ( "Padding 5-character IDs in lists has been disabled." ) ;
return ;
}
}
if ( ctx . Match ( "left" , "l" ) )
{
await ctx . Repository . UpdateSystemConfig ( ctx . System . Id , new ( ) { HidListPadding = SystemConfig . HidPadFormat . Left } ) ;
await ctx . Reply ( "5-character IDs displayed in lists will now have a padding space added to the beginning." ) ;
}
else if ( ctx . Match ( "right" , "r" ) )
{
await ctx . Repository . UpdateSystemConfig ( ctx . System . Id , new ( ) { HidListPadding = SystemConfig . HidPadFormat . Right } ) ;
await ctx . Reply ( "5-character IDs displayed in lists will now have a padding space added to the end." ) ;
}
else throw new PKError ( badInputError ) ;
}
2024-10-04 05:00:07 -06:00
2024-11-09 11:34:06 -07:00
public async Task ProxySwitch ( Context ctx )
{
if ( ! ctx . HasNext ( ) )
{
2024-12-05 18:24:20 -07:00
string msg = ctx . Config . ProxySwitch switch
{
SystemConfig . ProxySwitchAction . Off = > "Currently, when you proxy as a member, no switches are logged or changed." ,
SystemConfig . ProxySwitchAction . New = > "When you proxy as a member, currently it makes a new switch." ,
SystemConfig . ProxySwitchAction . Add = > "When you proxy as a member, currently it adds them to the current switch." ,
_ = > throw new Exception ( "unreachable" ) ,
} ;
2024-11-09 11:34:06 -07:00
await ctx . Reply ( msg ) ;
return ;
}
2024-12-05 18:24:20 -07:00
// toggle = false means off, toggle = true means new, otherwise if they said add that means add or if they said new they mean new. If none of those, error
var toggle = ctx . MatchToggleOrNull ( false ) ;
var newVal = toggle = = false ? SystemConfig . ProxySwitchAction . Off : toggle = = true ? SystemConfig . ProxySwitchAction . New : ctx . Match ( "add" , "a" ) ? SystemConfig . ProxySwitchAction . Add : ctx . Match ( "new" , "n" ) ? SystemConfig . ProxySwitchAction . New : throw new PKError ( "You must pass either \"new\", \"add\", or \"off\" to this command." ) ;
2024-11-09 11:34:06 -07:00
await ctx . Repository . UpdateSystemConfig ( ctx . System . Id , new ( ) { ProxySwitch = newVal } ) ;
2024-12-05 18:24:20 -07:00
switch ( newVal )
{
case SystemConfig . ProxySwitchAction . Off : await ctx . Reply ( "Now when you proxy as a member, no switches are logged or changed." ) ; break ;
case SystemConfig . ProxySwitchAction . New : await ctx . Reply ( "When you proxy as a member, it now makes a new switch." ) ; break ;
case SystemConfig . ProxySwitchAction . Add : await ctx . Reply ( "When you proxy as a member, it now adds them to the current switch." ) ; break ;
default : throw new Exception ( "unreachable" ) ;
}
2024-11-09 11:34:06 -07:00
}
2024-10-22 03:05:32 -04:00
public async Task NameFormat ( Context ctx )
{
2024-11-12 21:18:32 +13:00
var clearFlag = ctx . MatchClear ( ) ;
if ( ! ctx . HasNext ( ) & & ! clearFlag )
2024-10-22 03:05:32 -04:00
{
await ctx . Reply ( $"Member names are currently formatted as `{ctx.Config.NameFormat ?? ProxyMember.DefaultFormat}`" ) ;
return ;
}
2024-11-12 21:18:32 +13:00
string formatString ;
if ( clearFlag )
formatString = ProxyMember . DefaultFormat ;
else
formatString = ctx . RemainderOrNull ( ) ;
2024-10-22 03:05:32 -04:00
await ctx . Repository . UpdateSystemConfig ( ctx . System . Id , new ( ) { NameFormat = formatString } ) ;
await ctx . Reply ( $"Member names are now formatted as `{formatString}`" ) ;
}
2024-11-19 17:35:09 -07:00
public async Task ServerNameFormat ( Context ctx )
{
2024-11-20 16:28:42 -07:00
ctx . CheckGuildContext ( ) ;
2024-11-19 17:35:09 -07:00
var clearFlag = ctx . MatchClear ( ) ;
var format = ctx . MatchFormat ( ) ;
// if there's nothing next or what's next is raw/plaintext and we're not clearing, it's a query
if ( ( ! ctx . HasNext ( ) | | format ! = ReplyFormat . Standard ) & & ! clearFlag )
{
var guildCfg = await ctx . Repository . GetSystemGuild ( ctx . Guild . Id , ctx . System . Id ) ;
if ( guildCfg . NameFormat = = null )
await ctx . Reply ( "You do not have a specific name format set for this server and member names are formatted with your global name format." ) ;
else
switch ( format )
{
case ReplyFormat . Raw :
await ctx . Reply ( $"`{guildCfg.NameFormat}`" ) ;
break ;
case ReplyFormat . Plaintext :
var eb = new EmbedBuilder ( )
. Description ( $"Showing guild Name Format for system {ctx.System.DisplayHid(ctx.Config)}" ) ;
await ctx . Reply ( guildCfg . NameFormat , eb . Build ( ) ) ;
break ;
default :
await ctx . Reply ( $"Your member names in this server are currently formatted as `{guildCfg.NameFormat}`" ) ;
break ;
}
return ;
}
string? formatString = null ;
if ( ! clearFlag )
{
formatString = ctx . RemainderOrNull ( ) ;
}
await ctx . Repository . UpdateSystemGuild ( ctx . System . Id , ctx . Guild . Id , new ( ) { NameFormat = formatString } ) ;
if ( formatString = = null )
await ctx . Reply ( $"Member names are now formatted with your global name format in this server." ) ;
else
await ctx . Reply ( $"Member names are now formatted as `{formatString}` in this server." ) ;
}
2024-10-04 05:00:07 -06:00
public Task LimitUpdate ( Context ctx )
{
throw new PKError ( "You cannot update your own member or group limits. If you need a limit update, please join the " +
"support server and ask in #bot-support: https://discord.gg/PczBt78" ) ;
}
2021-11-29 21:35:21 -05:00
}