Implemented .linkonly (as an alternative to .imageonly). Updated pokaman with latest generations. Updated responses, fixed some warnings

This commit is contained in:
Kwoth
2022-07-27 03:14:47 +02:00
parent e20212a6cb
commit bb395f18a2
13 changed files with 3017 additions and 35 deletions

View File

@@ -5,4 +5,11 @@ public class ImageOnlyChannel : DbEntity
{
public ulong GuildId { get; set; }
public ulong ChannelId { get; set; }
public OnlyChannelType Type { get; set; }
}
public enum OnlyChannelType
{
Image,
Link
}

View File

@@ -1,4 +1,5 @@
using NadekoBot.Services.Database.Models;
#nullable disable warnings
using NadekoBot.Services.Database.Models;
namespace NadekoBot.Db.Models;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,26 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace NadekoBot.Migrations
{
public partial class linkonlychannels : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "Type",
table: "ImageOnlyChannels",
type: "INTEGER",
nullable: false,
defaultValue: 0);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Type",
table: "ImageOnlyChannels");
}
}
}

View File

@@ -1088,6 +1088,9 @@ namespace NadekoBot.Migrations
b.Property<ulong>("GuildId")
.HasColumnType("INTEGER");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("ChannelId")

View File

@@ -32,10 +32,10 @@ public partial class Administration : NadekoModule<AdministrationService>
Inherit
}
private readonly ImageOnlyChannelService _imageOnly;
private readonly SomethingOnlyChannelService _somethingOnly;
public Administration(ImageOnlyChannelService imageOnly)
=> _imageOnly = imageOnly;
public Administration(SomethingOnlyChannelService somethingOnly)
=> _somethingOnly = somethingOnly;
[Cmd]
[RequireContext(ContextType.Guild)]
@@ -43,12 +43,25 @@ public partial class Administration : NadekoModule<AdministrationService>
[BotPerm(GuildPerm.ManageGuild)]
public async Task ImageOnlyChannel(StoopidTime time = null)
{
var newValue = _imageOnly.ToggleImageOnlyChannel(ctx.Guild.Id, ctx.Channel.Id);
var newValue = await _somethingOnly.ToggleImageOnlyChannelAsync(ctx.Guild.Id, ctx.Channel.Id);
if (newValue)
await ReplyConfirmLocalizedAsync(strs.imageonly_enable);
else
await ReplyPendingLocalizedAsync(strs.imageonly_disable);
}
[Cmd]
[RequireContext(ContextType.Guild)]
[UserPerm(GuildPerm.Administrator)]
[BotPerm(GuildPerm.ManageGuild)]
public async Task LinkOnlyChannel(StoopidTime time = null)
{
var newValue = await _somethingOnly.ToggleLinkOnlyChannelAsync(ctx.Guild.Id, ctx.Channel.Id);
if (newValue)
await ReplyConfirmLocalizedAsync(strs.linkonly_enable);
else
await ReplyPendingLocalizedAsync(strs.linkonly_disable);
}
[Cmd]
[RequireContext(ContextType.Guild)]

View File

