mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-11 09:48:26 -04:00
Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
2d92424dd4 | ||
|
ffba03adbe | ||
|
76ebb87fb5 | ||
|
4a50c30c56 | ||
|
e70a91ae60 | ||
|
3470762b30 | ||
|
2cbb4ecd3d | ||
|
619bee811d | ||
|
a09be96200 | ||
|
81254ed5f6 | ||
|
d82e3bd444 | ||
|
9011646b02 | ||
|
2a1f45819d | ||
|
d2d0cb9e03 |
20
CHANGELOG.md
20
CHANGELOG.md
@@ -4,7 +4,27 @@ Experimental changelog. Mostly based on [keepachangelog](https://keepachangelog.
|
||||
|
||||
## Unreleased
|
||||
|
||||
## [3.0.5] - 20.09.2021
|
||||
|
||||
### Fixed
|
||||
- Fixed images not automatically reloading on startup if the keys don't exist
|
||||
- Fixed `.logserver` - it should no longer throw an exception if you had no logsettings previously
|
||||
|
||||
## [3.0.4] - 16.09.2021
|
||||
|
||||
### Added
|
||||
- Fully translated to Brazilian Portuguese 🎉
|
||||
- Added `%server.boosters%` and `%server.boost_level%` placeholders
|
||||
- Added `DmHelpTextKeywords` to `data/bot.yml`
|
||||
- Bot now sends dm help text ONLY if the message contains one of the keywords specified
|
||||
- If no keywords are specified, bot will reply to every DM (like before)
|
||||
|
||||
### Fixed
|
||||
- Possible fix for `.repeat` bug
|
||||
- Slight adjustment for repeater logic
|
||||
- Timer should no longer increase on some repeaters
|
||||
- Repeaters should no longer have periods when they're missing from the list
|
||||
- Fixed several commands which used error color for success confirmation messages
|
||||
|
||||
## [3.0.3] - 15.09.2021
|
||||
|
||||
|
@@ -1,3 +1,35 @@
|
||||
# Setting up NadekoBot with Docker
|
||||
|
||||
Soon:tm:
|
||||
# DO NOT USE YET - WORK IN PROGRESS
|
||||
|
||||
Upgrade from 2.x to v3 does not work because the file is mount readonly
|
||||
|
||||
### Docker Compose
|
||||
```yml
|
||||
version: "3.7"
|
||||
services:
|
||||
nadeko:
|
||||
image: registry.gitlab.com/veovis/nadekobot:v3-docker
|
||||
depends_on:
|
||||
- redis
|
||||
environment:
|
||||
TZ: Europe/Paris
|
||||
#NadekoBot_RedisOptions: redis,name=nadeko
|
||||
#NadekoBot_ShardRunCommand: dotnet
|
||||
#NadekoBot_ShardRunArguments: /app/NadekoBot.dll {0} {1}
|
||||
volumes:
|
||||
- /srv/nadeko/conf/creds.yml:/app/creds.yml:ro
|
||||
- /srv/nadeko/data:/app/data
|
||||
|
||||
redis:
|
||||
image: redis:4-alpine
|
||||
sysctls:
|
||||
- net.core.somaxconn=511
|
||||
command: redis-server --maxmemory 32M --maxmemory-policy volatile-lru
|
||||
volumes:
|
||||
- /srv/nadeko/redis-data:/data
|
||||
```
|
||||
### Updating
|
||||
- `cd /srv/nadeko`
|
||||
- `docker-compose pull`
|
||||
- `docker-compose up -d`
|
||||
|
@@ -61,10 +61,10 @@ Open Terminal (if you're on an installation with a window manager) and navigate
|
||||
|
||||
1. Stop the bot
|
||||
2. Download the latest release from <https://gitlab.com/Kwoth/nadekobot/-/releases>
|
||||
- Look for the file called "X.XX.X-linux-x64-build.tar" (where X.XX.X is a series of numbers) and download it
|
||||
- Look for the file called "x.x.x-linux-x64-build.tar" (where `X.X.X` is a version, for example 3.0.4) and download it
|
||||
3. Untar it
|
||||
- ⚠ Make sure that you change X.XX.X to the same series of numbers as in step 2!
|
||||
- `tar xf 2.99.8-linux-x64-build.tar`
|
||||
- ⚠ Make sure that you change `X.X.X` to the same series of numbers as in step 2!
|
||||
- `tar xf x.x.x-linux-x64-build.tar`
|
||||
4. Rename the old nadekobot directory to nadekobot-old (remove your old backup first if you have one, or back it up under a different name)
|
||||
- `rm -rf nadekobot-old 2>/dev/null`
|
||||
- `mv nadekobot nadekobot-old`
|
||||
@@ -75,7 +75,7 @@ Open Terminal (if you're on an installation with a window manager) and navigate
|
||||
- `rm nadekobot-old/data/aliases.yml`
|
||||
- `rm -r nadekobot-old/data/strings`
|
||||
7. Copy old data
|
||||
- `cp -RT nadekobot-old/data/ nadekobot/data/`
|
||||
- `cp -RT nadekobot-old/data/ nadekobot/data`
|
||||
8. Copy creds.yml
|
||||
- `cp nadekobot-old/creds.yml nadekobot/`
|
||||
9. Move into nadekobot directory and make the NadekoBot executable
|
||||
@@ -95,7 +95,135 @@ mv nadekobot nadekobot-old && \
|
||||
mv nadekobot-linux-x64 nadekobot && \
|
||||
rm nadekobot-old/data/aliases.yml && \
|
||||
rm -r nadekobot-old/data/strings && \
|
||||
cp -RT nadekobot-old/data/ nadekobot/data/ && \
|
||||
cp -RT nadekobot-old/data/ nadekobot/data && \
|
||||
cp nadekobot-old/creds.yml nadekobot/ && \
|
||||
cd nadekobot && chmod +x NadekoBot
|
||||
```
|
||||
|
||||
## Running Nadeko
|
||||
|
||||
While there are two run modes built into the installer, these options only run Nadeko within the current session. Below are 3 methods of running Nadeko as a background process.
|
||||
|
||||
### Tmux (Preferred Method)
|
||||
|
||||
Using `tmux` is the simplest method, and is therefore recommended for most users.
|
||||
|
||||
1. Start a tmux session:
|
||||
- `tmux`
|
||||
2. Navigate to the project's root directory
|
||||
- Project root directory location example: `/home/user/nadekobot/`
|
||||
3. Enter the `output` directory:
|
||||
- `cd output`
|
||||
4. Run the bot using:
|
||||
- `dotnet NadekoBot.dll`
|
||||
5. Detatch the tmux session:
|
||||
- Press `Ctrl` + `B`
|
||||
- Then press `D`
|
||||
|
||||
Nadeko should now be running in the background of your system. To re-open the tmux session to either update, restart, or whatever, execute `tmux a`.
|
||||
|
||||
### Systemd
|
||||
|
||||
Compared to using tmux, this method requires a little bit more work to set up, but has the benefit of allowing Nadeko to automatically start back up after a system reboot or the execution of the `.die` command.
|
||||
|
||||
1. Navigate to the project's root directory
|
||||
- Project root directory location example: `/home/user/nadekobot/`
|
||||
2. Use the following command to create a service that will be used to start Nadeko:
|
||||
|
||||
```bash
|
||||
echo "[Unit]
|
||||
Description=NadekoBot service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=$USER
|
||||
WorkingDirectory=$PWD/output
|
||||
# If you want Nadeko to be compiled prior to every startup, uncomment the lines
|
||||
# below. Note that it's not neccessary unless you are personally modifying the
|
||||
# source code.
|
||||
#ExecStartPre=/usr/bin/dotnet build ../src/NadekoBot/NadekoBot.csproj -c Release -o output/
|
||||
ExecStart=/usr/bin/dotnet NadekoBot.dll
|
||||
StandardOutput=syslog
|
||||
StandardError=syslog
|
||||
SyslogIdentifier=NadekoBot
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target" | sudo tee /etc/systemd/system/nadeko.service
|
||||
```
|
||||
|
||||
3. Make the new service available:
|
||||
- `sudo systemctl daemon-reload`
|
||||
4. Start Nadeko:
|
||||
- `sudo systemctl start nadeko.service && sudo systemctl enable nadeko.service`
|
||||
|
||||
|
||||
### Systemd + Script
|
||||
|
||||
This method is similar to the one above, but requires one extra step, with the added benefit of better error logging and control over what happens before and after the startup of Nadeko.
|
||||
|
||||
1. Locate the project and move to its parent directory
|
||||
- Project location example: `/home/user/nadekobot/`
|
||||
- Parent directory example: `/home/user/`
|
||||
2. Use the following command to create a service that will be used to execute `NadekoRun.sh`:
|
||||
|
||||
```bash
|
||||
echo "[Unit]
|
||||
Description=NadekoBot service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=$USER
|
||||
WorkingDirectory=$PWD
|
||||
ExecStart=/bin/bash NadekoRun.sh
|
||||
StandardOutput=syslog
|
||||
StandardError=syslog
|
||||
SyslogIdentifier=NadekoBot
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target" | sudo tee /etc/systemd/system/nadeko.service
|
||||
```
|
||||
|
||||
3. Make the new service available:
|
||||
- `sudo systemctl daemon-reload`
|
||||
4. Use the following command to create a script that will be used to start Nadeko:
|
||||
|
||||
```bash
|
||||
echo "#\!/bin/bash
|
||||
|
||||
echo \"\"
|
||||
echo \"Running NadekoBot in the background with auto restart\"
|
||||
youtube-dl -U
|
||||
|
||||
# If you want Nadeko to be compiled prior to every startup, uncomment the lines
|
||||
# below. Note that it's not neccessary unless you are personally modifying the
|
||||
# source code.
|
||||
#echo \"Compiling NadekoBot...\"
|
||||
#cd \"$PWD\"/nadekobot
|
||||
#dotnet build src/NadekoBot/NadekoBot.csproj -c Release -o output/
|
||||
|
||||
echo \"Starting NadekoBot...\"
|
||||
|
||||
while true; do
|
||||
{
|
||||
cd \"$PWD\"/nadekobot/output
|
||||
dotnet NadekoBot.dll
|
||||
## If a non-zero exit code is produced, exit this script.
|
||||
} || {
|
||||
error_code=\"\$?\"
|
||||
echo \"An error occurred when trying to start NadekBot\"
|
||||
echo \"EXIT CODE: \$?\"
|
||||
exit \"\$error_code\"
|
||||
}
|
||||
|
||||
youtube-dl -U
|
||||
echo \"Restarting NadekoBot...\"
|
||||
done
|
||||
|
||||
echo \"Stopping NadekoBot...\"" > NadekoRun.sh
|
||||
```
|
||||
|
||||
5. Start Nadeko:
|
||||
- `sudo systemctl start nadeko.service && sudo systemctl enable nadeko.service`
|
@@ -80,6 +80,7 @@ You can still install them manually:
|
||||
Open PowerShell (press windows button on your keyboard and type powershell, it should show up; alternatively, right click the start menu and select Windows PowerShell), and navigate to the location where you want to install the bot (for example `cd ~/Desktop/`)
|
||||
|
||||
1. `git clone https://gitlab.com/kwoth/nadekobot -b v3 --depth 1`
|
||||
2. `cd nadekobot`
|
||||
3. `dotnet publish -c Release -o output/ src/NadekoBot/`
|
||||
4. `cd output && cp creds_example.yml creds.yml`
|
||||
5. Open `creds.yml` with your favorite text editor (Please don't use Notepad or WordPad. You can use Notepad++, VSCode, Atom, Sublime, or something similar)
|
||||
@@ -91,16 +92,30 @@ Open PowerShell (press windows button on your keyboard and type powershell, it s
|
||||
|
||||
Open PowerShell as described above and run the following commands:
|
||||
|
||||
1. Navigate to your bot's folder, for example `cd ~/Desktop/nadekobot/src/NadekoBot`
|
||||
2. Pull the latest updates (this will fail if you have custom code changes).
|
||||
- If you don't have custom code changes, just run `git pull`
|
||||
- If you do have custom code changes, You have 3 options
|
||||
- Undo all changes with `git checkout -- * && git pull`
|
||||
- Stash changes and try to re-apply them `git stash && git pull && git stash apply`
|
||||
- Commit your changes and resolve merge conflicts `git add . && git commit -m "My commit message" && git pull`
|
||||
3. Re-run the bot `dotnet run -c Release`
|
||||
1. Stop the bot
|
||||
- ⚠️ Make sure you don't have your database, credentials or any other nadekobot folder open in some application, this might prevent some of the steps from executing succesfully
|
||||
2. Navigate to your bot's folder, example:
|
||||
- `cd ~/Desktop/nadekobot`
|
||||
3. Pull the new version
|
||||
- `git pull`
|
||||
- ⚠️ If this fails, you may want to stash or remove your code changes if you don't know how to resolve merge conflicts
|
||||
4. **Backup** old output in case your data is overwritten
|
||||
- `cp -r -fo output/ output-old`
|
||||
5. Build the bot again
|
||||
- `dotnet publish -c Release -o output/ src/NadekoBot/`
|
||||
6. Remove old strings and aliases to avoid overwriting the updated versions of those files
|
||||
- ⚠ If you've modified said files, back them up instead
|
||||
- `rm output-old/data/aliases.yml`
|
||||
- `rm -r output-old/data/strings`
|
||||
7. Copy old data
|
||||
- `cp -Recurse .\output-old\data\ .\output\ -Force`
|
||||
8. Copy creds.yml
|
||||
- `cp output-old/creds.yml output/`
|
||||
9. Run the bot
|
||||
- `cd output`
|
||||
- `dotnet NadekoBot.dll`
|
||||
|
||||
⚠ You're expected to understand that your database will be in `bin/Release/<framework>/data/`, and if `<framework>` gets changed in the future, you will have to move your database manually.
|
||||
🎉 Enjoy
|
||||
|
||||
#### Music prerequisites
|
||||
In order to use music commands, you need ffmpeg and youtube-dl installed.
|
||||
|
@@ -102,7 +102,6 @@ namespace NadekoBot
|
||||
.AddSingleton(Client) // discord socket client
|
||||
.AddSingleton(_commandService)
|
||||
.AddSingleton(this)
|
||||
.AddSingleton<IDataCache, RedisCache>()
|
||||
.AddSingleton<ISeria, JsonSeria>()
|
||||
.AddSingleton<IPubSub, RedisPubSub>()
|
||||
.AddSingleton<IConfigSeria, YamlSeria>()
|
||||
@@ -132,10 +131,18 @@ namespace NadekoBot
|
||||
}
|
||||
else
|
||||
{
|
||||
svcs.AddSingleton<ICoordinator, RemoteGrpcCoordinator>()
|
||||
.AddSingleton<IReadyExecutor>(x => (IReadyExecutor)x.GetRequiredService<ICoordinator>());
|
||||
svcs.AddSingleton<RemoteGrpcCoordinator>()
|
||||
.AddSingleton<ICoordinator>(x => x.GetRequiredService<RemoteGrpcCoordinator>())
|
||||
.AddSingleton<IReadyExecutor>(x => x.GetRequiredService<RemoteGrpcCoordinator>());
|
||||
}
|
||||
|
||||
svcs.AddSingleton<RedisLocalDataCache>()
|
||||
.AddSingleton<ILocalDataCache>(x => x.GetRequiredService<RedisLocalDataCache>())
|
||||
.AddSingleton<RedisImagesCache>()
|
||||
.AddSingleton<IImageCache>(x => x.GetRequiredService<RedisImagesCache>())
|
||||
.AddSingleton<IReadyExecutor>(x => x.GetRequiredService<RedisImagesCache>())
|
||||
.AddSingleton<IDataCache, RedisCache>();
|
||||
|
||||
svcs.Scan(scan => scan
|
||||
.FromAssemblyOf<IReadyExecutor>()
|
||||
.AddClasses(classes => classes.AssignableToAny(
|
||||
|
@@ -12,7 +12,7 @@ namespace NadekoBot.Common.Configs
|
||||
public sealed partial class BotConfig : ICloneable<BotConfig>
|
||||
{
|
||||
[Comment(@"DO NOT CHANGE")]
|
||||
public int Version { get; set; }
|
||||
public int Version { get; set; } = 2;
|
||||
|
||||
[Comment(@"Most commands, when executed, have a small colored line
|
||||
next to the response. The color depends whether the command
|
||||
@@ -49,6 +49,11 @@ 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.")]
|
||||
public List<string> DmHelpTextKeywords { get; set; }
|
||||
|
||||
[Comment(@"This is the response for the .h command")]
|
||||
[YamlMember(ScalarStyle = ScalarStyle.Literal)]
|
||||
public string HelpText { get; set; }
|
||||
@@ -89,7 +94,6 @@ See RotatingStatuses submodule in Administration.")]
|
||||
|
||||
public BotConfig()
|
||||
{
|
||||
Version = 1;
|
||||
var color = new ColorConfig();
|
||||
Color = color;
|
||||
DefaultLocale = new CultureInfo("en-US");
|
||||
@@ -127,6 +131,14 @@ See RotatingStatuses submodule in Administration.")]
|
||||
Prefix = ".";
|
||||
RotateStatuses = false;
|
||||
GroupGreets = false;
|
||||
DmHelpTextKeywords = new List<string>()
|
||||
{
|
||||
"help",
|
||||
"commands",
|
||||
"cmds",
|
||||
"module",
|
||||
"can you do"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -89,6 +89,8 @@ namespace NadekoBot.Common.Replacements
|
||||
_reps.TryAdd("%server.id%", () => g is null ? "DM" : g.Id.ToString());
|
||||
_reps.TryAdd("%server.name%", () => g is null ? "DM" : g.Name);
|
||||
_reps.TryAdd("%server.members%", () => g != null && g is SocketGuild sg ? sg.MemberCount.ToString() : "?");
|
||||
_reps.TryAdd("%server.boosters%", () => g.PremiumSubscriptionCount.ToString());
|
||||
_reps.TryAdd("%server.boost_level%", () => ((int)g.PremiumTier).ToString());
|
||||
_reps.TryAdd("%server.time%", () =>
|
||||
{
|
||||
TimeZoneInfo to = TimeZoneInfo.Local;
|
||||
|
@@ -121,6 +121,15 @@ namespace NadekoBot.Db
|
||||
.Where(x => x.GuildId == guildId)
|
||||
.FirstOrDefault();
|
||||
|
||||
if (logSetting is null)
|
||||
{
|
||||
ctx.LogSettings.Add(logSetting = new ()
|
||||
{
|
||||
GuildId = guildId
|
||||
});
|
||||
ctx.SaveChanges();
|
||||
}
|
||||
|
||||
return logSetting;
|
||||
}
|
||||
|
||||
|
@@ -90,7 +90,7 @@ namespace NadekoBot.Modules.Administration
|
||||
return;
|
||||
|
||||
await _service.TimedMute(user, ctx.User, time.Time, reason: reason).ConfigureAwait(false);
|
||||
await ReplyErrorLocalizedAsync(strs.user_muted_time(Format.Bold(user.ToString()), (int)time.Time.TotalMinutes));
|
||||
await ReplyConfirmLocalizedAsync(strs.user_muted_time(Format.Bold(user.ToString()), (int)time.Time.TotalMinutes));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -150,7 +150,7 @@ namespace NadekoBot.Modules.Administration
|
||||
return;
|
||||
|
||||
await _service.TimedMute(user, ctx.User, time.Time, MuteType.Chat, reason: reason).ConfigureAwait(false);
|
||||
await ReplyErrorLocalizedAsync(strs.user_chat_mute_time(Format.Bold(user.ToString()), (int)time.Time.TotalMinutes));
|
||||
await ReplyConfirmLocalizedAsync(strs.user_chat_mute_time(Format.Bold(user.ToString()), (int)time.Time.TotalMinutes));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -209,7 +209,7 @@ namespace NadekoBot.Modules.Administration
|
||||
return;
|
||||
|
||||
await _service.TimedMute(user, ctx.User, time.Time, MuteType.Voice, reason: reason).ConfigureAwait(false);
|
||||
await ReplyErrorLocalizedAsync(strs.user_voice_mute_time(Format.Bold(user.ToString()), (int)time.Time.TotalMinutes));
|
||||
await ReplyConfirmLocalizedAsync(strs.user_voice_mute_time(Format.Bold(user.ToString()), (int)time.Time.TotalMinutes));
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
@@ -61,7 +61,7 @@ namespace NadekoBot.Modules.Administration
|
||||
if (msg is null)
|
||||
return;
|
||||
|
||||
await ReplyErrorLocalizedAsync(strs.reprm(msg));
|
||||
await ReplyConfirmLocalizedAsync(strs.reprm(msg));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -28,7 +28,7 @@ namespace NadekoBot.Modules.Administration
|
||||
return;
|
||||
}
|
||||
|
||||
await ReplyErrorLocalizedAsync(strs.protection_not_running("Anti-Alt"));
|
||||
await ReplyConfirmLocalizedAsync(strs.protection_not_running("Anti-Alt"));
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
@@ -69,11 +69,11 @@ namespace NadekoBot.Modules.Administration
|
||||
{
|
||||
if (_service.TryStopAntiRaid(ctx.Guild.Id))
|
||||
{
|
||||
return ReplyErrorLocalizedAsync(strs.prot_disable("Anti-Raid"));
|
||||
return ReplyConfirmLocalizedAsync(strs.prot_disable("Anti-Raid"));
|
||||
}
|
||||
else
|
||||
{
|
||||
return ReplyErrorLocalizedAsync(strs.protection_not_running("Anti-Raid"));
|
||||
return ReplyPendingLocalizedAsync(strs.protection_not_running("Anti-Raid"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,11 +145,11 @@ namespace NadekoBot.Modules.Administration
|
||||
{
|
||||
if (_service.TryStopAntiSpam(ctx.Guild.Id))
|
||||
{
|
||||
return ReplyErrorLocalizedAsync(strs.prot_disable("Anti-Spam"));
|
||||
return ReplyConfirmLocalizedAsync(strs.prot_disable("Anti-Spam"));
|
||||
}
|
||||
else
|
||||
{
|
||||
return ReplyErrorLocalizedAsync(strs.protection_not_running("Anti-Spam"));
|
||||
return ReplyPendingLocalizedAsync(strs.protection_not_running("Anti-Spam"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -189,7 +189,7 @@ namespace NadekoBot.Modules.Administration
|
||||
index--;
|
||||
var rr = rrs[index];
|
||||
_service.Remove(ctx.Guild.Id, index);
|
||||
await ReplyErrorLocalizedAsync(strs.reaction_role_removed(index + 1));
|
||||
await ReplyConfirmLocalizedAsync(strs.reaction_role_removed(index + 1));
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
|
@@ -24,11 +24,11 @@ namespace NadekoBot.Modules.Administration
|
||||
|
||||
if (newVal)
|
||||
{
|
||||
await ReplyErrorLocalizedAsync(strs.adsarm_enable(Prefix));
|
||||
await ReplyConfirmLocalizedAsync(strs.adsarm_enable(Prefix));
|
||||
}
|
||||
else
|
||||
{
|
||||
await ReplyErrorLocalizedAsync(strs.adsarm_disable(Prefix));
|
||||
await ReplyConfirmLocalizedAsync(strs.adsarm_disable(Prefix));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -88,7 +88,7 @@ namespace NadekoBot.Modules.Administration
|
||||
};
|
||||
_service.AddNewAutoCommand(cmd);
|
||||
|
||||
await ReplyErrorLocalizedAsync(strs.autocmd_add(Format.Code(Format.Sanitize(cmdText)), cmd.Interval));
|
||||
await ReplyConfirmLocalizedAsync(strs.autocmd_add(Format.Code(Format.Sanitize(cmdText)), cmd.Interval));
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
@@ -226,7 +226,7 @@ namespace NadekoBot.Modules.Administration
|
||||
if (enabled)
|
||||
await ReplyConfirmLocalizedAsync(strs.fwdm_start).ConfigureAwait(false);
|
||||
else
|
||||
await ReplyConfirmLocalizedAsync(strs.fwdm_stop).ConfigureAwait(false);
|
||||
await ReplyPendingLocalizedAsync(strs.fwdm_stop).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
@@ -238,7 +238,7 @@ namespace NadekoBot.Modules.Administration
|
||||
if (enabled)
|
||||
await ReplyConfirmLocalizedAsync(strs.fwall_start).ConfigureAwait(false);
|
||||
else
|
||||
await ReplyConfirmLocalizedAsync(strs.fwall_stop).ConfigureAwait(false);
|
||||
await ReplyPendingLocalizedAsync(strs.fwall_stop).ConfigureAwait(false);
|
||||
|
||||
}
|
||||
|
||||
@@ -376,7 +376,7 @@ namespace NadekoBot.Modules.Administration
|
||||
var curUser = await ctx.Guild.GetCurrentUserAsync().ConfigureAwait(false);
|
||||
await curUser.ModifyAsync(u => u.Nickname = newNick).ConfigureAwait(false);
|
||||
|
||||
await ReplyErrorLocalizedAsync(strs.bot_nick(Format.Bold(newNick) ?? "-"));
|
||||
await ReplyConfirmLocalizedAsync(strs.bot_nick(Format.Bold(newNick) ?? "-"));
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
@@ -395,7 +395,7 @@ namespace NadekoBot.Modules.Administration
|
||||
|
||||
await gu.ModifyAsync(u => u.Nickname = newNick).ConfigureAwait(false);
|
||||
|
||||
await ReplyErrorLocalizedAsync(strs.user_nick(Format.Bold(gu.ToString()), Format.Bold(newNick) ?? "-"));
|
||||
await ReplyConfirmLocalizedAsync(strs.user_nick(Format.Bold(gu.ToString()), Format.Bold(newNick) ?? "-"));
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
@@ -496,7 +496,7 @@ namespace NadekoBot.Modules.Administration
|
||||
public async Task ImagesReload()
|
||||
{
|
||||
await _service.ReloadImagesAsync();
|
||||
await ReplyErrorLocalizedAsync(strs.images_loading);
|
||||
await ReplyConfirmLocalizedAsync(strs.images_loading);
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
|
@@ -294,7 +294,7 @@ namespace NadekoBot.Modules.CustomReactions
|
||||
.WithDescription("This will delete all custom reactions on this server.")).ConfigureAwait(false))
|
||||
{
|
||||
var count = _service.DeleteAllCustomReactions(ctx.Guild.Id);
|
||||
await ReplyErrorLocalizedAsync(strs.cleared(count));
|
||||
await ReplyConfirmLocalizedAsync(strs.cleared(count));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -217,7 +217,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
[Priority(0)]
|
||||
public async Task Cash(ulong userId)
|
||||
{
|
||||
await ReplyErrorLocalizedAsync(strs.has(Format.Code(userId.ToString()), $"{GetCurrency(userId)} {CurrencySign}"));
|
||||
await ReplyConfirmLocalizedAsync(strs.has(Format.Code(userId.ToString()), $"{GetCurrency(userId)} {CurrencySign}"));
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
@@ -269,7 +269,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
$"Awarded by bot owner. ({ctx.User.Username}/{ctx.User.Id}) {(msg ?? "")}",
|
||||
amount,
|
||||
gamble: (ctx.Client.CurrentUser.Id != usrId)).ConfigureAwait(false);
|
||||
await ReplyErrorLocalizedAsync(strs.awarded(n(amount) + CurrencySign, $"<@{usrId}>"));
|
||||
await ReplyConfirmLocalizedAsync(strs.awarded(n(amount) + CurrencySign, $"<@{usrId}>"));
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
@@ -340,7 +340,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
|
||||
if (await _cs.RemoveAsync(usrId, $"Taken by bot owner.({ctx.User.Username}/{ctx.User.Id})", amount,
|
||||
gamble: (ctx.Client.CurrentUser.Id != usrId)).ConfigureAwait(false))
|
||||
await ReplyErrorLocalizedAsync(strs.take(amount + CurrencySign, $"<@{usrId}>"));
|
||||
await ReplyConfirmLocalizedAsync(strs.take(amount + CurrencySign, $"<@{usrId}>"));
|
||||
else
|
||||
await ReplyErrorLocalizedAsync(strs.take_fail(amount + CurrencySign, Format.Code(usrId.ToString()), CurrencySign));
|
||||
}
|
||||
|
@@ -145,11 +145,11 @@ namespace NadekoBot.Modules.Gambling
|
||||
|
||||
if (result == DivorceResult.SucessWithPenalty)
|
||||
{
|
||||
await ReplyErrorLocalizedAsync(strs.waifu_divorced_like(Format.Bold(w.Waifu.ToString()), amount + CurrencySign));
|
||||
await ReplyConfirmLocalizedAsync(strs.waifu_divorced_like(Format.Bold(w.Waifu.ToString()), amount + CurrencySign));
|
||||
}
|
||||
else if (result == DivorceResult.Success)
|
||||
{
|
||||
await ReplyErrorLocalizedAsync(strs.waifu_divorced_notlike(amount + CurrencySign));
|
||||
await ReplyConfirmLocalizedAsync(strs.waifu_divorced_notlike(amount + CurrencySign));
|
||||
}
|
||||
else if (result == DivorceResult.NotYourWife)
|
||||
{
|
||||
@@ -306,7 +306,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
[Priority(1)]
|
||||
public async Task WaifuGift(int page = 1)
|
||||
{
|
||||
if (--page < 0 || page > 3)
|
||||
if (--page < 0 || page > (_config.Waifu.Items.Count - 1) / 9)
|
||||
return;
|
||||
|
||||
var waifuItems = _service.GetWaifuItems();
|
||||
|
@@ -434,7 +434,7 @@ namespace NadekoBot.Modules.Help
|
||||
[NadekoCommand, Aliases]
|
||||
public async Task Donate()
|
||||
{
|
||||
await ReplyErrorLocalizedAsync(strs.donate(PatreonUrl, PaypalUrl));
|
||||
await ReplyConfirmLocalizedAsync(strs.donate(PatreonUrl, PaypalUrl));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -45,6 +45,11 @@ namespace NadekoBot.Modules.Help.Services
|
||||
if (string.IsNullOrWhiteSpace(settings.DmHelpText) || settings.DmHelpText == "-")
|
||||
return Task.CompletedTask;
|
||||
|
||||
// only send dm help text if it contains one of the keywords, if they're specified
|
||||
// if they're not, then reply to every DM
|
||||
if (settings.DmHelpTextKeywords.Any() && !settings.DmHelpTextKeywords.Any(k => msg.Content.Contains(k)))
|
||||
return Task.CompletedTask;
|
||||
|
||||
var rep = new ReplacementBuilder()
|
||||
.WithOverride("%prefix%", () => _bss.Data.Prefix)
|
||||
.WithOverride("%bot.prefix%", () => _bss.Data.Prefix)
|
||||
|
@@ -125,7 +125,7 @@ namespace NadekoBot.Modules.Music
|
||||
queuedMessage?.DeleteAfter(10, _logService);
|
||||
if (mp.IsStopped)
|
||||
{
|
||||
var msg = await ReplyErrorLocalizedAsync(strs.queue_stopped(Format.Code(Prefix + "play")));
|
||||
var msg = await ReplyPendingLocalizedAsync(strs.queue_stopped(Format.Code(Prefix + "play")));
|
||||
msg.DeleteAfter(10, _logService);
|
||||
}
|
||||
}
|
||||
@@ -230,7 +230,7 @@ namespace NadekoBot.Modules.Music
|
||||
return;
|
||||
|
||||
await _service.SetVolumeAsync(ctx.Guild.Id, vol);
|
||||
await ReplyErrorLocalizedAsync(strs.volume_set(vol));
|
||||
await ReplyConfirmLocalizedAsync(strs.volume_set(vol));
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
|
@@ -189,7 +189,7 @@ namespace NadekoBot.Modules.NSFW
|
||||
return t;
|
||||
});
|
||||
|
||||
await ReplyErrorLocalizedAsync(strs.started(interval));
|
||||
await ReplyConfirmLocalizedAsync(strs.started(interval));
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
@@ -229,7 +229,7 @@ namespace NadekoBot.Modules.NSFW
|
||||
return t;
|
||||
});
|
||||
|
||||
await ReplyErrorLocalizedAsync(strs.started(interval));
|
||||
await ReplyConfirmLocalizedAsync(strs.started(interval));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -363,9 +363,9 @@ namespace NadekoBot.Modules.NSFW
|
||||
var added = _service.ToggleBlacklistedTag(ctx.Guild.Id, tag);
|
||||
|
||||
if (added)
|
||||
await ReplyErrorLocalizedAsync(strs.blacklisted_tag_add(tag));
|
||||
await ReplyPendingLocalizedAsync(strs.blacklisted_tag_add(tag));
|
||||
else
|
||||
await ReplyErrorLocalizedAsync(strs.blacklisted_tag_remove(tag));
|
||||
await ReplyPendingLocalizedAsync(strs.blacklisted_tag_remove(tag));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -217,7 +217,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
{
|
||||
}
|
||||
}
|
||||
await ReplyErrorLocalizedAsync(strs.perm_out_of_range).ConfigureAwait(false);
|
||||
await ReplyConfirmLocalizedAsync(strs.perm_out_of_range).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
|
@@ -66,7 +66,7 @@ namespace NadekoBot.Modules.Searches
|
||||
}
|
||||
}
|
||||
|
||||
await ReplyErrorLocalizedAsync(strs.feed_not_valid).ConfigureAwait(false);
|
||||
await ReplyConfirmLocalizedAsync(strs.feed_not_valid).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
|
@@ -191,7 +191,7 @@ namespace NadekoBot.Modules.Searches
|
||||
return;
|
||||
}
|
||||
|
||||
await ReplyErrorLocalizedAsync(strs.stream_message_set_all(count));
|
||||
await ReplyConfirmLocalizedAsync(strs.stream_message_set_all(count));
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
|
@@ -118,7 +118,7 @@ namespace NadekoBot.Modules.Searches
|
||||
|
||||
_searches.UserLanguages.AddOrUpdate(ucp, langs, (key, val) => langs);
|
||||
|
||||
await ReplyErrorLocalizedAsync(strs.atl_set(from, to));
|
||||
await ReplyConfirmLocalizedAsync(strs.atl_set(from, to));
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
|
@@ -37,7 +37,7 @@ namespace NadekoBot.Modules.Utility
|
||||
public async Task AliasesClear()
|
||||
{
|
||||
var count = _service.ClearAliases(ctx.Guild.Id);
|
||||
await ReplyErrorLocalizedAsync(strs.aliases_cleared(count));
|
||||
await ReplyConfirmLocalizedAsync(strs.aliases_cleared(count));
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
|
@@ -148,7 +148,7 @@ namespace NadekoBot.Modules.Utility
|
||||
}
|
||||
else
|
||||
{
|
||||
await ReplyErrorLocalizedAsync(strs.reminder_deleted(index + 1));
|
||||
await ReplyConfirmLocalizedAsync(strs.reminder_deleted(index + 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -183,7 +183,9 @@ namespace NadekoBot.Modules.Utility
|
||||
private string GetRepeaterInfoString(RunningRepeater runner)
|
||||
{
|
||||
var intervalString = Format.Bold(runner.Repeater.Interval.ToPrettyStringHM());
|
||||
var executesIn = runner.NextTime - DateTime.UtcNow;
|
||||
var executesIn = runner.NextTime < DateTime.UtcNow
|
||||
? TimeSpan.Zero
|
||||
: runner.NextTime - DateTime.UtcNow;
|
||||
var executesInString = Format.Bold(executesIn.ToPrettyStringHM());
|
||||
var message = Format.Sanitize(runner.Repeater.Message.TrimTo(50));
|
||||
|
||||
|
@@ -76,7 +76,9 @@ where ((guildid >> 22) % {_creds.TotalShards}) == {_client.ShardId};")
|
||||
// because repeaters might've been modified meanwhile
|
||||
if (timeout > TimeSpan.Zero)
|
||||
{
|
||||
await Task.Delay(timeout);
|
||||
await Task.Delay(timeout > TimeSpan.FromMinutes(1)
|
||||
? TimeSpan.FromMinutes(1)
|
||||
: timeout);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -84,16 +86,17 @@ where ((guildid >> 22) % {_creds.TotalShards}) == {_client.ShardId};")
|
||||
var now = DateTime.UtcNow + TimeSpan.FromSeconds(3);
|
||||
|
||||
var toExecute = new List<RunningRepeater>();
|
||||
while (true)
|
||||
{
|
||||
lock (_repeaterQueue)
|
||||
{
|
||||
var current = _repeaterQueue.First;
|
||||
while (true)
|
||||
{
|
||||
|
||||
if (current is null || current.Value.NextTime > now)
|
||||
break;
|
||||
|
||||
toExecute.Add(current.Value);
|
||||
_repeaterQueue.RemoveFirst();
|
||||
current = current.Next;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,13 +124,23 @@ where ((guildid >> 22) % {_creds.TotalShards}) == {_client.ShardId};")
|
||||
{
|
||||
if (rep.ErrorCount >= 10)
|
||||
{
|
||||
RemoveFromQueue(rep.Repeater.Id);
|
||||
await RemoveRepeaterInternal(rep.Repeater);
|
||||
return;
|
||||
}
|
||||
|
||||
UpdatePosition(rep);
|
||||
}
|
||||
|
||||
private void UpdatePosition(RunningRepeater rep)
|
||||
{
|
||||
lock (_queueLocker)
|
||||
{
|
||||
rep.UpdateNextTime();
|
||||
_repeaterQueue.Remove(rep);
|
||||
AddToQueue(rep);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> TriggerExternal(ulong guildId, int index)
|
||||
{
|
||||
|
@@ -92,5 +92,15 @@ namespace NadekoBot.Modules.Utility.Services
|
||||
var initialIntervalMultiplier = 1 - (triggerCount - Math.Truncate(triggerCount));
|
||||
return DateTime.UtcNow + (Repeater.Interval * initialIntervalMultiplier);
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is RunningRepeater rr && rr.Repeater.Id == this.Repeater.Id;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return this.Repeater.Id;
|
||||
}
|
||||
}
|
||||
}
|
@@ -31,7 +31,7 @@ namespace NadekoBot.Modules.Xp
|
||||
|
||||
_service.XpReset(ctx.Guild.Id, userId);
|
||||
|
||||
await ReplyErrorLocalizedAsync(strs.reset_user(userId));
|
||||
await ReplyConfirmLocalizedAsync(strs.reset_user(userId));
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
|
@@ -30,7 +30,7 @@ namespace NadekoBot.Modules.Xp.Services
|
||||
|
||||
private void Migrate()
|
||||
{
|
||||
if (_data.Version <= 1)
|
||||
if (_data.Version < 2)
|
||||
{
|
||||
ModifyConfig(c =>
|
||||
{
|
||||
|
@@ -128,7 +128,7 @@ namespace NadekoBot.Modules.Xp
|
||||
public async Task XpRoleReward(int level)
|
||||
{
|
||||
_service.ResetRoleReward(ctx.Guild.Id, level);
|
||||
await ReplyErrorLocalizedAsync(strs.xp_role_reward_cleared(level));
|
||||
await ReplyConfirmLocalizedAsync(strs.xp_role_reward_cleared(level));
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
|
@@ -11,11 +11,12 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using NadekoBot.Common.ModuleBehaviors;
|
||||
using Serilog;
|
||||
|
||||
namespace NadekoBot.Services
|
||||
{
|
||||
public sealed class RedisImagesCache : IImageCache
|
||||
public sealed class RedisImagesCache : IImageCache, IReadyExecutor
|
||||
{
|
||||
private readonly ConnectionMultiplexer _con;
|
||||
private readonly IBotCredentials _creds;
|
||||
@@ -73,6 +74,14 @@ namespace NadekoBot.Services
|
||||
Currency,
|
||||
}
|
||||
|
||||
public async Task OnReadyAsync()
|
||||
{
|
||||
if (await AllKeysExist())
|
||||
return;
|
||||
|
||||
await Reload();
|
||||
}
|
||||
|
||||
public RedisImagesCache(ConnectionMultiplexer con, IBotCredentials creds)
|
||||
{
|
||||
_con = con;
|
||||
|
@@ -5,7 +5,6 @@ using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using Discord;
|
||||
using Discord.WebSocket;
|
||||
|
||||
namespace NadekoBot.Services
|
||||
@@ -20,12 +19,13 @@ namespace NadekoBot.Services
|
||||
private readonly string _redisKey;
|
||||
private readonly EndPoint _redisEndpoint;
|
||||
|
||||
public RedisCache(ConnectionMultiplexer redis, IBotCredentials creds, DiscordSocketClient client)
|
||||
public RedisCache(ConnectionMultiplexer redis, IBotCredentials creds,
|
||||
IImageCache imageCache, ILocalDataCache dataCache)
|
||||
{
|
||||
Redis = redis;
|
||||
_redisEndpoint = Redis.GetEndPoints().First();
|
||||
LocalImages = new RedisImagesCache(Redis, creds);
|
||||
LocalData = new RedisLocalDataCache(Redis, creds, client.ShardId);
|
||||
LocalImages = imageCache;
|
||||
LocalData = dataCache;
|
||||
_redisKey = creds.RedisKey();
|
||||
}
|
||||
|
||||
|
@@ -7,6 +7,8 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Discord;
|
||||
using Discord.WebSocket;
|
||||
using Serilog;
|
||||
|
||||
namespace NadekoBot.Services
|
||||
@@ -25,56 +27,33 @@ namespace NadekoBot.Services
|
||||
|
||||
public IReadOnlyDictionary<string, SearchPokemon> Pokemons
|
||||
{
|
||||
get
|
||||
{
|
||||
return Get<Dictionary<string, SearchPokemon>>("pokemon_list");
|
||||
}
|
||||
private set
|
||||
{
|
||||
Set("pokemon_list", value);
|
||||
}
|
||||
get => Get<Dictionary<string, SearchPokemon>>("pokemon_list");
|
||||
private set => Set("pokemon_list", value);
|
||||
}
|
||||
|
||||
public IReadOnlyDictionary<string, SearchPokemonAbility> PokemonAbilities
|
||||
{
|
||||
get
|
||||
{
|
||||
return Get<Dictionary<string, SearchPokemonAbility>>("pokemon_abilities");
|
||||
}
|
||||
private set
|
||||
{
|
||||
Set("pokemon_abilities", value);
|
||||
}
|
||||
get => Get<Dictionary<string, SearchPokemonAbility>>("pokemon_abilities");
|
||||
private set => Set("pokemon_abilities", value);
|
||||
}
|
||||
|
||||
public TriviaQuestion[] TriviaQuestions
|
||||
{
|
||||
get
|
||||
{
|
||||
return Get<TriviaQuestion[]>("trivia_questions");
|
||||
}
|
||||
private set
|
||||
{
|
||||
Set("trivia_questions", value);
|
||||
}
|
||||
get => Get<TriviaQuestion[]>("trivia_questions");
|
||||
private set => Set("trivia_questions", value);
|
||||
}
|
||||
|
||||
public IReadOnlyDictionary<int, string> PokemonMap
|
||||
{
|
||||
get
|
||||
{
|
||||
return Get<Dictionary<int, string>>("pokemon_map");
|
||||
}
|
||||
private set
|
||||
{
|
||||
Set("pokemon_map", value);
|
||||
}
|
||||
get => Get<Dictionary<int, string>>("pokemon_map");
|
||||
private set => Set("pokemon_map", value);
|
||||
}
|
||||
|
||||
public RedisLocalDataCache(ConnectionMultiplexer con, IBotCredentials creds, int shardId)
|
||||
public RedisLocalDataCache(ConnectionMultiplexer con, IBotCredentials creds, DiscordSocketClient client)
|
||||
{
|
||||
_con = con;
|
||||
_creds = creds;
|
||||
var shardId = client.ShardId;
|
||||
|
||||
if (shardId == 0)
|
||||
{
|
||||
|
@@ -19,7 +19,7 @@ namespace NadekoBot.Services
|
||||
private readonly IBotCredentials _creds;
|
||||
private readonly DateTime _started;
|
||||
|
||||
public const string BotVersion = "3.0.3";
|
||||
public const string BotVersion = "3.0.5";
|
||||
public string Author => "Kwoth#2452";
|
||||
public string Library => "Discord.Net";
|
||||
|
||||
|
@@ -28,19 +28,15 @@ namespace NadekoBot.Services
|
||||
AddParsedProp("locale", bs => bs.DefaultLocale, ConfigParsers.Culture, ConfigPrinters.Culture);
|
||||
AddParsedProp("prefix", bs => bs.Prefix, ConfigParsers.String, ConfigPrinters.ToString);
|
||||
|
||||
UpdateColors();
|
||||
Migrate();
|
||||
}
|
||||
|
||||
private void UpdateColors()
|
||||
private void Migrate()
|
||||
{
|
||||
var ok = _data.Color.Ok;
|
||||
var error = _data.Color.Error;
|
||||
var pend = _data.Color.Pending;
|
||||
}
|
||||
|
||||
protected override void OnStateUpdate()
|
||||
if (_data.Version < 2)
|
||||
{
|
||||
UpdateColors();
|
||||
ModifyConfig(c => c.Version = 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
# DO NOT CHANGE
|
||||
version: 1
|
||||
version: 2
|
||||
# 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)
|
||||
@@ -28,6 +28,15 @@ forwardToAllOwners: false
|
||||
# Supports embeds. How it looks: https://puu.sh/B0BLV.png
|
||||
dmHelpText: |-
|
||||
{"description": "Type `%prefix%h` for help."}
|
||||
# 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.
|
||||
dmHelpTextKeywords:
|
||||
- help
|
||||
- commands
|
||||
- cmds
|
||||
- module
|
||||
- can you do
|
||||
# This is the response for the .h command
|
||||
helpText: |-
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user