2019-05-17 01:23:09 +02:00
using System.Net ;
2021-11-26 21:10:56 -05:00
2019-05-17 01:23:09 +02:00
using Humanizer ;
2021-11-26 21:10:56 -05:00
2019-06-13 16:53:04 +02:00
using NodaTime ;
2021-11-26 21:10:56 -05:00
2019-07-10 00:19:18 +02:00
using PluralKit.Core ;
2019-05-17 01:23:09 +02:00
2021-11-26 21:10:56 -05:00
namespace PluralKit.Bot ;
/// <summary>
/// An exception class representing user-facing errors caused when parsing and executing commands.
/// </summary>
public class PKError : Exception
2021-08-27 11:03:47 -04:00
{
2021-11-26 21:10:56 -05:00
public PKError ( string message ) : base ( message ) { }
}
/// <summary>
/// A subclass of <see cref="PKError" /> that represent command syntax errors, meaning they'll have their command
/// usages printed in the message.
/// </summary>
public class PKSyntaxError : PKError
{
public PKSyntaxError ( string message ) : base ( message ) { }
}
2020-02-12 15:16:19 +01:00
2021-11-26 21:10:56 -05:00
public static class Errors
{
// TODO: is returning constructed errors and throwing them at call site a good idea, or should these be methods that insta-throw instead?
// or should we just like... go back to inlining them? at least for the one-time-use commands
public static PKError NotOwnSystemError = > new ( "You can only run this command on your own system." ) ;
public static PKError NotOwnMemberError = > new ( "You can only run this command on your own member." ) ;
public static PKError NotOwnGroupError = > new ( "You can only run this command on your own group." ) ;
2021-12-06 00:32:54 -05:00
public static PKError NotOwnInfo = > new ( "You cannot look up private information of another system." ) ;
2024-12-31 08:09:18 -07:00
public static PKError NoSystemError ( string prefix ) = >
new ( $"You do not have a system registered with PluralKit. To create one, type `{prefix}system new`." ) ;
2021-11-26 21:10:56 -05:00
2024-12-31 08:09:18 -07:00
public static PKError ExistingSystemError ( string prefix ) = > new (
$"You already have a system registered with PluralKit. To view it, type `{prefix}system`. If you'd like to delete your system and start anew, type `{prefix}system delete`, or if you'd like to unlink this account from it, type `{prefix}unlink`." ) ;
2021-11-26 21:10:56 -05:00
public static PKError MissingMemberError = >
new PKSyntaxError ( "You need to specify a member to run this command on." ) ;
public static PKError ProxyMustHaveText = >
new PKSyntaxError ( "Example proxy message must contain the string 'text'." ) ;
public static PKError ProxyMultipleText = >
new PKSyntaxError ( "Example proxy message must contain the string 'text' exactly once." ) ;
public static PKError MemberDeleteCancelled = > new ( $"Member deletion cancelled. Stay safe! {Emojis.ThumbsUp}" ) ;
public static PKError AvatarInvalid = >
new ( "Could not read image file - perhaps it's corrupted or the wrong format. Try a different image." ) ;
public static PKError UserHasNoAvatar = > new ( "The given user has no avatar set." ) ;
public static PKError AccountAlreadyLinked = > new ( "That account is already linked to your system." ) ;
public static PKError AccountNotLinked = > new ( "That account isn't linked to your system." ) ;
2024-12-31 08:09:18 -07:00
public static PKError UnlinkingLastAccount ( string prefix ) = > new (
$"Since this is the only account linked to this system, you cannot unlink it (as that would leave your system account-less). If you would like to delete your system, use `{prefix}system delete`." ) ;
2021-11-26 21:10:56 -05:00
public static PKError MemberLinkCancelled = > new ( "Member link cancelled." ) ;
public static PKError MemberUnlinkCancelled = > new ( "Member unlink cancelled." ) ;
public static PKError DuplicateSwitchMembers = > new ( "Duplicate members in member list." ) ;
public static PKError SwitchMemberNotInSystem = > new ( "One or more switch members aren't in your own system." ) ;
public static PKError SwitchTimeInFuture = > new ( "Can't move switch to a time in the future." ) ;
public static PKError NoRegisteredSwitches = > new ( "There are no registered switches for this system." ) ;
public static PKError SwitchMoveCancelled = > new ( "Switch move cancelled." ) ;
public static PKError SwitchEditCancelled = > new ( "Switch edit cancelled." ) ;
public static PKError SwitchDeleteCancelled = > new ( "Switch deletion cancelled." ) ;
public static PKError TimezoneChangeCancelled = > new ( "Time zone change cancelled." ) ;
public static PKError NoImportFilePassed = >
new (
"You must either pass an URL to a file as a command parameter, or as an attachment to the message containing the command." ) ;
public static PKError InvalidImportFile = >
new (
"Imported data file invalid. Make sure this is a .json file directly exported from PluralKit or Tupperbox." ) ;
public static PKError ImportCancelled = > new ( "Import cancelled." ) ;
public static PKError FrontPercentTimeInFuture = >
new ( "Cannot get the front percent between now and a time in the future." ) ;
public static PKError LookupNotAllowed = > new ( "You do not have permission to access this information." ) ;
public static PKError StringTooLongError ( string name , int length , int maxLength ) = >
new ( $"{name} too long ({length}/{maxLength} characters)." ) ;
2021-08-27 11:03:47 -04:00
2021-11-26 21:10:56 -05:00
public static PKError MemberLimitReachedError ( int limit ) = > new (
$"System has reached the maximum number of members ({limit}). Please delete unused members first in order to create new ones." ) ;
public static PKError InvalidColorError ( string color ) = >
new ( $"\" { color } \ " is not a valid color. Color must be in 6-digit RGB hex format (eg. #ff0000)." ) ;
public static PKError BirthdayParseError ( string birthday ) = > new (
$"\" { birthday } \ " could not be parsed as a valid date. Try a format like \"2016-12-24\" or \"May 3 1996\"." ) ;
public static PKError AvatarServerError ( HttpStatusCode statusCode ) = > new (
$"Server responded with status code {(int)statusCode}, are you sure your link is working?" ) ;
public static PKError AvatarFileSizeLimit ( long size ) = > new (
$"File size too large ({size.Bytes().ToString(" # . # ")} > {Limits.AvatarFileSizeLimit.Bytes().ToString(" # . # ")}), try shrinking or compressing the image." ) ;
public static PKError AvatarNotAnImage ( string mimeType ) = > new (
$"The given link does not point to an image{(mimeType != null ? $" ( { mimeType } ) " : " ")}. Make sure you're using a direct link (ending in .jpg, .png, .gif)." ) ;
public static PKError AvatarDimensionsTooLarge ( int width , int height ) = > new (
$"Image too large ({width}x{height} > {Limits.AvatarDimensionLimit}x{Limits.AvatarDimensionLimit}), try resizing the image." ) ;
2022-12-06 10:15:20 +00:00
public static PKError InvalidUrl = > new ( "The given URL is invalid." ) ;
2021-11-26 21:10:56 -05:00
public static PKError UrlTooLong ( string url ) = >
new ( $"The given URL is too long ({url.Length}/{Limits.MaxUriLength} characters)." ) ;
2024-12-31 08:09:18 -07:00
public static PKError AccountInOtherSystem ( PKSystem system , SystemConfig config , string prefix ) = >
new ( $"The mentioned account is already linked to another system (see `{prefix}system {system.DisplayHid(config)}`)." ) ;
2021-11-26 21:10:56 -05:00
public static PKError SameSwitch ( ICollection < PKMember > members , LookupContext ctx )
2021-08-27 11:03:47 -04:00
{
2021-11-26 21:10:56 -05:00
if ( members . Count = = 0 ) return new PKError ( "There's already no one in front." ) ;
if ( members . Count = = 1 ) return new PKError ( $"Member {members.First().NameFor(ctx)} is already fronting." ) ;
return new PKError (
$"Members {string.Join(" , ", members.Select(m => m.NameFor(ctx)))} are already fronting." ) ;
2019-04-29 19:43:09 +02:00
}
2021-11-26 21:10:56 -05:00
public static PKError InvalidDateTime ( string str ) = > new (
$"Could not parse '{str}' as a valid date/time. Try using a syntax such as \" May 21 , 12 : 30 PM \ " or \"3d12h\" (ie. 3 days, 12 hours ago)." ) ;
public static PKError SwitchMoveBeforeSecondLast ( ZonedDateTime time ) = > new (
$"Can't move switch to before last switch time ({time.FormatZoned()}), as it would cause conflicts." ) ;
public static PKError TimezoneParseError ( string timezone ) = > new (
$"Could not parse timezone offset {timezone}. Offset must be a value like 'UTC+5' or 'GMT-4:30'." ) ;
public static PKError InvalidTimeZone ( string zoneStr ) = > new (
$"Invalid time zone ID '{zoneStr}'. To find your time zone ID, use the following website: <https://xske.github.io/tz>" ) ;
public static PKError AmbiguousTimeZone ( string zoneStr , int count ) = > new (
$"The time zone query '{zoneStr}' resulted in **{count}** different time zone regions. Try being more specific - e.g. pass an exact time zone specifier from the following website: <https://xske.github.io/tz>" ) ;
public static PKError MessageNotFound ( ulong id ) = >
new ( $"Message with ID '{id}' not found. Are you sure it's a message proxied by PluralKit?" ) ;
public static PKError DurationParseError ( string durationStr ) = > new (
$"Could not parse {durationStr.AsCode()} as a valid duration. Try a format such as `30d`, `1d3h` or `20m30s`." ) ;
public static PKError GuildNotFound ( ulong guildId ) = > new (
$"Guild with ID `{guildId}` not found, or I cannot access it. Note that you must be a member of the guild you are querying." ) ;
public static PKError DisplayNameTooLong ( string displayName , int maxLength ) = > new (
$"Display name too long ({displayName.Length} > {maxLength} characters). Use a shorter display name, or shorten your system tag." ) ;
public static PKError ProxyNameTooShort ( string name ) = > new (
$"The webhook's name, {name.AsCode()}, is shorter than two characters, and thus cannot be proxied. Please change the member name or use a longer system tag." ) ;
public static PKError ProxyNameTooLong ( string name ) = > new (
2024-10-22 03:05:32 -04:00
$"The webhook's name, {name.AsCode()}, is too long ({name.Length} > {Limits.MaxProxyNameLength} characters), and thus cannot be proxied. Please change the member name, display name, server display name, system tag, or use a shorter name format" ) ;
2021-11-26 21:10:56 -05:00
public static PKError ProxyTagAlreadyExists ( ProxyTag tagToAdd , PKMember member ) = > new (
$"That member already has the proxy tag {tagToAdd.ProxyString.AsCode()}. The member currently has these tags: {member.ProxyTagsString()}" ) ;
public static PKError ProxyTagDoesNotExist ( ProxyTag tagToRemove , PKMember member ) = > new (
$"That member does not have the proxy tag {tagToRemove.ProxyString.AsCode()}. The member currently has these tags: {member.ProxyTagsString()}" ) ;
2022-02-05 09:26:14 -05:00
public static PKError LegacyAlreadyHasProxyTag ( ProxyTag requested , PKMember member , Context ctx ) = > new (
2024-12-31 08:09:18 -07:00
$"This member already has more than one proxy tag set: {member.ProxyTagsString()}\nConsider using the {$" { ctx . DefaultPrefix } member { member . Reference ( ctx ) } proxy add { requested . ProxyString } ".AsCode()} command instead." ) ;
2021-11-26 21:10:56 -05:00
2022-02-05 09:26:14 -05:00
public static PKError EmptyProxyTags ( PKMember member , Context ctx ) = > new (
2024-12-31 08:09:18 -07:00
$"The example proxy `text` is equivalent to having no proxy tags at all, since there are no symbols or brackets on either end. If you'd like to clear your proxy tags, use `{ctx.DefaultPrefix}member {member.Reference(ctx)} proxy clear`." ) ;
2021-11-26 21:10:56 -05:00
public static PKError GenericCancelled ( ) = > new ( "Operation cancelled." ) ;
public static PKError AttachmentTooLarge ( int mb ) = > new (
$"PluralKit cannot proxy attachments over {mb} megabytes in this server (as webhooks aren't considered as having Discord Nitro) :(" ) ;
public static PKError ChannelNotFound ( string channelString ) = >
new ( $"Channel \" { channelString } \ " not found or is not in this server." ) ;
2019-04-29 19:43:09 +02:00
}