diff --git a/src/Nadeko.Bot.Generators.Strings/Nadeko.Bot.Generators.Strings.csproj b/src/Nadeko.Bot.Generators.Strings/Nadeko.Bot.Generators.Strings.csproj index c49280b68..8d39c500f 100644 --- a/src/Nadeko.Bot.Generators.Strings/Nadeko.Bot.Generators.Strings.csproj +++ b/src/Nadeko.Bot.Generators.Strings/Nadeko.Bot.Generators.Strings.csproj @@ -5,16 +5,12 @@ latest false true - true - enable - enable - NadekoBot.Generators - + diff --git a/src/Nadeko.Bot.Modules.Administration/LocalizationCommands.cs b/src/Nadeko.Bot.Modules.Administration/LocalizationCommands.cs index 8890811de..dca00a6ca 100644 --- a/src/Nadeko.Bot.Modules.Administration/LocalizationCommands.cs +++ b/src/Nadeko.Bot.Modules.Administration/LocalizationCommands.cs @@ -65,7 +65,10 @@ public partial class Administration _localization.SetGuildCulture(ctx.Guild, ci); } - await ReplyConfirmLocalizedAsync(strs.lang_set(Format.Bold(ci.ToString()), Format.Bold(ci.NativeName))); + var nativeName = ci.NativeName; + if (ci.Name == "ts-TS") + nativeName = _supportedLocales[ci.Name]; + await ReplyConfirmLocalizedAsync(strs.lang_set(Format.Bold(ci.ToString()), Format.Bold(nativeName))); } catch (Exception) { diff --git a/src/Nadeko.Bot.Modules.Xp/Club/Club.cs b/src/Nadeko.Bot.Modules.Xp/Club/Club.cs index f8d4cccf7..0f42dc4e3 100644 --- a/src/Nadeko.Bot.Modules.Xp/Club/Club.cs +++ b/src/Nadeko.Bot.Modules.Xp/Club/Club.cs @@ -283,6 +283,24 @@ public partial class Xp else if (result == ClubAcceptResult.NotOwnerOrAdmin) await ReplyErrorLocalizedAsync(strs.club_admin_perms); } + + [Cmd] + [Priority(1)] + public Task ClubReject(IUser user) + => ClubReject(user.ToString()); + + [Cmd] + [Priority(0)] + public async Task ClubReject([Leftover] string userName) + { + var result = _service.RejectApplication(ctx.User.Id, userName, out var discordUser); + if (result == ClubDenyResult.Rejected) + await ReplyConfirmLocalizedAsync(strs.club_rejected(Format.Bold(discordUser.ToString()))); + else if(result == ClubDenyResult.NoSuchApplicant) + await ReplyErrorLocalizedAsync(strs.club_accept_invalid_applicant); + else if(result == ClubDenyResult.NotOwnerOrAdmin) + await ReplyErrorLocalizedAsync(strs.club_admin_perms); + } [Cmd] public async Task ClubLeave() diff --git a/src/Nadeko.Bot.Modules.Xp/Club/ClubService.cs b/src/Nadeko.Bot.Modules.Xp/Club/ClubService.cs index 5c7ec0ea8..c8b088004 100644 --- a/src/Nadeko.Bot.Modules.Xp/Club/ClubService.cs +++ b/src/Nadeko.Bot.Modules.Xp/Club/ClubService.cs @@ -19,7 +19,6 @@ public class ClubService : INService, IClubService _httpFactory = httpFactory; } - public async Task CreateClubAsync(IUser user, string clubName) { if (!CheckClubName(clubName)) @@ -143,7 +142,7 @@ public class ClubService : INService, IClubService //user banned or a member of a club, or already applied, // or doesn't min minumum level requirement, can't apply - if (du.Club is not null) + if (du.ClubId is not null) return ClubApplyResult.AlreadyInAClub; if (club.Bans.Any(x => x.UserId == du.Id)) @@ -189,6 +188,26 @@ public class ClubService : INService, IClubService uow.SaveChanges(); return ClubAcceptResult.Accepted; } + + public ClubDenyResult RejectApplication(ulong clubOwnerUserId, string userName, out DiscordUser discordUser) + { + discordUser = null; + using var uow = _db.GetDbContext(); + var club = uow.Clubs.GetByOwnerOrAdmin(clubOwnerUserId); + if (club is null) + return ClubDenyResult.NotOwnerOrAdmin; + + var applicant = + club.Applicants.FirstOrDefault(x => x.User.ToString().ToUpperInvariant() == userName.ToUpperInvariant()); + if (applicant is null) + return ClubDenyResult.NoSuchApplicant; + + club.Applicants.Remove(applicant); + + discordUser = applicant.User; + uow.SaveChanges(); + return ClubDenyResult.Rejected; + } public ClubInfo GetClubWithBansAndApplications(ulong ownerUserId) { diff --git a/src/Nadeko.Bot.Modules.Xp/Club/IClubService.cs b/src/Nadeko.Bot.Modules.Xp/Club/IClubService.cs index 2ba29890b..de59e497f 100644 --- a/src/Nadeko.Bot.Modules.Xp/Club/IClubService.cs +++ b/src/Nadeko.Bot.Modules.Xp/Club/IClubService.cs @@ -13,6 +13,7 @@ public interface IClubService bool GetClubByName(string clubName, out ClubInfo club); ClubApplyResult ApplyToClub(IUser user, ClubInfo club); ClubAcceptResult AcceptApplication(ulong clubOwnerUserId, string userName, out DiscordUser discordUser); + ClubDenyResult RejectApplication(ulong clubOwnerUserId, string userName, out DiscordUser discordUser); ClubInfo? GetClubWithBansAndApplications(ulong ownerUserId); ClubLeaveResult LeaveClub(IUser user); bool SetDescription(ulong userId, string? desc); diff --git a/src/Nadeko.Bot.Modules.Xp/Club/Results/ClubAcceptResult.cs b/src/Nadeko.Bot.Modules.Xp/Club/Results/ClubAcceptResult.cs index c8e725c45..627ab5919 100644 --- a/src/Nadeko.Bot.Modules.Xp/Club/Results/ClubAcceptResult.cs +++ b/src/Nadeko.Bot.Modules.Xp/Club/Results/ClubAcceptResult.cs @@ -5,4 +5,11 @@ public enum ClubAcceptResult Accepted, NotOwnerOrAdmin, NoSuchApplicant, +} + +public enum ClubDenyResult +{ + Rejected, + NoSuchApplicant, + NotOwnerOrAdmin } \ No newline at end of file diff --git a/src/NadekoBot/NadekoBot.csproj b/src/NadekoBot/NadekoBot.csproj index 4dc463df6..ef3eff33b 100644 --- a/src/NadekoBot/NadekoBot.csproj +++ b/src/NadekoBot/NadekoBot.csproj @@ -29,7 +29,7 @@ - + diff --git a/src/NadekoBot/Services/Impl/GoogleApiService.cs b/src/NadekoBot/Services/Impl/GoogleApiService.cs index 9c91bd503..29432f9c3 100644 --- a/src/NadekoBot/Services/Impl/GoogleApiService.cs +++ b/src/NadekoBot/Services/Impl/GoogleApiService.cs @@ -57,7 +57,7 @@ public sealed partial class GoogleApiService : IGoogleApiService, INService return (await query.ExecuteAsync()).Items.Select(i => i.Id.PlaylistId); } - public async Task> GetRelatedVideosAsync(string id, int count = 1, string user = null) + public async Task> GetRelatedVideosAsync(string id, int count = 2, string user = null) { if (string.IsNullOrWhiteSpace(id)) throw new ArgumentNullException(nameof(id)); @@ -67,10 +67,14 @@ public sealed partial class GoogleApiService : IGoogleApiService, INService var query = _yt.Search.List("snippet"); query.MaxResults = count; - query.RelatedToVideoId = id; + query.Q = id; + // query.RelatedToVideoId = id; query.Type = "video"; query.QuotaUser = user; - return (await query.ExecuteAsync()).Items.Select(i => "https://www.youtube.com/watch?v=" + i.Id.VideoId); + // bad workaround as there's no replacement for related video querying right now. + // Query youtube with the id of the video, take a second video in the results + // skip the first one as that's probably the same video. + return (await query.ExecuteAsync()).Items.Select(i => "https://www.youtube.com/watch?v=" + i.Id.VideoId).Skip(1); } public async Task> GetVideoLinksByKeywordAsync(string keywords, int count = 1) diff --git a/src/NadekoBot/data/aliases.yml b/src/NadekoBot/data/aliases.yml index 897d0fc36..489ae6721 100644 --- a/src/NadekoBot/data/aliases.yml +++ b/src/NadekoBot/data/aliases.yml @@ -1116,6 +1116,8 @@ clubapply: - clubapply clubaccept: - clubaccept +clubreject: + - clubreject clubleave: - clubleave clubdisband: diff --git a/src/NadekoBot/data/strings/commands/commands.en-US.yml b/src/NadekoBot/data/strings/commands/commands.en-US.yml index 1955074ca..ec23dd5a6 100644 --- a/src/NadekoBot/data/strings/commands/commands.en-US.yml +++ b/src/NadekoBot/data/strings/commands/commands.en-US.yml @@ -1929,6 +1929,10 @@ clubaccept: desc: "Accept a user who applied to your club." args: - "user#1337" +clubreject: + desc: "Reject a user who applied to your club." + args: + - "user#1337" clubleave: desc: "Leaves the club you're currently in." args: diff --git a/src/NadekoBot/data/strings/responses/responses.en-US.json b/src/NadekoBot/data/strings/responses/responses.en-US.json index eab054924..a3f4d4d4d 100644 --- a/src/NadekoBot/data/strings/responses/responses.en-US.json +++ b/src/NadekoBot/data/strings/responses/responses.en-US.json @@ -847,6 +847,7 @@ "club_not_exists": "That club doesn't exist.", "club_applied": "You've applied for membership in {0} club.", "club_accepted": "Accepted user {0} to the club.", + "club_rejected": "The application by {0} has been rejected.", "club_accept_invalid_applicant": "That user has not applied to your club.", "club_left": "You've left the club.", "club_not_in_a_club": "You are not in a club.",