@@ -5,16 +5,18 @@ using NadekoBot.Common.ModuleBehaviors;
using System.Net;
using System.Threading.Channels;
using Nadeko.Common;
using NadekoBot.Services.Database.Models;
namespace NadekoBot.Modules.Administration.Services;
public sealed class ImageOnlyChannelService : IExecOnMessage
public sealed class SomethingOnlyChannelService : IExecOnMessage
{
public int Priority { get; } = 0;
private readonly IMemoryCache _ticketCache;
private readonly DiscordSocketClient _client;
private readonly DbService _db;
private readonly ConcurrentDictionary<ulong, ConcurrentHashSet<ulong>> _enabledOn;
private readonly ConcurrentDictionary<ulong, ConcurrentHashSet<ulong>> _imageOnly;
private readonly ConcurrentDictionary<ulong, ConcurrentHashSet<ulong>> _linkOnly;
private readonly Channel<IUserMessage> _deleteQueue = Channel.CreateBounded<IUserMessage>(
new BoundedChannelOptions(100)
@@ -25,32 +27,39 @@ public sealed class ImageOnlyChannelService : IExecOnMessage
});
public ImageOnlyChannelService(IMemoryCache ticketCache, DiscordSocketClient client, DbService db)
public SomethingOnlyChannelService(IMemoryCache ticketCache, DiscordSocketClient client, DbService db)
{
_ticketCache = ticketCache;
_client = client;
_db = db;
using var uow = _db.GetDbContext();
_enabledOn = uow.ImageOnlyChannels.ToList()
_imageOnly = uow.ImageOnlyChannels
.Where(x => x.Type == OnlyChannelType.Image)
.ToList()
.GroupBy(x => x.GuildId)
.ToDictionary(x => x.Key, x => new ConcurrentHashSet<ulong>(x.Select(y => y.ChannelId)))
.ToConcurrent();
_linkOnly = uow.ImageOnlyChannels
.Where(x => x.Type == OnlyChannelType.Link)
.ToList()
.GroupBy(x => x.GuildId)
.ToDictionary(x => x.Key, x => new ConcurrentHashSet<ulong>(x.Select(y => y.ChannelId)))
.ToConcurrent();
_ = Task.Run(DeleteQueueRunner);
_client.ChannelDestroyed += ClientOnChannelDestroyed;
}
private Task ClientOnChannelDestroyed(SocketChannel ch)
private async Task ClientOnChannelDestroyed(SocketChannel ch)
{
if (ch is not IGuildChannel gch)
return Task.CompletedTask;
return;
if (_enabledOn.TryGetValue(gch.GuildId, out var channels) && channels.TryRemove(ch.Id))
ToggleImageOnlyChannel(gch.GuildId, ch.Id, true);
return Task.CompletedTask;
if (_imageOnly.TryGetValue(gch.GuildId, out var channels) && channels.TryRemove(ch.Id))
await ToggleImageOnlyChannelAsync(gch.GuildId, ch.Id, true);
}
private async Task DeleteQueueRunner()
@@ -66,31 +75,68 @@ public sealed class ImageOnlyChannelService : IExecOnMessage
catch (HttpException ex) when (ex.HttpCode == HttpStatusCode.Forbidden)
{
// disable if bot can't delete messages in the channel
ToggleImageOnlyChannel(((ITextChannel)toDelete.Channel).GuildId, toDelete.Channel.Id, true);
await ToggleImageOnlyChannelAsync(((ITextChannel)toDelete.Channel).GuildId, toDelete.Channel.Id, true);
}
}
}
public bool ToggleImageOnlyChannel(ulong guildId, ulong channelId, bool forceDisable = false)
public async Task<bool> ToggleImageOnlyChannelAsync(ulong guildId, ulong channelId, bool forceDisable = false)
{
var newState = false;
using var uow = _db.GetDbContext();
if (forceDisable || (_enabledOn.TryGetValue(guildId, out var channels) && channels.TryRemove(channelId)))
uow.ImageOnlyChannels.Delete(x => x.ChannelId == channelId);
await using var uow = _db.GetDbContext();
if (forceDisable || (_imageOnly.TryGetValue(guildId, out var channels) && channels.TryRemove(channelId)))
{
await uow.ImageOnlyChannels.DeleteAsync(x => x.ChannelId == channelId && x.Type == OnlyChannelType.Link);
}
else
{
await uow.ImageOnlyChannels.DeleteAsync(x => x.ChannelId == channelId);
uow.ImageOnlyChannels.Add(new()
{
GuildId = guildId,
ChannelId = channelId
ChannelId = channelId,
Type = OnlyChannelType.Image
});
channels = _enabledOn.GetOrAdd(guildId, new ConcurrentHashSet<ulong>());
if (_linkOnly.TryGetValue(guildId, out var chs))
chs.TryRemove(channelId);
channels = _imageOnly.GetOrAdd(guildId, new ConcurrentHashSet<ulong>());
channels.Add(channelId);
newState = true;
}
uow.SaveChanges();
await uow.SaveChangesAsync();
return newState;
}
public async Task<bool> ToggleLinkOnlyChannelAsync(ulong guildId, ulong channelId, bool forceDisable = false)
{
var newState = false;
await using var uow = _db.GetDbContext();
if (forceDisable || (_linkOnly.TryGetValue(guildId, out var channels) && channels.TryRemove(channelId)))
{
await uow.ImageOnlyChannels.DeleteAsync(x => x.ChannelId == channelId && x.Type == OnlyChannelType.Link);
}
else
{
await uow.ImageOnlyChannels.DeleteAsync(x => x.ChannelId == channelId);
uow.ImageOnlyChannels.Add(new()
{
GuildId = guildId,
ChannelId = channelId,
Type = OnlyChannelType.Link
});
if (_imageOnly.TryGetValue(guildId, out var chs))
chs.TryRemove(channelId);
channels = _linkOnly.GetOrAdd(guildId, new ConcurrentHashSet<ulong>());
channels.Add(channelId);
newState = true;
}
await uow.SaveChangesAsync();
return newState;
}
@@ -99,12 +145,28 @@ public sealed class ImageOnlyChannelService : IExecOnMessage
if (msg.Channel is not ITextChannel tch)
return false;
if (msg.Attachments.Any(x => x is { Height: > 0, Width: > 0 }))
return false;
if (_imageOnly.TryGetValue(tch.GuildId, out var chs) && chs.Contains(msg.Channel.Id))
return await HandleOnlyChannel(tch, msg, OnlyChannelType.Image);
if (_linkOnly.TryGetValue(tch.GuildId, out chs) && chs.Contains(msg.Channel.Id))
return await HandleOnlyChannel(tch, msg, OnlyChannelType.Link);
if (!_enabledOn.TryGetValue(tch.GuildId, out var chs) || !chs.Contains(msg.Channel.Id))
return false;
return false;
}
private async Task<bool> HandleOnlyChannel(ITextChannel tch, IUserMessage msg, OnlyChannelType type)
{
if (type == OnlyChannelType.Image)
{
if (msg.Attachments.Any(x => x is { Height: > 0, Width: > 0 }))
return false;
}
else
{
if (msg.Content.TryGetUrlPath(out _))
return false;
}
var user = await tch.Guild.GetUserAsync(msg.Author.Id)
?? await _client.Rest.GetGuildUserAsync(tch.GuildId, msg.Author.Id);
@@ -114,7 +176,7 @@ public sealed class ImageOnlyChannelService : IExecOnMessage
// ignore owner and admin
if (user.Id == tch.Guild.OwnerId || user.GuildPermissions.Administrator)
{
Log.Information("Image-Only: Ignoring owner od admin ({ChannelId})", msg.Channel.Id);
Log.Information("{Type}-Only Channel: Ignoring owner od admin ({ChannelId})", type, msg.Channel.Id);
return false;
}
@@ -125,7 +187,11 @@ public sealed class ImageOnlyChannelService : IExecOnMessage
if (!botUser.GetPermissions(tch).ManageChannel)
{
ToggleImageOnlyChannel(tch.GuildId, tch.Id, true);
if(type == OnlyChannelType.Image)
await ToggleImageOnlyChannelAsync(tch.GuildId, tch.Id, true);
else
await ToggleImageOnlyChannelAsync(tch.GuildId, tch.Id, true);
return false;
}
@@ -133,7 +199,8 @@ public sealed class ImageOnlyChannelService : IExecOnMessage
if (shouldLock)
{
await tch.AddPermissionOverwriteAsync(msg.Author, new(sendMessages: PermValue.Deny));
Log.Warning("Image-Only: User {User} [{UserId}] has been banned from typing in the channel [{ChannelId}]",
Log.Warning("{Type}-Only Channel: User {User} [{UserId}] has been banned from typing in the channel [{ChannelId}]",
type,
msg.Author,
msg.Author.Id,
msg.Channel.Id);

View File

@@ -2,7 +2,7 @@ namespace NadekoBot.Modules.Games.Common.Trivia;
public sealed class PokemonQuestionPool : IQuestionPool
{
public int QuestionsCount => 721; // xd
public int QuestionsCount => 905; // xd
private readonly NadekoRandom _rng;
private readonly ILocalDataCache _cache;

View File

@@ -1,3 +1,4 @@
#nullable disable warnings
using LinqToDB;
using Microsoft.EntityFrameworkCore;
using NadekoBot.Common.ModuleBehaviors;
@@ -391,9 +392,9 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand
template = JsonConvert.DeserializeObject<XpTemplate>(
File.ReadAllText(XP_TEMPLATE_PATH),
settings);
settings)!;
if (template!.Version < 1)
if (template.Version < 1)
{
Log.Warning("Loaded default xp_template.json values as the old one was version 0. "
+ "Old one was renamed to xp_template.json.old");

View File

@@ -1219,6 +1219,10 @@ imageonlychannel:
- imageonlychannel
- imageonly
- imagesonly
linkonlychannel:
- linkonlychannel
- linkonly
- linkssonly
coordreload:
- coordreload
quotesexport:

File diff suppressed because one or more lines are too long

View File

@@ -2166,7 +2166,7 @@ imageonlychannel:
Users who send more than a few non-image messages will be banned from using the channel.
args:
- ""
linksonlychannel:
linkonlychannel:
desc: |-
Toggles whether the channel only allows links.
Users who send more than a few non-link messages will be banned from using the channel.

View File

@@ -971,7 +971,9 @@
"favorites": "Favorites",
"tags": "Tags",
"imageonly_enable": "This channel is now image-only.",
"linkonly_enable": "This channel is now link-only.",
"imageonly_disable": "This channel is no longer image-only.",
"linkonly_disable": "This channel is no longer link-only.",
"deleted_x_servers": "Deleted {0} servers.",
"curtr_gift": "Gift from {0} [{1}]",
"curtr_award": "Awarded by bot owner {0} [{1}]",