mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-10 17:28:27 -04:00
Make extensive use of raw string literals C#11 feature
This commit is contained in:
@@ -364,26 +364,27 @@ public sealed class Bot
|
|||||||
|
|
||||||
if (arg.Exception is { InnerException: WebSocketClosedException { CloseCode: 4014 } })
|
if (arg.Exception is { InnerException: WebSocketClosedException { CloseCode: 4014 } })
|
||||||
{
|
{
|
||||||
Log.Error(@"
|
Log.Error("""
|
||||||
Login failed.
|
Login failed.
|
||||||
|
|
||||||
*** Please enable privileged intents ***
|
*** Please enable privileged intents ***
|
||||||
|
|
||||||
Certain Nadeko features require Discord's privileged gateway intents.
|
Certain Nadeko features require Discord's privileged gateway intents.
|
||||||
These include greeting and goodbye messages, as well as creating the Owner message channels for DM forwarding.
|
These include greeting and goodbye messages, as well as creating the Owner message channels for DM forwarding.
|
||||||
|
|
||||||
How to enable privileged intents:
|
How to enable privileged intents:
|
||||||
1. Head over to the Discord Developer Portal https://discord.com/developers/applications/
|
1. Head over to the Discord Developer Portal https://discord.com/developers/applications/
|
||||||
2. Select your Application.
|
2. Select your Application.
|
||||||
3. Click on `Bot` in the left side navigation panel, and scroll down to the intents section.
|
3. Click on `Bot` in the left side navigation panel, and scroll down to the intents section.
|
||||||
4. Enable all intents.
|
4. Enable all intents.
|
||||||
5. Restart your bot.
|
5. Restart your bot.
|
||||||
|
|
||||||
Read this only if your bot is in 100 or more servers:
|
Read this only if your bot is in 100 or more servers:
|
||||||
|
|
||||||
You'll need to apply to use the intents with Discord, but for small selfhosts, all that is required is enabling the intents in the developer portal.
|
You'll need to apply to use the intents with Discord, but for small selfhosts, all that is required is enabling the intents in the developer portal.
|
||||||
Yes, this is a new thing from Discord, as of October 2020. No, there's nothing we can do about it. Yes, we're aware it worked before.
|
Yes, this is a new thing from Discord, as of October 2020. No, there's nothing we can do about it. Yes, we're aware it worked before.
|
||||||
While waiting for your bot to be accepted, you can change the 'usePrivilegedIntents' inside your creds.yml to 'false', although this will break many of the nadeko's features");
|
While waiting for your bot to be accepted, you can change the 'usePrivilegedIntents' inside your creds.yml to 'false', although this will break many of the nadeko's features
|
||||||
|
""");
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -11,74 +11,89 @@ namespace NadekoBot.Common.Configs;
|
|||||||
[Cloneable]
|
[Cloneable]
|
||||||
public sealed partial class BotConfig : ICloneable<BotConfig>
|
public sealed partial class BotConfig : ICloneable<BotConfig>
|
||||||
{
|
{
|
||||||
[Comment(@"DO NOT CHANGE")]
|
[Comment("""DO NOT CHANGE""")]
|
||||||
public int Version { get; set; } = 5;
|
public int Version { get; set; } = 5;
|
||||||
|
|
||||||
[Comment(@"Most commands, when executed, have a small colored line
|
[Comment("""
|
||||||
next to the response. The color depends whether the command
|
Most commands, when executed, have a small colored line
|
||||||
is completed, errored or in progress (pending)
|
next to the response. The color depends whether the command
|
||||||
Color settings below are for the color of those lines.
|
is completed, errored or in progress (pending)
|
||||||
To get color's hex, you can go here https://htmlcolorcodes.com/
|
Color settings below are for the color of those lines.
|
||||||
and copy the hex code fo your selected color (marked as #)")]
|
To get color's hex, you can go here https://htmlcolorcodes.com/
|
||||||
|
and copy the hex code fo your selected color (marked as #)
|
||||||
|
""")]
|
||||||
public ColorConfig Color { get; set; }
|
public ColorConfig Color { get; set; }
|
||||||
|
|
||||||
[Comment("Default bot language. It has to be in the list of supported languages (.langli)")]
|
[Comment("Default bot language. It has to be in the list of supported languages (.langli)")]
|
||||||
public CultureInfo DefaultLocale { get; set; }
|
public CultureInfo DefaultLocale { get; set; }
|
||||||
|
|
||||||
[Comment(@"Style in which executed commands will show up in the console.
|
[Comment("""
|
||||||
Allowed values: Simple, Normal, None")]
|
Style in which executed commands will show up in the console.
|
||||||
|
Allowed values: Simple, Normal, None
|
||||||
|
""")]
|
||||||
public ConsoleOutputType ConsoleOutputType { get; set; }
|
public ConsoleOutputType ConsoleOutputType { get; set; }
|
||||||
|
|
||||||
[Comment(@"Whether the bot will check for new releases every hour")]
|
[Comment("""Whether the bot will check for new releases every hour""")]
|
||||||
public bool CheckForUpdates { get; set; } = true;
|
public bool CheckForUpdates { get; set; } = true;
|
||||||
|
|
||||||
[Comment(@"Do you want any messages sent by users in Bot's DM to be forwarded to the owner(s)?")]
|
[Comment("""Do you want any messages sent by users in Bot's DM to be forwarded to the owner(s)?""")]
|
||||||
public bool ForwardMessages { get; set; }
|
public bool ForwardMessages { get; set; }
|
||||||
|
|
||||||
[Comment(
|
[Comment("""
|
||||||
@"Do you want the message to be forwarded only to the first owner specified in the list of owners (in creds.yml),
|
Do you want the message to be forwarded only to the first owner specified in the list of owners (in creds.yml),
|
||||||
or all owners? (this might cause the bot to lag if there's a lot of owners specified)")]
|
or all owners? (this might cause the bot to lag if there's a lot of owners specified)
|
||||||
|
""")]
|
||||||
public bool ForwardToAllOwners { get; set; }
|
public bool ForwardToAllOwners { get; set; }
|
||||||
|
|
||||||
[Comment(@"Any messages sent by users in Bot's DM to be forwarded to the specified channel.
|
[Comment("""
|
||||||
This option will only work when ForwardToAllOwners is set to false")]
|
Any messages sent by users in Bot's DM to be forwarded to the specified channel.
|
||||||
|
This option will only work when ForwardToAllOwners is set to false
|
||||||
|
""")]
|
||||||
public ulong? ForwardToChannel { get; set; }
|
public ulong? ForwardToChannel { get; set; }
|
||||||
|
|
||||||
[Comment(@"When a user DMs the bot with a message which is not a command
|
[Comment("""
|
||||||
they will receive this message. Leave empty for no response. The string which will be sent whenever someone DMs the bot.
|
When a user DMs the bot with a message which is not a command
|
||||||
Supports embeds. How it looks: https://puu.sh/B0BLV.png")]
|
they will receive this message. Leave empty for no response. The string which will be sent whenever someone DMs the bot.
|
||||||
|
Supports embeds. How it looks: https://puu.sh/B0BLV.png
|
||||||
|
""")]
|
||||||
[YamlMember(ScalarStyle = ScalarStyle.Literal)]
|
[YamlMember(ScalarStyle = ScalarStyle.Literal)]
|
||||||
public string DmHelpText { get; set; }
|
public string DmHelpText { get; set; }
|
||||||
|
|
||||||
[Comment(@"Only users who send a DM to the bot containing one of the specified words will get a DmHelpText response.
|
[Comment("""
|
||||||
Case insensitive.
|
Only users who send a DM to the bot containing one of the specified words will get a DmHelpText response.
|
||||||
Leave empty to reply with DmHelpText to every DM.")]
|
Case insensitive.
|
||||||
|
Leave empty to reply with DmHelpText to every DM.
|
||||||
|
""")]
|
||||||
public List<string> DmHelpTextKeywords { get; set; }
|
public List<string> DmHelpTextKeywords { get; set; }
|
||||||
|
|
||||||
[Comment(@"This is the response for the .h command")]
|
[Comment("""This is the response for the .h command""")]
|
||||||
[YamlMember(ScalarStyle = ScalarStyle.Literal)]
|
[YamlMember(ScalarStyle = ScalarStyle.Literal)]
|
||||||
public string HelpText { get; set; }
|
public string HelpText { get; set; }
|
||||||
|
|
||||||
[Comment(@"List of modules and commands completely blocked on the bot")]
|
[Comment("""List of modules and commands completely blocked on the bot""")]
|
||||||
public BlockedConfig Blocked { get; set; }
|
public BlockedConfig Blocked { get; set; }
|
||||||
|
|
||||||
[Comment(@"Which string will be used to recognize the commands")]
|
[Comment("""Which string will be used to recognize the commands""")]
|
||||||
public string Prefix { get; set; }
|
public string Prefix { get; set; }
|
||||||
|
|
||||||
[Comment(@"Toggles whether your bot will group greet/bye messages into a single message every 5 seconds.
|
[Comment("""
|
||||||
1st user who joins will get greeted immediately
|
Toggles whether your bot will group greet/bye messages into a single message every 5 seconds.
|
||||||
If more users join within the next 5 seconds, they will be greeted in groups of 5.
|
1st user who joins will get greeted immediately
|
||||||
This will cause %user.mention% and other placeholders to be replaced with multiple users.
|
If more users join within the next 5 seconds, they will be greeted in groups of 5.
|
||||||
Keep in mind this might break some of your embeds - for example if you have %user.avatar% in the thumbnail,
|
This will cause %user.mention% and other placeholders to be replaced with multiple users.
|
||||||
it will become invalid, as it will resolve to a list of avatars of grouped users.
|
Keep in mind this might break some of your embeds - for example if you have %user.avatar% in the thumbnail,
|
||||||
note: This setting is primarily used if you're afraid of raids, or you're running medium/large bots where some
|
it will become invalid, as it will resolve to a list of avatars of grouped users.
|
||||||
servers might get hundreds of people join at once. This is used to prevent the bot from getting ratelimited,
|
note: This setting is primarily used if you're afraid of raids, or you're running medium/large bots where some
|
||||||
and (slightly) reduce the greet spam in those servers.")]
|
servers might get hundreds of people join at once. This is used to prevent the bot from getting ratelimited,
|
||||||
|
and (slightly) reduce the greet spam in those servers.
|
||||||
|
""")]
|
||||||
public bool GroupGreets { get; set; }
|
public bool GroupGreets { get; set; }
|
||||||
|
|
||||||
[Comment(@"Whether the bot will rotate through all specified statuses.
|
[Comment("""
|
||||||
This setting can be changed via .ropl command.
|
Whether the bot will rotate through all specified statuses.
|
||||||
See RotatingStatuses submodule in Administration.")]
|
This setting can be changed via .ropl command.
|
||||||
|
See RotatingStatuses submodule in Administration.
|
||||||
|
""")]
|
||||||
public bool RotateStatuses { get; set; }
|
public bool RotateStatuses { get; set; }
|
||||||
|
|
||||||
public BotConfig()
|
public BotConfig()
|
||||||
@@ -89,32 +104,34 @@ See RotatingStatuses submodule in Administration.")]
|
|||||||
ConsoleOutputType = ConsoleOutputType.Normal;
|
ConsoleOutputType = ConsoleOutputType.Normal;
|
||||||
ForwardMessages = false;
|
ForwardMessages = false;
|
||||||
ForwardToAllOwners = false;
|
ForwardToAllOwners = false;
|
||||||
DmHelpText = @"{""description"": ""Type `%prefix%h` for help.""}";
|
DmHelpText = """{"description": "Type `%prefix%h` for help."}""";
|
||||||
HelpText = @"{
|
HelpText = """
|
||||||
""title"": ""To invite me to your server, use this link"",
|
{
|
||||||
""description"": ""https://discordapp.com/oauth2/authorize?client_id={0}&scope=bot&permissions=66186303"",
|
"title": "To invite me to your server, use this link",
|
||||||
""color"": 53380,
|
"description": "https://discordapp.com/oauth2/authorize?client_id={0}&scope=bot&permissions=66186303",
|
||||||
""thumbnail"": ""https://i.imgur.com/nKYyqMK.png"",
|
"color": 53380,
|
||||||
""fields"": [
|
"thumbnail": "https://i.imgur.com/nKYyqMK.png",
|
||||||
{
|
"fields": [
|
||||||
""name"": ""Useful help commands"",
|
{
|
||||||
""value"": ""`%bot.prefix%modules` Lists all bot modules.
|
"name": "Useful help commands",
|
||||||
`%prefix%h CommandName` Shows some help about a specific command.
|
"value": "`%bot.prefix%modules` Lists all bot modules.
|
||||||
`%prefix%commands ModuleName` Lists all commands in a module."",
|
`%prefix%h CommandName` Shows some help about a specific command.
|
||||||
""inline"": false
|
`%prefix%commands ModuleName` Lists all commands in a module.",
|
||||||
},
|
"inline": false
|
||||||
{
|
},
|
||||||
""name"": ""List of all Commands"",
|
{
|
||||||
""value"": ""https://nadeko.bot/commands"",
|
"name": "List of all Commands",
|
||||||
""inline"": false
|
"value": "https://nadeko.bot/commands",
|
||||||
},
|
"inline": false
|
||||||
{
|
},
|
||||||
""name"": ""Nadeko Support Server"",
|
{
|
||||||
""value"": ""https://discord.nadeko.bot/ "",
|
"name": "Nadeko Support Server",
|
||||||
""inline"": true
|
"value": "https://discord.nadeko.bot/ ",
|
||||||
}
|
"inline": true
|
||||||
]
|
}
|
||||||
}";
|
]
|
||||||
|
}
|
||||||
|
""";
|
||||||
var blocked = new BlockedConfig();
|
var blocked = new BlockedConfig();
|
||||||
Blocked = blocked;
|
Blocked = blocked;
|
||||||
Prefix = ".";
|
Prefix = ".";
|
||||||
@@ -160,13 +177,13 @@ public sealed partial class BlockedConfig
|
|||||||
[Cloneable]
|
[Cloneable]
|
||||||
public partial class ColorConfig
|
public partial class ColorConfig
|
||||||
{
|
{
|
||||||
[Comment(@"Color used for embed responses when command successfully executes")]
|
[Comment("""Color used for embed responses when command successfully executes""")]
|
||||||
public Rgba32 Ok { get; set; }
|
public Rgba32 Ok { get; set; }
|
||||||
|
|
||||||
[Comment(@"Color used for embed responses when command has an error")]
|
[Comment("""Color used for embed responses when command has an error""")]
|
||||||
public Rgba32 Error { get; set; }
|
public Rgba32 Error { get; set; }
|
||||||
|
|
||||||
[Comment(@"Color used for embed responses while command is doing work or is in progress")]
|
[Comment("""Color used for embed responses while command is doing work or is in progress""")]
|
||||||
public Rgba32 Pending { get; set; }
|
public Rgba32 Pending { get; set; }
|
||||||
|
|
||||||
public ColorConfig()
|
public ColorConfig()
|
||||||
|
@@ -5,115 +5,141 @@ namespace NadekoBot.Common;
|
|||||||
|
|
||||||
public sealed class Creds : IBotCredentials
|
public sealed class Creds : IBotCredentials
|
||||||
{
|
{
|
||||||
[Comment(@"DO NOT CHANGE")]
|
[Comment("""DO NOT CHANGE""")]
|
||||||
public int Version { get; set; }
|
public int Version { get; set; }
|
||||||
|
|
||||||
[Comment(@"Bot token. Do not share with anyone ever -> https://discordapp.com/developers/applications/")]
|
[Comment("""Bot token. Do not share with anyone ever -> https://discordapp.com/developers/applications/""")]
|
||||||
public string Token { get; set; }
|
public string Token { get; set; }
|
||||||
|
|
||||||
[Comment(@"List of Ids of the users who have bot owner permissions
|
[Comment("""
|
||||||
**DO NOT ADD PEOPLE YOU DON'T TRUST**")]
|
List of Ids of the users who have bot owner permissions
|
||||||
|
**DO NOT ADD PEOPLE YOU DON'T TRUST**
|
||||||
|
""")]
|
||||||
public ICollection<ulong> OwnerIds { get; set; }
|
public ICollection<ulong> OwnerIds { get; set; }
|
||||||
|
|
||||||
[Comment("Keep this on 'true' unless you're sure your bot shouldn't use privileged intents or you're waiting to be accepted")]
|
[Comment("Keep this on 'true' unless you're sure your bot shouldn't use privileged intents or you're waiting to be accepted")]
|
||||||
public bool UsePrivilegedIntents { get; set; }
|
public bool UsePrivilegedIntents { get; set; }
|
||||||
|
|
||||||
[Comment(@"The number of shards that the bot will be running on.
|
[Comment("""
|
||||||
Leave at 1 if you don't know what you're doing.
|
The number of shards that the bot will be running on.
|
||||||
|
Leave at 1 if you don't know what you're doing.
|
||||||
note: If you are planning to have more than one shard, then you must change botCache to 'redis'.
|
|
||||||
Also, in that case you should be using NadekoBot.Coordinator to start the bot, and it will correctly override this value.")]
|
note: If you are planning to have more than one shard, then you must change botCache to 'redis'.
|
||||||
|
Also, in that case you should be using NadekoBot.Coordinator to start the bot, and it will correctly override this value.
|
||||||
|
""")]
|
||||||
public int TotalShards { get; set; }
|
public int TotalShards { get; set; }
|
||||||
|
|
||||||
[Comment(
|
[Comment(
|
||||||
@"Login to https://console.cloud.google.com, create a new project, go to APIs & Services -> Library -> YouTube Data API and enable it.
|
"""
|
||||||
Then, go to APIs and Services -> Credentials and click Create credentials -> API key.
|
Login to https://console.cloud.google.com, create a new project, go to APIs & Services -> Library -> YouTube Data API and enable it.
|
||||||
Used only for Youtube Data Api (at the moment).")]
|
Then, go to APIs and Services -> Credentials and click Create credentials -> API key.
|
||||||
|
Used only for Youtube Data Api (at the moment).
|
||||||
|
""")]
|
||||||
public string GoogleApiKey { get; set; }
|
public string GoogleApiKey { get; set; }
|
||||||
|
|
||||||
[Comment(
|
[Comment(
|
||||||
@"Create a new custom search here https://programmablesearchengine.google.com/cse/create/new
|
"""
|
||||||
Enable SafeSearch
|
Create a new custom search here https://programmablesearchengine.google.com/cse/create/new
|
||||||
Remove all Sites to Search
|
Enable SafeSearch
|
||||||
Enable Search the entire web
|
Remove all Sites to Search
|
||||||
Copy the 'Search Engine ID' to the SearchId field
|
Enable Search the entire web
|
||||||
|
Copy the 'Search Engine ID' to the SearchId field
|
||||||
Do all steps again but enable image search for the ImageSearchId")]
|
|
||||||
|
Do all steps again but enable image search for the ImageSearchId
|
||||||
|
""")]
|
||||||
public GoogleApiConfig Google { get; set; }
|
public GoogleApiConfig Google { get; set; }
|
||||||
|
|
||||||
[Comment(@"Settings for voting system for discordbots. Meant for use on global Nadeko.")]
|
[Comment("""Settings for voting system for discordbots. Meant for use on global Nadeko.""")]
|
||||||
public VotesSettings Votes { get; set; }
|
public VotesSettings Votes { get; set; }
|
||||||
|
|
||||||
[Comment(@"Patreon auto reward system settings.
|
[Comment("""
|
||||||
go to https://www.patreon.com/portal -> my clients -> create client")]
|
Patreon auto reward system settings.
|
||||||
|
go to https://www.patreon.com/portal -> my clients -> create client
|
||||||
|
""")]
|
||||||
public PatreonSettings Patreon { get; set; }
|
public PatreonSettings Patreon { get; set; }
|
||||||
|
|
||||||
[Comment(@"Api key for sending stats to DiscordBotList.")]
|
[Comment("""Api key for sending stats to DiscordBotList.""")]
|
||||||
public string BotListToken { get; set; }
|
public string BotListToken { get; set; }
|
||||||
|
|
||||||
[Comment(@"Official cleverbot api key.")]
|
[Comment("""Official cleverbot api key.""")]
|
||||||
public string CleverbotApiKey { get; set; }
|
public string CleverbotApiKey { get; set; }
|
||||||
|
|
||||||
[Comment(@"Which cache implementation should bot use.
|
[Comment("""
|
||||||
'memory' - Cache will be in memory of the bot's process itself. Only use this on bots with a single shard. When the bot is restarted the cache is reset.
|
Which cache implementation should bot use.
|
||||||
'redis' - Uses redis (which needs to be separately downloaded and installed). The cache will persist through bot restarts. You can configure connection string in creds.yml")]
|
'memory' - Cache will be in memory of the bot's process itself. Only use this on bots with a single shard. When the bot is restarted the cache is reset.
|
||||||
|
'redis' - Uses redis (which needs to be separately downloaded and installed). The cache will persist through bot restarts. You can configure connection string in creds.yml
|
||||||
|
""")]
|
||||||
public BotCacheImplemenation BotCache { get; set; }
|
public BotCacheImplemenation BotCache { get; set; }
|
||||||
|
|
||||||
[Comment(@"Redis connection string. Don't change if you don't know what you're doing.
|
[Comment("""
|
||||||
Only used if botCache is set to 'redis'")]
|
Redis connection string. Don't change if you don't know what you're doing.
|
||||||
|
Only used if botCache is set to 'redis'
|
||||||
|
""")]
|
||||||
public string RedisOptions { get; set; }
|
public string RedisOptions { get; set; }
|
||||||
|
|
||||||
[Comment(@"Database options. Don't change if you don't know what you're doing. Leave null for default values")]
|
[Comment("""Database options. Don't change if you don't know what you're doing. Leave null for default values""")]
|
||||||
public DbOptions Db { get; set; }
|
public DbOptions Db { get; set; }
|
||||||
|
|
||||||
[Comment(@"Address and port of the coordinator endpoint. Leave empty for default.
|
[Comment("""
|
||||||
Change only if you've changed the coordinator address or port.")]
|
Address and port of the coordinator endpoint. Leave empty for default.
|
||||||
|
Change only if you've changed the coordinator address or port.
|
||||||
|
""")]
|
||||||
public string CoordinatorUrl { get; set; }
|
public string CoordinatorUrl { get; set; }
|
||||||
|
|
||||||
[Comment(
|
[Comment(
|
||||||
@"Api key obtained on https://rapidapi.com (go to MyApps -> Add New App -> Enter Name -> Application key)")]
|
"""Api key obtained on https://rapidapi.com (go to MyApps -> Add New App -> Enter Name -> Application key)""")]
|
||||||
public string RapidApiKey { get; set; }
|
public string RapidApiKey { get; set; }
|
||||||
|
|
||||||
[Comment(@"https://locationiq.com api key (register and you will receive the token in the email).
|
[Comment("""
|
||||||
Used only for .time command.")]
|
https://locationiq.com api key (register and you will receive the token in the email).
|
||||||
|
Used only for .time command.
|
||||||
|
""")]
|
||||||
public string LocationIqApiKey { get; set; }
|
public string LocationIqApiKey { get; set; }
|
||||||
|
|
||||||
[Comment(@"https://timezonedb.com api key (register and you will receive the token in the email).
|
[Comment("""
|
||||||
Used only for .time command")]
|
https://timezonedb.com api key (register and you will receive the token in the email).
|
||||||
|
Used only for .time command
|
||||||
|
""")]
|
||||||
public string TimezoneDbApiKey { get; set; }
|
public string TimezoneDbApiKey { get; set; }
|
||||||
|
|
||||||
[Comment(@"https://pro.coinmarketcap.com/account/ api key. There is a free plan for personal use.
|
[Comment("""
|
||||||
Used for cryptocurrency related commands.")]
|
https://pro.coinmarketcap.com/account/ api key. There is a free plan for personal use.
|
||||||
|
Used for cryptocurrency related commands.
|
||||||
|
""")]
|
||||||
public string CoinmarketcapApiKey { get; set; }
|
public string CoinmarketcapApiKey { get; set; }
|
||||||
|
|
||||||
// [Comment(@"https://polygon.io/dashboard/api-keys api key. Free plan allows for 5 queries per minute.
|
// [Comment(@"https://polygon.io/dashboard/api-keys api key. Free plan allows for 5 queries per minute.
|
||||||
// Used for stocks related commands.")]
|
// Used for stocks related commands.")]
|
||||||
// public string PolygonIoApiKey { get; set; }
|
// public string PolygonIoApiKey { get; set; }
|
||||||
|
|
||||||
[Comment(@"Api key used for Osu related commands. Obtain this key at https://osu.ppy.sh/p/api")]
|
[Comment("""Api key used for Osu related commands. Obtain this key at https://osu.ppy.sh/p/api""")]
|
||||||
public string OsuApiKey { get; set; }
|
public string OsuApiKey { get; set; }
|
||||||
|
|
||||||
[Comment(@"Optional Trovo client id.
|
[Comment("""
|
||||||
You should use this if Trovo stream notifications stopped working or you're getting ratelimit errors.")]
|
Optional Trovo client id.
|
||||||
|
You should use this if Trovo stream notifications stopped working or you're getting ratelimit errors.
|
||||||
|
""")]
|
||||||
public string TrovoClientId { get; set; }
|
public string TrovoClientId { get; set; }
|
||||||
|
|
||||||
[Comment(@"Obtain by creating an application at https://dev.twitch.tv/console/apps")]
|
[Comment("""Obtain by creating an application at https://dev.twitch.tv/console/apps""")]
|
||||||
public string TwitchClientId { get; set; }
|
public string TwitchClientId { get; set; }
|
||||||
|
|
||||||
[Comment(@"Obtain by creating an application at https://dev.twitch.tv/console/apps")]
|
[Comment("""Obtain by creating an application at https://dev.twitch.tv/console/apps""")]
|
||||||
public string TwitchClientSecret { get; set; }
|
public string TwitchClientSecret { get; set; }
|
||||||
|
|
||||||
[Comment(@"Command and args which will be used to restart the bot.
|
[Comment("""
|
||||||
Only used if bot is executed directly (NOT through the coordinator)
|
Command and args which will be used to restart the bot.
|
||||||
placeholders:
|
Only used if bot is executed directly (NOT through the coordinator)
|
||||||
{0} -> shard id
|
placeholders:
|
||||||
{1} -> total shards
|
{0} -> shard id
|
||||||
Linux default
|
{1} -> total shards
|
||||||
cmd: dotnet
|
Linux default
|
||||||
args: ""NadekoBot.dll -- {0}""
|
cmd: dotnet
|
||||||
Windows default
|
args: "NadekoBot.dll -- {0}"
|
||||||
cmd: NadekoBot.exe
|
Windows default
|
||||||
args: ""{0}""")]
|
cmd: NadekoBot.exe
|
||||||
|
args: "{0}"
|
||||||
|
""")]
|
||||||
public RestartConfig RestartCommand { get; set; }
|
public RestartConfig RestartCommand { get; set; }
|
||||||
|
|
||||||
public Creds()
|
public Creds()
|
||||||
@@ -145,15 +171,19 @@ Windows default
|
|||||||
|
|
||||||
public class DbOptions
|
public class DbOptions
|
||||||
{
|
{
|
||||||
[Comment(@"Database type. ""sqlite"", ""mysql"" and ""postgresql"" are supported.
|
[Comment("""
|
||||||
Default is ""sqlite""")]
|
Database type. "sqlite", "mysql" and "postgresql" are supported.
|
||||||
|
Default is "sqlite"
|
||||||
|
""")]
|
||||||
public string Type { get; set; }
|
public string Type { get; set; }
|
||||||
|
|
||||||
[Comment(@"Database connection string.
|
[Comment("""
|
||||||
You MUST change this if you're not using ""sqlite"" type.
|
Database connection string.
|
||||||
Default is ""Data Source=data/NadekoBot.db""
|
You MUST change this if you're not using "sqlite" type.
|
||||||
Example for mysql: ""Server=localhost;Port=3306;Uid=root;Pwd=my_super_secret_mysql_password;Database=nadeko""
|
Default is "Data Source=data/NadekoBot.db"
|
||||||
Example for postgresql: ""Server=localhost;Port=5432;User Id=postgres;Password=my_super_secret_postgres_password;Database=nadeko;""")]
|
Example for mysql: "Server=localhost;Port=3306;Uid=root;Pwd=my_super_secret_mysql_password;Database=nadeko"
|
||||||
|
Example for postgresql: "Server=localhost;Port=5432;User Id=postgres;Password=my_super_secret_postgres_password;Database=nadeko;"
|
||||||
|
""")]
|
||||||
public string ConnectionString { get; set; }
|
public string ConnectionString { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,7 +195,7 @@ Example for postgresql: ""Server=localhost;Port=5432;User Id=postgres;Password=m
|
|||||||
public string ClientSecret { get; set; }
|
public string ClientSecret { get; set; }
|
||||||
|
|
||||||
[Comment(
|
[Comment(
|
||||||
@"Campaign ID of your patreon page. Go to your patreon page (make sure you're logged in) and type ""prompt('Campaign ID', window.patreon.bootstrap.creator.data.id);"" in the console. (ctrl + shift + i)")]
|
"""Campaign ID of your patreon page. Go to your patreon page (make sure you're logged in) and type "prompt('Campaign ID', window.patreon.bootstrap.creator.data.id);" in the console. (ctrl + shift + i)""")]
|
||||||
public string CampaignId { get; set; }
|
public string CampaignId { get; set; }
|
||||||
|
|
||||||
public PatreonSettings(
|
public PatreonSettings(
|
||||||
@@ -187,22 +217,30 @@ Example for postgresql: ""Server=localhost;Port=5432;User Id=postgres;Password=m
|
|||||||
|
|
||||||
public sealed record VotesSettings
|
public sealed record VotesSettings
|
||||||
{
|
{
|
||||||
[Comment(@"top.gg votes service url
|
[Comment("""
|
||||||
This is the url of your instance of the NadekoBot.Votes api
|
top.gg votes service url
|
||||||
Example: https://votes.my.cool.bot.com")]
|
This is the url of your instance of the NadekoBot.Votes api
|
||||||
|
Example: https://votes.my.cool.bot.com
|
||||||
|
""")]
|
||||||
public string TopggServiceUrl { get; set; }
|
public string TopggServiceUrl { get; set; }
|
||||||
|
|
||||||
[Comment(@"Authorization header value sent to the TopGG service url with each request
|
[Comment("""
|
||||||
This should be equivalent to the TopggKey in your NadekoBot.Votes api appsettings.json file")]
|
Authorization header value sent to the TopGG service url with each request
|
||||||
|
This should be equivalent to the TopggKey in your NadekoBot.Votes api appsettings.json file
|
||||||
|
""")]
|
||||||
public string TopggKey { get; set; }
|
public string TopggKey { get; set; }
|
||||||
|
|
||||||
[Comment(@"discords.com votes service url
|
[Comment("""
|
||||||
This is the url of your instance of the NadekoBot.Votes api
|
discords.com votes service url
|
||||||
Example: https://votes.my.cool.bot.com")]
|
This is the url of your instance of the NadekoBot.Votes api
|
||||||
|
Example: https://votes.my.cool.bot.com
|
||||||
|
""")]
|
||||||
public string DiscordsServiceUrl { get; set; }
|
public string DiscordsServiceUrl { get; set; }
|
||||||
|
|
||||||
[Comment(@"Authorization header value sent to the Discords service url with each request
|
[Comment("""
|
||||||
This should be equivalent to the DiscordsKey in your NadekoBot.Votes api appsettings.json file")]
|
Authorization header value sent to the Discords service url with each request
|
||||||
|
This should be equivalent to the DiscordsKey in your NadekoBot.Votes api appsettings.json file
|
||||||
|
""")]
|
||||||
public string DiscordsKey { get; set; }
|
public string DiscordsKey { get; set; }
|
||||||
|
|
||||||
public VotesSettings()
|
public VotesSettings()
|
||||||
|
@@ -7,10 +7,10 @@ namespace Nadeko.Medusa;
|
|||||||
[Cloneable]
|
[Cloneable]
|
||||||
public sealed partial class MedusaConfig : ICloneable<MedusaConfig>
|
public sealed partial class MedusaConfig : ICloneable<MedusaConfig>
|
||||||
{
|
{
|
||||||
[Comment(@"DO NOT CHANGE")]
|
[Comment("""DO NOT CHANGE""")]
|
||||||
public int Version { get; set; } = 1;
|
public int Version { get; set; } = 1;
|
||||||
|
|
||||||
[Comment("List of medusae automatically loaded at startup")]
|
[Comment("""List of medusae automatically loaded at startup""")]
|
||||||
public List<string>? Loaded { get; set; }
|
public List<string>? Loaded { get; set; }
|
||||||
|
|
||||||
public MedusaConfig()
|
public MedusaConfig()
|
||||||
|
@@ -10,29 +10,35 @@ public static class MigrationQueries
|
|||||||
if (migrationBuilder.IsMySql())
|
if (migrationBuilder.IsMySql())
|
||||||
{
|
{
|
||||||
migrationBuilder.Sql(
|
migrationBuilder.Sql(
|
||||||
@"INSERT IGNORE into reactionroles(guildid, channelid, messageid, emote, roleid, `group`, levelreq, dateadded)
|
"""
|
||||||
select guildid, channelid, messageid, emotename, roleid, exclusive, 0, reactionrolemessage.dateadded
|
INSERT IGNORE into reactionroles(guildid, channelid, messageid, emote, roleid, `group`, levelreq, dateadded)
|
||||||
from reactionrole
|
select guildid, channelid, messageid, emotename, roleid, exclusive, 0, reactionrolemessage.dateadded
|
||||||
left join reactionrolemessage on reactionrolemessage.id = reactionrole.reactionrolemessageid
|
from reactionrole
|
||||||
left join guildconfigs on reactionrolemessage.guildconfigid = guildconfigs.id;");
|
left join reactionrolemessage on reactionrolemessage.id = reactionrole.reactionrolemessageid
|
||||||
|
left join guildconfigs on reactionrolemessage.guildconfigid = guildconfigs.id;
|
||||||
|
""");
|
||||||
}
|
}
|
||||||
else if (migrationBuilder.IsSqlite())
|
else if (migrationBuilder.IsSqlite())
|
||||||
{
|
{
|
||||||
migrationBuilder.Sql(
|
migrationBuilder.Sql(
|
||||||
@"insert or ignore into reactionroles(guildid, channelid, messageid, emote, roleid, 'group', levelreq, dateadded)
|
"""
|
||||||
select guildid, channelid, messageid, emotename, roleid, exclusive, 0, reactionrolemessage.dateadded
|
insert or ignore into reactionroles(guildid, channelid, messageid, emote, roleid, 'group', levelreq, dateadded)
|
||||||
from reactionrole
|
select guildid, channelid, messageid, emotename, roleid, exclusive, 0, reactionrolemessage.dateadded
|
||||||
left join reactionrolemessage on reactionrolemessage.id = reactionrole.reactionrolemessageid
|
from reactionrole
|
||||||
left join guildconfigs on reactionrolemessage.guildconfigid = guildconfigs.id;");
|
left join reactionrolemessage on reactionrolemessage.id = reactionrole.reactionrolemessageid
|
||||||
|
left join guildconfigs on reactionrolemessage.guildconfigid = guildconfigs.id;
|
||||||
|
""");
|
||||||
}
|
}
|
||||||
else if (migrationBuilder.IsNpgsql())
|
else if (migrationBuilder.IsNpgsql())
|
||||||
{
|
{
|
||||||
migrationBuilder.Sql(@"insert into reactionroles(guildid, channelid, messageid, emote, roleid, ""group"", levelreq, dateadded)
|
migrationBuilder.Sql("""
|
||||||
select guildid, channelid, messageid, emotename, roleid, exclusive::int, 0, reactionrolemessage.dateadded
|
insert into reactionroles(guildid, channelid, messageid, emote, roleid, "group", levelreq, dateadded)
|
||||||
from reactionrole
|
select guildid, channelid, messageid, emotename, roleid, exclusive::int, 0, reactionrolemessage.dateadded
|
||||||
left join reactionrolemessage on reactionrolemessage.id = reactionrole.reactionrolemessageid
|
from reactionrole
|
||||||
left join guildconfigs on reactionrolemessage.guildconfigid = guildconfigs.id
|
left join reactionrolemessage on reactionrolemessage.id = reactionrole.reactionrolemessageid
|
||||||
ON CONFLICT DO NOTHING;");
|
left join guildconfigs on reactionrolemessage.guildconfigid = guildconfigs.id
|
||||||
|
ON CONFLICT DO NOTHING;
|
||||||
|
""");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@@ -28,14 +28,16 @@ namespace NadekoBot.Migrations
|
|||||||
table: "NsfwBlacklistedTags",
|
table: "NsfwBlacklistedTags",
|
||||||
column: "GuildId");
|
column: "GuildId");
|
||||||
|
|
||||||
migrationBuilder.Sql(@"INSERT INTO NsfwBlacklistedTags(Id, GuildId, Tag, DateAdded)
|
migrationBuilder.Sql("""
|
||||||
SELECT
|
INSERT INTO NsfwBlacklistedTags(Id, GuildId, Tag, DateAdded)
|
||||||
Id,
|
SELECT
|
||||||
(SELECT GuildId From GuildConfigs WHERE Id=GuildConfigId),
|
Id,
|
||||||
Tag,
|
(SELECT GuildId From GuildConfigs WHERE Id=GuildConfigId),
|
||||||
DateAdded
|
Tag,
|
||||||
FROM NsfwBlacklitedTag
|
DateAdded
|
||||||
WHERE GuildConfigId in (SELECT Id from GuildConfigs);");
|
FROM NsfwBlacklitedTag
|
||||||
|
WHERE GuildConfigId in (SELECT Id from GuildConfigs);
|
||||||
|
""");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "NsfwBlacklitedTag");
|
name: "NsfwBlacklitedTag");
|
||||||
|
@@ -50,24 +50,30 @@ namespace NadekoBot.Migrations
|
|||||||
principalTable: "GuildConfigs",
|
principalTable: "GuildConfigs",
|
||||||
principalColumn: "Id");
|
principalColumn: "Id");
|
||||||
|
|
||||||
migrationBuilder.Sql(@"UPDATE Permissions
|
migrationBuilder.Sql("""
|
||||||
SET SecondaryTargetName='ACTUALEXPRESSIONS'
|
UPDATE Permissions
|
||||||
WHERE SecondaryTargetName='ActualCustomReactions' COLLATE NOCASE;");
|
SET SecondaryTargetName='ACTUALEXPRESSIONS'
|
||||||
|
WHERE SecondaryTargetName='ActualCustomReactions' COLLATE NOCASE;
|
||||||
|
""");
|
||||||
|
|
||||||
migrationBuilder.Sql(@"UPDATE Permissions
|
migrationBuilder.Sql("""
|
||||||
SET SecondaryTargetName='EXPRESSIONS'
|
UPDATE Permissions
|
||||||
WHERE SecondaryTargetName='CustomReactions' COLLATE NOCASE;");
|
SET SecondaryTargetName='EXPRESSIONS'
|
||||||
|
WHERE SecondaryTargetName='CustomReactions' COLLATE NOCASE;
|
||||||
|
""");
|
||||||
|
|
||||||
migrationBuilder.Sql(@"UPDATE Permissions
|
migrationBuilder.Sql("""
|
||||||
SET SecondaryTargetName= case lower(SecondaryTargetName)
|
UPDATE Permissions
|
||||||
WHEN 'editcustreact' THEN 'expredit'
|
SET SecondaryTargetName= case lower(SecondaryTargetName)
|
||||||
WHEN 'delcustreact' THEN 'exprdel'
|
WHEN 'editcustreact' THEN 'expredit'
|
||||||
WHEN 'listcustreact' THEN 'exprlist'
|
WHEN 'delcustreact' THEN 'exprdel'
|
||||||
WHEN 'addcustreact' THEN 'expradd'
|
WHEN 'listcustreact' THEN 'exprlist'
|
||||||
WHEN 'showcustreact' THEN 'exprshow'
|
WHEN 'addcustreact' THEN 'expradd'
|
||||||
ELSE SecondaryTargetName
|
WHEN 'showcustreact' THEN 'exprshow'
|
||||||
END
|
ELSE SecondaryTargetName
|
||||||
WHERE lower(SecondaryTargetName) in ('editcustreact', 'delcustreact', 'listcustreact', 'addcustreact', 'showcustreact');");
|
END
|
||||||
|
WHERE lower(SecondaryTargetName) in ('editcustreact', 'delcustreact', 'listcustreact', 'addcustreact', 'showcustreact');
|
||||||
|
""");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
@@ -42,13 +42,15 @@ namespace NadekoBot.Migrations
|
|||||||
table: "FilterWordsChannelId",
|
table: "FilterWordsChannelId",
|
||||||
column: "GuildConfigId");
|
column: "GuildConfigId");
|
||||||
|
|
||||||
migrationBuilder.Sql(@"INSERT INTO FilterWordsChannelId(Id, ChannelId, GuildConfigId, DateAdded)
|
migrationBuilder.Sql("""
|
||||||
SELECT Id, ChannelId, GuildConfigId1, DateAdded
|
INSERT INTO FilterWordsChannelId(Id, ChannelId, GuildConfigId, DateAdded)
|
||||||
FROM FilterChannelId
|
SELECT Id, ChannelId, GuildConfigId1, DateAdded
|
||||||
WHERE GuildConfigId1 is not null;
|
FROM FilterChannelId
|
||||||
-- Remove them after moving them to a different table
|
WHERE GuildConfigId1 is not null;
|
||||||
DELETE FROM FilterChannelId
|
-- Remove them after moving them to a different table
|
||||||
WHERE GuildConfigId is null;");
|
DELETE FROM FilterChannelId
|
||||||
|
WHERE GuildConfigId is null;
|
||||||
|
""");
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
migrationBuilder.DropColumn(
|
||||||
name: "GuildConfigId1",
|
name: "GuildConfigId1",
|
||||||
|
@@ -9,19 +9,21 @@ namespace NadekoBot.Migrations
|
|||||||
{
|
{
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
{
|
{
|
||||||
migrationBuilder.Sql(@"UPDATE Clubs
|
migrationBuilder.Sql("""
|
||||||
SET Name = Name || '#' || Discrim
|
UPDATE Clubs
|
||||||
WHERE Discrim <> 1;
|
SET Name = Name || '#' || Discrim
|
||||||
|
WHERE Discrim <> 1;
|
||||||
UPDATE Clubs as co
|
|
||||||
SET Name =
|
UPDATE Clubs as co
|
||||||
CASE (select count(*) from Clubs as ci where co.Name == ci.Name) = 1
|
SET Name =
|
||||||
WHEN true
|
CASE (select count(*) from Clubs as ci where co.Name == ci.Name) = 1
|
||||||
THEN Name
|
WHEN true
|
||||||
ELSE
|
THEN Name
|
||||||
Name || '#' || Discrim
|
ELSE
|
||||||
END
|
Name || '#' || Discrim
|
||||||
WHERE Discrim = 1;");
|
END
|
||||||
|
WHERE Discrim = 1;
|
||||||
|
""");
|
||||||
|
|
||||||
migrationBuilder.DropForeignKey(
|
migrationBuilder.DropForeignKey(
|
||||||
name: "FK_Clubs_DiscordUser_OwnerId",
|
name: "FK_Clubs_DiscordUser_OwnerId",
|
||||||
|
@@ -19,19 +19,21 @@ public sealed class NadekoExpressionsService : IExecOnMessage, IReadyExecutor
|
|||||||
private const string MENTION_PH = "%bot.mention%";
|
private const string MENTION_PH = "%bot.mention%";
|
||||||
|
|
||||||
private const string PREPEND_EXPORT =
|
private const string PREPEND_EXPORT =
|
||||||
@"# Keys are triggers, Each key has a LIST of expressions in the following format:
|
"""
|
||||||
# - res: Response string
|
# Keys are triggers, Each key has a LIST of expressions in the following format:
|
||||||
# id: Alphanumeric id used for commands related to the expression. (Note, when using .exprsimport, a new id will be generated.)
|
# - res: Response string
|
||||||
# react:
|
# id: Alphanumeric id used for commands related to the expression. (Note, when using .exprsimport, a new id will be generated.)
|
||||||
# - <List
|
# react:
|
||||||
# - of
|
# - <List
|
||||||
# - reactions>
|
# - of
|
||||||
# at: Whether expression allows targets (see .h .exprat)
|
# - reactions>
|
||||||
# ca: Whether expression expects trigger anywhere (see .h .exprca)
|
# at: Whether expression allows targets (see .h .exprat)
|
||||||
# dm: Whether expression DMs the response (see .h .exprdm)
|
# ca: Whether expression expects trigger anywhere (see .h .exprca)
|
||||||
# ad: Whether expression automatically deletes triggering message (see .h .exprad)
|
# dm: Whether expression DMs the response (see .h .exprdm)
|
||||||
|
# ad: Whether expression automatically deletes triggering message (see .h .exprad)
|
||||||
|
|
||||||
|
|
||||||
";
|
""";
|
||||||
|
|
||||||
private static readonly ISerializer _exportSerializer = new SerializerBuilder()
|
private static readonly ISerializer _exportSerializer = new SerializerBuilder()
|
||||||
.WithEventEmitter(args
|
.WithEventEmitter(args
|
||||||
|
@@ -10,50 +10,58 @@ namespace NadekoBot.Modules.Gambling.Common;
|
|||||||
[Cloneable]
|
[Cloneable]
|
||||||
public sealed partial class GamblingConfig : ICloneable<GamblingConfig>
|
public sealed partial class GamblingConfig : ICloneable<GamblingConfig>
|
||||||
{
|
{
|
||||||
[Comment(@"DO NOT CHANGE")]
|
[Comment("""DO NOT CHANGE""")]
|
||||||
public int Version { get; set; } = 2;
|
public int Version { get; set; } = 2;
|
||||||
|
|
||||||
[Comment(@"Currency settings")]
|
[Comment("""Currency settings""")]
|
||||||
public CurrencyConfig Currency { get; set; }
|
public CurrencyConfig Currency { get; set; }
|
||||||
|
|
||||||
[Comment(@"Minimum amount users can bet (>=0)")]
|
[Comment("""Minimum amount users can bet (>=0)""")]
|
||||||
public int MinBet { get; set; } = 0;
|
public int MinBet { get; set; } = 0;
|
||||||
|
|
||||||
[Comment(@"Maximum amount users can bet
|
[Comment("""
|
||||||
Set 0 for unlimited")]
|
Maximum amount users can bet
|
||||||
|
Set 0 for unlimited
|
||||||
|
""")]
|
||||||
public int MaxBet { get; set; } = 0;
|
public int MaxBet { get; set; } = 0;
|
||||||
|
|
||||||
[Comment(@"Settings for betflip command")]
|
[Comment("""Settings for betflip command""")]
|
||||||
public BetFlipConfig BetFlip { get; set; }
|
public BetFlipConfig BetFlip { get; set; }
|
||||||
|
|
||||||
[Comment(@"Settings for betroll command")]
|
[Comment("""Settings for betroll command""")]
|
||||||
public BetRollConfig BetRoll { get; set; }
|
public BetRollConfig BetRoll { get; set; }
|
||||||
|
|
||||||
[Comment(@"Automatic currency generation settings.")]
|
[Comment("""Automatic currency generation settings.""")]
|
||||||
public GenerationConfig Generation { get; set; }
|
public GenerationConfig Generation { get; set; }
|
||||||
|
|
||||||
[Comment(@"Settings for timely command
|
[Comment("""
|
||||||
(letting people claim X amount of currency every Y hours)")]
|
Settings for timely command
|
||||||
|
(letting people claim X amount of currency every Y hours)
|
||||||
|
""")]
|
||||||
public TimelyConfig Timely { get; set; }
|
public TimelyConfig Timely { get; set; }
|
||||||
|
|
||||||
[Comment(@"How much will each user's owned currency decay over time.")]
|
[Comment("""How much will each user's owned currency decay over time.""")]
|
||||||
public DecayConfig Decay { get; set; }
|
public DecayConfig Decay { get; set; }
|
||||||
|
|
||||||
[Comment(@"Settings for LuckyLadder command")]
|
[Comment("""Settings for LuckyLadder command""")]
|
||||||
public LuckyLadderSettings LuckyLadder { get; set; }
|
public LuckyLadderSettings LuckyLadder { get; set; }
|
||||||
|
|
||||||
[Comment(@"Settings related to waifus")]
|
[Comment("""Settings related to waifus""")]
|
||||||
public WaifuConfig Waifu { get; set; }
|
public WaifuConfig Waifu { get; set; }
|
||||||
|
|
||||||
[Comment(@"Amount of currency selfhosters will get PER pledged dollar CENT.
|
[Comment("""
|
||||||
1 = 100 currency per $. Used almost exclusively on public nadeko.")]
|
Amount of currency selfhosters will get PER pledged dollar CENT.
|
||||||
|
1 = 100 currency per $. Used almost exclusively on public nadeko.
|
||||||
|
""")]
|
||||||
public decimal PatreonCurrencyPerCent { get; set; } = 1;
|
public decimal PatreonCurrencyPerCent { get; set; } = 1;
|
||||||
|
|
||||||
[Comment(@"Currency reward per vote.
|
[Comment("""
|
||||||
This will work only if you've set up VotesApi and correct credentials for topgg and/or discords voting")]
|
Currency reward per vote.
|
||||||
|
This will work only if you've set up VotesApi and correct credentials for topgg and/or discords voting
|
||||||
|
""")]
|
||||||
public long VoteReward { get; set; } = 100;
|
public long VoteReward { get; set; } = 100;
|
||||||
|
|
||||||
[Comment(@"Slot config")]
|
[Comment("""Slot config""")]
|
||||||
public SlotsConfig Slots { get; set; }
|
public SlotsConfig Slots { get; set; }
|
||||||
|
|
||||||
public GamblingConfig()
|
public GamblingConfig()
|
||||||
@@ -72,42 +80,50 @@ This will work only if you've set up VotesApi and correct credentials for topgg
|
|||||||
|
|
||||||
public class CurrencyConfig
|
public class CurrencyConfig
|
||||||
{
|
{
|
||||||
[Comment(@"What is the emoji/character which represents the currency")]
|
[Comment("""What is the emoji/character which represents the currency""")]
|
||||||
public string Sign { get; set; } = "🌸";
|
public string Sign { get; set; } = "🌸";
|
||||||
|
|
||||||
[Comment(@"What is the name of the currency")]
|
[Comment("""What is the name of the currency""")]
|
||||||
public string Name { get; set; } = "Nadeko Flower";
|
public string Name { get; set; } = "Nadeko Flower";
|
||||||
|
|
||||||
[Comment(@"For how long (in days) will the transactions be kept in the database (curtrs)
|
[Comment("""
|
||||||
Set 0 to disable cleanup (keep transactions forever)")]
|
For how long (in days) will the transactions be kept in the database (curtrs)
|
||||||
|
Set 0 to disable cleanup (keep transactions forever)
|
||||||
|
""")]
|
||||||
public int TransactionsLifetime { get; set; } = 0;
|
public int TransactionsLifetime { get; set; } = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Cloneable]
|
[Cloneable]
|
||||||
public partial class TimelyConfig
|
public partial class TimelyConfig
|
||||||
{
|
{
|
||||||
[Comment(@"How much currency will the users get every time they run .timely command
|
[Comment("""
|
||||||
setting to 0 or less will disable this feature")]
|
How much currency will the users get every time they run .timely command
|
||||||
|
setting to 0 or less will disable this feature
|
||||||
|
""")]
|
||||||
public int Amount { get; set; } = 0;
|
public int Amount { get; set; } = 0;
|
||||||
|
|
||||||
[Comment(@"How often (in hours) can users claim currency with .timely command
|
[Comment("""
|
||||||
setting to 0 or less will disable this feature")]
|
How often (in hours) can users claim currency with .timely command
|
||||||
|
setting to 0 or less will disable this feature
|
||||||
|
""")]
|
||||||
public int Cooldown { get; set; } = 24;
|
public int Cooldown { get; set; } = 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Cloneable]
|
[Cloneable]
|
||||||
public partial class BetFlipConfig
|
public partial class BetFlipConfig
|
||||||
{
|
{
|
||||||
[Comment(@"Bet multiplier if user guesses correctly")]
|
[Comment("""Bet multiplier if user guesses correctly""")]
|
||||||
public decimal Multiplier { get; set; } = 1.95M;
|
public decimal Multiplier { get; set; } = 1.95M;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Cloneable]
|
[Cloneable]
|
||||||
public partial class BetRollConfig
|
public partial class BetRollConfig
|
||||||
{
|
{
|
||||||
[Comment(@"When betroll is played, user will roll a number 0-100.
|
[Comment("""
|
||||||
This setting will describe which multiplier is used for when the roll is higher than the given number.
|
When betroll is played, user will roll a number 0-100.
|
||||||
Doesn't have to be ordered.")]
|
This setting will describe which multiplier is used for when the roll is higher than the given number.
|
||||||
|
Doesn't have to be ordered.
|
||||||
|
""")]
|
||||||
public BetRollPair[] Pairs { get; set; } = Array.Empty<BetRollPair>();
|
public BetRollPair[] Pairs { get; set; } = Array.Empty<BetRollPair>();
|
||||||
|
|
||||||
public BetRollConfig()
|
public BetRollConfig()
|
||||||
@@ -134,48 +150,56 @@ Doesn't have to be ordered.")]
|
|||||||
[Cloneable]
|
[Cloneable]
|
||||||
public partial class GenerationConfig
|
public partial class GenerationConfig
|
||||||
{
|
{
|
||||||
[Comment(@"when currency is generated, should it also have a random password
|
[Comment("""
|
||||||
associated with it which users have to type after the .pick command
|
when currency is generated, should it also have a random password
|
||||||
in order to get it")]
|
associated with it which users have to type after the .pick command
|
||||||
|
in order to get it
|
||||||
|
""")]
|
||||||
public bool HasPassword { get; set; } = true;
|
public bool HasPassword { get; set; } = true;
|
||||||
|
|
||||||
[Comment(@"Every message sent has a certain % chance to generate the currency
|
[Comment("""
|
||||||
specify the percentage here (1 being 100%, 0 being 0% - for example
|
Every message sent has a certain % chance to generate the currency
|
||||||
default is 0.02, which is 2%")]
|
specify the percentage here (1 being 100%, 0 being 0% - for example
|
||||||
|
default is 0.02, which is 2%
|
||||||
|
""")]
|
||||||
public decimal Chance { get; set; } = 0.02M;
|
public decimal Chance { get; set; } = 0.02M;
|
||||||
|
|
||||||
[Comment(@"How many seconds have to pass for the next message to have a chance to spawn currency")]
|
[Comment("""How many seconds have to pass for the next message to have a chance to spawn currency""")]
|
||||||
public int GenCooldown { get; set; } = 10;
|
public int GenCooldown { get; set; } = 10;
|
||||||
|
|
||||||
[Comment(@"Minimum amount of currency that can spawn")]
|
[Comment("""Minimum amount of currency that can spawn""")]
|
||||||
public int MinAmount { get; set; } = 1;
|
public int MinAmount { get; set; } = 1;
|
||||||
|
|
||||||
[Comment(@"Maximum amount of currency that can spawn.
|
[Comment("""
|
||||||
Set to the same value as MinAmount to always spawn the same amount")]
|
Maximum amount of currency that can spawn.
|
||||||
|
Set to the same value as MinAmount to always spawn the same amount
|
||||||
|
""")]
|
||||||
public int MaxAmount { get; set; } = 1;
|
public int MaxAmount { get; set; } = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Cloneable]
|
[Cloneable]
|
||||||
public partial class DecayConfig
|
public partial class DecayConfig
|
||||||
{
|
{
|
||||||
[Comment(@"Percentage of user's current currency which will be deducted every 24h.
|
[Comment("""
|
||||||
0 - 1 (1 is 100%, 0.5 50%, 0 disabled)")]
|
Percentage of user's current currency which will be deducted every 24h.
|
||||||
|
0 - 1 (1 is 100%, 0.5 50%, 0 disabled)
|
||||||
|
""")]
|
||||||
public decimal Percent { get; set; } = 0;
|
public decimal Percent { get; set; } = 0;
|
||||||
|
|
||||||
[Comment(@"Maximum amount of user's currency that can decay at each interval. 0 for unlimited.")]
|
[Comment("""Maximum amount of user's currency that can decay at each interval. 0 for unlimited.""")]
|
||||||
public int MaxDecay { get; set; } = 0;
|
public int MaxDecay { get; set; } = 0;
|
||||||
|
|
||||||
[Comment(@"Only users who have more than this amount will have their currency decay.")]
|
[Comment("""Only users who have more than this amount will have their currency decay.""")]
|
||||||
public int MinThreshold { get; set; } = 99;
|
public int MinThreshold { get; set; } = 99;
|
||||||
|
|
||||||
[Comment(@"How often, in hours, does the decay run. Default is 24 hours")]
|
[Comment("""How often, in hours, does the decay run. Default is 24 hours""")]
|
||||||
public int HourInterval { get; set; } = 24;
|
public int HourInterval { get; set; } = 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Cloneable]
|
[Cloneable]
|
||||||
public partial class LuckyLadderSettings
|
public partial class LuckyLadderSettings
|
||||||
{
|
{
|
||||||
[Comment(@"Self-Explanatory. Has to have 8 values, otherwise the command won't work.")]
|
[Comment("""Self-Explanatory. Has to have 8 values, otherwise the command won't work.""")]
|
||||||
public decimal[] Multipliers { get; set; }
|
public decimal[] Multipliers { get; set; }
|
||||||
|
|
||||||
public LuckyLadderSettings()
|
public LuckyLadderSettings()
|
||||||
@@ -185,17 +209,21 @@ public partial class LuckyLadderSettings
|
|||||||
[Cloneable]
|
[Cloneable]
|
||||||
public sealed partial class WaifuConfig
|
public sealed partial class WaifuConfig
|
||||||
{
|
{
|
||||||
[Comment(@"Minimum price a waifu can have")]
|
[Comment("""Minimum price a waifu can have""")]
|
||||||
public long MinPrice { get; set; } = 50;
|
public long MinPrice { get; set; } = 50;
|
||||||
|
|
||||||
public MultipliersData Multipliers { get; set; } = new();
|
public MultipliersData Multipliers { get; set; } = new();
|
||||||
|
|
||||||
[Comment(@"Settings for periodic waifu price decay.
|
[Comment("""
|
||||||
Waifu price decays only if the waifu has no claimer.")]
|
Settings for periodic waifu price decay.
|
||||||
|
Waifu price decays only if the waifu has no claimer.
|
||||||
|
""")]
|
||||||
public WaifuDecayConfig Decay { get; set; } = new();
|
public WaifuDecayConfig Decay { get; set; } = new();
|
||||||
|
|
||||||
[Comment(@"List of items available for gifting.
|
[Comment("""
|
||||||
If negative is true, gift will instead reduce waifu value.")]
|
List of items available for gifting.
|
||||||
|
If negative is true, gift will instead reduce waifu value.
|
||||||
|
""")]
|
||||||
public List<WaifuItemModel> Items { get; set; } = new();
|
public List<WaifuItemModel> Items { get; set; } = new();
|
||||||
|
|
||||||
public WaifuConfig()
|
public WaifuConfig()
|
||||||
@@ -241,16 +269,20 @@ If negative is true, gift will instead reduce waifu value.")]
|
|||||||
|
|
||||||
public class WaifuDecayConfig
|
public class WaifuDecayConfig
|
||||||
{
|
{
|
||||||
[Comment(@"Percentage (0 - 100) of the waifu value to reduce.
|
[Comment("""
|
||||||
Set 0 to disable
|
Percentage (0 - 100) of the waifu value to reduce.
|
||||||
For example if a waifu has a price of 500$, setting this value to 10 would reduce the waifu value by 10% (50$)")]
|
Set 0 to disable
|
||||||
|
For example if a waifu has a price of 500$, setting this value to 10 would reduce the waifu value by 10% (50$)
|
||||||
|
""")]
|
||||||
public int Percent { get; set; } = 0;
|
public int Percent { get; set; } = 0;
|
||||||
|
|
||||||
[Comment(@"How often to decay waifu values, in hours")]
|
[Comment("""How often to decay waifu values, in hours""")]
|
||||||
public int HourInterval { get; set; } = 24;
|
public int HourInterval { get; set; } = 24;
|
||||||
|
|
||||||
[Comment(@"Minimum waifu price required for the decay to be applied.
|
[Comment("""
|
||||||
For example if this value is set to 300, any waifu with the price 300 or less will not experience decay.")]
|
Minimum waifu price required for the decay to be applied.
|
||||||
|
For example if this value is set to 300, any waifu with the price 300 or less will not experience decay.
|
||||||
|
""")]
|
||||||
public long MinPrice { get; set; } = 300;
|
public long MinPrice { get; set; } = 300;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -258,47 +290,61 @@ For example if this value is set to 300, any waifu with the price 300 or less wi
|
|||||||
[Cloneable]
|
[Cloneable]
|
||||||
public sealed partial class MultipliersData
|
public sealed partial class MultipliersData
|
||||||
{
|
{
|
||||||
[Comment(@"Multiplier for waifureset. Default 150.
|
[Comment("""
|
||||||
Formula (at the time of writing this):
|
Multiplier for waifureset. Default 150.
|
||||||
price = (waifu_price * 1.25f) + ((number_of_divorces + changes_of_heart + 2) * WaifuReset) rounded up")]
|
Formula (at the time of writing this):
|
||||||
|
price = (waifu_price * 1.25f) + ((number_of_divorces + changes_of_heart + 2) * WaifuReset) rounded up
|
||||||
|
""")]
|
||||||
public int WaifuReset { get; set; } = 150;
|
public int WaifuReset { get; set; } = 150;
|
||||||
|
|
||||||
[Comment(@"The minimum amount of currency that you have to pay
|
[Comment("""
|
||||||
in order to buy a waifu who doesn't have a crush on you.
|
The minimum amount of currency that you have to pay
|
||||||
Default is 1.1
|
in order to buy a waifu who doesn't have a crush on you.
|
||||||
Example: If a waifu is worth 100, you will have to pay at least 100 * NormalClaim currency to claim her.
|
Default is 1.1
|
||||||
(100 * 1.1 = 110)")]
|
Example: If a waifu is worth 100, you will have to pay at least 100 * NormalClaim currency to claim her.
|
||||||
|
(100 * 1.1 = 110)
|
||||||
|
""")]
|
||||||
public decimal NormalClaim { get; set; } = 1.1m;
|
public decimal NormalClaim { get; set; } = 1.1m;
|
||||||
|
|
||||||
[Comment(@"The minimum amount of currency that you have to pay
|
[Comment("""
|
||||||
in order to buy a waifu that has a crush on you.
|
The minimum amount of currency that you have to pay
|
||||||
Default is 0.88
|
in order to buy a waifu that has a crush on you.
|
||||||
Example: If a waifu is worth 100, you will have to pay at least 100 * CrushClaim currency to claim her.
|
Default is 0.88
|
||||||
(100 * 0.88 = 88)")]
|
Example: If a waifu is worth 100, you will have to pay at least 100 * CrushClaim currency to claim her.
|
||||||
|
(100 * 0.88 = 88)
|
||||||
|
""")]
|
||||||
public decimal CrushClaim { get; set; } = 0.88M;
|
public decimal CrushClaim { get; set; } = 0.88M;
|
||||||
|
|
||||||
[Comment(@"When divorcing a waifu, her new value will be her current value multiplied by this number.
|
[Comment("""
|
||||||
Default 0.75 (meaning will lose 25% of her value)")]
|
When divorcing a waifu, her new value will be her current value multiplied by this number.
|
||||||
|
Default 0.75 (meaning will lose 25% of her value)
|
||||||
|
""")]
|
||||||
public decimal DivorceNewValue { get; set; } = 0.75M;
|
public decimal DivorceNewValue { get; set; } = 0.75M;
|
||||||
|
|
||||||
[Comment(@"All gift prices will be multiplied by this number.
|
[Comment("""
|
||||||
Default 1 (meaning no effect)")]
|
All gift prices will be multiplied by this number.
|
||||||
|
Default 1 (meaning no effect)
|
||||||
|
""")]
|
||||||
public decimal AllGiftPrices { get; set; } = 1.0M;
|
public decimal AllGiftPrices { get; set; } = 1.0M;
|
||||||
|
|
||||||
[Comment(@"What percentage of the value of the gift will a waifu gain when she's gifted.
|
[Comment("""
|
||||||
Default 0.95 (meaning 95%)
|
What percentage of the value of the gift will a waifu gain when she's gifted.
|
||||||
Example: If a waifu is worth 1000, and she receives a gift worth 100, her new value will be 1095)")]
|
Default 0.95 (meaning 95%)
|
||||||
|
Example: If a waifu is worth 1000, and she receives a gift worth 100, her new value will be 1095)
|
||||||
|
""")]
|
||||||
public decimal GiftEffect { get; set; } = 0.95M;
|
public decimal GiftEffect { get; set; } = 0.95M;
|
||||||
|
|
||||||
[Comment(@"What percentage of the value of the gift will a waifu lose when she's gifted a gift marked as 'negative'.
|
[Comment("""
|
||||||
Default 0.5 (meaning 50%)
|
What percentage of the value of the gift will a waifu lose when she's gifted a gift marked as 'negative'.
|
||||||
Example: If a waifu is worth 1000, and she receives a negative gift worth 100, her new value will be 950)")]
|
Default 0.5 (meaning 50%)
|
||||||
|
Example: If a waifu is worth 1000, and she receives a negative gift worth 100, her new value will be 950)
|
||||||
|
""")]
|
||||||
public decimal NegativeGiftEffect { get; set; } = 0.50M;
|
public decimal NegativeGiftEffect { get; set; } = 0.50M;
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class SlotsConfig
|
public sealed class SlotsConfig
|
||||||
{
|
{
|
||||||
[Comment(@"Hex value of the color which the numbers on the slot image will have.")]
|
[Comment("""Hex value of the color which the numbers on the slot image will have.""")]
|
||||||
public Rgba32 CurrencyFontColor { get; set; } = Color.Red;
|
public Rgba32 CurrencyFontColor { get; set; } = Color.Red;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -96,9 +96,12 @@ public class GamblingService : INService, IReadyExecutor
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.Information(@"Decaying users' currency - decay: {ConfigDecayPercent}%
|
Log.Information("""
|
||||||
| max: {MaxDecay}
|
--- Decaying users' currency ---
|
||||||
| threshold: {DecayMinTreshold}",
|
| decay: {ConfigDecayPercent}%
|
||||||
|
| max: {MaxDecay}
|
||||||
|
| threshold: {DecayMinTreshold}
|
||||||
|
""",
|
||||||
config.Decay.Percent * 100,
|
config.Decay.Percent * 100,
|
||||||
maxDecay,
|
maxDecay,
|
||||||
config.Decay.MinThreshold);
|
config.Decay.MinThreshold);
|
||||||
|
@@ -187,11 +187,13 @@ public class ChatterBotService : IExecOnMessage
|
|||||||
// , footer: counter > 0 ? counter.ToString() : null
|
// , footer: counter > 0 ? counter.ToString() : null
|
||||||
);
|
);
|
||||||
|
|
||||||
Log.Information(@"CleverBot Executed
|
Log.Information("""
|
||||||
Server: {GuildName} [{GuildId}]
|
CleverBot Executed
|
||||||
Channel: {ChannelName} [{ChannelId}]
|
Server: {GuildName} [{GuildId}]
|
||||||
UserId: {Author} [{AuthorId}]
|
Channel: {ChannelName} [{ChannelId}]
|
||||||
Message: {Content}",
|
UserId: {Author} [{AuthorId}]
|
||||||
|
Message: {Content}
|
||||||
|
""",
|
||||||
guild.Name,
|
guild.Name,
|
||||||
guild.Id,
|
guild.Id,
|
||||||
usrMsg.Channel?.Name,
|
usrMsg.Channel?.Name,
|
||||||
|
@@ -110,8 +110,10 @@ public sealed partial class TriviaConfig
|
|||||||
[Comment("The amount of currency awarded to the winner of the trivia game.")]
|
[Comment("The amount of currency awarded to the winner of the trivia game.")]
|
||||||
public long CurrencyReward { get; set; }
|
public long CurrencyReward { get; set; }
|
||||||
|
|
||||||
[Comment(@"Users won't be able to start trivia games which have
|
[Comment("""
|
||||||
a smaller win requirement than the one specified by this setting.")]
|
Users won't be able to start trivia games which have
|
||||||
|
a smaller win requirement than the one specified by this setting.
|
||||||
|
""")]
|
||||||
public int MinimumWinReq { get; set; } = 1;
|
public int MinimumWinReq { get; set; } = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -14,13 +14,15 @@ public partial class Games
|
|||||||
=> await SendConfirmAsync(GetText(strs.hangman_types(prefix)), _service.GetHangmanTypes().Join('\n'));
|
=> await SendConfirmAsync(GetText(strs.hangman_types(prefix)), _service.GetHangmanTypes().Join('\n'));
|
||||||
|
|
||||||
private static string Draw(HangmanGame.State state)
|
private static string Draw(HangmanGame.State state)
|
||||||
=> $@". ┌─────┐
|
=> $"""
|
||||||
.┃...............┋
|
. ┌─────┐
|
||||||
.┃...............┋
|
.┃...............┋
|
||||||
.┃{(state.Errors > 0 ? ".............😲" : "")}
|
.┃...............┋
|
||||||
.┃{(state.Errors > 1 ? "............./" : "")} {(state.Errors > 2 ? "|" : "")} {(state.Errors > 3 ? "\\" : "")}
|
.┃{(state.Errors > 0 ? ".............😲" : "")}
|
||||||
.┃{(state.Errors > 4 ? "............../" : "")} {(state.Errors > 5 ? "\\" : "")}
|
.┃{(state.Errors > 1 ? "............./" : "")} {(state.Errors > 2 ? "|" : "")} {(state.Errors > 3 ? "\\" : "")}
|
||||||
/-\";
|
.┃{(state.Errors > 4 ? "............../" : "")} {(state.Errors > 5 ? "\\" : "")}
|
||||||
|
/-\
|
||||||
|
""";
|
||||||
|
|
||||||
public static IEmbedBuilder GetEmbed(IEmbedBuilderService eb, HangmanGame.State state)
|
public static IEmbedBuilder GetEmbed(IEmbedBuilderService eb, HangmanGame.State state)
|
||||||
{
|
{
|
||||||
|
@@ -69,7 +69,7 @@ public class TypingGame
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
await Channel.SendConfirmAsync(_eb,
|
await Channel.SendConfirmAsync(_eb,
|
||||||
$@":clock2: Next contest will last for {i} seconds. Type the bolded text as fast as you can.");
|
$":clock2: Next contest will last for {i} seconds. Type the bolded text as fast as you can.");
|
||||||
|
|
||||||
|
|
||||||
var time = _options.StartTime;
|
var time = _options.StartTime;
|
||||||
|
@@ -78,13 +78,13 @@ public class TriviaQuestion
|
|||||||
private static string Clean(string str)
|
private static string Clean(string str)
|
||||||
{
|
{
|
||||||
str = " " + str.ToLowerInvariant() + " ";
|
str = " " + str.ToLowerInvariant() + " ";
|
||||||
str = Regex.Replace(str, "\\s+", " ");
|
str = Regex.Replace(str, @"\s+", " ");
|
||||||
str = Regex.Replace(str, "[^\\w\\d\\s]", "");
|
str = Regex.Replace(str, @"[^\w\d\s]", "");
|
||||||
//Here's where custom modification can be done
|
//Here's where custom modification can be done
|
||||||
str = Regex.Replace(str, "\\s(a|an|the|of|in|for|to|as|at|be)\\s", " ");
|
str = Regex.Replace(str, @"\s(a|an|the|of|in|for|to|as|at|be)\s", " ");
|
||||||
//End custom mod and cleanup whitespace
|
//End custom mod and cleanup whitespace
|
||||||
str = Regex.Replace(str, "^\\s+", "");
|
str = Regex.Replace(str, @"^\s+", "");
|
||||||
str = Regex.Replace(str, "\\s+$", "");
|
str = Regex.Replace(str, @"\s+$", "");
|
||||||
//Trim the really long answers
|
//Trim the really long answers
|
||||||
str = str.Length <= MAX_STRING_LENGTH ? str : str[..MAX_STRING_LENGTH];
|
str = str.Length <= MAX_STRING_LENGTH ? str : str[..MAX_STRING_LENGTH];
|
||||||
return str;
|
return str;
|
||||||
|
@@ -490,13 +490,15 @@ public partial class Help : NadekoModule<HelpService>
|
|||||||
|
|
||||||
private Task SelfhostAction(SocketMessageComponent smc, object _)
|
private Task SelfhostAction(SocketMessageComponent smc, object _)
|
||||||
=> smc.RespondConfirmAsync(_eb,
|
=> smc.RespondConfirmAsync(_eb,
|
||||||
@"- In case you don't want or cannot Donate to NadekoBot project, but you
|
"""
|
||||||
- NadekoBot is a completely free and fully [open source](https://gitlab.com/kwoth/nadekobot) project which means you can run your own ""selfhosted"" instance on your computer or server for free.
|
- In case you don't want or cannot Donate to NadekoBot project, but you
|
||||||
|
- NadekoBot is a completely free and fully [open source](https://gitlab.com/kwoth/nadekobot) project which means you can run your own "selfhosted" instance on your computer or server for free.
|
||||||
*Keep in mind that running the bot on your computer means that the bot will be offline when you turn off your computer*
|
|
||||||
|
*Keep in mind that running the bot on your computer means that the bot will be offline when you turn off your computer*
|
||||||
- You can find the selfhosting guides by using the `.guide` command and clicking on the second link that pops up.
|
|
||||||
- If you decide to selfhost the bot, still consider [supporting the project](https://patreon.com/join/nadekobot) to keep the development going :)",
|
- You can find the selfhosting guides by using the `.guide` command and clicking on the second link that pops up.
|
||||||
|
- If you decide to selfhost the bot, still consider [supporting the project](https://patreon.com/join/nadekobot) to keep the development going :)
|
||||||
|
""",
|
||||||
true);
|
true);
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
@@ -541,12 +543,14 @@ Nadeko will DM you the welcome instructions, and you may start using the patron-
|
|||||||
🎉 **Enjoy!** 🎉
|
🎉 **Enjoy!** 🎉
|
||||||
")
|
")
|
||||||
.AddField("Troubleshooting",
|
.AddField("Troubleshooting",
|
||||||
@"
|
"""
|
||||||
*In case you didn't receive the rewards within 5 minutes:*
|
|
||||||
`1.` Make sure your DMs are open to everyone. Maybe your pledge was processed successfully but the bot was unable to DM you. Use the `.patron` command to check your status.
|
*In case you didn't receive the rewards within 5 minutes:*
|
||||||
`2.` Make sure you've connected the CORRECT Discord account. Quite often users log in to different Discord accounts in their browser. You may also try disconnecting and reconnecting your account.
|
`1.` Make sure your DMs are open to everyone. Maybe your pledge was processed successfully but the bot was unable to DM you. Use the `.patron` command to check your status.
|
||||||
`3.` Make sure your payment has been processed and not declined by Patreon.
|
`2.` Make sure you've connected the CORRECT Discord account. Quite often users log in to different Discord accounts in their browser. You may also try disconnecting and reconnecting your account.
|
||||||
`4.` If any of the previous steps don't help, you can join the nadeko support server <https://discord.nadeko.bot> and ask for help in the #help channel");
|
`3.` Make sure your payment has been processed and not declined by Patreon.
|
||||||
|
`4.` If any of the previous steps don't help, you can join the nadeko support server <https://discord.nadeko.bot> and ask for help in the #help channel
|
||||||
|
""");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@@ -39,9 +39,9 @@ public static class MusicExtensions
|
|||||||
if (trackInfo.Duration == TimeSpan.MaxValue)
|
if (trackInfo.Duration == TimeSpan.MaxValue)
|
||||||
return "∞";
|
return "∞";
|
||||||
if (trackInfo.Duration.TotalHours >= 1)
|
if (trackInfo.Duration.TotalHours >= 1)
|
||||||
return trackInfo.Duration.ToString(@"hh\:mm\:ss");
|
return trackInfo.Duration.ToString("""hh\:mm\:ss""");
|
||||||
|
|
||||||
return trackInfo.Duration.ToString(@"mm\:ss");
|
return trackInfo.Duration.ToString("""mm\:ss""");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ICachableTrackData ToCachedData(this ITrackInfo trackInfo, string id)
|
public static ICachableTrackData ToCachedData(this ITrackInfo trackInfo, string id)
|
||||||
|
@@ -5,10 +5,10 @@ namespace NadekoBot.Modules.Music.Resolvers;
|
|||||||
|
|
||||||
public class RadioResolver : IRadioResolver
|
public class RadioResolver : IRadioResolver
|
||||||
{
|
{
|
||||||
private readonly Regex _plsRegex = new("File1=(?<url>.*?)\\n", RegexOptions.Compiled);
|
private readonly Regex _plsRegex = new(@"File1=(?<url>.*?)\n", RegexOptions.Compiled);
|
||||||
private readonly Regex _m3URegex = new("(?<url>^[^#].*)", RegexOptions.Compiled | RegexOptions.Multiline);
|
private readonly Regex _m3URegex = new(@"(?<url>^[^#].*)", RegexOptions.Compiled | RegexOptions.Multiline);
|
||||||
private readonly Regex _asxRegex = new("<ref href=\"(?<url>.*?)\"", RegexOptions.Compiled);
|
private readonly Regex _asxRegex = new(@"<ref href=""(?<url>.*?)""", RegexOptions.Compiled);
|
||||||
private readonly Regex _xspfRegex = new("<location>(?<url>.*?)</location>", RegexOptions.Compiled);
|
private readonly Regex _xspfRegex = new(@"<location>(?<url>.*?)</location>", RegexOptions.Compiled);
|
||||||
|
|
||||||
public async Task<ITrackInfo> ResolveByQueryAsync(string query)
|
public async Task<ITrackInfo> ResolveByQueryAsync(string query)
|
||||||
{
|
{
|
||||||
|
@@ -24,7 +24,7 @@ public partial class Searches
|
|||||||
|
|
||||||
var channelId = m.Groups["channelid"].Value;
|
var channelId = m.Groups["channelid"].Value;
|
||||||
|
|
||||||
return Feed("https://www.youtube.com/feeds/videos.xml?channel_id=" + channelId, channel, message);
|
return Feed($"https://www.youtube.com/feeds/videos.xml?channel_id={channelId}", channel, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
|
@@ -304,7 +304,7 @@ public partial class Searches
|
|||||||
|
|
||||||
private static string ShortLeagueName(string str)
|
private static string ShortLeagueName(string str)
|
||||||
{
|
{
|
||||||
var league = Regex.Replace(str, "Hardcore", "HC", RegexOptions.IgnoreCase);
|
var league = str.Replace("Hardcore", "HC", StringComparison.InvariantCultureIgnoreCase);
|
||||||
|
|
||||||
return league;
|
return league;
|
||||||
}
|
}
|
||||||
|
@@ -9,51 +9,61 @@ public partial class SearchesConfig : ICloneable<SearchesConfig>
|
|||||||
[Comment("DO NOT CHANGE")]
|
[Comment("DO NOT CHANGE")]
|
||||||
public int Version { get; set; } = 0;
|
public int Version { get; set; } = 0;
|
||||||
|
|
||||||
[Comment(@"Which engine should .search command
|
[Comment("""
|
||||||
'google_scrape' - default. Scrapes the webpage for results. May break. Requires no api keys.
|
Which engine should .search command
|
||||||
'google' - official google api. Requires googleApiKey and google.searchId set in creds.yml
|
'google_scrape' - default. Scrapes the webpage for results. May break. Requires no api keys.
|
||||||
'searx' - requires at least one searx instance specified in the 'searxInstances' property below")]
|
'google' - official google api. Requires googleApiKey and google.searchId set in creds.yml
|
||||||
|
'searx' - requires at least one searx instance specified in the 'searxInstances' property below
|
||||||
|
""")]
|
||||||
public WebSearchEngine WebSearchEngine { get; set; } = WebSearchEngine.Google_Scrape;
|
public WebSearchEngine WebSearchEngine { get; set; } = WebSearchEngine.Google_Scrape;
|
||||||
|
|
||||||
[Comment(@"Which engine should .image command use
|
[Comment("""
|
||||||
'google'- official google api. googleApiKey and google.imageSearchId set in creds.yml
|
Which engine should .image command use
|
||||||
'searx' requires at least one searx instance specified in the 'searxInstances' property below")]
|
'google'- official google api. googleApiKey and google.imageSearchId set in creds.yml
|
||||||
|
'searx' requires at least one searx instance specified in the 'searxInstances' property below
|
||||||
|
""")]
|
||||||
public ImgSearchEngine ImgSearchEngine { get; set; } = ImgSearchEngine.Google;
|
public ImgSearchEngine ImgSearchEngine { get; set; } = ImgSearchEngine.Google;
|
||||||
|
|
||||||
|
|
||||||
[Comment(@"Which search provider will be used for the `.youtube` command.
|
[Comment("""
|
||||||
|
Which search provider will be used for the `.youtube` command.
|
||||||
- `ytDataApiv3` - uses google's official youtube data api. Requires `GoogleApiKey` set in creds and youtube data api enabled in developers console
|
|
||||||
|
- `ytDataApiv3` - uses google's official youtube data api. Requires `GoogleApiKey` set in creds and youtube data api enabled in developers console
|
||||||
- `ytdl` - default, uses youtube-dl. Requires `youtube-dl` to be installed and it's path added to env variables. Slow.
|
|
||||||
|
- `ytdl` - default, uses youtube-dl. Requires `youtube-dl` to be installed and it's path added to env variables. Slow.
|
||||||
- `ytdlp` - recommended easy, uses `yt-dlp`. Requires `yt-dlp` to be installed and it's path added to env variables
|
|
||||||
|
- `ytdlp` - recommended easy, uses `yt-dlp`. Requires `yt-dlp` to be installed and it's path added to env variables
|
||||||
- `invidious` - recommended advanced, uses invidious api. Requires at least one invidious instance specified in the `invidiousInstances` property")]
|
|
||||||
|
- `invidious` - recommended advanced, uses invidious api. Requires at least one invidious instance specified in the `invidiousInstances` property
|
||||||
|
""")]
|
||||||
public YoutubeSearcher YtProvider { get; set; } = YoutubeSearcher.Ytdl;
|
public YoutubeSearcher YtProvider { get; set; } = YoutubeSearcher.Ytdl;
|
||||||
|
|
||||||
[Comment(@"Set the searx instance urls in case you want to use 'searx' for either img or web search.
|
[Comment("""
|
||||||
Nadeko will use a random one for each request.
|
Set the searx instance urls in case you want to use 'searx' for either img or web search.
|
||||||
Use a fully qualified url. Example: `https://my-searx-instance.mydomain.com`
|
Nadeko will use a random one for each request.
|
||||||
Instances specified must support 'format=json' query parameter.
|
Use a fully qualified url. Example: `https://my-searx-instance.mydomain.com`
|
||||||
- In case you're running your own searx instance, set
|
Instances specified must support 'format=json' query parameter.
|
||||||
|
- In case you're running your own searx instance, set
|
||||||
search:
|
|
||||||
formats:
|
search:
|
||||||
- json
|
formats:
|
||||||
|
- json
|
||||||
in 'searxng/settings.yml' on your server
|
|
||||||
|
in 'searxng/settings.yml' on your server
|
||||||
- If you're using a public instance, make sure that the instance you're using supports it (they usually don't)")]
|
|
||||||
|
- If you're using a public instance, make sure that the instance you're using supports it (they usually don't)
|
||||||
|
""")]
|
||||||
public List<string> SearxInstances { get; set; } = new List<string>();
|
public List<string> SearxInstances { get; set; } = new List<string>();
|
||||||
|
|
||||||
[Comment(@"Set the invidious instance urls in case you want to use 'invidious' for `.youtube` search
|
[Comment("""
|
||||||
Nadeko will use a random one for each request.
|
Set the invidious instance urls in case you want to use 'invidious' for `.youtube` search
|
||||||
These instances may be used for music queue functionality in the future.
|
Nadeko will use a random one for each request.
|
||||||
Use a fully qualified url. Example: https://my-invidious-instance.mydomain.com
|
These instances may be used for music queue functionality in the future.
|
||||||
|
Use a fully qualified url. Example: https://my-invidious-instance.mydomain.com
|
||||||
Instances specified must have api available.
|
|
||||||
You check that by opening an api endpoint in your browser. For example: https://my-invidious-instance.mydomain.com/api/v1/trending")]
|
Instances specified must have api available.
|
||||||
|
You check that by opening an api endpoint in your browser. For example: https://my-invidious-instance.mydomain.com/api/v1/trending
|
||||||
|
""")]
|
||||||
public List<string> InvidiousInstances { get; set; } = new List<string>();
|
public List<string> InvidiousInstances { get; set; } = new List<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -23,8 +23,10 @@ public class TrovoProvider : Provider
|
|||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(creds.GetCreds().TrovoClientId))
|
if (string.IsNullOrWhiteSpace(creds.GetCreds().TrovoClientId))
|
||||||
{
|
{
|
||||||
Log.Warning(@"Trovo streams are using a default clientId.
|
Log.Warning("""
|
||||||
If you are experiencing ratelimits, you should create your own application at: https://developer.trovo.live/");
|
Trovo streams are using a default clientId.
|
||||||
|
If you are experiencing ratelimits, you should create your own application at: https://developer.trovo.live/
|
||||||
|
""");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -52,7 +52,7 @@ public partial class Utility
|
|||||||
var expiryString = inv.MaxAge is null or 0 || inv.CreatedAt is null
|
var expiryString = inv.MaxAge is null or 0 || inv.CreatedAt is null
|
||||||
? "∞"
|
? "∞"
|
||||||
: (inv.CreatedAt.Value.AddSeconds(inv.MaxAge.Value).UtcDateTime - DateTime.UtcNow).ToString(
|
: (inv.CreatedAt.Value.AddSeconds(inv.MaxAge.Value).UtcDateTime - DateTime.UtcNow).ToString(
|
||||||
@"d\.hh\:mm\:ss");
|
"""d\.hh\:mm\:ss""");
|
||||||
var creator = inv.Inviter.ToString().TrimTo(25);
|
var creator = inv.Inviter.ToString().TrimTo(25);
|
||||||
var usesString = $"{inv.Uses} / {(inv.MaxUses == 0 ? "∞" : inv.MaxUses?.ToString())}";
|
var usesString = $"{inv.Uses} / {(inv.MaxUses == 0 ? "∞" : inv.MaxUses?.ToString())}";
|
||||||
|
|
||||||
|
@@ -782,13 +782,15 @@ public sealed class PatronageService
|
|||||||
patron.ValidThru.AddDays(1).ToShortAndRelativeTimestampTag(),
|
patron.ValidThru.AddDays(1).ToShortAndRelativeTimestampTag(),
|
||||||
true)
|
true)
|
||||||
.AddField("Instructions",
|
.AddField("Instructions",
|
||||||
@"*- Within the next **1-2 minutes** you will have all of the benefits of the Tier you've subscribed to.*
|
"""
|
||||||
*- You can check your benefits on <https://www.patreon.com/join/nadekobot>*
|
*- Within the next **1-2 minutes** you will have all of the benefits of the Tier you've subscribed to.*
|
||||||
*- You can use the `.patron` command in this chat to check your current quota usage for the Patron-only commands*
|
*- You can check your benefits on <https://www.patreon.com/join/nadekobot>*
|
||||||
*- **ALL** of the servers that you **own** will enjoy your Patron benefits.*
|
*- You can use the `.patron` command in this chat to check your current quota usage for the Patron-only commands*
|
||||||
*- You can use any of the commands available in your tier on any server (assuming you have sufficient permissions to run those commands)*
|
*- **ALL** of the servers that you **own** will enjoy your Patron benefits.*
|
||||||
*- Any user in any of your servers can use Patron-only commands, but they will spend **your quota**, which is why it's recommended to use Nadeko's command cooldown system (.h .cmdcd) or permission system to limit the command usage for your server members.*
|
*- You can use any of the commands available in your tier on any server (assuming you have sufficient permissions to run those commands)*
|
||||||
*- Permission guide can be found here if you're not familiar with it: <https://nadekobot.readthedocs.io/en/latest/permissions-system/>*",
|
*- Any user in any of your servers can use Patron-only commands, but they will spend **your quota**, which is why it's recommended to use Nadeko's command cooldown system (.h .cmdcd) or permission system to limit the command usage for your server members.*
|
||||||
|
*- Permission guide can be found here if you're not familiar with it: <https://nadekobot.readthedocs.io/en/latest/permissions-system/>*
|
||||||
|
""",
|
||||||
isInline: false)
|
isInline: false)
|
||||||
.WithFooter($"platform id: {patron.UniquePlatformUserId}");
|
.WithFooter($"platform id: {patron.UniquePlatformUserId}");
|
||||||
|
|
||||||
|
@@ -13,12 +13,14 @@ public partial class Utility
|
|||||||
public partial class QuoteCommands : NadekoModule
|
public partial class QuoteCommands : NadekoModule
|
||||||
{
|
{
|
||||||
private const string PREPEND_EXPORT =
|
private const string PREPEND_EXPORT =
|
||||||
@"# Keys are keywords, Each key has a LIST of quotes in the following format:
|
"""
|
||||||
# - id: Alphanumeric id used for commands related to the quote. (Note, when using .quotesimport, a new id will be generated.)
|
# Keys are keywords, Each key has a LIST of quotes in the following format:
|
||||||
# an: Author name
|
# - id: Alphanumeric id used for commands related to the quote. (Note, when using .quotesimport, a new id will be generated.)
|
||||||
# aid: Author id
|
# an: Author name
|
||||||
# txt: Quote text
|
# aid: Author id
|
||||||
";
|
# txt: Quote text
|
||||||
|
|
||||||
|
""";
|
||||||
|
|
||||||
private static readonly ISerializer _exportSerializer = new SerializerBuilder()
|
private static readonly ISerializer _exportSerializer = new SerializerBuilder()
|
||||||
.WithEventEmitter(args
|
.WithEventEmitter(args
|
||||||
|
@@ -9,58 +9,68 @@ namespace NadekoBot.Modules.Xp;
|
|||||||
[Cloneable]
|
[Cloneable]
|
||||||
public sealed partial class XpConfig : ICloneable<XpConfig>
|
public sealed partial class XpConfig : ICloneable<XpConfig>
|
||||||
{
|
{
|
||||||
[Comment(@"DO NOT CHANGE")]
|
[Comment("""DO NOT CHANGE""")]
|
||||||
public int Version { get; set; } = 5;
|
public int Version { get; set; } = 5;
|
||||||
|
|
||||||
[Comment(@"How much XP will the users receive per message")]
|
[Comment("""How much XP will the users receive per message""")]
|
||||||
public int XpPerMessage { get; set; } = 3;
|
public int XpPerMessage { get; set; } = 3;
|
||||||
|
|
||||||
[Comment(@"How often can the users receive XP in minutes")]
|
[Comment("""How often can the users receive XP in minutes""")]
|
||||||
public int MessageXpCooldown { get; set; } = 5;
|
public int MessageXpCooldown { get; set; } = 5;
|
||||||
|
|
||||||
[Comment(@"Amount of xp users gain from posting an image")]
|
[Comment("""Amount of xp users gain from posting an image""")]
|
||||||
public int XpFromImage { get; set; } = 0;
|
public int XpFromImage { get; set; } = 0;
|
||||||
|
|
||||||
[Comment(@"Average amount of xp earned per minute in VC")]
|
[Comment("""Average amount of xp earned per minute in VC""")]
|
||||||
public double VoiceXpPerMinute { get; set; } = 0;
|
public double VoiceXpPerMinute { get; set; } = 0;
|
||||||
|
|
||||||
[Comment(@"The maximum amount of minutes the bot will keep track of a user in a voice channel")]
|
[Comment("""The maximum amount of minutes the bot will keep track of a user in a voice channel""")]
|
||||||
public int VoiceMaxMinutes { get; set; } = 720;
|
public int VoiceMaxMinutes { get; set; } = 720;
|
||||||
|
|
||||||
[Comment(@"The amount of currency users will receive for each point of global xp that they earn")]
|
[Comment("""The amount of currency users will receive for each point of global xp that they earn""")]
|
||||||
public float CurrencyPerXp { get; set; } = 0;
|
public float CurrencyPerXp { get; set; } = 0;
|
||||||
|
|
||||||
[Comment(@"Xp Shop config")]
|
[Comment("""Xp Shop config""")]
|
||||||
public ShopConfig Shop { get; set; } = new();
|
public ShopConfig Shop { get; set; } = new();
|
||||||
|
|
||||||
public sealed class ShopConfig
|
public sealed class ShopConfig
|
||||||
{
|
{
|
||||||
[Comment(@"Whether the xp shop is enabled
|
[Comment("""
|
||||||
True -> Users can access the xp shop using .xpshop command
|
Whether the xp shop is enabled
|
||||||
False -> Users can't access the xp shop")]
|
True -> Users can access the xp shop using .xpshop command
|
||||||
|
False -> Users can't access the xp shop
|
||||||
|
""")]
|
||||||
public bool IsEnabled { get; set; } = false;
|
public bool IsEnabled { get; set; } = false;
|
||||||
|
|
||||||
[Comment(@"Which patron tier do users need in order to use the .xpshop bgs command
|
[Comment("""
|
||||||
Leave at 'None' if patron system is disabled or you don't want any restrictions")]
|
Which patron tier do users need in order to use the .xpshop bgs command
|
||||||
|
Leave at 'None' if patron system is disabled or you don't want any restrictions
|
||||||
|
""")]
|
||||||
public PatronTier BgsTierRequirement { get; set; } = PatronTier.None;
|
public PatronTier BgsTierRequirement { get; set; } = PatronTier.None;
|
||||||
|
|
||||||
[Comment(@"Which patron tier do users need in order to use the .xpshop frames command
|
[Comment("""
|
||||||
Leave at 'None' if patron system is disabled or you don't want any restrictions")]
|
Which patron tier do users need in order to use the .xpshop frames command
|
||||||
|
Leave at 'None' if patron system is disabled or you don't want any restrictions
|
||||||
|
""")]
|
||||||
public PatronTier FramesTierRequirement { get; set; } = PatronTier.None;
|
public PatronTier FramesTierRequirement { get; set; } = PatronTier.None;
|
||||||
|
|
||||||
[Comment(@"Frames available for sale. Keys are unique IDs.
|
[Comment("""
|
||||||
Do not change keys as they are not publicly visible. Only change properties (name, price, id)
|
Frames available for sale. Keys are unique IDs.
|
||||||
Removing a key which previously existed means that all previous purchases will also be unusable.
|
Do not change keys as they are not publicly visible. Only change properties (name, price, id)
|
||||||
To remove an item from the shop, but keep previous purchases, set the price to -1")]
|
Removing a key which previously existed means that all previous purchases will also be unusable.
|
||||||
|
To remove an item from the shop, but keep previous purchases, set the price to -1
|
||||||
|
""")]
|
||||||
public Dictionary<string, ShopItemInfo>? Frames { get; set; } = new()
|
public Dictionary<string, ShopItemInfo>? Frames { get; set; } = new()
|
||||||
{
|
{
|
||||||
{"default", new() {Name = "No frame", Price = 0, Url = string.Empty}}
|
{"default", new() {Name = "No frame", Price = 0, Url = string.Empty}}
|
||||||
};
|
};
|
||||||
|
|
||||||
[Comment(@"Backgrounds available for sale. Keys are unique IDs.
|
[Comment("""
|
||||||
Do not change keys as they are not publicly visible. Only change properties (name, price, id)
|
Backgrounds available for sale. Keys are unique IDs.
|
||||||
Removing a key which previously existed means that all previous purchases will also be unusable.
|
Do not change keys as they are not publicly visible. Only change properties (name, price, id)
|
||||||
To remove an item from the shop, but keep previous purchases, set the price to -1")]
|
Removing a key which previously existed means that all previous purchases will also be unusable.
|
||||||
|
To remove an item from the shop, but keep previous purchases, set the price to -1
|
||||||
|
""")]
|
||||||
public Dictionary<string, ShopItemInfo>? Bgs { get; set; } = new()
|
public Dictionary<string, ShopItemInfo>? Bgs { get; set; } = new()
|
||||||
{
|
{
|
||||||
{"default", new() {Name = "Default Background", Price = 0, Url = string.Empty}}
|
{"default", new() {Name = "Default Background", Price = 0, Url = string.Empty}}
|
||||||
@@ -69,19 +79,19 @@ To remove an item from the shop, but keep previous purchases, set the price to -
|
|||||||
|
|
||||||
public sealed class ShopItemInfo
|
public sealed class ShopItemInfo
|
||||||
{
|
{
|
||||||
[Comment(@"Visible name of the item")]
|
[Comment("""Visible name of the item""")]
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
[Comment(@"Price of the item. Set to -1 if you no longer want to sell the item but want the users to be able to keep their old purchase")]
|
[Comment("""Price of the item. Set to -1 if you no longer want to sell the item but want the users to be able to keep their old purchase""")]
|
||||||
public int Price { get; set; }
|
public int Price { get; set; }
|
||||||
|
|
||||||
[Comment(@"Direct url to the .png image which will be applied to the user's XP card")]
|
[Comment("""Direct url to the .png image which will be applied to the user's XP card""")]
|
||||||
public string Url { get; set; }
|
public string Url { get; set; }
|
||||||
|
|
||||||
[Comment(@"Optional preview url which will show instead of the real URL in the shop ")]
|
[Comment("""Optional preview url which will show instead of the real URL in the shop """)]
|
||||||
public string Preview { get; set; }
|
public string Preview { get; set; }
|
||||||
|
|
||||||
[Comment(@"Optional description of the item")]
|
[Comment("""Optional description of the item""")]
|
||||||
public string Desc { get; set; }
|
public string Desc { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -43,7 +43,7 @@ public partial class Xp
|
|||||||
.OrderBy(x => x.Level)
|
.OrderBy(x => x.Level)
|
||||||
.Select(x =>
|
.Select(x =>
|
||||||
{
|
{
|
||||||
var sign = !x.Remove ? @"✅ " : @"❌ ";
|
var sign = !x.Remove ? "✅ " : "❌ ";
|
||||||
|
|
||||||
var str = ctx.Guild.GetRole(x.RoleId)?.ToString();
|
var str = ctx.Guild.GetRole(x.RoleId)?.ToString();
|
||||||
|
|
||||||
|
@@ -147,11 +147,13 @@ public class CommandHandler : INService, IReadyExecutor
|
|||||||
{
|
{
|
||||||
if (_bss.Data.ConsoleOutputType == ConsoleOutputType.Normal)
|
if (_bss.Data.ConsoleOutputType == ConsoleOutputType.Normal)
|
||||||
{
|
{
|
||||||
Log.Information(@"Command Executed after {ExecTime}s
|
Log.Information("""
|
||||||
User: {User}
|
Command Executed after {ExecTime}s
|
||||||
Server: {Server}
|
User: {User}
|
||||||
Channel: {Channel}
|
Server: {Server}
|
||||||
Message: {Message}",
|
Channel: {Channel}
|
||||||
|
Message: {Message}
|
||||||
|
""",
|
||||||
string.Join("/", execPoints.Select(x => (x * ONE_THOUSANDTH).ToString("F3"))),
|
string.Join("/", execPoints.Select(x => (x * ONE_THOUSANDTH).ToString("F3"))),
|
||||||
usrMsg.Author + " [" + usrMsg.Author.Id + "]",
|
usrMsg.Author + " [" + usrMsg.Author.Id + "]",
|
||||||
channel is null ? "PRIVATE" : channel.Guild.Name + " [" + channel.Guild.Id + "]",
|
channel is null ? "PRIVATE" : channel.Guild.Name + " [" + channel.Guild.Id + "]",
|
||||||
@@ -178,12 +180,14 @@ public class CommandHandler : INService, IReadyExecutor
|
|||||||
{
|
{
|
||||||
if (_bss.Data.ConsoleOutputType == ConsoleOutputType.Normal)
|
if (_bss.Data.ConsoleOutputType == ConsoleOutputType.Normal)
|
||||||
{
|
{
|
||||||
Log.Warning(@"Command Errored after {ExecTime}s
|
Log.Warning("""
|
||||||
User: {User}
|
Command Errored after {ExecTime}s
|
||||||
Server: {Guild}
|
User: {User}
|
||||||
Channel: {Channel}
|
Server: {Guild}
|
||||||
Message: {Message}
|
Channel: {Channel}
|
||||||
Error: {ErrorMessage}",
|
Message: {Message}
|
||||||
|
Error: {ErrorMessage}
|
||||||
|
""",
|
||||||
string.Join("/", execPoints.Select(x => (x * ONE_THOUSANDTH).ToString("F3"))),
|
string.Join("/", execPoints.Select(x => (x * ONE_THOUSANDTH).ToString("F3"))),
|
||||||
usrMsg.Author + " [" + usrMsg.Author.Id + "]",
|
usrMsg.Author + " [" + usrMsg.Author.Id + "]",
|
||||||
channel is null ? "DM" : channel.Guild.Name + " [" + channel.Guild.Id + "]",
|
channel is null ? "DM" : channel.Guild.Name + " [" + channel.Guild.Id + "]",
|
||||||
@@ -193,8 +197,10 @@ public class CommandHandler : INService, IReadyExecutor
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log.Warning(@"Err | g:{GuildId} | c: {ChannelId} | u: {UserId} | msg: {Message}
|
Log.Warning("""
|
||||||
Err: {ErrorMessage}",
|
Err | g:{GuildId} | c: {ChannelId} | u: {UserId} | msg: {Message}
|
||||||
|
Err: {ErrorMessage}
|
||||||
|
""",
|
||||||
channel?.Guild.Id.ToString() ?? "-",
|
channel?.Guild.Id.ToString() ?? "-",
|
||||||
channel?.Id.ToString() ?? "-",
|
channel?.Id.ToString() ?? "-",
|
||||||
usrMsg.Author.Id,
|
usrMsg.Author.Id,
|
||||||
|
@@ -13,7 +13,7 @@ namespace NadekoBot.Services;
|
|||||||
public sealed partial class GoogleApiService : IGoogleApiService, INService
|
public sealed partial class GoogleApiService : IGoogleApiService, INService
|
||||||
{
|
{
|
||||||
private static readonly Regex
|
private static readonly Regex
|
||||||
_plRegex = new("(?:youtu\\.be\\/|list=)(?<id>[\\da-zA-Z\\-_]*)", RegexOptions.Compiled);
|
_plRegex = new(@"(?:youtu\.be\/|list=)(?<id>[\da-zA-Z\-_]*)", RegexOptions.Compiled);
|
||||||
|
|
||||||
|
|
||||||
private readonly YouTubeService _yt;
|
private readonly YouTubeService _yt;
|
||||||
|
@@ -2,140 +2,142 @@
|
|||||||
|
|
||||||
public sealed partial class GoogleApiService
|
public sealed partial class GoogleApiService
|
||||||
{
|
{
|
||||||
private const string SUPPORTED = @"afrikaans af
|
private const string SUPPORTED = """
|
||||||
albanian sq
|
afrikaans af
|
||||||
amharic am
|
albanian sq
|
||||||
arabic ar
|
amharic am
|
||||||
armenian hy
|
arabic ar
|
||||||
assamese as
|
armenian hy
|
||||||
aymara ay
|
assamese as
|
||||||
azerbaijani az
|
aymara ay
|
||||||
bambara bm
|
azerbaijani az
|
||||||
basque eu
|
bambara bm
|
||||||
belarusian be
|
basque eu
|
||||||
bengali bn
|
belarusian be
|
||||||
bhojpuri bho
|
bengali bn
|
||||||
bosnian bs
|
bhojpuri bho
|
||||||
bulgarian bg
|
bosnian bs
|
||||||
catalan ca
|
bulgarian bg
|
||||||
cebuano ceb
|
catalan ca
|
||||||
chinese zh-CN
|
cebuano ceb
|
||||||
chinese-trad zh-TW
|
chinese zh-CN
|
||||||
corsican co
|
chinese-trad zh-TW
|
||||||
croatian hr
|
corsican co
|
||||||
czech cs
|
croatian hr
|
||||||
danish da
|
czech cs
|
||||||
dhivehi dv
|
danish da
|
||||||
dogri doi
|
dhivehi dv
|
||||||
dutch nl
|
dogri doi
|
||||||
english en
|
dutch nl
|
||||||
esperanto eo
|
english en
|
||||||
estonian et
|
esperanto eo
|
||||||
ewe ee
|
estonian et
|
||||||
filipino fil
|
ewe ee
|
||||||
finnish fi
|
filipino fil
|
||||||
french fr
|
finnish fi
|
||||||
frisian fy
|
french fr
|
||||||
galician gl
|
frisian fy
|
||||||
georgian ka
|
galician gl
|
||||||
german de
|
georgian ka
|
||||||
greek el
|
german de
|
||||||
guarani gn
|
greek el
|
||||||
gujarati gu
|
guarani gn
|
||||||
haitian ht
|
gujarati gu
|
||||||
hausa ha
|
haitian ht
|
||||||
hawaiian haw
|
hausa ha
|
||||||
hebrew he
|
hawaiian haw
|
||||||
hindi hi
|
hebrew he
|
||||||
hmong hmn
|
hindi hi
|
||||||
hungarian hu
|
hmong hmn
|
||||||
icelandic is
|
hungarian hu
|
||||||
igbo ig
|
icelandic is
|
||||||
ilocano ilo
|
igbo ig
|
||||||
indonesian id
|
ilocano ilo
|
||||||
irish ga
|
indonesian id
|
||||||
italian it
|
irish ga
|
||||||
japanese ja
|
italian it
|
||||||
javanese jv
|
japanese ja
|
||||||
kannada kn
|
javanese jv
|
||||||
kazakh kk
|
kannada kn
|
||||||
khmer km
|
kazakh kk
|
||||||
kinyarwanda rw
|
khmer km
|
||||||
konkani gom
|
kinyarwanda rw
|
||||||
korean ko
|
konkani gom
|
||||||
krio kri
|
korean ko
|
||||||
kurdish ku
|
krio kri
|
||||||
kurdish-sor ckb
|
kurdish ku
|
||||||
kyrgyz ky
|
kurdish-sor ckb
|
||||||
lao lo
|
kyrgyz ky
|
||||||
latin la
|
lao lo
|
||||||
latvian lv
|
latin la
|
||||||
lingala ln
|
latvian lv
|
||||||
lithuanian lt
|
lingala ln
|
||||||
luganda lg
|
lithuanian lt
|
||||||
luxembourgish lb
|
luganda lg
|
||||||
macedonian mk
|
luxembourgish lb
|
||||||
maithili mai
|
macedonian mk
|
||||||
malagasy mg
|
maithili mai
|
||||||
malay ms
|
malagasy mg
|
||||||
malayalam ml
|
malay ms
|
||||||
maltese mt
|
malayalam ml
|
||||||
maori mi
|
maltese mt
|
||||||
marathi mr
|
maori mi
|
||||||
meiteilon mni-Mtei
|
marathi mr
|
||||||
mizo lus
|
meiteilon mni-Mtei
|
||||||
mongolian mn
|
mizo lus
|
||||||
myanmar my
|
mongolian mn
|
||||||
nepali ne
|
myanmar my
|
||||||
norwegian no
|
nepali ne
|
||||||
nyanja ny
|
norwegian no
|
||||||
odia or
|
nyanja ny
|
||||||
oromo om
|
odia or
|
||||||
pashto ps
|
oromo om
|
||||||
persian fa
|
pashto ps
|
||||||
polish pl
|
persian fa
|
||||||
portuguese pt
|
polish pl
|
||||||
punjabi pa
|
portuguese pt
|
||||||
quechua qu
|
punjabi pa
|
||||||
romanian ro
|
quechua qu
|
||||||
russian ru
|
romanian ro
|
||||||
samoan sm
|
russian ru
|
||||||
sanskrit sa
|
samoan sm
|
||||||
scots gd
|
sanskrit sa
|
||||||
sepedi nso
|
scots gd
|
||||||
serbian sr
|
sepedi nso
|
||||||
sesotho st
|
serbian sr
|
||||||
shona sn
|
sesotho st
|
||||||
sindhi sd
|
shona sn
|
||||||
sinhala si
|
sindhi sd
|
||||||
slovak sk
|
sinhala si
|
||||||
slovenian sl
|
slovak sk
|
||||||
somali so
|
slovenian sl
|
||||||
spanish es
|
somali so
|
||||||
sundanese su
|
spanish es
|
||||||
swahili sw
|
sundanese su
|
||||||
swedish sv
|
swahili sw
|
||||||
tagalog tl
|
swedish sv
|
||||||
tajik tg
|
tagalog tl
|
||||||
tamil ta
|
tajik tg
|
||||||
tatar tt
|
tamil ta
|
||||||
telugu te
|
tatar tt
|
||||||
thai th
|
telugu te
|
||||||
tigrinya ti
|
thai th
|
||||||
tsonga ts
|
tigrinya ti
|
||||||
turkish tr
|
tsonga ts
|
||||||
turkmen tk
|
turkish tr
|
||||||
twi ak
|
turkmen tk
|
||||||
ukrainian uk
|
twi ak
|
||||||
urdu ur
|
ukrainian uk
|
||||||
uyghur ug
|
urdu ur
|
||||||
uzbek uz
|
uyghur ug
|
||||||
vietnamese vi
|
uzbek uz
|
||||||
welsh cy
|
vietnamese vi
|
||||||
xhosa xh
|
welsh cy
|
||||||
yiddish yi
|
xhosa xh
|
||||||
yoruba yo
|
yiddish yi
|
||||||
zulu zu";
|
yoruba yo
|
||||||
|
zulu zu
|
||||||
|
""";
|
||||||
|
|
||||||
|
|
||||||
public IReadOnlyDictionary<string, string> Languages { get; }
|
public IReadOnlyDictionary<string, string> Languages { get; }
|
||||||
|
Reference in New Issue
Block a user