mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-10 09:18: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 } })
|
||||
{
|
||||
Log.Error(@"
|
||||
Login failed.
|
||||
|
||||
*** Please enable privileged 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.
|
||||
|
||||
How to enable privileged intents:
|
||||
1. Head over to the Discord Developer Portal https://discord.com/developers/applications/
|
||||
2. Select your Application.
|
||||
3. Click on `Bot` in the left side navigation panel, and scroll down to the intents section.
|
||||
4. Enable all intents.
|
||||
5. Restart your bot.
|
||||
|
||||
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.
|
||||
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");
|
||||
Log.Error("""
|
||||
Login failed.
|
||||
|
||||
*** Please enable privileged 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.
|
||||
|
||||
How to enable privileged intents:
|
||||
1. Head over to the Discord Developer Portal https://discord.com/developers/applications/
|
||||
2. Select your Application.
|
||||
3. Click on `Bot` in the left side navigation panel, and scroll down to the intents section.
|
||||
4. Enable all intents.
|
||||
5. Restart your bot.
|
||||
|
||||
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.
|
||||
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
|
||||
""");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
|
@@ -11,74 +11,89 @@ namespace NadekoBot.Common.Configs;
|
||||
[Cloneable]
|
||||
public sealed partial class BotConfig : ICloneable<BotConfig>
|
||||
{
|
||||
[Comment(@"DO NOT CHANGE")]
|
||||
[Comment("""DO NOT CHANGE""")]
|
||||
public int Version { get; set; } = 5;
|
||||
|
||||
[Comment(@"Most commands, when executed, have a small colored line
|
||||
next to the response. The color depends whether the command
|
||||
is completed, errored or in progress (pending)
|
||||
Color settings below are for the color of those lines.
|
||||
To get color's hex, you can go here https://htmlcolorcodes.com/
|
||||
and copy the hex code fo your selected color (marked as #)")]
|
||||
[Comment("""
|
||||
Most commands, when executed, have a small colored line
|
||||
next to the response. The color depends whether the command
|
||||
is completed, errored or in progress (pending)
|
||||
Color settings below are for the color of those lines.
|
||||
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; }
|
||||
|
||||
[Comment("Default bot language. It has to be in the list of supported languages (.langli)")]
|
||||
public CultureInfo DefaultLocale { get; set; }
|
||||
|
||||
[Comment(@"Style in which executed commands will show up in the console.
|
||||
Allowed values: Simple, Normal, None")]
|
||||
[Comment("""
|
||||
Style in which executed commands will show up in the console.
|
||||
Allowed values: Simple, Normal, None
|
||||
""")]
|
||||
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;
|
||||
|
||||
[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; }
|
||||
|
||||
[Comment(
|
||||
@"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)")]
|
||||
[Comment("""
|
||||
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)
|
||||
""")]
|
||||
public bool ForwardToAllOwners { get; set; }
|
||||
|
||||
[Comment(@"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")]
|
||||
[Comment("""
|
||||
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; }
|
||||
|
||||
[Comment(@"When a user DMs the bot with a message which is not a command
|
||||
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")]
|
||||
[Comment("""
|
||||
When a user DMs the bot with a message which is not a command
|
||||
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)]
|
||||
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.
|
||||
Case insensitive.
|
||||
Leave empty to reply with DmHelpText to every DM.")]
|
||||
[Comment("""
|
||||
Only users who send a DM to the bot containing one of the specified words will get a DmHelpText response.
|
||||
Case insensitive.
|
||||
Leave empty to reply with DmHelpText to every DM.
|
||||
""")]
|
||||
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)]
|
||||
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; }
|
||||
|
||||
[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; }
|
||||
|
||||
[Comment(@"Toggles whether your bot will group greet/bye messages into a single message every 5 seconds.
|
||||
1st user who joins will get greeted immediately
|
||||
If more users join within the next 5 seconds, they will be greeted in groups of 5.
|
||||
This will cause %user.mention% and other placeholders to be replaced with multiple users.
|
||||
Keep in mind this might break some of your embeds - for example if you have %user.avatar% in the thumbnail,
|
||||
it will become invalid, as it will resolve to a list of avatars of grouped users.
|
||||
note: This setting is primarily used if you're afraid of raids, or you're running medium/large bots where some
|
||||
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.")]
|
||||
[Comment("""
|
||||
Toggles whether your bot will group greet/bye messages into a single message every 5 seconds.
|
||||
1st user who joins will get greeted immediately
|
||||
If more users join within the next 5 seconds, they will be greeted in groups of 5.
|
||||
This will cause %user.mention% and other placeholders to be replaced with multiple users.
|
||||
Keep in mind this might break some of your embeds - for example if you have %user.avatar% in the thumbnail,
|
||||
it will become invalid, as it will resolve to a list of avatars of grouped users.
|
||||
note: This setting is primarily used if you're afraid of raids, or you're running medium/large bots where some
|
||||
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; }
|
||||
|
||||
[Comment(@"Whether the bot will rotate through all specified statuses.
|
||||
This setting can be changed via .ropl command.
|
||||
See RotatingStatuses submodule in Administration.")]
|
||||
[Comment("""
|
||||
Whether the bot will rotate through all specified statuses.
|
||||
This setting can be changed via .ropl command.
|
||||
See RotatingStatuses submodule in Administration.
|
||||
""")]
|
||||
public bool RotateStatuses { get; set; }
|
||||
|
||||
public BotConfig()
|
||||
@@ -89,32 +104,34 @@ See RotatingStatuses submodule in Administration.")]
|
||||
ConsoleOutputType = ConsoleOutputType.Normal;
|
||||
ForwardMessages = false;
|
||||
ForwardToAllOwners = false;
|
||||
DmHelpText = @"{""description"": ""Type `%prefix%h` for help.""}";
|
||||
HelpText = @"{
|
||||
""title"": ""To invite me to your server, use this link"",
|
||||
""description"": ""https://discordapp.com/oauth2/authorize?client_id={0}&scope=bot&permissions=66186303"",
|
||||
""color"": 53380,
|
||||
""thumbnail"": ""https://i.imgur.com/nKYyqMK.png"",
|
||||
""fields"": [
|
||||
{
|
||||
""name"": ""Useful help commands"",
|
||||
""value"": ""`%bot.prefix%modules` Lists all bot modules.
|
||||
`%prefix%h CommandName` Shows some help about a specific command.
|
||||
`%prefix%commands ModuleName` Lists all commands in a module."",
|
||||
""inline"": false
|
||||
},
|
||||
{
|
||||
""name"": ""List of all Commands"",
|
||||
""value"": ""https://nadeko.bot/commands"",
|
||||
""inline"": false
|
||||
},
|
||||
{
|
||||
""name"": ""Nadeko Support Server"",
|
||||
""value"": ""https://discord.nadeko.bot/ "",
|
||||
""inline"": true
|
||||
}
|
||||
]
|
||||
}";
|
||||
DmHelpText = """{"description": "Type `%prefix%h` for help."}""";
|
||||
HelpText = """
|
||||
{
|
||||
"title": "To invite me to your server, use this link",
|
||||
"description": "https://discordapp.com/oauth2/authorize?client_id={0}&scope=bot&permissions=66186303",
|
||||
"color": 53380,
|
||||
"thumbnail": "https://i.imgur.com/nKYyqMK.png",
|
||||
"fields": [
|
||||
{
|
||||
"name": "Useful help commands",
|
||||
"value": "`%bot.prefix%modules` Lists all bot modules.
|
||||
`%prefix%h CommandName` Shows some help about a specific command.
|
||||
`%prefix%commands ModuleName` Lists all commands in a module.",
|
||||
"inline": false
|
||||
},
|
||||
{
|
||||
"name": "List of all Commands",
|
||||
"value": "https://nadeko.bot/commands",
|
||||
"inline": false
|
||||
},
|
||||
{
|
||||
"name": "Nadeko Support Server",
|
||||
"value": "https://discord.nadeko.bot/ ",
|
||||
"inline": true
|
||||
}
|
||||
]
|
||||
}
|
||||
""";
|
||||
var blocked = new BlockedConfig();
|
||||
Blocked = blocked;
|
||||
Prefix = ".";
|
||||
@@ -160,13 +177,13 @@ public sealed partial class BlockedConfig
|
||||
[Cloneable]
|
||||
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; }
|
||||
|
||||
[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; }
|
||||
|
||||
[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 ColorConfig()
|
||||
|
@@ -5,115 +5,141 @@ namespace NadekoBot.Common;
|
||||
|
||||
public sealed class Creds : IBotCredentials
|
||||
{
|
||||
[Comment(@"DO NOT CHANGE")]
|
||||
[Comment("""DO NOT CHANGE""")]
|
||||
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; }
|
||||
|
||||
[Comment(@"List of Ids of the users who have bot owner permissions
|
||||
**DO NOT ADD PEOPLE YOU DON'T TRUST**")]
|
||||
[Comment("""
|
||||
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; }
|
||||
|
||||
[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; }
|
||||
|
||||
[Comment(@"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.")]
|
||||
[Comment("""
|
||||
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.
|
||||
""")]
|
||||
public int TotalShards { get; set; }
|
||||
|
||||
[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.
|
||||
Used only for Youtube Data Api (at the moment).")]
|
||||
"""
|
||||
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.
|
||||
Used only for Youtube Data Api (at the moment).
|
||||
""")]
|
||||
public string GoogleApiKey { get; set; }
|
||||
|
||||
[Comment(
|
||||
@"Create a new custom search here https://programmablesearchengine.google.com/cse/create/new
|
||||
Enable SafeSearch
|
||||
Remove all Sites to Search
|
||||
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")]
|
||||
"""
|
||||
Create a new custom search here https://programmablesearchengine.google.com/cse/create/new
|
||||
Enable SafeSearch
|
||||
Remove all Sites to Search
|
||||
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
|
||||
""")]
|
||||
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; }
|
||||
|
||||
[Comment(@"Patreon auto reward system settings.
|
||||
go to https://www.patreon.com/portal -> my clients -> create client")]
|
||||
[Comment("""
|
||||
Patreon auto reward system settings.
|
||||
go to https://www.patreon.com/portal -> my clients -> create client
|
||||
""")]
|
||||
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; }
|
||||
|
||||
[Comment(@"Official cleverbot api key.")]
|
||||
[Comment("""Official cleverbot api key.""")]
|
||||
public string CleverbotApiKey { get; set; }
|
||||
|
||||
[Comment(@"Which cache implementation should bot use.
|
||||
'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")]
|
||||
[Comment("""
|
||||
Which cache implementation should bot use.
|
||||
'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; }
|
||||
|
||||
[Comment(@"Redis connection string. Don't change if you don't know what you're doing.
|
||||
Only used if botCache is set to 'redis'")]
|
||||
[Comment("""
|
||||
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; }
|
||||
|
||||
[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; }
|
||||
|
||||
[Comment(@"Address and port of the coordinator endpoint. Leave empty for default.
|
||||
Change only if you've changed the coordinator address or port.")]
|
||||
[Comment("""
|
||||
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; }
|
||||
|
||||
[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; }
|
||||
|
||||
[Comment(@"https://locationiq.com api key (register and you will receive the token in the email).
|
||||
Used only for .time command.")]
|
||||
[Comment("""
|
||||
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; }
|
||||
|
||||
[Comment(@"https://timezonedb.com api key (register and you will receive the token in the email).
|
||||
Used only for .time command")]
|
||||
[Comment("""
|
||||
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; }
|
||||
|
||||
[Comment(@"https://pro.coinmarketcap.com/account/ api key. There is a free plan for personal use.
|
||||
Used for cryptocurrency related commands.")]
|
||||
[Comment("""
|
||||
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; }
|
||||
|
||||
// [Comment(@"https://polygon.io/dashboard/api-keys api key. Free plan allows for 5 queries per minute.
|
||||
// Used for stocks related commands.")]
|
||||
// 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; }
|
||||
|
||||
[Comment(@"Optional Trovo client id.
|
||||
You should use this if Trovo stream notifications stopped working or you're getting ratelimit errors.")]
|
||||
[Comment("""
|
||||
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; }
|
||||
|
||||
[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; }
|
||||
|
||||
[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; }
|
||||
|
||||
[Comment(@"Command and args which will be used to restart the bot.
|
||||
Only used if bot is executed directly (NOT through the coordinator)
|
||||
placeholders:
|
||||
{0} -> shard id
|
||||
{1} -> total shards
|
||||
Linux default
|
||||
cmd: dotnet
|
||||
args: ""NadekoBot.dll -- {0}""
|
||||
Windows default
|
||||
cmd: NadekoBot.exe
|
||||
args: ""{0}""")]
|
||||
[Comment("""
|
||||
Command and args which will be used to restart the bot.
|
||||
Only used if bot is executed directly (NOT through the coordinator)
|
||||
placeholders:
|
||||
{0} -> shard id
|
||||
{1} -> total shards
|
||||
Linux default
|
||||
cmd: dotnet
|
||||
args: "NadekoBot.dll -- {0}"
|
||||
Windows default
|
||||
cmd: NadekoBot.exe
|
||||
args: "{0}"
|
||||
""")]
|
||||
public RestartConfig RestartCommand { get; set; }
|
||||
|
||||
public Creds()
|
||||
@@ -145,15 +171,19 @@ Windows default
|
||||
|
||||
public class DbOptions
|
||||
{
|
||||
[Comment(@"Database type. ""sqlite"", ""mysql"" and ""postgresql"" are supported.
|
||||
Default is ""sqlite""")]
|
||||
[Comment("""
|
||||
Database type. "sqlite", "mysql" and "postgresql" are supported.
|
||||
Default is "sqlite"
|
||||
""")]
|
||||
public string Type { get; set; }
|
||||
|
||||
[Comment(@"Database connection string.
|
||||
You MUST change this if you're not using ""sqlite"" type.
|
||||
Default is ""Data Source=data/NadekoBot.db""
|
||||
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;""")]
|
||||
[Comment("""
|
||||
Database connection string.
|
||||
You MUST change this if you're not using "sqlite" type.
|
||||
Default is "Data Source=data/NadekoBot.db"
|
||||
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; }
|
||||
}
|
||||
|
||||
@@ -165,7 +195,7 @@ Example for postgresql: ""Server=localhost;Port=5432;User Id=postgres;Password=m
|
||||
public string ClientSecret { get; set; }
|
||||
|
||||
[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 PatreonSettings(
|
||||
@@ -187,22 +217,30 @@ Example for postgresql: ""Server=localhost;Port=5432;User Id=postgres;Password=m
|
||||
|
||||
public sealed record VotesSettings
|
||||
{
|
||||
[Comment(@"top.gg votes service url
|
||||
This is the url of your instance of the NadekoBot.Votes api
|
||||
Example: https://votes.my.cool.bot.com")]
|
||||
[Comment("""
|
||||
top.gg votes service url
|
||||
This is the url of your instance of the NadekoBot.Votes api
|
||||
Example: https://votes.my.cool.bot.com
|
||||
""")]
|
||||
public string TopggServiceUrl { get; set; }
|
||||
|
||||
[Comment(@"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")]
|
||||
[Comment("""
|
||||
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; }
|
||||
|
||||
[Comment(@"discords.com votes service url
|
||||
This is the url of your instance of the NadekoBot.Votes api
|
||||
Example: https://votes.my.cool.bot.com")]
|
||||
[Comment("""
|
||||
discords.com votes service url
|
||||
This is the url of your instance of the NadekoBot.Votes api
|
||||
Example: https://votes.my.cool.bot.com
|
||||
""")]
|
||||
public string DiscordsServiceUrl { get; set; }
|
||||
|
||||
[Comment(@"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")]
|
||||
[Comment("""
|
||||
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 VotesSettings()
|
||||
|
@@ -7,10 +7,10 @@ namespace Nadeko.Medusa;
|
||||
[Cloneable]
|
||||
public sealed partial class MedusaConfig : ICloneable<MedusaConfig>
|
||||
{
|
||||
[Comment(@"DO NOT CHANGE")]
|
||||
[Comment("""DO NOT CHANGE""")]
|
||||
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 MedusaConfig()
|
||||
|
@@ -10,29 +10,35 @@ public static class MigrationQueries
|
||||
if (migrationBuilder.IsMySql())
|
||||
{
|
||||
migrationBuilder.Sql(
|
||||
@"INSERT IGNORE into reactionroles(guildid, channelid, messageid, emote, roleid, `group`, levelreq, dateadded)
|
||||
select guildid, channelid, messageid, emotename, roleid, exclusive, 0, reactionrolemessage.dateadded
|
||||
from reactionrole
|
||||
left join reactionrolemessage on reactionrolemessage.id = reactionrole.reactionrolemessageid
|
||||
left join guildconfigs on reactionrolemessage.guildconfigid = guildconfigs.id;");
|
||||
"""
|
||||
INSERT IGNORE into reactionroles(guildid, channelid, messageid, emote, roleid, `group`, levelreq, dateadded)
|
||||
select guildid, channelid, messageid, emotename, roleid, exclusive, 0, reactionrolemessage.dateadded
|
||||
from reactionrole
|
||||
left join reactionrolemessage on reactionrolemessage.id = reactionrole.reactionrolemessageid
|
||||
left join guildconfigs on reactionrolemessage.guildconfigid = guildconfigs.id;
|
||||
""");
|
||||
}
|
||||
else if (migrationBuilder.IsSqlite())
|
||||
{
|
||||
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
|
||||
from reactionrole
|
||||
left join reactionrolemessage on reactionrolemessage.id = reactionrole.reactionrolemessageid
|
||||
left join guildconfigs on reactionrolemessage.guildconfigid = guildconfigs.id;");
|
||||
"""
|
||||
insert or ignore into reactionroles(guildid, channelid, messageid, emote, roleid, 'group', levelreq, dateadded)
|
||||
select guildid, channelid, messageid, emotename, roleid, exclusive, 0, reactionrolemessage.dateadded
|
||||
from reactionrole
|
||||
left join reactionrolemessage on reactionrolemessage.id = reactionrole.reactionrolemessageid
|
||||
left join guildconfigs on reactionrolemessage.guildconfigid = guildconfigs.id;
|
||||
""");
|
||||
}
|
||||
else if (migrationBuilder.IsNpgsql())
|
||||
{
|
||||
migrationBuilder.Sql(@"insert into reactionroles(guildid, channelid, messageid, emote, roleid, ""group"", levelreq, dateadded)
|
||||
select guildid, channelid, messageid, emotename, roleid, exclusive::int, 0, reactionrolemessage.dateadded
|
||||
from reactionrole
|
||||
left join reactionrolemessage on reactionrolemessage.id = reactionrole.reactionrolemessageid
|
||||
left join guildconfigs on reactionrolemessage.guildconfigid = guildconfigs.id
|
||||
ON CONFLICT DO NOTHING;");
|
||||
migrationBuilder.Sql("""
|
||||
insert into reactionroles(guildid, channelid, messageid, emote, roleid, "group", levelreq, dateadded)
|
||||
select guildid, channelid, messageid, emotename, roleid, exclusive::int, 0, reactionrolemessage.dateadded
|
||||
from reactionrole
|
||||
left join reactionrolemessage on reactionrolemessage.id = reactionrole.reactionrolemessageid
|
||||
left join guildconfigs on reactionrolemessage.guildconfigid = guildconfigs.id
|
||||
ON CONFLICT DO NOTHING;
|
||||
""");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@@ -28,14 +28,16 @@ namespace NadekoBot.Migrations
|
||||
table: "NsfwBlacklistedTags",
|
||||
column: "GuildId");
|
||||
|
||||
migrationBuilder.Sql(@"INSERT INTO NsfwBlacklistedTags(Id, GuildId, Tag, DateAdded)
|
||||
SELECT
|
||||
Id,
|
||||
(SELECT GuildId From GuildConfigs WHERE Id=GuildConfigId),
|
||||
Tag,
|
||||
DateAdded
|
||||
FROM NsfwBlacklitedTag
|
||||
WHERE GuildConfigId in (SELECT Id from GuildConfigs);");
|
||||
migrationBuilder.Sql("""
|
||||
INSERT INTO NsfwBlacklistedTags(Id, GuildId, Tag, DateAdded)
|
||||
SELECT
|
||||
Id,
|
||||
(SELECT GuildId From GuildConfigs WHERE Id=GuildConfigId),
|
||||
Tag,
|
||||
DateAdded
|
||||
FROM NsfwBlacklitedTag
|
||||
WHERE GuildConfigId in (SELECT Id from GuildConfigs);
|
||||
""");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "NsfwBlacklitedTag");
|
||||
|
@@ -50,24 +50,30 @@ namespace NadekoBot.Migrations
|
||||
principalTable: "GuildConfigs",
|
||||
principalColumn: "Id");
|
||||
|
||||
migrationBuilder.Sql(@"UPDATE Permissions
|
||||
SET SecondaryTargetName='ACTUALEXPRESSIONS'
|
||||
WHERE SecondaryTargetName='ActualCustomReactions' COLLATE NOCASE;");
|
||||
migrationBuilder.Sql("""
|
||||
UPDATE Permissions
|
||||
SET SecondaryTargetName='ACTUALEXPRESSIONS'
|
||||
WHERE SecondaryTargetName='ActualCustomReactions' COLLATE NOCASE;
|
||||
""");
|
||||
|
||||
migrationBuilder.Sql(@"UPDATE Permissions
|
||||
SET SecondaryTargetName='EXPRESSIONS'
|
||||
WHERE SecondaryTargetName='CustomReactions' COLLATE NOCASE;");
|
||||
migrationBuilder.Sql("""
|
||||
UPDATE Permissions
|
||||
SET SecondaryTargetName='EXPRESSIONS'
|
||||
WHERE SecondaryTargetName='CustomReactions' COLLATE NOCASE;
|
||||
""");
|
||||
|
||||
migrationBuilder.Sql(@"UPDATE Permissions
|
||||
SET SecondaryTargetName= case lower(SecondaryTargetName)
|
||||
WHEN 'editcustreact' THEN 'expredit'
|
||||
WHEN 'delcustreact' THEN 'exprdel'
|
||||
WHEN 'listcustreact' THEN 'exprlist'
|
||||
WHEN 'addcustreact' THEN 'expradd'
|
||||
WHEN 'showcustreact' THEN 'exprshow'
|
||||
ELSE SecondaryTargetName
|
||||
END
|
||||
WHERE lower(SecondaryTargetName) in ('editcustreact', 'delcustreact', 'listcustreact', 'addcustreact', 'showcustreact');");
|
||||
migrationBuilder.Sql("""
|
||||
UPDATE Permissions
|
||||
SET SecondaryTargetName= case lower(SecondaryTargetName)
|
||||
WHEN 'editcustreact' THEN 'expredit'
|
||||
WHEN 'delcustreact' THEN 'exprdel'
|
||||
WHEN 'listcustreact' THEN 'exprlist'
|
||||
WHEN 'addcustreact' THEN 'expradd'
|
||||
WHEN 'showcustreact' THEN 'exprshow'
|
||||
ELSE SecondaryTargetName
|
||||
END
|
||||
WHERE lower(SecondaryTargetName) in ('editcustreact', 'delcustreact', 'listcustreact', 'addcustreact', 'showcustreact');
|
||||
""");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
|
@@ -42,13 +42,15 @@ namespace NadekoBot.Migrations
|
||||
table: "FilterWordsChannelId",
|
||||
column: "GuildConfigId");
|
||||
|
||||
migrationBuilder.Sql(@"INSERT INTO FilterWordsChannelId(Id, ChannelId, GuildConfigId, DateAdded)
|
||||
SELECT Id, ChannelId, GuildConfigId1, DateAdded
|
||||
FROM FilterChannelId
|
||||
WHERE GuildConfigId1 is not null;
|
||||
-- Remove them after moving them to a different table
|
||||
DELETE FROM FilterChannelId
|
||||
WHERE GuildConfigId is null;");
|
||||
migrationBuilder.Sql("""
|
||||
INSERT INTO FilterWordsChannelId(Id, ChannelId, GuildConfigId, DateAdded)
|
||||
SELECT Id, ChannelId, GuildConfigId1, DateAdded
|
||||
FROM FilterChannelId
|
||||
WHERE GuildConfigId1 is not null;
|
||||
-- Remove them after moving them to a different table
|
||||
DELETE FROM FilterChannelId
|
||||
WHERE GuildConfigId is null;
|
||||
""");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "GuildConfigId1",
|
||||
|
@@ -9,19 +9,21 @@ namespace NadekoBot.Migrations
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.Sql(@"UPDATE Clubs
|
||||
SET Name = Name || '#' || Discrim
|
||||
WHERE Discrim <> 1;
|
||||
|
||||
UPDATE Clubs as co
|
||||
SET Name =
|
||||
CASE (select count(*) from Clubs as ci where co.Name == ci.Name) = 1
|
||||
WHEN true
|
||||
THEN Name
|
||||
ELSE
|
||||
Name || '#' || Discrim
|
||||
END
|
||||
WHERE Discrim = 1;");
|
||||
migrationBuilder.Sql("""
|
||||
UPDATE Clubs
|
||||
SET Name = Name || '#' || Discrim
|
||||
WHERE Discrim <> 1;
|
||||
|
||||
UPDATE Clubs as co
|
||||
SET Name =
|
||||
CASE (select count(*) from Clubs as ci where co.Name == ci.Name) = 1
|
||||
WHEN true
|
||||
THEN Name
|
||||
ELSE
|
||||
Name || '#' || Discrim
|
||||
END
|
||||
WHERE Discrim = 1;
|
||||
""");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
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 PREPEND_EXPORT =
|
||||
@"# Keys are triggers, Each key has a LIST of expressions in the following format:
|
||||
# - res: Response string
|
||||
# id: Alphanumeric id used for commands related to the expression. (Note, when using .exprsimport, a new id will be generated.)
|
||||
# react:
|
||||
# - <List
|
||||
# - of
|
||||
# - reactions>
|
||||
# at: Whether expression allows targets (see .h .exprat)
|
||||
# ca: Whether expression expects trigger anywhere (see .h .exprca)
|
||||
# dm: Whether expression DMs the response (see .h .exprdm)
|
||||
# ad: Whether expression automatically deletes triggering message (see .h .exprad)
|
||||
"""
|
||||
# Keys are triggers, Each key has a LIST of expressions in the following format:
|
||||
# - res: Response string
|
||||
# id: Alphanumeric id used for commands related to the expression. (Note, when using .exprsimport, a new id will be generated.)
|
||||
# react:
|
||||
# - <List
|
||||
# - of
|
||||
# - reactions>
|
||||
# at: Whether expression allows targets (see .h .exprat)
|
||||
# ca: Whether expression expects trigger anywhere (see .h .exprca)
|
||||
# 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()
|
||||
.WithEventEmitter(args
|
||||
|
@@ -10,50 +10,58 @@ namespace NadekoBot.Modules.Gambling.Common;
|
||||
[Cloneable]
|
||||
public sealed partial class GamblingConfig : ICloneable<GamblingConfig>
|
||||
{
|
||||
[Comment(@"DO NOT CHANGE")]
|
||||
[Comment("""DO NOT CHANGE""")]
|
||||
public int Version { get; set; } = 2;
|
||||
|
||||
[Comment(@"Currency settings")]
|
||||
[Comment("""Currency settings""")]
|
||||
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;
|
||||
|
||||
[Comment(@"Maximum amount users can bet
|
||||
Set 0 for unlimited")]
|
||||
[Comment("""
|
||||
Maximum amount users can bet
|
||||
Set 0 for unlimited
|
||||
""")]
|
||||
public int MaxBet { get; set; } = 0;
|
||||
|
||||
[Comment(@"Settings for betflip command")]
|
||||
[Comment("""Settings for betflip command""")]
|
||||
public BetFlipConfig BetFlip { get; set; }
|
||||
|
||||
[Comment(@"Settings for betroll command")]
|
||||
[Comment("""Settings for betroll command""")]
|
||||
public BetRollConfig BetRoll { get; set; }
|
||||
|
||||
[Comment(@"Automatic currency generation settings.")]
|
||||
[Comment("""Automatic currency generation settings.""")]
|
||||
public GenerationConfig Generation { get; set; }
|
||||
|
||||
[Comment(@"Settings for timely command
|
||||
(letting people claim X amount of currency every Y hours)")]
|
||||
[Comment("""
|
||||
Settings for timely command
|
||||
(letting people claim X amount of currency every Y hours)
|
||||
""")]
|
||||
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; }
|
||||
|
||||
[Comment(@"Settings for LuckyLadder command")]
|
||||
[Comment("""Settings for LuckyLadder command""")]
|
||||
public LuckyLadderSettings LuckyLadder { get; set; }
|
||||
|
||||
[Comment(@"Settings related to waifus")]
|
||||
[Comment("""Settings related to waifus""")]
|
||||
public WaifuConfig Waifu { get; set; }
|
||||
|
||||
[Comment(@"Amount of currency selfhosters will get PER pledged dollar CENT.
|
||||
1 = 100 currency per $. Used almost exclusively on public nadeko.")]
|
||||
[Comment("""
|
||||
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;
|
||||
|
||||
[Comment(@"Currency reward per vote.
|
||||
This will work only if you've set up VotesApi and correct credentials for topgg and/or discords voting")]
|
||||
[Comment("""
|
||||
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;
|
||||
|
||||
[Comment(@"Slot config")]
|
||||
[Comment("""Slot config""")]
|
||||
public SlotsConfig Slots { get; set; }
|
||||
|
||||
public GamblingConfig()
|
||||
@@ -72,42 +80,50 @@ This will work only if you've set up VotesApi and correct credentials for topgg
|
||||
|
||||
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; } = "🌸";
|
||||
|
||||
[Comment(@"What is the name of the currency")]
|
||||
[Comment("""What is the name of the currency""")]
|
||||
public string Name { get; set; } = "Nadeko Flower";
|
||||
|
||||
[Comment(@"For how long (in days) will the transactions be kept in the database (curtrs)
|
||||
Set 0 to disable cleanup (keep transactions forever)")]
|
||||
[Comment("""
|
||||
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;
|
||||
}
|
||||
|
||||
[Cloneable]
|
||||
public partial class TimelyConfig
|
||||
{
|
||||
[Comment(@"How much currency will the users get every time they run .timely command
|
||||
setting to 0 or less will disable this feature")]
|
||||
[Comment("""
|
||||
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;
|
||||
|
||||
[Comment(@"How often (in hours) can users claim currency with .timely command
|
||||
setting to 0 or less will disable this feature")]
|
||||
[Comment("""
|
||||
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;
|
||||
}
|
||||
|
||||
[Cloneable]
|
||||
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;
|
||||
}
|
||||
|
||||
[Cloneable]
|
||||
public partial class BetRollConfig
|
||||
{
|
||||
[Comment(@"When betroll is played, user will roll a number 0-100.
|
||||
This setting will describe which multiplier is used for when the roll is higher than the given number.
|
||||
Doesn't have to be ordered.")]
|
||||
[Comment("""
|
||||
When betroll is played, user will roll a number 0-100.
|
||||
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 BetRollConfig()
|
||||
@@ -134,48 +150,56 @@ Doesn't have to be ordered.")]
|
||||
[Cloneable]
|
||||
public partial class GenerationConfig
|
||||
{
|
||||
[Comment(@"when currency is generated, should it also have a random password
|
||||
associated with it which users have to type after the .pick command
|
||||
in order to get it")]
|
||||
[Comment("""
|
||||
when currency is generated, should it also have a random password
|
||||
associated with it which users have to type after the .pick command
|
||||
in order to get it
|
||||
""")]
|
||||
public bool HasPassword { get; set; } = true;
|
||||
|
||||
[Comment(@"Every message sent has a certain % chance to generate the currency
|
||||
specify the percentage here (1 being 100%, 0 being 0% - for example
|
||||
default is 0.02, which is 2%")]
|
||||
[Comment("""
|
||||
Every message sent has a certain % chance to generate the currency
|
||||
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;
|
||||
|
||||
[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;
|
||||
|
||||
[Comment(@"Minimum amount of currency that can spawn")]
|
||||
[Comment("""Minimum amount of currency that can spawn""")]
|
||||
public int MinAmount { get; set; } = 1;
|
||||
|
||||
[Comment(@"Maximum amount of currency that can spawn.
|
||||
Set to the same value as MinAmount to always spawn the same amount")]
|
||||
[Comment("""
|
||||
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;
|
||||
}
|
||||
|
||||
[Cloneable]
|
||||
public partial class DecayConfig
|
||||
{
|
||||
[Comment(@"Percentage of user's current currency which will be deducted every 24h.
|
||||
0 - 1 (1 is 100%, 0.5 50%, 0 disabled)")]
|
||||
[Comment("""
|
||||
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;
|
||||
|
||||
[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;
|
||||
|
||||
[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;
|
||||
|
||||
[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;
|
||||
}
|
||||
|
||||
[Cloneable]
|
||||
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 LuckyLadderSettings()
|
||||
@@ -185,17 +209,21 @@ public partial class LuckyLadderSettings
|
||||
[Cloneable]
|
||||
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 MultipliersData Multipliers { get; set; } = new();
|
||||
|
||||
[Comment(@"Settings for periodic waifu price decay.
|
||||
Waifu price decays only if the waifu has no claimer.")]
|
||||
[Comment("""
|
||||
Settings for periodic waifu price decay.
|
||||
Waifu price decays only if the waifu has no claimer.
|
||||
""")]
|
||||
public WaifuDecayConfig Decay { get; set; } = new();
|
||||
|
||||
[Comment(@"List of items available for gifting.
|
||||
If negative is true, gift will instead reduce waifu value.")]
|
||||
[Comment("""
|
||||
List of items available for gifting.
|
||||
If negative is true, gift will instead reduce waifu value.
|
||||
""")]
|
||||
public List<WaifuItemModel> Items { get; set; } = new();
|
||||
|
||||
public WaifuConfig()
|
||||
@@ -241,16 +269,20 @@ If negative is true, gift will instead reduce waifu value.")]
|
||||
|
||||
public class WaifuDecayConfig
|
||||
{
|
||||
[Comment(@"Percentage (0 - 100) of the waifu value to reduce.
|
||||
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$)")]
|
||||
[Comment("""
|
||||
Percentage (0 - 100) of the waifu value to reduce.
|
||||
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;
|
||||
|
||||
[Comment(@"How often to decay waifu values, in hours")]
|
||||
[Comment("""How often to decay waifu values, in hours""")]
|
||||
public int HourInterval { get; set; } = 24;
|
||||
|
||||
[Comment(@"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.")]
|
||||
[Comment("""
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -258,47 +290,61 @@ For example if this value is set to 300, any waifu with the price 300 or less wi
|
||||
[Cloneable]
|
||||
public sealed partial class MultipliersData
|
||||
{
|
||||
[Comment(@"Multiplier for waifureset. Default 150.
|
||||
Formula (at the time of writing this):
|
||||
price = (waifu_price * 1.25f) + ((number_of_divorces + changes_of_heart + 2) * WaifuReset) rounded up")]
|
||||
[Comment("""
|
||||
Multiplier for waifureset. Default 150.
|
||||
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;
|
||||
|
||||
[Comment(@"The minimum amount of currency that you have to pay
|
||||
in order to buy a waifu who doesn't have a crush on you.
|
||||
Default is 1.1
|
||||
Example: If a waifu is worth 100, you will have to pay at least 100 * NormalClaim currency to claim her.
|
||||
(100 * 1.1 = 110)")]
|
||||
[Comment("""
|
||||
The minimum amount of currency that you have to pay
|
||||
in order to buy a waifu who doesn't have a crush on you.
|
||||
Default is 1.1
|
||||
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;
|
||||
|
||||
[Comment(@"The minimum amount of currency that you have to pay
|
||||
in order to buy a waifu that has a crush on you.
|
||||
Default is 0.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)")]
|
||||
[Comment("""
|
||||
The minimum amount of currency that you have to pay
|
||||
in order to buy a waifu that has a crush on you.
|
||||
Default is 0.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;
|
||||
|
||||
[Comment(@"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)")]
|
||||
[Comment("""
|
||||
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;
|
||||
|
||||
[Comment(@"All gift prices will be multiplied by this number.
|
||||
Default 1 (meaning no effect)")]
|
||||
[Comment("""
|
||||
All gift prices will be multiplied by this number.
|
||||
Default 1 (meaning no effect)
|
||||
""")]
|
||||
public decimal AllGiftPrices { get; set; } = 1.0M;
|
||||
|
||||
[Comment(@"What percentage of the value of the gift will a waifu gain when she's gifted.
|
||||
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)")]
|
||||
[Comment("""
|
||||
What percentage of the value of the gift will a waifu gain when she's gifted.
|
||||
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;
|
||||
|
||||
[Comment(@"What percentage of the value of the gift will a waifu lose when she's gifted a gift marked as 'negative'.
|
||||
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)")]
|
||||
[Comment("""
|
||||
What percentage of the value of the gift will a waifu lose when she's gifted a gift marked as 'negative'.
|
||||
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 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;
|
||||
}
|
||||
|
||||
|
@@ -96,9 +96,12 @@ public class GamblingService : INService, IReadyExecutor
|
||||
continue;
|
||||
}
|
||||
|
||||
Log.Information(@"Decaying users' currency - decay: {ConfigDecayPercent}%
|
||||
| max: {MaxDecay}
|
||||
| threshold: {DecayMinTreshold}",
|
||||
Log.Information("""
|
||||
--- Decaying users' currency ---
|
||||
| decay: {ConfigDecayPercent}%
|
||||
| max: {MaxDecay}
|
||||
| threshold: {DecayMinTreshold}
|
||||
""",
|
||||
config.Decay.Percent * 100,
|
||||
maxDecay,
|
||||
config.Decay.MinThreshold);
|
||||
|
@@ -187,11 +187,13 @@ public class ChatterBotService : IExecOnMessage
|
||||
// , footer: counter > 0 ? counter.ToString() : null
|
||||
);
|
||||
|
||||
Log.Information(@"CleverBot Executed
|
||||
Server: {GuildName} [{GuildId}]
|
||||
Channel: {ChannelName} [{ChannelId}]
|
||||
UserId: {Author} [{AuthorId}]
|
||||
Message: {Content}",
|
||||
Log.Information("""
|
||||
CleverBot Executed
|
||||
Server: {GuildName} [{GuildId}]
|
||||
Channel: {ChannelName} [{ChannelId}]
|
||||
UserId: {Author} [{AuthorId}]
|
||||
Message: {Content}
|
||||
""",
|
||||
guild.Name,
|
||||
guild.Id,
|
||||
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.")]
|
||||
public long CurrencyReward { get; set; }
|
||||
|
||||
[Comment(@"Users won't be able to start trivia games which have
|
||||
a smaller win requirement than the one specified by this setting.")]
|
||||
[Comment("""
|
||||
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;
|
||||
}
|
||||
|
||||
|
@@ -14,13 +14,15 @@ public partial class Games
|
||||
=> await SendConfirmAsync(GetText(strs.hangman_types(prefix)), _service.GetHangmanTypes().Join('\n'));
|
||||
|
||||
private static string Draw(HangmanGame.State state)
|
||||
=> $@". ┌─────┐
|
||||
.┃...............┋
|
||||
.┃...............┋
|
||||
.┃{(state.Errors > 0 ? ".............😲" : "")}
|
||||
.┃{(state.Errors > 1 ? "............./" : "")} {(state.Errors > 2 ? "|" : "")} {(state.Errors > 3 ? "\\" : "")}
|
||||
.┃{(state.Errors > 4 ? "............../" : "")} {(state.Errors > 5 ? "\\" : "")}
|
||||
/-\";
|
||||
=> $"""
|
||||
. ┌─────┐
|
||||
.┃...............┋
|
||||
.┃...............┋
|
||||
.┃{(state.Errors > 0 ? ".............😲" : "")}
|
||||
.┃{(state.Errors > 1 ? "............./" : "")} {(state.Errors > 2 ? "|" : "")} {(state.Errors > 3 ? "\\" : "")}
|
||||
.┃{(state.Errors > 4 ? "............../" : "")} {(state.Errors > 5 ? "\\" : "")}
|
||||
/-\
|
||||
""";
|
||||
|
||||
public static IEmbedBuilder GetEmbed(IEmbedBuilderService eb, HangmanGame.State state)
|
||||
{
|
||||
|
@@ -69,7 +69,7 @@ public class TypingGame
|
||||
try
|
||||
{
|
||||
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;
|
||||
|
@@ -78,13 +78,13 @@ public class TriviaQuestion
|
||||
private static string Clean(string str)
|
||||
{
|
||||
str = " " + str.ToLowerInvariant() + " ";
|
||||
str = Regex.Replace(str, "\\s+", " ");
|
||||
str = Regex.Replace(str, "[^\\w\\d\\s]", "");
|
||||
str = Regex.Replace(str, @"\s+", " ");
|
||||
str = Regex.Replace(str, @"[^\w\d\s]", "");
|
||||
//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
|
||||
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
|
||||
str = str.Length <= MAX_STRING_LENGTH ? str : str[..MAX_STRING_LENGTH];
|
||||
return str;
|
||||
|
@@ -490,13 +490,15 @@ public partial class Help : NadekoModule<HelpService>
|
||||
|
||||
private Task SelfhostAction(SocketMessageComponent smc, object _)
|
||||
=> 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.
|
||||
|
||||
*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 :)",
|
||||
"""
|
||||
- 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*
|
||||
|
||||
- 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);
|
||||
|
||||
[Cmd]
|
||||
@@ -541,12 +543,14 @@ Nadeko will DM you the welcome instructions, and you may start using the patron-
|
||||
🎉 **Enjoy!** 🎉
|
||||
")
|
||||
.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.
|
||||
`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.
|
||||
`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");
|
||||
"""
|
||||
|
||||
*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.
|
||||
`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.
|
||||
`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
|
||||
{
|
||||
|
@@ -39,9 +39,9 @@ public static class MusicExtensions
|
||||
if (trackInfo.Duration == TimeSpan.MaxValue)
|
||||
return "∞";
|
||||
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)
|
||||
|
@@ -5,10 +5,10 @@ namespace NadekoBot.Modules.Music.Resolvers;
|
||||
|
||||
public class RadioResolver : IRadioResolver
|
||||
{
|
||||
private readonly Regex _plsRegex = new("File1=(?<url>.*?)\\n", RegexOptions.Compiled);
|
||||
private readonly Regex _m3URegex = new("(?<url>^[^#].*)", RegexOptions.Compiled | RegexOptions.Multiline);
|
||||
private readonly Regex _asxRegex = new("<ref href=\"(?<url>.*?)\"", RegexOptions.Compiled);
|
||||
private readonly Regex _xspfRegex = new("<location>(?<url>.*?)</location>", 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 _asxRegex = new(@"<ref href=""(?<url>.*?)""", RegexOptions.Compiled);
|
||||
private readonly Regex _xspfRegex = new(@"<location>(?<url>.*?)</location>", RegexOptions.Compiled);
|
||||
|
||||
public async Task<ITrackInfo> ResolveByQueryAsync(string query)
|
||||
{
|
||||
|
@@ -24,7 +24,7 @@ public partial class Searches
|
||||
|
||||
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]
|
||||
|
@@ -304,7 +304,7 @@ public partial class Searches
|
||||
|
||||
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;
|
||||
}
|
||||
|
@@ -9,51 +9,61 @@ public partial class SearchesConfig : ICloneable<SearchesConfig>
|
||||
[Comment("DO NOT CHANGE")]
|
||||
public int Version { get; set; } = 0;
|
||||
|
||||
[Comment(@"Which engine should .search command
|
||||
'google_scrape' - default. Scrapes the webpage for results. May break. Requires no api keys.
|
||||
'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")]
|
||||
[Comment("""
|
||||
Which engine should .search command
|
||||
'google_scrape' - default. Scrapes the webpage for results. May break. Requires no api keys.
|
||||
'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;
|
||||
|
||||
[Comment(@"Which engine should .image command use
|
||||
'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")]
|
||||
[Comment("""
|
||||
Which engine should .image command use
|
||||
'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;
|
||||
|
||||
|
||||
[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
|
||||
|
||||
- `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
|
||||
|
||||
- `invidious` - recommended advanced, uses invidious api. Requires at least one invidious instance specified in the `invidiousInstances` property")]
|
||||
[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
|
||||
|
||||
- `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
|
||||
|
||||
- `invidious` - recommended advanced, uses invidious api. Requires at least one invidious instance specified in the `invidiousInstances` property
|
||||
""")]
|
||||
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.
|
||||
Nadeko will use a random one for each request.
|
||||
Use a fully qualified url. Example: `https://my-searx-instance.mydomain.com`
|
||||
Instances specified must support 'format=json' query parameter.
|
||||
- In case you're running your own searx instance, set
|
||||
|
||||
search:
|
||||
formats:
|
||||
- json
|
||||
|
||||
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)")]
|
||||
[Comment("""
|
||||
Set the searx instance urls in case you want to use 'searx' for either img or web search.
|
||||
Nadeko will use a random one for each request.
|
||||
Use a fully qualified url. Example: `https://my-searx-instance.mydomain.com`
|
||||
Instances specified must support 'format=json' query parameter.
|
||||
- In case you're running your own searx instance, set
|
||||
|
||||
search:
|
||||
formats:
|
||||
- json
|
||||
|
||||
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)
|
||||
""")]
|
||||
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
|
||||
Nadeko will use a random one for each request.
|
||||
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")]
|
||||
[Comment("""
|
||||
Set the invidious instance urls in case you want to use 'invidious' for `.youtube` search
|
||||
Nadeko will use a random one for each request.
|
||||
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
|
||||
""")]
|
||||
public List<string> InvidiousInstances { get; set; } = new List<string>();
|
||||
}
|
||||
|
||||
|
@@ -23,8 +23,10 @@ public class TrovoProvider : Provider
|
||||
|
||||
if (string.IsNullOrWhiteSpace(creds.GetCreds().TrovoClientId))
|
||||
{
|
||||
Log.Warning(@"Trovo streams are using a default clientId.
|
||||
If you are experiencing ratelimits, you should create your own application at: https://developer.trovo.live/");
|
||||
Log.Warning("""
|
||||
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
|
||||
? "∞"
|
||||
: (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 usesString = $"{inv.Uses} / {(inv.MaxUses == 0 ? "∞" : inv.MaxUses?.ToString())}";
|
||||
|
||||
|
@@ -782,13 +782,15 @@ public sealed class PatronageService
|
||||
patron.ValidThru.AddDays(1).ToShortAndRelativeTimestampTag(),
|
||||
true)
|
||||
.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>*
|
||||
*- You can use the `.patron` command in this chat to check your current quota usage for the Patron-only commands*
|
||||
*- **ALL** of the servers that you **own** will enjoy your Patron benefits.*
|
||||
*- You can use any of the commands available in your tier on any server (assuming you have sufficient permissions to run those commands)*
|
||||
*- 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/>*",
|
||||
"""
|
||||
*- 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>*
|
||||
*- You can use the `.patron` command in this chat to check your current quota usage for the Patron-only commands*
|
||||
*- **ALL** of the servers that you **own** will enjoy your Patron benefits.*
|
||||
*- You can use any of the commands available in your tier on any server (assuming you have sufficient permissions to run those commands)*
|
||||
*- 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)
|
||||
.WithFooter($"platform id: {patron.UniquePlatformUserId}");
|
||||
|
||||
|
@@ -13,12 +13,14 @@ public partial class Utility
|
||||
public partial class QuoteCommands : NadekoModule
|
||||
{
|
||||
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.)
|
||||
# an: Author name
|
||||
# aid: Author id
|
||||
# txt: Quote text
|
||||
";
|
||||
"""
|
||||
# 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.)
|
||||
# an: Author name
|
||||
# aid: Author id
|
||||
# txt: Quote text
|
||||
|
||||
""";
|
||||
|
||||
private static readonly ISerializer _exportSerializer = new SerializerBuilder()
|
||||
.WithEventEmitter(args
|
||||
|
@@ -9,58 +9,68 @@ namespace NadekoBot.Modules.Xp;
|
||||
[Cloneable]
|
||||
public sealed partial class XpConfig : ICloneable<XpConfig>
|
||||
{
|
||||
[Comment(@"DO NOT CHANGE")]
|
||||
[Comment("""DO NOT CHANGE""")]
|
||||
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;
|
||||
|
||||
[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;
|
||||
|
||||
[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;
|
||||
|
||||
[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;
|
||||
|
||||
[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;
|
||||
|
||||
[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;
|
||||
|
||||
[Comment(@"Xp Shop config")]
|
||||
[Comment("""Xp Shop config""")]
|
||||
public ShopConfig Shop { get; set; } = new();
|
||||
|
||||
public sealed class ShopConfig
|
||||
{
|
||||
[Comment(@"Whether the xp shop is enabled
|
||||
True -> Users can access the xp shop using .xpshop command
|
||||
False -> Users can't access the xp shop")]
|
||||
[Comment("""
|
||||
Whether the xp shop is enabled
|
||||
True -> Users can access the xp shop using .xpshop command
|
||||
False -> Users can't access the xp shop
|
||||
""")]
|
||||
public bool IsEnabled { get; set; } = false;
|
||||
|
||||
[Comment(@"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")]
|
||||
[Comment("""
|
||||
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;
|
||||
|
||||
[Comment(@"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")]
|
||||
[Comment("""
|
||||
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;
|
||||
|
||||
[Comment(@"Frames available for sale. Keys are unique IDs.
|
||||
Do not change keys as they are not publicly visible. Only change properties (name, price, id)
|
||||
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")]
|
||||
[Comment("""
|
||||
Frames available for sale. Keys are unique IDs.
|
||||
Do not change keys as they are not publicly visible. Only change properties (name, price, id)
|
||||
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()
|
||||
{
|
||||
{"default", new() {Name = "No frame", Price = 0, Url = string.Empty}}
|
||||
};
|
||||
|
||||
[Comment(@"Backgrounds available for sale. Keys are unique IDs.
|
||||
Do not change keys as they are not publicly visible. Only change properties (name, price, id)
|
||||
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")]
|
||||
[Comment("""
|
||||
Backgrounds available for sale. Keys are unique IDs.
|
||||
Do not change keys as they are not publicly visible. Only change properties (name, price, id)
|
||||
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()
|
||||
{
|
||||
{"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
|
||||
{
|
||||
[Comment(@"Visible name of the item")]
|
||||
[Comment("""Visible name of the item""")]
|
||||
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; }
|
||||
|
||||
[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; }
|
||||
|
||||
[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; }
|
||||
|
||||
[Comment(@"Optional description of the item")]
|
||||
[Comment("""Optional description of the item""")]
|
||||
public string Desc { get; set; }
|
||||
}
|
||||
}
|
||||
|
@@ -43,7 +43,7 @@ public partial class Xp
|
||||
.OrderBy(x => x.Level)
|
||||
.Select(x =>
|
||||
{
|
||||
var sign = !x.Remove ? @"✅ " : @"❌ ";
|
||||
var sign = !x.Remove ? "✅ " : "❌ ";
|
||||
|
||||
var str = ctx.Guild.GetRole(x.RoleId)?.ToString();
|
||||
|
||||
|
@@ -147,11 +147,13 @@ public class CommandHandler : INService, IReadyExecutor
|
||||
{
|
||||
if (_bss.Data.ConsoleOutputType == ConsoleOutputType.Normal)
|
||||
{
|
||||
Log.Information(@"Command Executed after {ExecTime}s
|
||||
User: {User}
|
||||
Server: {Server}
|
||||
Channel: {Channel}
|
||||
Message: {Message}",
|
||||
Log.Information("""
|
||||
Command Executed after {ExecTime}s
|
||||
User: {User}
|
||||
Server: {Server}
|
||||
Channel: {Channel}
|
||||
Message: {Message}
|
||||
""",
|
||||
string.Join("/", execPoints.Select(x => (x * ONE_THOUSANDTH).ToString("F3"))),
|
||||
usrMsg.Author + " [" + usrMsg.Author.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)
|
||||
{
|
||||
Log.Warning(@"Command Errored after {ExecTime}s
|
||||
User: {User}
|
||||
Server: {Guild}
|
||||
Channel: {Channel}
|
||||
Message: {Message}
|
||||
Error: {ErrorMessage}",
|
||||
Log.Warning("""
|
||||
Command Errored after {ExecTime}s
|
||||
User: {User}
|
||||
Server: {Guild}
|
||||
Channel: {Channel}
|
||||
Message: {Message}
|
||||
Error: {ErrorMessage}
|
||||
""",
|
||||
string.Join("/", execPoints.Select(x => (x * ONE_THOUSANDTH).ToString("F3"))),
|
||||
usrMsg.Author + " [" + usrMsg.Author.Id + "]",
|
||||
channel is null ? "DM" : channel.Guild.Name + " [" + channel.Guild.Id + "]",
|
||||
@@ -193,8 +197,10 @@ public class CommandHandler : INService, IReadyExecutor
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Warning(@"Err | g:{GuildId} | c: {ChannelId} | u: {UserId} | msg: {Message}
|
||||
Err: {ErrorMessage}",
|
||||
Log.Warning("""
|
||||
Err | g:{GuildId} | c: {ChannelId} | u: {UserId} | msg: {Message}
|
||||
Err: {ErrorMessage}
|
||||
""",
|
||||
channel?.Guild.Id.ToString() ?? "-",
|
||||
channel?.Id.ToString() ?? "-",
|
||||
usrMsg.Author.Id,
|
||||
|
@@ -13,7 +13,7 @@ namespace NadekoBot.Services;
|
||||
public sealed partial class GoogleApiService : IGoogleApiService, INService
|
||||
{
|
||||
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;
|
||||
|
@@ -2,140 +2,142 @@
|
||||
|
||||
public sealed partial class GoogleApiService
|
||||
{
|
||||
private const string SUPPORTED = @"afrikaans af
|
||||
albanian sq
|
||||
amharic am
|
||||
arabic ar
|
||||
armenian hy
|
||||
assamese as
|
||||
aymara ay
|
||||
azerbaijani az
|
||||
bambara bm
|
||||
basque eu
|
||||
belarusian be
|
||||
bengali bn
|
||||
bhojpuri bho
|
||||
bosnian bs
|
||||
bulgarian bg
|
||||
catalan ca
|
||||
cebuano ceb
|
||||
chinese zh-CN
|
||||
chinese-trad zh-TW
|
||||
corsican co
|
||||
croatian hr
|
||||
czech cs
|
||||
danish da
|
||||
dhivehi dv
|
||||
dogri doi
|
||||
dutch nl
|
||||
english en
|
||||
esperanto eo
|
||||
estonian et
|
||||
ewe ee
|
||||
filipino fil
|
||||
finnish fi
|
||||
french fr
|
||||
frisian fy
|
||||
galician gl
|
||||
georgian ka
|
||||
german de
|
||||
greek el
|
||||
guarani gn
|
||||
gujarati gu
|
||||
haitian ht
|
||||
hausa ha
|
||||
hawaiian haw
|
||||
hebrew he
|
||||
hindi hi
|
||||
hmong hmn
|
||||
hungarian hu
|
||||
icelandic is
|
||||
igbo ig
|
||||
ilocano ilo
|
||||
indonesian id
|
||||
irish ga
|
||||
italian it
|
||||
japanese ja
|
||||
javanese jv
|
||||
kannada kn
|
||||
kazakh kk
|
||||
khmer km
|
||||
kinyarwanda rw
|
||||
konkani gom
|
||||
korean ko
|
||||
krio kri
|
||||
kurdish ku
|
||||
kurdish-sor ckb
|
||||
kyrgyz ky
|
||||
lao lo
|
||||
latin la
|
||||
latvian lv
|
||||
lingala ln
|
||||
lithuanian lt
|
||||
luganda lg
|
||||
luxembourgish lb
|
||||
macedonian mk
|
||||
maithili mai
|
||||
malagasy mg
|
||||
malay ms
|
||||
malayalam ml
|
||||
maltese mt
|
||||
maori mi
|
||||
marathi mr
|
||||
meiteilon mni-Mtei
|
||||
mizo lus
|
||||
mongolian mn
|
||||
myanmar my
|
||||
nepali ne
|
||||
norwegian no
|
||||
nyanja ny
|
||||
odia or
|
||||
oromo om
|
||||
pashto ps
|
||||
persian fa
|
||||
polish pl
|
||||
portuguese pt
|
||||
punjabi pa
|
||||
quechua qu
|
||||
romanian ro
|
||||
russian ru
|
||||
samoan sm
|
||||
sanskrit sa
|
||||
scots gd
|
||||
sepedi nso
|
||||
serbian sr
|
||||
sesotho st
|
||||
shona sn
|
||||
sindhi sd
|
||||
sinhala si
|
||||
slovak sk
|
||||
slovenian sl
|
||||
somali so
|
||||
spanish es
|
||||
sundanese su
|
||||
swahili sw
|
||||
swedish sv
|
||||
tagalog tl
|
||||
tajik tg
|
||||
tamil ta
|
||||
tatar tt
|
||||
telugu te
|
||||
thai th
|
||||
tigrinya ti
|
||||
tsonga ts
|
||||
turkish tr
|
||||
turkmen tk
|
||||
twi ak
|
||||
ukrainian uk
|
||||
urdu ur
|
||||
uyghur ug
|
||||
uzbek uz
|
||||
vietnamese vi
|
||||
welsh cy
|
||||
xhosa xh
|
||||
yiddish yi
|
||||
yoruba yo
|
||||
zulu zu";
|
||||
private const string SUPPORTED = """
|
||||
afrikaans af
|
||||
albanian sq
|
||||
amharic am
|
||||
arabic ar
|
||||
armenian hy
|
||||
assamese as
|
||||
aymara ay
|
||||
azerbaijani az
|
||||
bambara bm
|
||||
basque eu
|
||||
belarusian be
|
||||
bengali bn
|
||||
bhojpuri bho
|
||||
bosnian bs
|
||||
bulgarian bg
|
||||
catalan ca
|
||||
cebuano ceb
|
||||
chinese zh-CN
|
||||
chinese-trad zh-TW
|
||||
corsican co
|
||||
croatian hr
|
||||
czech cs
|
||||
danish da
|
||||
dhivehi dv
|
||||
dogri doi
|
||||
dutch nl
|
||||
english en
|
||||
esperanto eo
|
||||
estonian et
|
||||
ewe ee
|
||||
filipino fil
|
||||
finnish fi
|
||||
french fr
|
||||
frisian fy
|
||||
galician gl
|
||||
georgian ka
|
||||
german de
|
||||
greek el
|
||||
guarani gn
|
||||
gujarati gu
|
||||
haitian ht
|
||||
hausa ha
|
||||
hawaiian haw
|
||||
hebrew he
|
||||
hindi hi
|
||||
hmong hmn
|
||||
hungarian hu
|
||||
icelandic is
|
||||
igbo ig
|
||||
ilocano ilo
|
||||
indonesian id
|
||||
irish ga
|
||||
italian it
|
||||
japanese ja
|
||||
javanese jv
|
||||
kannada kn
|
||||
kazakh kk
|
||||
khmer km
|
||||
kinyarwanda rw
|
||||
konkani gom
|
||||
korean ko
|
||||
krio kri
|
||||
kurdish ku
|
||||
kurdish-sor ckb
|
||||
kyrgyz ky
|
||||
lao lo
|
||||
latin la
|
||||
latvian lv
|
||||
lingala ln
|
||||
lithuanian lt
|
||||
luganda lg
|
||||
luxembourgish lb
|
||||
macedonian mk
|
||||
maithili mai
|
||||
malagasy mg
|
||||
malay ms
|
||||
malayalam ml
|
||||
maltese mt
|
||||
maori mi
|
||||
marathi mr
|
||||
meiteilon mni-Mtei
|
||||
mizo lus
|
||||
mongolian mn
|
||||
myanmar my
|
||||
nepali ne
|
||||
norwegian no
|
||||
nyanja ny
|
||||
odia or
|
||||
oromo om
|
||||
pashto ps
|
||||
persian fa
|
||||
polish pl
|
||||
portuguese pt
|
||||
punjabi pa
|
||||
quechua qu
|
||||
romanian ro
|
||||
russian ru
|
||||
samoan sm
|
||||
sanskrit sa
|
||||
scots gd
|
||||
sepedi nso
|
||||
serbian sr
|
||||
sesotho st
|
||||
shona sn
|
||||
sindhi sd
|
||||
sinhala si
|
||||
slovak sk
|
||||
slovenian sl
|
||||
somali so
|
||||
spanish es
|
||||
sundanese su
|
||||
swahili sw
|
||||
swedish sv
|
||||
tagalog tl
|
||||
tajik tg
|
||||
tamil ta
|
||||
tatar tt
|
||||
telugu te
|
||||
thai th
|
||||
tigrinya ti
|
||||
tsonga ts
|
||||
turkish tr
|
||||
turkmen tk
|
||||
twi ak
|
||||
ukrainian uk
|
||||
urdu ur
|
||||
uyghur ug
|
||||
uzbek uz
|
||||
vietnamese vi
|
||||
welsh cy
|
||||
xhosa xh
|
||||
yiddish yi
|
||||
yoruba yo
|
||||
zulu zu
|
||||
""";
|
||||
|
||||
|
||||
public IReadOnlyDictionary<string, string> Languages { get; }
|
||||
|
Reference in New Issue
Block a user