mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-10 09:18:27 -04:00
Merge branch 'v4' into v5
This commit is contained in:
23
CHANGELOG.md
23
CHANGELOG.md
@@ -2,6 +2,29 @@
|
||||
|
||||
Experimental changelog. Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except date format. a-c-f-r-o
|
||||
|
||||
## [4.3.18] - 26.12.2023
|
||||
|
||||
### Added
|
||||
|
||||
- Added `.cacheusers` command (thx Kotz)
|
||||
- Added `.clubreject` which lets you reject club applications
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated discord lib, there should be less console errors now
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed `icon_url` when using `.showembed`
|
||||
- Fixed `.quoteshow` not showing sometimes (thx Cata)
|
||||
- Notifications will no longer be sent if dms are off when using `.give`
|
||||
- Users should no longer be able to apply to clubs while in a club already (especially not to the same club they're already in)
|
||||
|
||||
### Removed
|
||||
|
||||
- `.revimg` and `.revav` as google removed reverse image search
|
||||
-
|
||||
|
||||
## [4.3.17] - 06.09.2023
|
||||
|
||||
### Fixed
|
||||
|
@@ -49,6 +49,13 @@ public sealed class DoAsUserMessage : IUserMessage
|
||||
return _msg.RemoveAllReactionsForEmoteAsync(emote, options);
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<IReadOnlyCollection<IUser>> GetReactionUsersAsync(
|
||||
IEmote emoji,
|
||||
int limit,
|
||||
RequestOptions? options = null,
|
||||
ReactionType type = ReactionType.Normal)
|
||||
=> _msg.GetReactionUsersAsync(emoji, limit, options, type);
|
||||
|
||||
public IAsyncEnumerable<IReadOnlyCollection<IUser>> GetReactionUsersAsync(IEmote emoji, int limit,
|
||||
RequestOptions? options = null)
|
||||
{
|
||||
@@ -137,5 +144,7 @@ public sealed class DoAsUserMessage : IUserMessage
|
||||
return _msg.Resolve(userHandling, channelHandling, roleHandling, everyoneHandling, emojiHandling);
|
||||
}
|
||||
|
||||
public MessageResolvedData ResolvedData => _msg.ResolvedData;
|
||||
|
||||
public IUserMessage ReferencedMessage => _msg.ReferencedMessage;
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
using NadekoBot.Services.Currency;
|
||||
using NadekoBot.Services.Currency;
|
||||
|
||||
namespace NadekoBot.Services;
|
||||
|
||||
@@ -27,13 +27,19 @@ public static class CurrencyServiceExtensions
|
||||
|
||||
if (await fromWallet.Transfer(amount, toWallet, extra))
|
||||
{
|
||||
await to.SendConfirmAsync(ebs,
|
||||
string.IsNullOrWhiteSpace(note)
|
||||
? $"Received {formattedAmount} from {from} "
|
||||
: $"Received {formattedAmount} from {from}: {note}");
|
||||
try
|
||||
{
|
||||
await to.SendConfirmAsync(ebs,
|
||||
string.IsNullOrWhiteSpace(note)
|
||||
? $"Received {formattedAmount} from {from} "
|
||||
: $"Received {formattedAmount} from {from}: {note}");
|
||||
}
|
||||
catch
|
||||
{
|
||||
//ignored
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,6 @@
|
||||
#nullable disable
|
||||
using Newtonsoft.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace NadekoBot;
|
||||
|
||||
@@ -8,6 +9,7 @@ public class SmartTextEmbedAuthor
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonProperty("icon_url")]
|
||||
[JsonPropertyName("icon_url")]
|
||||
public string IconUrl { get; set; }
|
||||
|
||||
public string Url { get; set; }
|
||||
|
@@ -1,5 +1,6 @@
|
||||
#nullable disable
|
||||
using Newtonsoft.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace NadekoBot;
|
||||
|
||||
@@ -8,5 +9,6 @@ public class SmartTextEmbedFooter
|
||||
public string Text { get; set; }
|
||||
|
||||
[JsonProperty("icon_url")]
|
||||
[JsonPropertyName("icon_url")]
|
||||
public string IconUrl { get; set; }
|
||||
}
|
@@ -8,6 +8,54 @@ namespace NadekoBot.Db;
|
||||
|
||||
public static class DiscordUserExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds the specified <paramref name="users"/> to the database. If a database user with placeholder name
|
||||
/// and discriminator is present in <paramref name="users"/>, their name and discriminator get updated accordingly.
|
||||
/// </summary>
|
||||
/// <param name="ctx">This database context.</param>
|
||||
/// <param name="users">The users to add or update in the database.</param>
|
||||
/// <returns>A tuple with the amount of new users added and old users updated.</returns>
|
||||
public static async Task<(long UsersAdded, long UsersUpdated)> RefreshUsersAsync(this NadekoContext ctx, List<IUser> users)
|
||||
{
|
||||
var presentDbUsers = await ctx.DiscordUser
|
||||
.Select(x => new { x.UserId, x.Username, x.Discriminator })
|
||||
.Where(x => users.Select(y => y.Id).Contains(x.UserId))
|
||||
.ToArrayAsyncEF();
|
||||
|
||||
var usersToAdd = users
|
||||
.Where(x => !presentDbUsers.Select(x => x.UserId).Contains(x.Id))
|
||||
.Select(x => new DiscordUser()
|
||||
{
|
||||
UserId = x.Id,
|
||||
AvatarId = x.AvatarId,
|
||||
Username = x.Username,
|
||||
Discriminator = x.Discriminator
|
||||
});
|
||||
|
||||
var added = (await ctx.BulkCopyAsync(usersToAdd)).RowsCopied;
|
||||
var toUpdateUserIds = presentDbUsers
|
||||
.Where(x => x.Username == "Unknown" && x.Discriminator == "????")
|
||||
.Select(x => x.UserId)
|
||||
.ToArray();
|
||||
|
||||
foreach (var user in users.Where(x => toUpdateUserIds.Contains(x.Id)))
|
||||
{
|
||||
await ctx.DiscordUser
|
||||
.Where(x => x.UserId == user.Id)
|
||||
.UpdateAsync(x => new DiscordUser()
|
||||
{
|
||||
Username = user.Username,
|
||||
Discriminator = user.Discriminator,
|
||||
|
||||
// .award tends to set AvatarId and DateAdded to NULL, so account for that.
|
||||
AvatarId = user.AvatarId,
|
||||
DateAdded = x.DateAdded ?? DateTime.UtcNow
|
||||
});
|
||||
}
|
||||
|
||||
return (added, toUpdateUserIds.Length);
|
||||
}
|
||||
|
||||
public static Task<DiscordUser> GetByUserIdAsync(
|
||||
this IQueryable<DiscordUser> set,
|
||||
ulong userId)
|
||||
|
@@ -1,4 +1,5 @@
|
||||
#nullable disable
|
||||
using NadekoBot.Db;
|
||||
using NadekoBot.Modules.Administration.Services;
|
||||
using Nadeko.Bot.Db.Models;
|
||||
using Nadeko.Common.Medusa;
|
||||
@@ -22,19 +23,53 @@ public partial class Administration
|
||||
private readonly IBotStrings _strings;
|
||||
private readonly IMedusaLoaderService _medusaLoader;
|
||||
private readonly ICoordinator _coord;
|
||||
private readonly DbService _db;
|
||||
|
||||
public SelfCommands(
|
||||
DiscordSocketClient client,
|
||||
DbService db,
|
||||
IBotStrings strings,
|
||||
ICoordinator coord,
|
||||
IMedusaLoaderService medusaLoader)
|
||||
{
|
||||
_client = client;
|
||||
_db = db;
|
||||
_strings = strings;
|
||||
_coord = coord;
|
||||
_medusaLoader = medusaLoader;
|
||||
}
|
||||
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[OwnerOnly]
|
||||
public Task CacheUsers()
|
||||
=> CacheUsers(ctx.Guild);
|
||||
|
||||
[Cmd]
|
||||
[OwnerOnly]
|
||||
public async Task CacheUsers(IGuild guild)
|
||||
{
|
||||
var downloadUsersTask = guild.DownloadUsersAsync();
|
||||
var message = await ReplyPendingLocalizedAsync(strs.cache_users_pending);
|
||||
using var dbContext = _db.GetDbContext();
|
||||
|
||||
await downloadUsersTask;
|
||||
|
||||
var users = (await guild.GetUsersAsync(CacheMode.CacheOnly))
|
||||
.Cast<IUser>()
|
||||
.ToList();
|
||||
|
||||
var (added, updated) = await dbContext.RefreshUsersAsync(users);
|
||||
|
||||
await message.ModifyAsync(x =>
|
||||
x.Embed = _eb.Create()
|
||||
.WithDescription(GetText(strs.cache_users_done(added, updated)))
|
||||
.WithOkColor()
|
||||
.Build()
|
||||
);
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
[OwnerOnly]
|
||||
public async Task DoAs(IUser user, [Leftover] string message)
|
||||
|
@@ -421,30 +421,6 @@ public partial class Searches : NadekoModule<SearchesService>
|
||||
await SendConfirmAsync("🐈" + GetText(strs.catfact), fact);
|
||||
}
|
||||
|
||||
//done in 3.0
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task Revav([Leftover] IGuildUser usr = null)
|
||||
{
|
||||
if (usr is null)
|
||||
usr = (IGuildUser)ctx.User;
|
||||
|
||||
var av = usr.RealAvatarUrl();
|
||||
await SendConfirmAsync($"https://images.google.com/searchbyimage?image_url={av}");
|
||||
}
|
||||
|
||||
//done in 3.0
|
||||
[Cmd]
|
||||
public async Task Revimg([Leftover] string imageLink = null)
|
||||
{
|
||||
imageLink = imageLink?.Trim() ?? "";
|
||||
|
||||
if (string.IsNullOrWhiteSpace(imageLink))
|
||||
return;
|
||||
|
||||
await SendConfirmAsync($"https://images.google.com/searchbyimage?image_url={imageLink}");
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
public async Task Wiki([Leftover] string query = null)
|
||||
{
|
||||
|
@@ -8,6 +8,9 @@ using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.Drawing.Processing;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using SixLabors.ImageSharp.Processing;
|
||||
using System.Collections;
|
||||
using System.Net.Http.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Color = SixLabors.ImageSharp.Color;
|
||||
using Image = SixLabors.ImageSharp.Image;
|
||||
|
||||
|
@@ -129,15 +129,27 @@ public partial class Utility
|
||||
}
|
||||
|
||||
private async Task ShowQuoteData(Quote data)
|
||||
=> await ctx.Channel.EmbedAsync(_eb.Create(ctx)
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.quote_id($"#{data.Id}")))
|
||||
.AddField(GetText(strs.trigger), data.Keyword)
|
||||
.AddField(GetText(strs.response),
|
||||
Format.Sanitize(data.Text).Replace("](", "]\\("))
|
||||
.WithFooter(
|
||||
GetText(strs.created_by($"{data.AuthorName} ({data.AuthorId})"))));
|
||||
{
|
||||
var eb = _eb.Create(ctx)
|
||||
.WithOkColor()
|
||||
.WithTitle($"{GetText(strs.quote_id($"#{data.Id}"))} | {GetText(strs.response)}:")
|
||||
.WithDescription(Format.Sanitize(data.Text).Replace("](", "]\\(").TrimTo(4096))
|
||||
.AddField(GetText(strs.trigger), data.Keyword)
|
||||
.WithFooter(
|
||||
GetText(strs.created_by($"{data.AuthorName} ({data.AuthorId})")))
|
||||
.Build();
|
||||
|
||||
if (!(data.Text.Length > 4096))
|
||||
{
|
||||
await ctx.Channel.SendMessageAsync(embed: eb);
|
||||
return;
|
||||
}
|
||||
|
||||
await ctx.Channel.SendFileAsync(
|
||||
attachment: new FileAttachment(await data.Text.ToStream(), "quote.txt"),
|
||||
embed: eb);
|
||||
}
|
||||
|
||||
private async Task QuoteSearchinternalAsync(string? keyword, string textOrAuthor)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(textOrAuthor))
|
||||
|
@@ -1,4 +1,6 @@
|
||||
#nullable disable
|
||||
using Microsoft.CodeAnalysis.CSharp.Scripting;
|
||||
using Microsoft.CodeAnalysis.Scripting;
|
||||
using NadekoBot.Modules.Utility.Services;
|
||||
using Newtonsoft.Json;
|
||||
using System.Diagnostics;
|
||||
@@ -461,13 +463,14 @@ public partial class Utility : NadekoModule
|
||||
{
|
||||
if (tags.Length == 0)
|
||||
tags = new[] { name };
|
||||
|
||||
await ctx.Guild.CreateStickerAsync(name,
|
||||
|
||||
await ctx.Guild.CreateStickerAsync(
|
||||
name,
|
||||
stream,
|
||||
$"{name}.{format}",
|
||||
tags,
|
||||
description: string.IsNullOrWhiteSpace(description) ? "Missing description" : description
|
||||
);
|
||||
string.IsNullOrWhiteSpace(description) ? "Missing description" : description
|
||||
);
|
||||
|
||||
await ctx.OkAsync();
|
||||
}
|
||||
|
@@ -27,6 +27,7 @@
|
||||
<PackageReference Include="AWSSDK.S3" Version="3.7.101.58" />
|
||||
<PackageReference Include="CodeHollow.FeedReader" Version="1.2.6" />
|
||||
<PackageReference Include="CommandLineParser" Version="2.9.1" />
|
||||
<PackageReference Include="Discord.Net" Version="3.203.0" />
|
||||
<PackageReference Include="CoreCLR-NCalc" Version="2.2.110" />
|
||||
<PackageReference Include="Google.Apis.Urlshortener.v1" Version="1.41.1.138" />
|
||||
<PackageReference Include="Google.Apis.YouTube.v3" Version="1.62.1.3205" />
|
||||
|
@@ -647,10 +647,6 @@ chucknorris:
|
||||
magicitem:
|
||||
- magicitem
|
||||
- mi
|
||||
revav:
|
||||
- revav
|
||||
revimg:
|
||||
- revimg
|
||||
safebooru:
|
||||
- safebooru
|
||||
wiki:
|
||||
@@ -1393,4 +1389,6 @@ autopublish:
|
||||
- autopublish
|
||||
doas:
|
||||
- doas
|
||||
- execas
|
||||
- execas
|
||||
cacheusers:
|
||||
- cacheusers
|
@@ -2371,4 +2371,9 @@ doas:
|
||||
clubrename:
|
||||
desc: "Renames your club. Requires you club ownership or club-admin status."
|
||||
args:
|
||||
- "New cool club name"
|
||||
- "New cool club name"
|
||||
cacheusers:
|
||||
desc: Caches users of a Discord server and saves them to the database.
|
||||
args:
|
||||
- ""
|
||||
- "serverId"
|
@@ -1060,5 +1060,7 @@
|
||||
"sticker_missing_name": "Please specify a name for the sticker.",
|
||||
"thread_deleted": "Thread Deleted",
|
||||
"thread_created": "Thread Created",
|
||||
"supported_languages": "Supported Languages"
|
||||
"supported_languages": "Supported Languages",
|
||||
"cache_users_pending": "Updating users, please wait...",
|
||||
"cache_users_done": "{0} users were added and {1} users were updated."
|
||||
}
|
||||
|
Reference in New Issue
Block a user