mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-10 17:28:27 -04:00
Implemented .linkonly (as an alternative to .imageonly). Updated pokaman with latest generations. Updated responses, fixed some warnings
This commit is contained in:
@@ -5,4 +5,11 @@ public class ImageOnlyChannel : DbEntity
|
|||||||
{
|
{
|
||||||
public ulong GuildId { get; set; }
|
public ulong GuildId { get; set; }
|
||||||
public ulong ChannelId { get; set; }
|
public ulong ChannelId { get; set; }
|
||||||
|
public OnlyChannelType Type { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum OnlyChannelType
|
||||||
|
{
|
||||||
|
Image,
|
||||||
|
Link
|
||||||
}
|
}
|
@@ -1,4 +1,5 @@
|
|||||||
using NadekoBot.Services.Database.Models;
|
#nullable disable warnings
|
||||||
|
using NadekoBot.Services.Database.Models;
|
||||||
|
|
||||||
namespace NadekoBot.Db.Models;
|
namespace NadekoBot.Db.Models;
|
||||||
|
|
||||||
|
2858
src/NadekoBot/Migrations/Sqlite/20220727005807_linkonly-channels.Designer.cs
generated
Normal file
2858
src/NadekoBot/Migrations/Sqlite/20220727005807_linkonly-channels.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 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1088,6 +1088,9 @@ namespace NadekoBot.Migrations
|
|||||||
b.Property<ulong>("GuildId")
|
b.Property<ulong>("GuildId")
|
||||||
.HasColumnType("INTEGER");
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<int>("Type")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.HasIndex("ChannelId")
|
b.HasIndex("ChannelId")
|
||||||
|
@@ -32,10 +32,10 @@ public partial class Administration : NadekoModule<AdministrationService>
|
|||||||
Inherit
|
Inherit
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly ImageOnlyChannelService _imageOnly;
|
private readonly SomethingOnlyChannelService _somethingOnly;
|
||||||
|
|
||||||
public Administration(ImageOnlyChannelService imageOnly)
|
public Administration(SomethingOnlyChannelService somethingOnly)
|
||||||
=> _imageOnly = imageOnly;
|
=> _somethingOnly = somethingOnly;
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
@@ -43,13 +43,26 @@ public partial class Administration : NadekoModule<AdministrationService>
|
|||||||
[BotPerm(GuildPerm.ManageGuild)]
|
[BotPerm(GuildPerm.ManageGuild)]
|
||||||
public async Task ImageOnlyChannel(StoopidTime time = null)
|
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)
|
if (newValue)
|
||||||
await ReplyConfirmLocalizedAsync(strs.imageonly_enable);
|
await ReplyConfirmLocalizedAsync(strs.imageonly_enable);
|
||||||
else
|
else
|
||||||
await ReplyPendingLocalizedAsync(strs.imageonly_disable);
|
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]
|
[Cmd]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[UserPerm(ChannelPerm.ManageChannels)]
|
[UserPerm(ChannelPerm.ManageChannels)]
|
||||||
|
@@ -5,16 +5,18 @@ using NadekoBot.Common.ModuleBehaviors;
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading.Channels;
|
using System.Threading.Channels;
|
||||||
using Nadeko.Common;
|
using Nadeko.Common;
|
||||||
|
using NadekoBot.Services.Database.Models;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration.Services;
|
namespace NadekoBot.Modules.Administration.Services;
|
||||||
|
|
||||||
public sealed class ImageOnlyChannelService : IExecOnMessage
|
public sealed class SomethingOnlyChannelService : IExecOnMessage
|
||||||
{
|
{
|
||||||
public int Priority { get; } = 0;
|
public int Priority { get; } = 0;
|
||||||
private readonly IMemoryCache _ticketCache;
|
private readonly IMemoryCache _ticketCache;
|
||||||
private readonly DiscordSocketClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly DbService _db;
|
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>(
|
private readonly Channel<IUserMessage> _deleteQueue = Channel.CreateBounded<IUserMessage>(
|
||||||
new BoundedChannelOptions(100)
|
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;
|
_ticketCache = ticketCache;
|
||||||
_client = client;
|
_client = client;
|
||||||
_db = db;
|
_db = db;
|
||||||
|
|
||||||
using var uow = _db.GetDbContext();
|
using var uow = _db.GetDbContext();
|
||||||
_enabledOn = uow.ImageOnlyChannels.ToList()
|
_imageOnly = uow.ImageOnlyChannels
|
||||||
|
.Where(x => x.Type == OnlyChannelType.Image)
|
||||||
|
.ToList()
|
||||||
.GroupBy(x => x.GuildId)
|
.GroupBy(x => x.GuildId)
|
||||||
.ToDictionary(x => x.Key, x => new ConcurrentHashSet<ulong>(x.Select(y => y.ChannelId)))
|
.ToDictionary(x => x.Key, x => new ConcurrentHashSet<ulong>(x.Select(y => y.ChannelId)))
|
||||||
.ToConcurrent();
|
.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);
|
_ = Task.Run(DeleteQueueRunner);
|
||||||
|
|
||||||
_client.ChannelDestroyed += ClientOnChannelDestroyed;
|
_client.ChannelDestroyed += ClientOnChannelDestroyed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task ClientOnChannelDestroyed(SocketChannel ch)
|
private async Task ClientOnChannelDestroyed(SocketChannel ch)
|
||||||
{
|
{
|
||||||
if (ch is not IGuildChannel gch)
|
if (ch is not IGuildChannel gch)
|
||||||
return Task.CompletedTask;
|
return;
|
||||||
|
|
||||||
if (_enabledOn.TryGetValue(gch.GuildId, out var channels) && channels.TryRemove(ch.Id))
|
if (_imageOnly.TryGetValue(gch.GuildId, out var channels) && channels.TryRemove(ch.Id))
|
||||||
ToggleImageOnlyChannel(gch.GuildId, ch.Id, true);
|
await ToggleImageOnlyChannelAsync(gch.GuildId, ch.Id, true);
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task DeleteQueueRunner()
|
private async Task DeleteQueueRunner()
|
||||||
@@ -66,31 +75,68 @@ public sealed class ImageOnlyChannelService : IExecOnMessage
|
|||||||
catch (HttpException ex) when (ex.HttpCode == HttpStatusCode.Forbidden)
|
catch (HttpException ex) when (ex.HttpCode == HttpStatusCode.Forbidden)
|
||||||
{
|
{
|
||||||
// disable if bot can't delete messages in the channel
|
// 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;
|
var newState = false;
|
||||||
using var uow = _db.GetDbContext();
|
await using var uow = _db.GetDbContext();
|
||||||
if (forceDisable || (_enabledOn.TryGetValue(guildId, out var channels) && channels.TryRemove(channelId)))
|
if (forceDisable || (_imageOnly.TryGetValue(guildId, out var channels) && channels.TryRemove(channelId)))
|
||||||
uow.ImageOnlyChannels.Delete(x => x.ChannelId == channelId);
|
{
|
||||||
|
await uow.ImageOnlyChannels.DeleteAsync(x => x.ChannelId == channelId && x.Type == OnlyChannelType.Link);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
await uow.ImageOnlyChannels.DeleteAsync(x => x.ChannelId == channelId);
|
||||||
uow.ImageOnlyChannels.Add(new()
|
uow.ImageOnlyChannels.Add(new()
|
||||||
{
|
{
|
||||||
GuildId = guildId,
|
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);
|
channels.Add(channelId);
|
||||||
newState = true;
|
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;
|
return newState;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,11 +145,27 @@ public sealed class ImageOnlyChannelService : IExecOnMessage
|
|||||||
if (msg.Channel is not ITextChannel tch)
|
if (msg.Channel is not ITextChannel tch)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (msg.Attachments.Any(x => x is { Height: > 0, Width: > 0 }))
|
if (_imageOnly.TryGetValue(tch.GuildId, out var chs) && chs.Contains(msg.Channel.Id))
|
||||||
return false;
|
return await HandleOnlyChannel(tch, msg, OnlyChannelType.Image);
|
||||||
|
|
||||||
if (!_enabledOn.TryGetValue(tch.GuildId, out var chs) || !chs.Contains(msg.Channel.Id))
|
if (_linkOnly.TryGetValue(tch.GuildId, out chs) && chs.Contains(msg.Channel.Id))
|
||||||
return false;
|
return await HandleOnlyChannel(tch, msg, OnlyChannelType.Link);
|
||||||
|
|
||||||
|
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)
|
var user = await tch.Guild.GetUserAsync(msg.Author.Id)
|
||||||
?? await _client.Rest.GetGuildUserAsync(tch.GuildId, 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
|
// ignore owner and admin
|
||||||
if (user.Id == tch.Guild.OwnerId || user.GuildPermissions.Administrator)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,7 +187,11 @@ public sealed class ImageOnlyChannelService : IExecOnMessage
|
|||||||
|
|
||||||
if (!botUser.GetPermissions(tch).ManageChannel)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,7 +199,8 @@ public sealed class ImageOnlyChannelService : IExecOnMessage
|
|||||||
if (shouldLock)
|
if (shouldLock)
|
||||||
{
|
{
|
||||||
await tch.AddPermissionOverwriteAsync(msg.Author, new(sendMessages: PermValue.Deny));
|
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,
|
||||||
msg.Author.Id,
|
msg.Author.Id,
|
||||||
msg.Channel.Id);
|
msg.Channel.Id);
|
||||||
|
@@ -2,7 +2,7 @@ namespace NadekoBot.Modules.Games.Common.Trivia;
|
|||||||
|
|
||||||
public sealed class PokemonQuestionPool : IQuestionPool
|
public sealed class PokemonQuestionPool : IQuestionPool
|
||||||
{
|
{
|
||||||
public int QuestionsCount => 721; // xd
|
public int QuestionsCount => 905; // xd
|
||||||
private readonly NadekoRandom _rng;
|
private readonly NadekoRandom _rng;
|
||||||
private readonly ILocalDataCache _cache;
|
private readonly ILocalDataCache _cache;
|
||||||
|
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
#nullable disable warnings
|
||||||
using LinqToDB;
|
using LinqToDB;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using NadekoBot.Common.ModuleBehaviors;
|
using NadekoBot.Common.ModuleBehaviors;
|
||||||
@@ -391,9 +392,9 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand
|
|||||||
|
|
||||||
template = JsonConvert.DeserializeObject<XpTemplate>(
|
template = JsonConvert.DeserializeObject<XpTemplate>(
|
||||||
File.ReadAllText(XP_TEMPLATE_PATH),
|
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. "
|
Log.Warning("Loaded default xp_template.json values as the old one was version 0. "
|
||||||
+ "Old one was renamed to xp_template.json.old");
|
+ "Old one was renamed to xp_template.json.old");
|
||||||
|
@@ -1219,6 +1219,10 @@ imageonlychannel:
|
|||||||
- imageonlychannel
|
- imageonlychannel
|
||||||
- imageonly
|
- imageonly
|
||||||
- imagesonly
|
- imagesonly
|
||||||
|
linkonlychannel:
|
||||||
|
- linkonlychannel
|
||||||
|
- linkonly
|
||||||
|
- linkssonly
|
||||||
coordreload:
|
coordreload:
|
||||||
- coordreload
|
- coordreload
|
||||||
quotesexport:
|
quotesexport:
|
||||||
|
File diff suppressed because one or more lines are too long
@@ -2166,7 +2166,7 @@ imageonlychannel:
|
|||||||
Users who send more than a few non-image messages will be banned from using the channel.
|
Users who send more than a few non-image messages will be banned from using the channel.
|
||||||
args:
|
args:
|
||||||
- ""
|
- ""
|
||||||
linksonlychannel:
|
linkonlychannel:
|
||||||
desc: |-
|
desc: |-
|
||||||
Toggles whether the channel only allows links.
|
Toggles whether the channel only allows links.
|
||||||
Users who send more than a few non-link messages will be banned from using the channel.
|
Users who send more than a few non-link messages will be banned from using the channel.
|
||||||
|
@@ -971,7 +971,9 @@
|
|||||||
"favorites": "Favorites",
|
"favorites": "Favorites",
|
||||||
"tags": "Tags",
|
"tags": "Tags",
|
||||||
"imageonly_enable": "This channel is now image-only.",
|
"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.",
|
"imageonly_disable": "This channel is no longer image-only.",
|
||||||
|
"linkonly_disable": "This channel is no longer link-only.",
|
||||||
"deleted_x_servers": "Deleted {0} servers.",
|
"deleted_x_servers": "Deleted {0} servers.",
|
||||||
"curtr_gift": "Gift from {0} [{1}]",
|
"curtr_gift": "Gift from {0} [{1}]",
|
||||||
"curtr_award": "Awarded by bot owner {0} [{1}]",
|
"curtr_award": "Awarded by bot owner {0} [{1}]",
|
||||||
|
Reference in New Issue
Block a user