mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-11 09:48:26 -04:00
Compare commits
60 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
e49e3eec69 | ||
|
3992ae392b | ||
|
8f0c5fab47 | ||
|
780a260b88 | ||
|
25692b9585 | ||
|
ed3ce52865 | ||
|
f5f0f1e250 | ||
|
9d9e61fdfb | ||
|
e68e948a80 | ||
|
cb98f4aa15 | ||
|
bfec0cbcbf | ||
|
3e1268f3bb | ||
|
c28f458972 | ||
|
27ac948463 | ||
|
3f9a3c4c18 | ||
|
9a5545a951 | ||
|
584193db18 | ||
|
1a132fd234 | ||
|
fd6a51ac82 | ||
|
eb1fabb2b7 | ||
|
d079e684bd | ||
|
bf817a1436 | ||
|
78f1624aaf | ||
|
793a49fc64 | ||
|
8b6be656b3 | ||
|
89a88304dc | ||
|
a7fe9ae08f | ||
|
0469705037 | ||
|
dc568fe0e2 | ||
|
eb01bb6c08 | ||
|
71a3539d0e | ||
|
c896a0cdb8 | ||
|
8effe817ad | ||
|
eedf6998b6 | ||
|
e6b7c31a72 | ||
|
2f77fd57b0 | ||
|
fda3d92134 | ||
|
fe6f28143b | ||
|
df3909fc55 | ||
|
9ffa701742 | ||
|
a4f7df8aee | ||
|
15e6cff14a | ||
|
e63ac07a52 | ||
|
a294e3bf8f | ||
|
a5b2fac69c | ||
|
a8e06a5ae4 | ||
|
761bdd8610 | ||
|
b5904889b0 | ||
|
5b4517cf5c | ||
|
72158c0a2c | ||
|
1ca6f6dc5c | ||
|
005fd7b8c6 | ||
|
3fc53b0609 | ||
|
62ec2241e4 | ||
|
75f8254a8e | ||
|
f23ffe0c67 | ||
|
d1a818542c | ||
|
15f67e3a51 | ||
|
412f346ac8 | ||
|
8107a80c4c |
@@ -104,7 +104,7 @@ publish-medusa-package:
|
|||||||
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_TAG
|
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH || $CI_COMMIT_TAG
|
||||||
script:
|
script:
|
||||||
- LAST_TAG=$(git describe --tags --abbrev=0)
|
- LAST_TAG=$(git describe --tags --abbrev=0)
|
||||||
- if [ $CI_COMMIT_TAG ];then MEDUSA_VERSION="$CI_COMMIT_TAG"; else MEDUSA_VERSION="$LAST_TAG-$CI_COMMIT_SHA"; fi
|
- if [ $CI_COMMIT_TAG ];then MEDUSA_VERSION="$CI_COMMIT_TAG"; else MEDUSA_VERSION="$LAST_TAG-$CI_COMMIT_SHORT_SHA"; fi
|
||||||
- cd src/Nadeko.Medusa/
|
- cd src/Nadeko.Medusa/
|
||||||
- dotnet pack -c Release /p:Version=$MEDUSA_VERSION -o bin/Release/packed
|
- dotnet pack -c Release /p:Version=$MEDUSA_VERSION -o bin/Release/packed
|
||||||
- dotnet nuget push bin/Release/packed/ --source https://www.myget.org/F/nadeko/api/v2/package --api-key "$MYGET_API_KEY"
|
- dotnet nuget push bin/Release/packed/ --source https://www.myget.org/F/nadeko/api/v2/package --api-key "$MYGET_API_KEY"
|
||||||
|
86
CHANGELOG.md
86
CHANGELOG.md
@@ -2,6 +2,92 @@
|
|||||||
|
|
||||||
Experimental changelog. Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except date format. a-c-f-r-o
|
Experimental changelog. Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except date format. a-c-f-r-o
|
||||||
|
|
||||||
|
## [4.3.10] - 10.11.2022
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- `.filterlist` / `.fl` command which lists link and invite filtering channels and status
|
||||||
|
- Added support for `%target%` placeholder in `.alias` command
|
||||||
|
- Added .forwardtochannel which will forward messages to the current channel. It has lower priority than fwtoall
|
||||||
|
- Added .exprtoggleglobal / .extg which can be used to toggle usage of global expressions on the server
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- .meload and .meunload are now case sensitive. Previously loaded medusae may need to be reloaded or data/medusae/medusa.yml may need to be edited manually
|
||||||
|
- Several club related command have their error messages improved
|
||||||
|
- Updated help text for .antispam and .antiraid
|
||||||
|
- You can now specify time and date (time is optional) in `.remind` command instead of relative time, in the format `HH:mm dd.MM.YYYY`
|
||||||
|
- OwnerId will be automatically added to `creds.yml` at bot startup if it's missing
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed `.cmdcd` console error
|
||||||
|
- Fixed an error when currency is add per xp
|
||||||
|
- Fixed an issue preventing execution of expressions starting with @Bot when cleverbot is enabled on the server
|
||||||
|
- Fixed `.feedadd`
|
||||||
|
- Fixed `.prune @target` not working
|
||||||
|
- Medusa modules (sneks) should now inherit medusa description when listed in .mdls command
|
||||||
|
- Fixed command cooldown calculation
|
||||||
|
|
||||||
|
## [4.3.9] - 12.10.2022
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- `.betstats` shows sum of all bets, payouts and the payout rate in %. Updates once an hour
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- `.betstats` looks way better (except on Mac)
|
||||||
|
- `.feedadd` errors clarified and separated in individual error messages for each issue.
|
||||||
|
- `.clubban` and `.clubunban` errors clarified and separated in individual error messages for each issue.
|
||||||
|
- `.clubapply` better error messages
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- `.timely` 'Remind' button fixed in DMs
|
||||||
|
- `.cmdcd` database bugs fixed
|
||||||
|
- Fixed bugged mysql and postgresql migrations
|
||||||
|
- Fixed issues with lodaing medusae due to strict versioning
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- `.slotstats` Superseded by `.betstats`
|
||||||
|
|
||||||
|
## [4.3.8] - 02.10.2022
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Added `.autopublish` command which will automatically publish messages posted in the channel.
|
||||||
|
- Added `--after <messageid>` option to prune which will make prune only delete messages after the specified message id.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- `.prune` options `--after` and `--safe` are now proper command options, and will show in .h help
|
||||||
|
- `.cmdcd` code mostly rewritten, slight QoL improvements.
|
||||||
|
- Clarified `.remind` permission requirements in help text
|
||||||
|
- `.cmdcds` looks a little better, and is paginated
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed trivia bugs
|
||||||
|
- Fixed `.yun` not working with channels with underscore in the name
|
||||||
|
|
||||||
|
## [4.3.7] - 14.09.2022
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Added `.exprdelserv` (.exds) to completement .exas. Deletes an expression on the current server and is susceptible to .dpo, unlike .exd
|
||||||
|
- Added `.shopreq` which lets you set role requirement for specific shop items
|
||||||
|
- Added `.shopbuy` alias to `.buy`
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed `.convertlist` showing currencies twice (this may not apply to existing users and it may require you to manually remove all currencies from units.json)
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- Removed `Viewer` field from stream online notification as it is (almost?) always 0.
|
||||||
|
|
||||||
## [4.3.6] - 08.09.2022
|
## [4.3.6] - 08.09.2022
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@@ -17,7 +17,7 @@ It is recommended that you use **Ubuntu 20.04**, as there have been nearly no pr
|
|||||||
|
|
||||||
##### Compatible operating systems:
|
##### Compatible operating systems:
|
||||||
|
|
||||||
- Ubuntu: 16.04, 18.04, 20.04, 21.04, 21.10 22.04
|
- Ubuntu: 16.04, 18.04, 20.04, 21.04, 21.10, 22.04
|
||||||
- Mint: 19, 20
|
- Mint: 19, 20
|
||||||
- Debian: 9, 10
|
- Debian: 9, 10
|
||||||
- CentOS: 7
|
- CentOS: 7
|
||||||
@@ -316,6 +316,26 @@ This method is similar to the one above, but requires one extra step, with the a
|
|||||||
|
|
||||||
If you want Nadeko to play music for you 24/7 without having to hosting it on your PC and want to keep it cheap, reliable and convenient as possible, you can try Nadeko on Linux Digital Ocean Droplet using the link [DigitalOcean](http://m.do.co/c/46b4d3d44795/) (by using this link, you will get **$10 credit** and also support Nadeko)
|
If you want Nadeko to play music for you 24/7 without having to hosting it on your PC and want to keep it cheap, reliable and convenient as possible, you can try Nadeko on Linux Digital Ocean Droplet using the link [DigitalOcean](http://m.do.co/c/46b4d3d44795/) (by using this link, you will get **$10 credit** and also support Nadeko)
|
||||||
|
|
||||||
|
To set up the VPS, please select the options below
|
||||||
|
```
|
||||||
|
These are the min requirements you must follow:
|
||||||
|
|
||||||
|
OS: Any between Ubuntu, Fedora, and Debian
|
||||||
|
|
||||||
|
Plan: Basic
|
||||||
|
|
||||||
|
CPU options: regular with SSD
|
||||||
|
1 GB / 1 CPU
|
||||||
|
25 GB SSD Disk
|
||||||
|
1000 GB transfer
|
||||||
|
|
||||||
|
Note: You can select the cheapest option with 512 MB /1 CPU but this has been a hit or miss.
|
||||||
|
|
||||||
|
Datacenter region: Choose one depending on where you are located.
|
||||||
|
|
||||||
|
Authentication: Password or SSH
|
||||||
|
(Select SSH if you know what you are doing, otherwise choose password)
|
||||||
|
```
|
||||||
**Setting up NadekoBot**
|
**Setting up NadekoBot**
|
||||||
Assuming you have followed the link above to setup an account and a Droplet with a 64-bit operational system on Digital Ocean and got the `IP address and root password (in your e-mail)` to login, it's time to get started.
|
Assuming you have followed the link above to setup an account and a Droplet with a 64-bit operational system on Digital Ocean and got the `IP address and root password (in your e-mail)` to login, it's time to get started.
|
||||||
|
|
||||||
|
@@ -7,7 +7,7 @@ Open Terminal (if you don't know how to, click on the magnifying glass on the to
|
|||||||
###### Homebrew/wget
|
###### Homebrew/wget
|
||||||
*Skip this step if you already have homebrew installed*
|
*Skip this step if you already have homebrew installed*
|
||||||
- Copy and paste this command, then press Enter:
|
- Copy and paste this command, then press Enter:
|
||||||
- `/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"`
|
- `/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"`
|
||||||
- Install wget
|
- Install wget
|
||||||
- `brew install wget`
|
- `brew install wget`
|
||||||
|
|
||||||
|
@@ -155,7 +155,7 @@ This section will guide you through how to create a simple custom medusa. You ca
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<!-- Base medusa package. You MUST reference this in order to have a working medusa -->
|
<!-- Base medusa package. You MUST reference this in order to have a working medusa -->
|
||||||
<!-- Also, this package comes from MyGet, which requires you to have a NuGet.Config file next to your .csproj -->
|
<!-- Also, this package comes from MyGet, which requires you to have a NuGet.Config file next to your .csproj -->
|
||||||
<PackageReference Include="Nadeko.Medusa" Version="1.0.1">
|
<PackageReference Include="Nadeko.Medusa" Version="4.3.9">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|
||||||
@@ -248,4 +248,4 @@ hello:
|
|||||||
- Unload it
|
- Unload it
|
||||||
- `.meunload example_medusa`
|
- `.meunload example_medusa`
|
||||||
|
|
||||||
- Congrats! You've just made your first medusa!
|
- Congrats! You've just made your first medusa!
|
||||||
|
@@ -17,4 +17,7 @@
|
|||||||
<PackageReference Include="YamlDotNet" Version="11.2.1" />
|
<PackageReference Include="YamlDotNet" Version="11.2.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition=" '$(Version)' == '' ">
|
||||||
|
<Version>5.0.0</Version>
|
||||||
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@@ -116,10 +116,6 @@ public sealed class Bot
|
|||||||
// cache
|
// cache
|
||||||
.AddCache(_creds);
|
.AddCache(_creds);
|
||||||
|
|
||||||
// admin
|
|
||||||
#if GLOBAL_NADEKO
|
|
||||||
svcs.AddSingleton<ILogCommandService, DummyLogCommandService>();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
svcs.AddHttpClient();
|
svcs.AddHttpClient();
|
||||||
svcs.AddHttpClient("memelist")
|
svcs.AddHttpClient("memelist")
|
||||||
@@ -317,10 +313,29 @@ public sealed class Bot
|
|||||||
await _commandService.AddModulesAsync(typeof(Bot).Assembly, Services);
|
await _commandService.AddModulesAsync(typeof(Bot).Assembly, Services);
|
||||||
// await _interactionService.AddModulesAsync(typeof(Bot).Assembly, Services);
|
// await _interactionService.AddModulesAsync(typeof(Bot).Assembly, Services);
|
||||||
IsReady = true;
|
IsReady = true;
|
||||||
|
|
||||||
|
await EnsureBotOwnershipAsync();
|
||||||
_ = Task.Run(ExecuteReadySubscriptions);
|
_ = Task.Run(ExecuteReadySubscriptions);
|
||||||
Log.Information("Shard {ShardId} ready", Client.ShardId);
|
Log.Information("Shard {ShardId} ready", Client.ShardId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async ValueTask EnsureBotOwnershipAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_creds.OwnerIds.Count != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Log.Information("Initializing Owner Id...");
|
||||||
|
var info = await Client.GetApplicationInfoAsync();
|
||||||
|
_credsProvider.ModifyCredsFile(x => x.OwnerIds = new[] { info.Owner.Id });
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Warning("Getting application info failed: {ErrorMessage}", ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Task ExecuteReadySubscriptions()
|
private Task ExecuteReadySubscriptions()
|
||||||
{
|
{
|
||||||
var readyExecutors = Services.GetServices<IReadyExecutor>();
|
var readyExecutors = Services.GetServices<IReadyExecutor>();
|
||||||
|
@@ -12,7 +12,7 @@ namespace NadekoBot.Common.Configs;
|
|||||||
public sealed partial class BotConfig : ICloneable<BotConfig>
|
public sealed partial class BotConfig : ICloneable<BotConfig>
|
||||||
{
|
{
|
||||||
[Comment(@"DO NOT CHANGE")]
|
[Comment(@"DO NOT CHANGE")]
|
||||||
public int Version { get; set; } = 4;
|
public int Version { get; set; } = 5;
|
||||||
|
|
||||||
[Comment(@"Most commands, when executed, have a small colored line
|
[Comment(@"Most commands, when executed, have a small colored line
|
||||||
next to the response. The color depends whether the command
|
next to the response. The color depends whether the command
|
||||||
@@ -39,6 +39,10 @@ Allowed values: Simple, Normal, None")]
|
|||||||
@"Do you want the message to be forwarded only to the first owner specified in the list of owners (in creds.yml),
|
@"Do you want the message to be forwarded only to the first owner specified in the list of owners (in creds.yml),
|
||||||
or all owners? (this might cause the bot to lag if there's a lot of owners specified)")]
|
or all owners? (this might cause the bot to lag if there's a lot of owners specified)")]
|
||||||
public bool ForwardToAllOwners { get; set; }
|
public bool ForwardToAllOwners { get; set; }
|
||||||
|
|
||||||
|
[Comment(@"Any messages sent by users in Bot's DM to be forwarded to the specified channel.
|
||||||
|
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
|
[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.
|
they will receive this message. Leave empty for no response. The string which will be sent whenever someone DMs the bot.
|
||||||
|
@@ -186,7 +186,6 @@ public sealed class MedusaLoaderService : IMedusaLoaderService, IReadyExecutor,
|
|||||||
return MedusaLoadResult.AlreadyLoaded;
|
return MedusaLoadResult.AlreadyLoaded;
|
||||||
|
|
||||||
var safeName = Uri.EscapeDataString(name);
|
var safeName = Uri.EscapeDataString(name);
|
||||||
name = name.ToLowerInvariant();
|
|
||||||
|
|
||||||
await _lock.WaitAsync();
|
await _lock.WaitAsync();
|
||||||
try
|
try
|
||||||
@@ -525,7 +524,6 @@ public sealed class MedusaLoaderService : IMedusaLoaderService, IReadyExecutor,
|
|||||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
private async Task<MedusaUnloadResult> InternalUnloadAsync(string name)
|
private async Task<MedusaUnloadResult> InternalUnloadAsync(string name)
|
||||||
{
|
{
|
||||||
name = name.ToLowerInvariant();
|
|
||||||
if (!_resolved.Remove(name, out var lsi))
|
if (!_resolved.Remove(name, out var lsi))
|
||||||
return MedusaUnloadResult.NotLoaded;
|
return MedusaUnloadResult.NotLoaded;
|
||||||
|
|
||||||
|
@@ -1,15 +1,14 @@
|
|||||||
#nullable disable
|
using CommandLine;
|
||||||
using CommandLine;
|
|
||||||
|
|
||||||
namespace NadekoBot.Common;
|
namespace NadekoBot.Common;
|
||||||
|
|
||||||
public static class OptionsParser
|
public static class OptionsParser
|
||||||
{
|
{
|
||||||
public static T ParseFrom<T>(string[] args)
|
public static T ParseFrom<T>(string[]? args)
|
||||||
where T : INadekoCommandOptions, new()
|
where T : INadekoCommandOptions, new()
|
||||||
=> ParseFrom(new T(), args).Item1;
|
=> ParseFrom(new T(), args).Item1;
|
||||||
|
|
||||||
public static (T, bool) ParseFrom<T>(T options, string[] args)
|
public static (T, bool) ParseFrom<T>(T options, string[]? args)
|
||||||
where T : INadekoCommandOptions
|
where T : INadekoCommandOptions
|
||||||
{
|
{
|
||||||
using var p = new Parser(x =>
|
using var p = new Parser(x =>
|
||||||
|
33
src/NadekoBot/Common/TypeReaders/GuildUserTypeReader.cs
Normal file
33
src/NadekoBot/Common/TypeReaders/GuildUserTypeReader.cs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
namespace NadekoBot.Common.TypeReaders;
|
||||||
|
|
||||||
|
public sealed class GuildUserTypeReader : NadekoTypeReader<IGuildUser>
|
||||||
|
{
|
||||||
|
public override async ValueTask<TypeReaderResult<IGuildUser>> ReadAsync(ICommandContext ctx, string input)
|
||||||
|
{
|
||||||
|
if (ctx.Guild is null)
|
||||||
|
return TypeReaderResult.FromError<IGuildUser>(CommandError.Unsuccessful, "Must be in a guild.");
|
||||||
|
|
||||||
|
input = input.Trim();
|
||||||
|
IGuildUser? user = null;
|
||||||
|
if (MentionUtils.TryParseUser(input, out var id))
|
||||||
|
user = await ctx.Guild.GetUserAsync(id, CacheMode.AllowDownload);
|
||||||
|
|
||||||
|
if (ulong.TryParse(input, out id))
|
||||||
|
user = await ctx.Guild.GetUserAsync(id, CacheMode.AllowDownload);
|
||||||
|
|
||||||
|
if (user is null)
|
||||||
|
{
|
||||||
|
var users = await ctx.Guild.GetUsersAsync(CacheMode.CacheOnly);
|
||||||
|
user = users.FirstOrDefault(x => x.Username == input)
|
||||||
|
?? users.FirstOrDefault(x =>
|
||||||
|
string.Equals(x.ToString(), input, StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
?? users.FirstOrDefault(x =>
|
||||||
|
string.Equals(x.Username, input, StringComparison.InvariantCultureIgnoreCase));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user is null)
|
||||||
|
return TypeReaderResult.FromError<IGuildUser>(CommandError.ObjectNotFound, "User not found.");
|
||||||
|
|
||||||
|
return TypeReaderResult.FromSuccess(user);
|
||||||
|
}
|
||||||
|
}
|
@@ -1,4 +1,5 @@
|
|||||||
#nullable disable
|
#nullable disable
|
||||||
|
using LinqToDB.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
|
|
||||||
@@ -6,12 +7,14 @@ namespace NadekoBot.Db;
|
|||||||
|
|
||||||
public static class CurrencyTransactionExtensions
|
public static class CurrencyTransactionExtensions
|
||||||
{
|
{
|
||||||
public static List<CurrencyTransaction> GetPageFor(this DbSet<CurrencyTransaction> set, ulong userId, int page)
|
public static Task<List<CurrencyTransaction>> GetPageFor(
|
||||||
=> set.AsQueryable()
|
this DbSet<CurrencyTransaction> set,
|
||||||
.AsNoTracking()
|
ulong userId,
|
||||||
.Where(x => x.UserId == userId)
|
int page)
|
||||||
.OrderByDescending(x => x.DateAdded)
|
=> set.ToLinqToDBTable()
|
||||||
.Skip(15 * page)
|
.Where(x => x.UserId == userId)
|
||||||
.Take(15)
|
.OrderByDescending(x => x.DateAdded)
|
||||||
.ToList();
|
.Skip(15 * page)
|
||||||
|
.Take(15)
|
||||||
|
.ToListAsyncLinqToDB();
|
||||||
}
|
}
|
9
src/NadekoBot/Db/Models/AutoPublishChannel.cs
Normal file
9
src/NadekoBot/Db/Models/AutoPublishChannel.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
using NadekoBot.Services.Database.Models;
|
||||||
|
|
||||||
|
namespace NadekoBot.Db.Models;
|
||||||
|
|
||||||
|
public class AutoPublishChannel : DbEntity
|
||||||
|
{
|
||||||
|
public ulong GuildId { get; set; }
|
||||||
|
public ulong ChannelId { get; set; }
|
||||||
|
}
|
9
src/NadekoBot/Db/Models/GamblingStats.cs
Normal file
9
src/NadekoBot/Db/Models/GamblingStats.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#nullable disable
|
||||||
|
namespace NadekoBot.Services.Database.Models;
|
||||||
|
|
||||||
|
public class GamblingStats : DbEntity
|
||||||
|
{
|
||||||
|
public string Feature { get; set; }
|
||||||
|
public decimal Bet { get; set; }
|
||||||
|
public decimal PaidOut { get; set; }
|
||||||
|
}
|
@@ -95,6 +95,8 @@ public class GuildConfig : DbEntity
|
|||||||
public int WarnExpireHours { get; set; }
|
public int WarnExpireHours { get; set; }
|
||||||
public WarnExpireAction WarnExpireAction { get; set; } = WarnExpireAction.Clear;
|
public WarnExpireAction WarnExpireAction { get; set; } = WarnExpireAction.Clear;
|
||||||
|
|
||||||
|
public bool DisableGlobalExpressions { get; set; } = false;
|
||||||
|
|
||||||
#region Boost Message
|
#region Boost Message
|
||||||
|
|
||||||
public bool SendBoostMessage { get; set; }
|
public bool SendBoostMessage { get; set; }
|
||||||
|
@@ -24,6 +24,7 @@ public class ShopEntry : DbEntity, IIndexed
|
|||||||
|
|
||||||
//list
|
//list
|
||||||
public HashSet<ShopEntryItem> Items { get; set; } = new();
|
public HashSet<ShopEntryItem> Items { get; set; } = new();
|
||||||
|
public ulong? RoleRequirement { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ShopEntryItem : DbEntity
|
public class ShopEntryItem : DbEntity
|
||||||
|
@@ -464,6 +464,22 @@ public abstract class NadekoContext : DbContext
|
|||||||
});
|
});
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region AutoPublish
|
||||||
|
|
||||||
|
modelBuilder.Entity<AutoPublishChannel>(apc => apc
|
||||||
|
.HasIndex(x => x.GuildId)
|
||||||
|
.IsUnique());
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region GamblingStats
|
||||||
|
|
||||||
|
modelBuilder.Entity<GamblingStats>(gs => gs
|
||||||
|
.HasIndex(x => x.Feature)
|
||||||
|
.IsUnique());
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
3550
src/NadekoBot/Migrations/Mysql/20220913192520_shop-role-req.Designer.cs
generated
Normal file
3550
src/NadekoBot/Migrations/Mysql/20220913192520_shop-role-req.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,25 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace NadekoBot.Migrations.Mysql
|
||||||
|
{
|
||||||
|
public partial class shoprolereq : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<ulong>(
|
||||||
|
name: "rolerequirement",
|
||||||
|
table: "shopentry",
|
||||||
|
type: "bigint unsigned",
|
||||||
|
nullable: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "rolerequirement",
|
||||||
|
table: "shopentry");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
3579
src/NadekoBot/Migrations/Mysql/20220916194514_autopub.Designer.cs
generated
Normal file
3579
src/NadekoBot/Migrations/Mysql/20220916194514_autopub.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
42
src/NadekoBot/Migrations/Mysql/20220916194514_autopub.cs
Normal file
42
src/NadekoBot/Migrations/Mysql/20220916194514_autopub.cs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace NadekoBot.Migrations.Mysql
|
||||||
|
{
|
||||||
|
public partial class autopub : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "autopublishchannel",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
id = table.Column<int>(type: "int", nullable: false)
|
||||||
|
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||||
|
guildid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
||||||
|
channelid = table.Column<ulong>(type: "bigint unsigned", nullable: false),
|
||||||
|
dateadded = table.Column<DateTime>(type: "datetime(6)", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_autopublishchannel", x => x.id);
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_autopublishchannel_guildid",
|
||||||
|
table: "autopublishchannel",
|
||||||
|
column: "guildid",
|
||||||
|
unique: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "autopublishchannel");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
3612
src/NadekoBot/Migrations/Mysql/20221003175743_gambling-stats.Designer.cs
generated
Normal file
3612
src/NadekoBot/Migrations/Mysql/20221003175743_gambling-stats.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,44 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace NadekoBot.Migrations.Mysql
|
||||||
|
{
|
||||||
|
public partial class gamblingstats : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "gamblingstats",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
id = table.Column<int>(type: "int", nullable: false)
|
||||||
|
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||||
|
feature = table.Column<string>(type: "varchar(255)", nullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
bet = table.Column<decimal>(type: "decimal(65,30)", nullable: false),
|
||||||
|
paidout = table.Column<decimal>(type: "decimal(65,30)", nullable: false),
|
||||||
|
dateadded = table.Column<DateTime>(type: "datetime(6)", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_gamblingstats", x => x.id);
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_gamblingstats_feature",
|
||||||
|
table: "gamblingstats",
|
||||||
|
column: "feature",
|
||||||
|
unique: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "gamblingstats");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
3616
src/NadekoBot/Migrations/Mysql/20221021192758_toggle-global-expressions.Designer.cs
generated
Normal file
3616
src/NadekoBot/Migrations/Mysql/20221021192758_toggle-global-expressions.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,26 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace NadekoBot.Migrations.Mysql
|
||||||
|
{
|
||||||
|
public partial class toggleglobalexpressions : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "disableglobalexpressions",
|
||||||
|
table: "guildconfigs",
|
||||||
|
type: "tinyint(1)",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "disableglobalexpressions",
|
||||||
|
table: "guildconfigs");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -19,6 +19,35 @@ namespace NadekoBot.Migrations.Mysql
|
|||||||
.HasAnnotation("ProductVersion", "6.0.7")
|
.HasAnnotation("ProductVersion", "6.0.7")
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Db.Models.AutoPublishChannel", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
b.Property<ulong>("ChannelId")
|
||||||
|
.HasColumnType("bigint unsigned")
|
||||||
|
.HasColumnName("channelid");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DateAdded")
|
||||||
|
.HasColumnType("datetime(6)")
|
||||||
|
.HasColumnName("dateadded");
|
||||||
|
|
||||||
|
b.Property<ulong>("GuildId")
|
||||||
|
.HasColumnType("bigint unsigned")
|
||||||
|
.HasColumnName("guildid");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_autopublishchannel");
|
||||||
|
|
||||||
|
b.HasIndex("GuildId")
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("ix_autopublishchannel_guildid");
|
||||||
|
|
||||||
|
b.ToTable("autopublishchannel", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Db.Models.BankUser", b =>
|
modelBuilder.Entity("NadekoBot.Db.Models.BankUser", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
@@ -1072,6 +1101,39 @@ namespace NadekoBot.Migrations.Mysql
|
|||||||
b.ToTable("filterwordschannelid", (string)null);
|
b.ToTable("filterwordschannelid", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.GamblingStats", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
b.Property<decimal>("Bet")
|
||||||
|
.HasColumnType("decimal(65,30)")
|
||||||
|
.HasColumnName("bet");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DateAdded")
|
||||||
|
.HasColumnType("datetime(6)")
|
||||||
|
.HasColumnName("dateadded");
|
||||||
|
|
||||||
|
b.Property<string>("Feature")
|
||||||
|
.HasColumnType("varchar(255)")
|
||||||
|
.HasColumnName("feature");
|
||||||
|
|
||||||
|
b.Property<decimal>("PaidOut")
|
||||||
|
.HasColumnType("decimal(65,30)")
|
||||||
|
.HasColumnName("paidout");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_gamblingstats");
|
||||||
|
|
||||||
|
b.HasIndex("Feature")
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("ix_gamblingstats_feature");
|
||||||
|
|
||||||
|
b.ToTable("gamblingstats", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b =>
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
@@ -1196,6 +1258,10 @@ namespace NadekoBot.Migrations.Mysql
|
|||||||
.HasColumnType("tinyint(1)")
|
.HasColumnType("tinyint(1)")
|
||||||
.HasColumnName("deletestreamonlinemessage");
|
.HasColumnName("deletestreamonlinemessage");
|
||||||
|
|
||||||
|
b.Property<bool>("DisableGlobalExpressions")
|
||||||
|
.HasColumnType("tinyint(1)")
|
||||||
|
.HasColumnName("disableglobalexpressions");
|
||||||
|
|
||||||
b.Property<string>("DmGreetMessageText")
|
b.Property<string>("DmGreetMessageText")
|
||||||
.HasColumnType("longtext")
|
.HasColumnType("longtext")
|
||||||
.HasColumnName("dmgreetmessagetext");
|
.HasColumnName("dmgreetmessagetext");
|
||||||
@@ -2236,6 +2302,10 @@ namespace NadekoBot.Migrations.Mysql
|
|||||||
.HasColumnType("longtext")
|
.HasColumnType("longtext")
|
||||||
.HasColumnName("rolename");
|
.HasColumnName("rolename");
|
||||||
|
|
||||||
|
b.Property<ulong?>("RoleRequirement")
|
||||||
|
.HasColumnType("bigint unsigned")
|
||||||
|
.HasColumnName("rolerequirement");
|
||||||
|
|
||||||
b.Property<int>("Type")
|
b.Property<int>("Type")
|
||||||
.HasColumnType("int")
|
.HasColumnType("int")
|
||||||
.HasColumnName("type");
|
.HasColumnName("type");
|
3694
src/NadekoBot/Migrations/PostgreSql/20220913192529_shop-role-req.Designer.cs
generated
Normal file
3694
src/NadekoBot/Migrations/PostgreSql/20220913192529_shop-role-req.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,25 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace NadekoBot.Migrations.PostgreSql
|
||||||
|
{
|
||||||
|
public partial class shoprolereq : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<decimal>(
|
||||||
|
name: "rolerequirement",
|
||||||
|
table: "shopentry",
|
||||||
|
type: "numeric(20,0)",
|
||||||
|
nullable: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "rolerequirement",
|
||||||
|
table: "shopentry");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
3725
src/NadekoBot/Migrations/PostgreSql/20220916194523_autopub.Designer.cs
generated
Normal file
3725
src/NadekoBot/Migrations/PostgreSql/20220916194523_autopub.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,51 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace NadekoBot.Migrations.PostgreSql
|
||||||
|
{
|
||||||
|
public partial class autopub : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<decimal>(
|
||||||
|
name: "rolerequirement",
|
||||||
|
table: "shopentry",
|
||||||
|
type: "numeric(20,0)",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "autopublishchannel",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
id = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||||
|
guildid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
||||||
|
channelid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
||||||
|
dateadded = table.Column<DateTime>(type: "timestamp without time zone", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_autopublishchannel", x => x.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_autopublishchannel_guildid",
|
||||||
|
table: "autopublishchannel",
|
||||||
|
column: "guildid",
|
||||||
|
unique: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "autopublishchannel");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "rolerequirement",
|
||||||
|
table: "shopentry");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
3760
src/NadekoBot/Migrations/PostgreSql/20221003175752_gambling-stats.Designer.cs
generated
Normal file
3760
src/NadekoBot/Migrations/PostgreSql/20221003175752_gambling-stats.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,42 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace NadekoBot.Migrations.PostgreSql
|
||||||
|
{
|
||||||
|
public partial class gamblingstats : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "gamblingstats",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
id = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||||
|
feature = table.Column<string>(type: "text", nullable: true),
|
||||||
|
bet = table.Column<decimal>(type: "numeric", nullable: false),
|
||||||
|
paidout = table.Column<decimal>(type: "numeric", nullable: false),
|
||||||
|
dateadded = table.Column<DateTime>(type: "timestamp without time zone", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_gamblingstats", x => x.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "ix_gamblingstats_feature",
|
||||||
|
table: "gamblingstats",
|
||||||
|
column: "feature",
|
||||||
|
unique: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "gamblingstats");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
3764
src/NadekoBot/Migrations/PostgreSql/20221021192807_toggle-global-expressions.Designer.cs
generated
Normal file
3764
src/NadekoBot/Migrations/PostgreSql/20221021192807_toggle-global-expressions.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,26 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace NadekoBot.Migrations.PostgreSql
|
||||||
|
{
|
||||||
|
public partial class toggleglobalexpressions : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "disableglobalexpressions",
|
||||||
|
table: "guildconfigs",
|
||||||
|
type: "boolean",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "disableglobalexpressions",
|
||||||
|
table: "guildconfigs");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -22,6 +22,37 @@ namespace NadekoBot.Migrations.PostgreSql
|
|||||||
|
|
||||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Db.Models.AutoPublishChannel", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<decimal>("ChannelId")
|
||||||
|
.HasColumnType("numeric(20,0)")
|
||||||
|
.HasColumnName("channelid");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DateAdded")
|
||||||
|
.HasColumnType("timestamp without time zone")
|
||||||
|
.HasColumnName("dateadded");
|
||||||
|
|
||||||
|
b.Property<decimal>("GuildId")
|
||||||
|
.HasColumnType("numeric(20,0)")
|
||||||
|
.HasColumnName("guildid");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_autopublishchannel");
|
||||||
|
|
||||||
|
b.HasIndex("GuildId")
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("ix_autopublishchannel_guildid");
|
||||||
|
|
||||||
|
b.ToTable("autopublishchannel", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Db.Models.BankUser", b =>
|
modelBuilder.Entity("NadekoBot.Db.Models.BankUser", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
@@ -1126,6 +1157,41 @@ namespace NadekoBot.Migrations.PostgreSql
|
|||||||
b.ToTable("filterwordschannelid", (string)null);
|
b.ToTable("filterwordschannelid", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.GamblingStats", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasColumnName("id");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<decimal>("Bet")
|
||||||
|
.HasColumnType("numeric")
|
||||||
|
.HasColumnName("bet");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DateAdded")
|
||||||
|
.HasColumnType("timestamp without time zone")
|
||||||
|
.HasColumnName("dateadded");
|
||||||
|
|
||||||
|
b.Property<string>("Feature")
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("feature");
|
||||||
|
|
||||||
|
b.Property<decimal>("PaidOut")
|
||||||
|
.HasColumnType("numeric")
|
||||||
|
.HasColumnName("paidout");
|
||||||
|
|
||||||
|
b.HasKey("Id")
|
||||||
|
.HasName("pk_gamblingstats");
|
||||||
|
|
||||||
|
b.HasIndex("Feature")
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("ix_gamblingstats_feature");
|
||||||
|
|
||||||
|
b.ToTable("gamblingstats", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b =>
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
@@ -1256,6 +1322,10 @@ namespace NadekoBot.Migrations.PostgreSql
|
|||||||
.HasColumnType("boolean")
|
.HasColumnType("boolean")
|
||||||
.HasColumnName("deletestreamonlinemessage");
|
.HasColumnName("deletestreamonlinemessage");
|
||||||
|
|
||||||
|
b.Property<bool>("DisableGlobalExpressions")
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasColumnName("disableglobalexpressions");
|
||||||
|
|
||||||
b.Property<string>("DmGreetMessageText")
|
b.Property<string>("DmGreetMessageText")
|
||||||
.HasColumnType("text")
|
.HasColumnType("text")
|
||||||
.HasColumnName("dmgreetmessagetext");
|
.HasColumnName("dmgreetmessagetext");
|
||||||
@@ -2342,6 +2412,10 @@ namespace NadekoBot.Migrations.PostgreSql
|
|||||||
.HasColumnType("text")
|
.HasColumnType("text")
|
||||||
.HasColumnName("rolename");
|
.HasColumnName("rolename");
|
||||||
|
|
||||||
|
b.Property<decimal?>("RoleRequirement")
|
||||||
|
.HasColumnType("numeric(20,0)")
|
||||||
|
.HasColumnName("rolerequirement");
|
||||||
|
|
||||||
b.Property<int>("Type")
|
b.Property<int>("Type")
|
||||||
.HasColumnType("integer")
|
.HasColumnType("integer")
|
||||||
.HasColumnName("type");
|
.HasColumnName("type");
|
2849
src/NadekoBot/Migrations/Sqlite/20220913190532_shop-role-req.Designer.cs
generated
Normal file
2849
src/NadekoBot/Migrations/Sqlite/20220913190532_shop-role-req.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,25 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace NadekoBot.Migrations
|
||||||
|
{
|
||||||
|
public partial class shoprolereq : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<ulong>(
|
||||||
|
name: "RoleRequirement",
|
||||||
|
table: "ShopEntry",
|
||||||
|
type: "INTEGER",
|
||||||
|
nullable: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "RoleRequirement",
|
||||||
|
table: "ShopEntry");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
2872
src/NadekoBot/Migrations/Sqlite/20220916191702_autopub.Designer.cs
generated
Normal file
2872
src/NadekoBot/Migrations/Sqlite/20220916191702_autopub.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
40
src/NadekoBot/Migrations/Sqlite/20220916191702_autopub.cs
Normal file
40
src/NadekoBot/Migrations/Sqlite/20220916191702_autopub.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace NadekoBot.Migrations
|
||||||
|
{
|
||||||
|
public partial class autopub : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "AutoPublishChannel",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
GuildId = table.Column<ulong>(type: "INTEGER", nullable: false),
|
||||||
|
ChannelId = table.Column<ulong>(type: "INTEGER", nullable: false),
|
||||||
|
DateAdded = table.Column<DateTime>(type: "TEXT", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_AutoPublishChannel", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_AutoPublishChannel_GuildId",
|
||||||
|
table: "AutoPublishChannel",
|
||||||
|
column: "GuildId",
|
||||||
|
unique: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "AutoPublishChannel");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
2898
src/NadekoBot/Migrations/Sqlite/20221003111019_gambling-stats.Designer.cs
generated
Normal file
2898
src/NadekoBot/Migrations/Sqlite/20221003111019_gambling-stats.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,41 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace NadekoBot.Migrations
|
||||||
|
{
|
||||||
|
public partial class gamblingstats : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "GamblingStats",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
Feature = table.Column<string>(type: "TEXT", nullable: true),
|
||||||
|
Bet = table.Column<decimal>(type: "TEXT", nullable: false),
|
||||||
|
PaidOut = table.Column<decimal>(type: "TEXT", nullable: false),
|
||||||
|
DateAdded = table.Column<DateTime>(type: "TEXT", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_GamblingStats", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_GamblingStats_Feature",
|
||||||
|
table: "GamblingStats",
|
||||||
|
column: "Feature",
|
||||||
|
unique: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "GamblingStats");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
2901
src/NadekoBot/Migrations/Sqlite/20221021192121_toggle-global-expressions.Designer.cs
generated
Normal file
2901
src/NadekoBot/Migrations/Sqlite/20221021192121_toggle-global-expressions.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,26 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace NadekoBot.Migrations
|
||||||
|
{
|
||||||
|
public partial class toggleglobalexpressions : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "DisableGlobalExpressions",
|
||||||
|
table: "GuildConfigs",
|
||||||
|
type: "INTEGER",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "DisableGlobalExpressions",
|
||||||
|
table: "GuildConfigs");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -17,6 +17,29 @@ namespace NadekoBot.Migrations
|
|||||||
#pragma warning disable 612, 618
|
#pragma warning disable 612, 618
|
||||||
modelBuilder.HasAnnotation("ProductVersion", "6.0.7");
|
modelBuilder.HasAnnotation("ProductVersion", "6.0.7");
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Db.Models.AutoPublishChannel", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<ulong>("ChannelId")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DateAdded")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<ulong>("GuildId")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GuildId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("AutoPublishChannel");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Db.Models.BankUser", b =>
|
modelBuilder.Entity("NadekoBot.Db.Models.BankUser", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
@@ -841,6 +864,32 @@ namespace NadekoBot.Migrations
|
|||||||
b.ToTable("FilterWordsChannelId");
|
b.ToTable("FilterWordsChannelId");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.GamblingStats", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<decimal>("Bet")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DateAdded")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Feature")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<decimal>("PaidOut")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("Feature")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("GamblingStats");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b =>
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
@@ -937,6 +986,9 @@ namespace NadekoBot.Migrations
|
|||||||
b.Property<bool>("DeleteStreamOnlineMessage")
|
b.Property<bool>("DeleteStreamOnlineMessage")
|
||||||
.HasColumnType("INTEGER");
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<bool>("DisableGlobalExpressions")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
b.Property<string>("DmGreetMessageText")
|
b.Property<string>("DmGreetMessageText")
|
||||||
.HasColumnType("TEXT");
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
@@ -1745,6 +1797,9 @@ namespace NadekoBot.Migrations
|
|||||||
b.Property<string>("RoleName")
|
b.Property<string>("RoleName")
|
||||||
.HasColumnType("TEXT");
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<ulong?>("RoleRequirement")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
b.Property<int>("Type")
|
b.Property<int>("Type")
|
||||||
.HasColumnType("INTEGER");
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
@@ -33,9 +33,13 @@ public partial class Administration : NadekoModule<AdministrationService>
|
|||||||
}
|
}
|
||||||
|
|
||||||
private readonly SomethingOnlyChannelService _somethingOnly;
|
private readonly SomethingOnlyChannelService _somethingOnly;
|
||||||
|
private readonly AutoPublishService _autoPubService;
|
||||||
|
|
||||||
public Administration(SomethingOnlyChannelService somethingOnly)
|
public Administration(SomethingOnlyChannelService somethingOnly, AutoPublishService autoPubService)
|
||||||
=> _somethingOnly = somethingOnly;
|
{
|
||||||
|
_somethingOnly = somethingOnly;
|
||||||
|
_autoPubService = autoPubService;
|
||||||
|
}
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
@@ -376,4 +380,26 @@ public partial class Administration : NadekoModule<AdministrationService>
|
|||||||
await t.DeleteAsync();
|
await t.DeleteAsync();
|
||||||
await ctx.OkAsync();
|
await ctx.OkAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Cmd]
|
||||||
|
[UserPerm(ChannelPerm.ManageMessages)]
|
||||||
|
public async Task AutoPublish()
|
||||||
|
{
|
||||||
|
if (ctx.Channel.GetChannelType() != ChannelType.News)
|
||||||
|
{
|
||||||
|
await ReplyErrorLocalizedAsync(strs.req_announcement_channel);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var newState = await _autoPubService.ToggleAutoPublish(ctx.Guild.Id, ctx.Channel.Id);
|
||||||
|
|
||||||
|
if (newState)
|
||||||
|
{
|
||||||
|
await ReplyConfirmLocalizedAsync(strs.autopublish_enable);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await ReplyConfirmLocalizedAsync(strs.autopublish_disable);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@@ -1,6 +1,5 @@
|
|||||||
#nullable disable
|
#nullable disable
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Nadeko.Common;
|
|
||||||
using NadekoBot.Db;
|
using NadekoBot.Db;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
|
|
||||||
|
87
src/NadekoBot/Modules/Administration/AutoPublishService.cs
Normal file
87
src/NadekoBot/Modules/Administration/AutoPublishService.cs
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
#nullable disable
|
||||||
|
using LinqToDB;
|
||||||
|
using LinqToDB.EntityFrameworkCore;
|
||||||
|
using NadekoBot.Common.ModuleBehaviors;
|
||||||
|
using NadekoBot.Db.Models;
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.Administration.Services;
|
||||||
|
|
||||||
|
public class AutoPublishService : IExecNoCommand, IReadyExecutor, INService
|
||||||
|
{
|
||||||
|
private readonly DbService _db;
|
||||||
|
private readonly DiscordSocketClient _client;
|
||||||
|
private readonly IBotCredsProvider _creds;
|
||||||
|
private ConcurrentDictionary<ulong, ulong> _enabled;
|
||||||
|
|
||||||
|
public AutoPublishService(DbService db, DiscordSocketClient client, IBotCredsProvider creds)
|
||||||
|
{
|
||||||
|
_db = db;
|
||||||
|
_client = client;
|
||||||
|
_creds = creds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ExecOnNoCommandAsync(IGuild guild, IUserMessage msg)
|
||||||
|
{
|
||||||
|
if (guild is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (msg.Channel.GetChannelType() != ChannelType.News)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!_enabled.TryGetValue(guild.Id, out var cid) || cid != msg.Channel.Id)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await msg.CrosspostAsync(new RequestOptions()
|
||||||
|
{
|
||||||
|
RetryMode = RetryMode.AlwaysFail
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task OnReadyAsync()
|
||||||
|
{
|
||||||
|
var creds = _creds.GetCreds();
|
||||||
|
|
||||||
|
await using var ctx = _db.GetDbContext();
|
||||||
|
var items = await ctx.GetTable<AutoPublishChannel>()
|
||||||
|
.Where(x => Linq2DbExpressions.GuildOnShard(x.GuildId, creds.TotalShards, _client.ShardId))
|
||||||
|
.ToListAsyncLinqToDB();
|
||||||
|
|
||||||
|
_enabled = items
|
||||||
|
.ToDictionary(x => x.GuildId, x => x.ChannelId)
|
||||||
|
.ToConcurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> ToggleAutoPublish(ulong guildId, ulong channelId)
|
||||||
|
{
|
||||||
|
await using var ctx = _db.GetDbContext();
|
||||||
|
var deleted = await ctx.GetTable<AutoPublishChannel>()
|
||||||
|
.DeleteAsync(x => x.GuildId == guildId && x.ChannelId == channelId);
|
||||||
|
|
||||||
|
if (deleted != 0)
|
||||||
|
{
|
||||||
|
_enabled.TryRemove(guildId, out _);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
await ctx.GetTable<AutoPublishChannel>()
|
||||||
|
.InsertOrUpdateAsync(() => new()
|
||||||
|
{
|
||||||
|
GuildId = guildId,
|
||||||
|
ChannelId = channelId,
|
||||||
|
DateAdded = DateTime.UtcNow,
|
||||||
|
},
|
||||||
|
old => new()
|
||||||
|
{
|
||||||
|
ChannelId = channelId,
|
||||||
|
DateAdded = DateTime.UtcNow,
|
||||||
|
},
|
||||||
|
() => new()
|
||||||
|
{
|
||||||
|
GuildId = guildId
|
||||||
|
});
|
||||||
|
|
||||||
|
_enabled[guildId] = channelId;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@@ -1,4 +1,5 @@
|
|||||||
#nullable disable
|
#nullable disable
|
||||||
|
using CommandLine;
|
||||||
using NadekoBot.Modules.Administration.Services;
|
using NadekoBot.Modules.Administration.Services;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration;
|
namespace NadekoBot.Modules.Administration;
|
||||||
@@ -10,17 +11,34 @@ public partial class Administration
|
|||||||
{
|
{
|
||||||
private static readonly TimeSpan _twoWeeks = TimeSpan.FromDays(14);
|
private static readonly TimeSpan _twoWeeks = TimeSpan.FromDays(14);
|
||||||
|
|
||||||
//delets her own messages, no perm required
|
public sealed class PruneOptions : INadekoCommandOptions
|
||||||
|
{
|
||||||
|
[Option(shortName: 's', longName: "safe", Default = false, HelpText = "Whether pinned messages should be deleted.", Required = false)]
|
||||||
|
public bool Safe { get; set; }
|
||||||
|
|
||||||
|
[Option(shortName: 'a', longName: "after", Default = null, HelpText = "Prune only messages after the specified message ID.", Required = false)]
|
||||||
|
public ulong? After { get; set; }
|
||||||
|
|
||||||
|
public void NormalizeOptions()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//deletes her own messages, no perm required
|
||||||
[Cmd]
|
[Cmd]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task Prune(string parameter = null)
|
[NadekoOptions(typeof(PruneOptions))]
|
||||||
|
public async Task Prune(params string[] args)
|
||||||
{
|
{
|
||||||
|
var (opts, _) = OptionsParser.ParseFrom<PruneOptions>(new PruneOptions(), args);
|
||||||
|
|
||||||
var user = await ctx.Guild.GetCurrentUserAsync();
|
var user = await ctx.Guild.GetCurrentUserAsync();
|
||||||
|
|
||||||
if (parameter is "-s" or "--safe")
|
if (opts.Safe)
|
||||||
await _service.PruneWhere((ITextChannel)ctx.Channel, 100, x => x.Author.Id == user.Id && !x.IsPinned);
|
await _service.PruneWhere((ITextChannel)ctx.Channel, 100, x => x.Author.Id == user.Id && !x.IsPinned, opts.After);
|
||||||
else
|
else
|
||||||
await _service.PruneWhere((ITextChannel)ctx.Channel, 100, x => x.Author.Id == user.Id);
|
await _service.PruneWhere((ITextChannel)ctx.Channel, 100, x => x.Author.Id == user.Id, opts.After);
|
||||||
|
|
||||||
ctx.Message.DeleteAfter(3);
|
ctx.Message.DeleteAfter(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,19 +47,22 @@ public partial class Administration
|
|||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[UserPerm(ChannelPerm.ManageMessages)]
|
[UserPerm(ChannelPerm.ManageMessages)]
|
||||||
[BotPerm(ChannelPerm.ManageMessages)]
|
[BotPerm(ChannelPerm.ManageMessages)]
|
||||||
|
[NadekoOptions(typeof(PruneOptions))]
|
||||||
[Priority(1)]
|
[Priority(1)]
|
||||||
public async Task Prune(int count, string parameter = null)
|
public async Task Prune(int count, params string[] args)
|
||||||
{
|
{
|
||||||
count++;
|
count++;
|
||||||
if (count < 1)
|
if (count < 1)
|
||||||
return;
|
return;
|
||||||
if (count > 1000)
|
if (count > 1000)
|
||||||
count = 1000;
|
count = 1000;
|
||||||
|
|
||||||
|
var (opts, _) = OptionsParser.ParseFrom<PruneOptions>(new PruneOptions(), args);
|
||||||
|
|
||||||
if (parameter is "-s" or "--safe")
|
if (opts.Safe)
|
||||||
await _service.PruneWhere((ITextChannel)ctx.Channel, count, x => !x.IsPinned);
|
await _service.PruneWhere((ITextChannel)ctx.Channel, count, x => !x.IsPinned, opts.After);
|
||||||
else
|
else
|
||||||
await _service.PruneWhere((ITextChannel)ctx.Channel, count, _ => true);
|
await _service.PruneWhere((ITextChannel)ctx.Channel, count, _ => true, opts.After);
|
||||||
}
|
}
|
||||||
|
|
||||||
//prune @user [x]
|
//prune @user [x]
|
||||||
@@ -49,17 +70,19 @@ public partial class Administration
|
|||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[UserPerm(ChannelPerm.ManageMessages)]
|
[UserPerm(ChannelPerm.ManageMessages)]
|
||||||
[BotPerm(ChannelPerm.ManageMessages)]
|
[BotPerm(ChannelPerm.ManageMessages)]
|
||||||
|
[NadekoOptions(typeof(PruneOptions))]
|
||||||
[Priority(0)]
|
[Priority(0)]
|
||||||
public Task Prune(IGuildUser user, int count = 100, string parameter = null)
|
public Task Prune(IGuildUser user, int count = 100, params string[] args)
|
||||||
=> Prune(user.Id, count, parameter);
|
=> Prune(user.Id, count, args);
|
||||||
|
|
||||||
//prune userid [x]
|
//prune userid [x]
|
||||||
[Cmd]
|
[Cmd]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[UserPerm(ChannelPerm.ManageMessages)]
|
[UserPerm(ChannelPerm.ManageMessages)]
|
||||||
[BotPerm(ChannelPerm.ManageMessages)]
|
[BotPerm(ChannelPerm.ManageMessages)]
|
||||||
|
[NadekoOptions(typeof(PruneOptions))]
|
||||||
[Priority(0)]
|
[Priority(0)]
|
||||||
public async Task Prune(ulong userId, int count = 100, string parameter = null)
|
public async Task Prune(ulong userId, int count = 100, params string[] args)
|
||||||
{
|
{
|
||||||
if (userId == ctx.User.Id)
|
if (userId == ctx.User.Id)
|
||||||
count++;
|
count++;
|
||||||
@@ -70,17 +93,21 @@ public partial class Administration
|
|||||||
if (count > 1000)
|
if (count > 1000)
|
||||||
count = 1000;
|
count = 1000;
|
||||||
|
|
||||||
if (parameter is "-s" or "--safe")
|
var (opts, _) = OptionsParser.ParseFrom<PruneOptions>(new PruneOptions(), args);
|
||||||
|
|
||||||
|
if (opts.Safe)
|
||||||
{
|
{
|
||||||
await _service.PruneWhere((ITextChannel)ctx.Channel,
|
await _service.PruneWhere((ITextChannel)ctx.Channel,
|
||||||
count,
|
count,
|
||||||
m => m.Author.Id == userId && DateTime.UtcNow - m.CreatedAt < _twoWeeks && !m.IsPinned);
|
m => m.Author.Id == userId && DateTime.UtcNow - m.CreatedAt < _twoWeeks && !m.IsPinned,
|
||||||
|
opts.After);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await _service.PruneWhere((ITextChannel)ctx.Channel,
|
await _service.PruneWhere((ITextChannel)ctx.Channel,
|
||||||
count,
|
count,
|
||||||
m => m.Author.Id == userId && DateTime.UtcNow - m.CreatedAt < _twoWeeks);
|
m => m.Author.Id == userId && DateTime.UtcNow - m.CreatedAt < _twoWeeks,
|
||||||
|
opts.After);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
#nullable disable
|
#nullable disable
|
||||||
using Nadeko.Common;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration.Services;
|
namespace NadekoBot.Modules.Administration.Services;
|
||||||
|
|
||||||
public class PruneService : INService
|
public class PruneService : INService
|
||||||
@@ -13,7 +11,7 @@ public class PruneService : INService
|
|||||||
public PruneService(ILogCommandService logService)
|
public PruneService(ILogCommandService logService)
|
||||||
=> _logService = logService;
|
=> _logService = logService;
|
||||||
|
|
||||||
public async Task PruneWhere(ITextChannel channel, int amount, Func<IMessage, bool> predicate)
|
public async Task PruneWhere(ITextChannel channel, int amount, Func<IMessage, bool> predicate, ulong? after = null)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(channel, nameof(channel));
|
ArgumentNullException.ThrowIfNull(channel, nameof(channel));
|
||||||
|
|
||||||
@@ -28,7 +26,14 @@ public class PruneService : INService
|
|||||||
var now = DateTime.UtcNow;
|
var now = DateTime.UtcNow;
|
||||||
IMessage[] msgs;
|
IMessage[] msgs;
|
||||||
IMessage lastMessage = null;
|
IMessage lastMessage = null;
|
||||||
msgs = (await channel.GetMessagesAsync(50).FlattenAsync()).Where(predicate).Take(amount).ToArray();
|
var dled = await channel.GetMessagesAsync(50).FlattenAsync();
|
||||||
|
|
||||||
|
msgs = dled
|
||||||
|
.Where(predicate)
|
||||||
|
.Where(x => after is ulong a ? x.Id > a : true)
|
||||||
|
.Take(amount)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
while (amount > 0 && msgs.Any())
|
while (amount > 0 && msgs.Any())
|
||||||
{
|
{
|
||||||
lastMessage = msgs[^1];
|
lastMessage = msgs[^1];
|
||||||
@@ -62,10 +67,13 @@ public class PruneService : INService
|
|||||||
amount -= 50;
|
amount -= 50;
|
||||||
if (amount > 0)
|
if (amount > 0)
|
||||||
{
|
{
|
||||||
msgs = (await channel.GetMessagesAsync(lastMessage, Direction.Before, 50).FlattenAsync())
|
dled = await channel.GetMessagesAsync(lastMessage, Direction.Before, 50).FlattenAsync();
|
||||||
.Where(predicate)
|
|
||||||
.Take(amount)
|
msgs = dled
|
||||||
.ToArray();
|
.Where(predicate)
|
||||||
|
.Where(x => after is ulong a ? x.Id > a : true)
|
||||||
|
.Take(amount)
|
||||||
|
.ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -67,42 +67,52 @@ public partial class Administration
|
|||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[UserPerm(GuildPerm.ManageRoles)]
|
[UserPerm(GuildPerm.ManageRoles)]
|
||||||
[BotPerm(GuildPerm.ManageRoles)]
|
[BotPerm(GuildPerm.ManageRoles)]
|
||||||
public async Task ReactionRolesList()
|
public async Task ReactionRolesList(int page = 1)
|
||||||
{
|
{
|
||||||
|
if (--page < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
var reros = await _rero.GetReactionRolesAsync(ctx.Guild.Id);
|
var reros = await _rero.GetReactionRolesAsync(ctx.Guild.Id);
|
||||||
|
|
||||||
var embed = _eb.Create(ctx)
|
await ctx.SendPaginatedConfirmAsync(page, curPage =>
|
||||||
.WithOkColor();
|
|
||||||
|
|
||||||
var content = string.Empty;
|
|
||||||
foreach (var g in reros.GroupBy(x => x.MessageId).OrderBy(x => x.Key))
|
|
||||||
{
|
{
|
||||||
var messageId = g.Key;
|
var embed = _eb.Create(ctx)
|
||||||
content +=
|
.WithOkColor();
|
||||||
$"[{messageId}](https://discord.com/channels/{ctx.Guild.Id}/{g.First().ChannelId}/{g.Key})\n";
|
|
||||||
|
|
||||||
var groupGroups = g.GroupBy(x => x.Group);
|
var content = string.Empty;
|
||||||
|
foreach (var g in reros.OrderBy(x => x.Group)
|
||||||
foreach (var ggs in groupGroups)
|
.Skip(curPage * 10)
|
||||||
|
.GroupBy(x => x.MessageId)
|
||||||
|
.OrderBy(x => x.Key))
|
||||||
{
|
{
|
||||||
content += $"`< {(g.Key == 0 ? ("Not Exclusive (Group 0)") : ($"Group {ggs.Key}"))} >`\n";
|
var messageId = g.Key;
|
||||||
|
content +=
|
||||||
|
$"[{messageId}](https://discord.com/channels/{ctx.Guild.Id}/{g.First().ChannelId}/{g.Key})\n";
|
||||||
|
|
||||||
foreach (var rero in ggs)
|
var groupGroups = g.GroupBy(x => x.Group);
|
||||||
|
|
||||||
|
foreach (var ggs in groupGroups)
|
||||||
{
|
{
|
||||||
content += $"\t{rero.Emote} -> {(ctx.Guild.GetRole(rero.RoleId)?.Mention ?? "<missing role>")}";
|
content += $"`< {(g.Key == 0 ? ("Not Exclusive (Group 0)") : ($"Group {ggs.Key}"))} >`\n";
|
||||||
if (rero.LevelReq > 0)
|
|
||||||
content += $" (lvl {rero.LevelReq}+)";
|
foreach (var rero in ggs)
|
||||||
content += '\n';
|
{
|
||||||
|
content +=
|
||||||
|
$"\t{rero.Emote} -> {(ctx.Guild.GetRole(rero.RoleId)?.Mention ?? "<missing role>")}";
|
||||||
|
if (rero.LevelReq > 0)
|
||||||
|
content += $" (lvl {rero.LevelReq}+)";
|
||||||
|
content += '\n';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
embed.WithDescription(string.IsNullOrWhiteSpace(content)
|
||||||
|
? "There are no reaction roles on this server"
|
||||||
|
: content);
|
||||||
|
|
||||||
embed.WithDescription(string.IsNullOrWhiteSpace(content)
|
return embed;
|
||||||
? "There are no reaction roles on this server"
|
}, reros.Count, 10);
|
||||||
: content);
|
|
||||||
|
|
||||||
await ctx.Channel.EmbedAsync(embed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
|
@@ -230,6 +230,19 @@ public partial class Administration
|
|||||||
await ReplyPendingLocalizedAsync(strs.fwall_stop);
|
await ReplyPendingLocalizedAsync(strs.fwall_stop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Cmd]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
[OwnerOnly]
|
||||||
|
public async Task ForwardToChannel()
|
||||||
|
{
|
||||||
|
var enabled = _service.ForwardToChannel(ctx.Channel.Id);
|
||||||
|
|
||||||
|
if (enabled)
|
||||||
|
await ReplyConfirmLocalizedAsync(strs.fwch_start);
|
||||||
|
else
|
||||||
|
await ReplyPendingLocalizedAsync(strs.fwch_stop);
|
||||||
|
}
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
public async Task ShardStats(int page = 1)
|
public async Task ShardStats(int page = 1)
|
||||||
{
|
{
|
||||||
|
@@ -85,12 +85,12 @@ public sealed class SelfService : IExecNoCommand, IReadyExecutor, INService
|
|||||||
await using var uow = _db.GetDbContext();
|
await using var uow = _db.GetDbContext();
|
||||||
|
|
||||||
autoCommands = uow.AutoCommands.AsNoTracking()
|
autoCommands = uow.AutoCommands.AsNoTracking()
|
||||||
.Where(x => x.Interval >= 5)
|
.Where(x => x.Interval >= 5)
|
||||||
.AsEnumerable()
|
.AsEnumerable()
|
||||||
.GroupBy(x => x.GuildId)
|
.GroupBy(x => x.GuildId)
|
||||||
.ToDictionary(x => x.Key,
|
.ToDictionary(x => x.Key,
|
||||||
y => y.ToDictionary(x => x.Id, TimerFromAutoCommand).ToConcurrent())
|
y => y.ToDictionary(x => x.Id, TimerFromAutoCommand).ToConcurrent())
|
||||||
.ToConcurrent();
|
.ToConcurrent();
|
||||||
|
|
||||||
var startupCommands = uow.AutoCommands.AsNoTracking().Where(x => x.Interval == 0);
|
var startupCommands = uow.AutoCommands.AsNoTracking().Where(x => x.Interval == 0);
|
||||||
foreach (var cmd in startupCommands)
|
foreach (var cmd in startupCommands)
|
||||||
@@ -169,18 +169,18 @@ public sealed class SelfService : IExecNoCommand, IReadyExecutor, INService
|
|||||||
private async Task LoadOwnerChannels()
|
private async Task LoadOwnerChannels()
|
||||||
{
|
{
|
||||||
var channels = await _creds.OwnerIds.Select(id =>
|
var channels = await _creds.OwnerIds.Select(id =>
|
||||||
{
|
{
|
||||||
var user = _client.GetUser(id);
|
var user = _client.GetUser(id);
|
||||||
if (user is null)
|
if (user is null)
|
||||||
return Task.FromResult<IDMChannel>(null);
|
return Task.FromResult<IDMChannel>(null);
|
||||||
|
|
||||||
return user.CreateDMChannelAsync();
|
return user.CreateDMChannelAsync();
|
||||||
})
|
})
|
||||||
.WhenAll();
|
.WhenAll();
|
||||||
|
|
||||||
ownerChannels = channels.Where(x => x is not null)
|
ownerChannels = channels.Where(x => x is not null)
|
||||||
.ToDictionary(x => x.Recipient.Id, x => x)
|
.ToDictionary(x => x.Recipient.Id, x => x)
|
||||||
.ToImmutableDictionary();
|
.ToImmutableDictionary();
|
||||||
|
|
||||||
if (!ownerChannels.Any())
|
if (!ownerChannels.Any())
|
||||||
{
|
{
|
||||||
@@ -202,7 +202,7 @@ public sealed class SelfService : IExecNoCommand, IReadyExecutor, INService
|
|||||||
public async Task ExecOnNoCommandAsync(IGuild guild, IUserMessage msg)
|
public async Task ExecOnNoCommandAsync(IGuild guild, IUserMessage msg)
|
||||||
{
|
{
|
||||||
var bs = _bss.Data;
|
var bs = _bss.Data;
|
||||||
if (msg.Channel is IDMChannel && bs.ForwardMessages && ownerChannels.Any())
|
if (msg.Channel is IDMChannel && bs.ForwardMessages && (ownerChannels.Any() || bs.ForwardToChannel is not null))
|
||||||
{
|
{
|
||||||
var title = _strings.GetText(strs.dm_from) + $" [{msg.Author}]({msg.Author.Id})";
|
var title = _strings.GetText(strs.dm_from) + $" [{msg.Author}]({msg.Author.Id})";
|
||||||
|
|
||||||
@@ -232,6 +232,18 @@ public sealed class SelfService : IExecNoCommand, IReadyExecutor, INService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (bs.ForwardToChannel is ulong cid)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_client.GetChannel(cid) is ITextChannel ch)
|
||||||
|
await ch.SendConfirmAsync(_eb, title, toSend);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
Log.Warning("Error forwarding message to the channel");
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var firstOwnerChannel = ownerChannels.Values.First();
|
var firstOwnerChannel = ownerChannels.Values.First();
|
||||||
@@ -333,6 +345,20 @@ public sealed class SelfService : IExecNoCommand, IReadyExecutor, INService
|
|||||||
return isToAll;
|
return isToAll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool ForwardToChannel(ulong? channelId)
|
||||||
|
{
|
||||||
|
using var uow = _db.GetDbContext();
|
||||||
|
|
||||||
|
_bss.ModifyConfig(config =>
|
||||||
|
{
|
||||||
|
config.ForwardToChannel = channelId == config.ForwardToChannel
|
||||||
|
? null
|
||||||
|
: channelId;
|
||||||
|
});
|
||||||
|
|
||||||
|
return channelId is not null;
|
||||||
|
}
|
||||||
|
|
||||||
private void HandleStatusChanges()
|
private void HandleStatusChanges()
|
||||||
=> _pubSub.Sub(_activitySetKey,
|
=> _pubSub.Sub(_activitySetKey,
|
||||||
async data =>
|
async data =>
|
||||||
|
@@ -3,6 +3,9 @@
|
|||||||
namespace NadekoBot.Modules.Administration;
|
namespace NadekoBot.Modules.Administration;
|
||||||
|
|
||||||
public sealed class DummyLogCommandService : ILogCommandService
|
public sealed class DummyLogCommandService : ILogCommandService
|
||||||
|
#if GLOBAL_NADEKO
|
||||||
|
, INService
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
public void AddDeleteIgnore(ulong xId)
|
public void AddDeleteIgnore(ulong xId)
|
||||||
{
|
{
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user