mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2024-10-02 20:13:13 +00:00
Merge branch 'force-add' into 'v4'
Implemented command to force users into the database, closes #425 Closes #425 See merge request Kwoth/nadekobot!312
This commit is contained in:
commit
9bf5a5a3cd
5 changed files with 95 additions and 2 deletions
|
@ -4,11 +4,60 @@ using LinqToDB.EntityFrameworkCore;
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Db.Models;
|
||||
using NadekoBot.Services.Database;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
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,5 +1,6 @@
|
|||
#nullable disable
|
||||
using Nadeko.Medusa;
|
||||
using NadekoBot.Db;
|
||||
using NadekoBot.Modules.Administration.Services;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
|
||||
|
@ -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)
|
||||
|
|
|
@ -1390,4 +1390,6 @@ autopublish:
|
|||
- autopublish
|
||||
doas:
|
||||
- doas
|
||||
- execas
|
||||
- execas
|
||||
cacheusers:
|
||||
- cacheusers
|
|
@ -2363,3 +2363,8 @@ doas:
|
|||
desc: "Execute the command as if you were the target user. Requires bot ownership and server administrator permission."
|
||||
args:
|
||||
- "@Thief .give all @Admin"
|
||||
cacheusers:
|
||||
desc: Caches users of a Discord server and saves them to the database.
|
||||
args:
|
||||
- ""
|
||||
- "serverId"
|
|
@ -1058,5 +1058,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."
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue