Only a few things with permissions left, and prefixes
This commit is contained in:
parent
dfb4c778d2
commit
6d27271d4a
@ -0,0 +1,14 @@
|
|||||||
|
using Discord;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NadekoBot.DataStructures.ModuleBehaviors
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Implemented by modules which block execution before anything is executed
|
||||||
|
/// </summary>
|
||||||
|
public interface IEarlyBlocker
|
||||||
|
{
|
||||||
|
Task<bool> TryBlockEarly(DiscordShardedClient client, IGuild guild, IUserMessage msg);
|
||||||
|
}
|
||||||
|
}
|
@ -7,12 +7,12 @@ namespace NadekoBot.DataStructures.ModuleBehaviors
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Implemented by modules which can execute something and prevent further commands from being executed.
|
/// Implemented by modules which can execute something and prevent further commands from being executed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IBlockingExecutor
|
public interface IEarlyBlockingExecutor
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Try to execute some logic within some module's service.
|
/// Try to execute some logic within some module's service.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Whether it should block other command executions after it.</returns>
|
/// <returns>Whether it should block other command executions after it.</returns>
|
||||||
Task<bool> TryExecute(DiscordShardedClient client, IGuild guild, IUserMessage msg);
|
Task<bool> TryExecuteEarly(DiscordShardedClient client, IGuild guild, IUserMessage msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
namespace NadekoBot.DataStructures.ModuleBehaviors
|
||||||
|
{
|
||||||
|
public interface IEarlyExecutor
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
12
src/NadekoBot/DataStructures/ModuleBehaviors/ILateBlocker.cs
Normal file
12
src/NadekoBot/DataStructures/ModuleBehaviors/ILateBlocker.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using Discord;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NadekoBot.DataStructures.ModuleBehaviors
|
||||||
|
{
|
||||||
|
public interface ILateBlocker
|
||||||
|
{
|
||||||
|
Task<bool> TryBlockLate(DiscordShardedClient client, IUserMessage msg, IGuild guild,
|
||||||
|
IMessageChannel channel, IUser user, string moduleName, string commandName);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
namespace NadekoBot.DataStructures.ModuleBehaviors
|
||||||
|
{
|
||||||
|
public interface ILateBlockingExecutor
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
using Discord;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NadekoBot.DataStructures.ModuleBehaviors
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Last thing to be executed, won't stop further executions
|
||||||
|
/// </summary>
|
||||||
|
public interface ILateExecutor
|
||||||
|
{
|
||||||
|
Task LateExecute(DiscordShardedClient client, IGuild guild, IUserMessage msg);
|
||||||
|
}
|
||||||
|
}
|
18
src/NadekoBot/DataStructures/NoPublicBotPrecondition.cs
Normal file
18
src/NadekoBot/DataStructures/NoPublicBotPrecondition.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using Discord.Commands;
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NadekoBot.DataStructures
|
||||||
|
{
|
||||||
|
public class NoPublicBot : PreconditionAttribute
|
||||||
|
{
|
||||||
|
public override Task<PreconditionResult> CheckPermissions(ICommandContext context, CommandInfo command, IServiceProvider services)
|
||||||
|
{
|
||||||
|
#if GLOBAL_NADEKo
|
||||||
|
return Task.FromResult(PreconditionResult.FromError("Not available on the public bot"));
|
||||||
|
#else
|
||||||
|
return Task.FromResult(PreconditionResult.FromSuccess());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -702,7 +702,7 @@ namespace NadekoBot.Migrations
|
|||||||
column: "BotConfigId");
|
column: "BotConfigId");
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
||||||
name: "IX_Repeaters_ChannelId",
|
name: "IX_Repeaters_channelId",
|
||||||
table: "Repeaters",
|
table: "Repeaters",
|
||||||
column: "ChannelId",
|
column: "ChannelId",
|
||||||
unique: true);
|
unique: true);
|
||||||
|
@ -30,7 +30,7 @@ namespace NadekoBot.Migrations
|
|||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
||||||
name: "IX_Repeaters_ChannelId",
|
name: "IX_Repeaters_channelId",
|
||||||
table: "Repeaters",
|
table: "Repeaters",
|
||||||
column: "ChannelId",
|
column: "ChannelId",
|
||||||
unique: true);
|
unique: true);
|
||||||
|
1556
src/NadekoBot/Migrations/20170528001839_permissions-version.Designer.cs
generated
Normal file
1556
src/NadekoBot/Migrations/20170528001839_permissions-version.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,23 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace NadekoBot.Migrations
|
||||||
|
{
|
||||||
|
public partial class permissionsversion : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "PermissionVersion",
|
||||||
|
table: "BotConfig",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "PermissionVersion",
|
||||||
|
table: "BotConfig");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -12,7 +12,7 @@ namespace NadekoBot.Migrations
|
|||||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
modelBuilder
|
modelBuilder
|
||||||
.HasAnnotation("ProductVersion", "1.1.0-rtm-22752");
|
.HasAnnotation("ProductVersion", "1.1.1");
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiRaidSetting", b =>
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiRaidSetting", b =>
|
||||||
{
|
{
|
||||||
@ -165,6 +165,8 @@ namespace NadekoBot.Migrations
|
|||||||
|
|
||||||
b.Property<string>("OkColor");
|
b.Property<string>("OkColor");
|
||||||
|
|
||||||
|
b.Property<int>("PermissionVersion");
|
||||||
|
|
||||||
b.Property<string>("RemindMessageFormat");
|
b.Property<string>("RemindMessageFormat");
|
||||||
|
|
||||||
b.Property<bool>("RotatingStatuses");
|
b.Property<bool>("RotatingStatuses");
|
||||||
|
@ -15,10 +15,10 @@ namespace NadekoBot.Modules.Administration
|
|||||||
public partial class Administration : NadekoTopLevelModule
|
public partial class Administration : NadekoTopLevelModule
|
||||||
{
|
{
|
||||||
private IGuild _nadekoSupportServer;
|
private IGuild _nadekoSupportServer;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
private readonly AdministrationService _admin;
|
private readonly AdministrationService _admin;
|
||||||
|
|
||||||
public Administration(DbHandler db, AdministrationService admin)
|
public Administration(DbService db, AdministrationService admin)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
_admin = admin;
|
_admin = admin;
|
||||||
|
@ -14,10 +14,10 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[Group]
|
[Group]
|
||||||
public class AutoAssignRoleCommands : NadekoSubmodule
|
public class AutoAssignRoleCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
private readonly AutoAssignRoleService _service;
|
private readonly AutoAssignRoleService _service;
|
||||||
|
|
||||||
public AutoAssignRoleCommands(AutoAssignRoleService service, DbHandler db)
|
public AutoAssignRoleCommands(AutoAssignRoleService service, DbService db)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
_service = service;
|
_service = service;
|
||||||
|
@ -12,10 +12,10 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[Group]
|
[Group]
|
||||||
public class GameChannelCommands : NadekoSubmodule
|
public class GameChannelCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
private readonly GameVoiceChannelService _service;
|
private readonly GameVoiceChannelService _service;
|
||||||
|
|
||||||
public GameChannelCommands(GameVoiceChannelService service, DbHandler db)
|
public GameChannelCommands(GameVoiceChannelService service, DbService db)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
_service = service;
|
_service = service;
|
||||||
|
@ -22,9 +22,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
public class Migration : NadekoSubmodule
|
public class Migration : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private const int CURRENT_VERSION = 1;
|
private const int CURRENT_VERSION = 1;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public Migration(DbHandler db)
|
public Migration(DbService db)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
}
|
}
|
||||||
|
@ -14,9 +14,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
public class MuteCommands : NadekoSubmodule
|
public class MuteCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly MuteService _service;
|
private readonly MuteService _service;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public MuteCommands(MuteService service, DbHandler db)
|
public MuteCommands(MuteService service, DbService db)
|
||||||
{
|
{
|
||||||
_service = service;
|
_service = service;
|
||||||
_db = db;
|
_db = db;
|
||||||
|
@ -14,10 +14,10 @@ namespace NadekoBot.Modules.Administration
|
|||||||
public class PlayingRotateCommands : NadekoSubmodule
|
public class PlayingRotateCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private static readonly object _locker = new object();
|
private static readonly object _locker = new object();
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
private readonly PlayingRotateService _service;
|
private readonly PlayingRotateService _service;
|
||||||
|
|
||||||
public PlayingRotateCommands(PlayingRotateService service, DbHandler db)
|
public PlayingRotateCommands(PlayingRotateService service, DbService db)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
_service = service;
|
_service = service;
|
||||||
|
@ -19,9 +19,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
{
|
{
|
||||||
private readonly ProtectionService _service;
|
private readonly ProtectionService _service;
|
||||||
private readonly MuteService _mute;
|
private readonly MuteService _mute;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public ProtectionCommands(ProtectionService service, MuteService mute, DbHandler db)
|
public ProtectionCommands(ProtectionService service, MuteService mute, DbService db)
|
||||||
{
|
{
|
||||||
_service = service;
|
_service = service;
|
||||||
_mute = mute;
|
_mute = mute;
|
||||||
|
@ -15,12 +15,12 @@ namespace NadekoBot.Modules.Administration
|
|||||||
public partial class Administration
|
public partial class Administration
|
||||||
{
|
{
|
||||||
[Group]
|
[Group]
|
||||||
public class RatelimitCommands : NadekoSubmodule
|
public class SlowModeCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly RatelimitService _service;
|
private readonly SlowmodeService _service;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public RatelimitCommands(RatelimitService service, DbHandler db)
|
public SlowModeCommands(SlowmodeService service, DbService db)
|
||||||
{
|
{
|
||||||
_service = service;
|
_service = service;
|
||||||
_db = db;
|
_db = db;
|
||||||
|
@ -18,9 +18,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[Group]
|
[Group]
|
||||||
public class SelfAssignedRolesCommands : NadekoSubmodule
|
public class SelfAssignedRolesCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public SelfAssignedRolesCommands(DbHandler db)
|
public SelfAssignedRolesCommands(DbService db)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
}
|
}
|
||||||
|
@ -21,14 +21,14 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[Group]
|
[Group]
|
||||||
public class SelfCommands : NadekoSubmodule
|
public class SelfCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
private static readonly object _locker = new object();
|
private static readonly object _locker = new object();
|
||||||
private readonly SelfService _service;
|
private readonly SelfService _service;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordShardedClient _client;
|
||||||
private readonly IImagesService _images;
|
private readonly IImagesService _images;
|
||||||
|
|
||||||
public SelfCommands(DbHandler db, SelfService service, DiscordShardedClient client,
|
public SelfCommands(DbService db, SelfService service, DiscordShardedClient client,
|
||||||
IImagesService images)
|
IImagesService images)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
@ -204,64 +204,6 @@ namespace NadekoBot.Modules.Administration
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//todo dm forwarding
|
|
||||||
//public async Task HandleDmForwarding(IUserMessage msg, ImmutableArray<AsyncLazy<IDMChannel>> ownerChannels)
|
|
||||||
//{
|
|
||||||
// if (_service.ForwardDMs && ownerChannels.Length > 0)
|
|
||||||
// {
|
|
||||||
// var title = _strings.GetText("dm_from",
|
|
||||||
// NadekoBot.Localization.DefaultCultureInfo,
|
|
||||||
// typeof(Administration).Name.ToLowerInvariant()) +
|
|
||||||
// $" [{msg.Author}]({msg.Author.Id})";
|
|
||||||
|
|
||||||
// var attachamentsTxt = GetTextStatic("attachments",
|
|
||||||
// NadekoBot.Localization.DefaultCultureInfo,
|
|
||||||
// typeof(Administration).Name.ToLowerInvariant());
|
|
||||||
|
|
||||||
// var toSend = msg.Content;
|
|
||||||
|
|
||||||
// if (msg.Attachments.Count > 0)
|
|
||||||
// {
|
|
||||||
// toSend += $"\n\n{Format.Code(attachamentsTxt)}:\n" +
|
|
||||||
// string.Join("\n", msg.Attachments.Select(a => a.ProxyUrl));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (_service.ForwardDMsToAllOwners)
|
|
||||||
// {
|
|
||||||
// var allOwnerChannels = await Task.WhenAll(ownerChannels
|
|
||||||
// .Select(x => x.Value))
|
|
||||||
// .ConfigureAwait(false);
|
|
||||||
|
|
||||||
// foreach (var ownerCh in allOwnerChannels.Where(ch => ch.Recipient.Id != msg.Author.Id))
|
|
||||||
// {
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// await ownerCh.SendConfirmAsync(title, toSend).ConfigureAwait(false);
|
|
||||||
// }
|
|
||||||
// catch
|
|
||||||
// {
|
|
||||||
// _log.Warn("Can't contact owner with id {0}", ownerCh.Recipient.Id);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// var firstOwnerChannel = await ownerChannels[0];
|
|
||||||
// if (firstOwnerChannel.Recipient.Id != msg.Author.Id)
|
|
||||||
// {
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// await firstOwnerChannel.SendConfirmAsync(title, toSend).ConfigureAwait(false);
|
|
||||||
// }
|
|
||||||
// catch
|
|
||||||
// {
|
|
||||||
// // ignored
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[OwnerOnly]
|
[OwnerOnly]
|
||||||
public async Task ConnectShard(int shardid)
|
public async Task ConnectShard(int shardid)
|
||||||
|
@ -14,9 +14,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
public class ServerGreetCommands : NadekoSubmodule
|
public class ServerGreetCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly GreetSettingsService _greetService;
|
private readonly GreetSettingsService _greetService;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public ServerGreetCommands(GreetSettingsService greetService, DbHandler db)
|
public ServerGreetCommands(GreetSettingsService greetService, DbService db)
|
||||||
{
|
{
|
||||||
_greetService = greetService;
|
_greetService = greetService;
|
||||||
_db = db;
|
_db = db;
|
||||||
|
@ -19,10 +19,10 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[Group]
|
[Group]
|
||||||
public class UserPunishCommands : NadekoSubmodule
|
public class UserPunishCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
private readonly MuteService _muteService;
|
private readonly MuteService _muteService;
|
||||||
|
|
||||||
public UserPunishCommands(DbHandler db, MuteService muteService)
|
public UserPunishCommands(DbService db, MuteService muteService)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
_muteService = muteService;
|
_muteService = muteService;
|
||||||
|
@ -19,9 +19,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
public class VcRoleCommands : NadekoSubmodule
|
public class VcRoleCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly VcRoleService _service;
|
private readonly VcRoleService _service;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public VcRoleCommands(VcRoleService service, DbHandler db)
|
public VcRoleCommands(VcRoleService service, DbService db)
|
||||||
{
|
{
|
||||||
_service = service;
|
_service = service;
|
||||||
_db = db;
|
_db = db;
|
||||||
@ -31,7 +31,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[RequireUserPermission(GuildPermission.ManageRoles)]
|
[RequireUserPermission(GuildPermission.ManageRoles)]
|
||||||
[RequireUserPermission(GuildPermission.ManageChannels)]
|
[RequireUserPermission(GuildPermission.ManageChannels)]
|
||||||
[RequireBotPermission(GuildPermission.ManageRoles)]
|
[RequireBotPermission(GuildPermission.ManageRoles)]
|
||||||
//todo discord.net [RequireBotPermission(GuildPermission.ManageChannels)]
|
//todo 999 discord.net [RequireBotPermission(GuildPermission.ManageChannels)]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task VcRole([Remainder]IRole role = null)
|
public async Task VcRole([Remainder]IRole role = null)
|
||||||
{
|
{
|
||||||
|
@ -18,9 +18,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
public class VoicePlusTextCommands : NadekoSubmodule
|
public class VoicePlusTextCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly VplusTService _service;
|
private readonly VplusTService _service;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public VoicePlusTextCommands(VplusTService service, DbHandler db)
|
public VoicePlusTextCommands(VplusTService service, DbService db)
|
||||||
{
|
{
|
||||||
_service = service;
|
_service = service;
|
||||||
_db = db;
|
_db = db;
|
||||||
|
@ -15,11 +15,11 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
public class CustomReactions : NadekoTopLevelModule
|
public class CustomReactions : NadekoTopLevelModule
|
||||||
{
|
{
|
||||||
private readonly IBotCredentials _creds;
|
private readonly IBotCredentials _creds;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
private readonly CustomReactionsService _crs;
|
private readonly CustomReactionsService _crs;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordShardedClient _client;
|
||||||
|
|
||||||
public CustomReactions(IBotCredentials creds, DbHandler db, CustomReactionsService crs,
|
public CustomReactions(IBotCredentials creds, DbService db, CustomReactionsService crs,
|
||||||
DiscordShardedClient client)
|
DiscordShardedClient client)
|
||||||
{
|
{
|
||||||
_creds = creds;
|
_creds = creds;
|
||||||
@ -239,7 +239,7 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
if ((toDelete.GuildId == null || toDelete.GuildId == 0) && Context.Guild == null)
|
if ((toDelete.GuildId == null || toDelete.GuildId == 0) && Context.Guild == null)
|
||||||
{
|
{
|
||||||
uow.CustomReactions.Remove(toDelete);
|
uow.CustomReactions.Remove(toDelete);
|
||||||
//todo i can dramatically improve performance of this, if Ids are ordered.
|
//todo 91 i can dramatically improve performance of this, if Ids are ordered.
|
||||||
_crs.GlobalReactions = _crs.GlobalReactions.Where(cr => cr?.Id != toDelete.Id).ToArray();
|
_crs.GlobalReactions = _crs.GlobalReactions.Where(cr => cr?.Id != toDelete.Id).ToArray();
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
|
@ -21,16 +21,16 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
public class AnimalRacing : NadekoSubmodule
|
public class AnimalRacing : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly BotConfig _bc;
|
private readonly BotConfig _bc;
|
||||||
private readonly CurrencyHandler _ch;
|
private readonly CurrencyService _cs;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordShardedClient _client;
|
||||||
|
|
||||||
|
|
||||||
public static ConcurrentDictionary<ulong, AnimalRace> AnimalRaces { get; } = new ConcurrentDictionary<ulong, AnimalRace>();
|
public static ConcurrentDictionary<ulong, AnimalRace> AnimalRaces { get; } = new ConcurrentDictionary<ulong, AnimalRace>();
|
||||||
|
|
||||||
public AnimalRacing(BotConfig bc, CurrencyHandler ch, DiscordShardedClient client)
|
public AnimalRacing(BotConfig bc, CurrencyService cs, DiscordShardedClient client)
|
||||||
{
|
{
|
||||||
_bc = bc;
|
_bc = bc;
|
||||||
_ch = ch;
|
_cs = cs;
|
||||||
_client = client;
|
_client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
public async Task Race()
|
public async Task Race()
|
||||||
{
|
{
|
||||||
var ar = new AnimalRace(Context.Guild.Id, (ITextChannel)Context.Channel, Prefix,
|
var ar = new AnimalRace(Context.Guild.Id, (ITextChannel)Context.Channel, Prefix,
|
||||||
_bc, _ch, _client,_localization, _strings);
|
_bc, _cs, _client,_localization, _strings);
|
||||||
|
|
||||||
if (ar.Fail)
|
if (ar.Fail)
|
||||||
await ReplyErrorLocalized("race_failed_starting").ConfigureAwait(false);
|
await ReplyErrorLocalized("race_failed_starting").ConfigureAwait(false);
|
||||||
@ -63,7 +63,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
await ar.JoinRace(Context.User as IGuildUser, amount);
|
await ar.JoinRace(Context.User as IGuildUser, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
//todo needs to be completely isolated, shouldn't use any services in the constructor,
|
//todo 85 needs to be completely isolated, shouldn't use any services in the constructor,
|
||||||
//then move the rest either to the module itself, or the service
|
//then move the rest either to the module itself, or the service
|
||||||
public class AnimalRace
|
public class AnimalRace
|
||||||
{
|
{
|
||||||
@ -81,7 +81,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
|
|
||||||
private readonly ITextChannel _raceChannel;
|
private readonly ITextChannel _raceChannel;
|
||||||
private readonly BotConfig _bc;
|
private readonly BotConfig _bc;
|
||||||
private readonly CurrencyHandler _ch;
|
private readonly CurrencyService _cs;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordShardedClient _client;
|
||||||
private readonly ILocalization _localization;
|
private readonly ILocalization _localization;
|
||||||
private readonly NadekoStrings _strings;
|
private readonly NadekoStrings _strings;
|
||||||
@ -89,12 +89,12 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
public bool Started { get; private set; }
|
public bool Started { get; private set; }
|
||||||
|
|
||||||
public AnimalRace(ulong serverId, ITextChannel channel, string prefix, BotConfig bc,
|
public AnimalRace(ulong serverId, ITextChannel channel, string prefix, BotConfig bc,
|
||||||
CurrencyHandler ch, DiscordShardedClient client, ILocalization localization,
|
CurrencyService cs, DiscordShardedClient client, ILocalization localization,
|
||||||
NadekoStrings strings)
|
NadekoStrings strings)
|
||||||
{
|
{
|
||||||
_prefix = prefix;
|
_prefix = prefix;
|
||||||
_bc = bc;
|
_bc = bc;
|
||||||
_ch = ch;
|
_cs = cs;
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_serverId = serverId;
|
_serverId = serverId;
|
||||||
_raceChannel = channel;
|
_raceChannel = channel;
|
||||||
@ -144,7 +144,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
var p = _participants.FirstOrDefault();
|
var p = _participants.FirstOrDefault();
|
||||||
|
|
||||||
if (p != null && p.AmountBet > 0)
|
if (p != null && p.AmountBet > 0)
|
||||||
await _ch.AddCurrencyAsync(p.User, "BetRace", p.AmountBet, false).ConfigureAwait(false);
|
await _cs.AddAsync(p.User, "BetRace", p.AmountBet, false).ConfigureAwait(false);
|
||||||
End();
|
End();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -232,7 +232,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
{
|
{
|
||||||
var wonAmount = winner.AmountBet * (_participants.Count - 1);
|
var wonAmount = winner.AmountBet * (_participants.Count - 1);
|
||||||
|
|
||||||
await _ch.AddCurrencyAsync(winner.User, "Won a Race", wonAmount, true)
|
await _cs.AddAsync(winner.User, "Won a Race", wonAmount, true)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
await _raceChannel.SendConfirmAsync(GetText("animal_race"),
|
await _raceChannel.SendConfirmAsync(GetText("animal_race"),
|
||||||
Format.Bold(GetText("animal_race_won_money", winner.User.Mention,
|
Format.Bold(GetText("animal_race_won_money", winner.User.Mention,
|
||||||
@ -287,7 +287,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (amount > 0)
|
if (amount > 0)
|
||||||
if (!await _ch.RemoveCurrencyAsync(u, "BetRace", amount, false).ConfigureAwait(false))
|
if (!await _cs.RemoveAsync(u, "BetRace", amount, false).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
await _raceChannel.SendErrorAsync(GetText("not_enough", _bc.CurrencySign)).ConfigureAwait(false);
|
await _raceChannel.SendErrorAsync(GetText("not_enough", _bc.CurrencySign)).ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
|
@ -36,13 +36,13 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
private string _secretCode = string.Empty;
|
private string _secretCode = string.Empty;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordShardedClient _client;
|
||||||
private readonly BotConfig _bc;
|
private readonly BotConfig _bc;
|
||||||
private readonly CurrencyHandler _ch;
|
private readonly CurrencyService _cs;
|
||||||
|
|
||||||
public CurrencyEvents(DiscordShardedClient client, BotConfig bc, CurrencyHandler ch)
|
public CurrencyEvents(DiscordShardedClient client, BotConfig bc, CurrencyService cs)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
_bc = bc;
|
_bc = bc;
|
||||||
_ch = ch;
|
_cs = cs;
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -111,7 +111,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
{
|
{
|
||||||
var _ = Task.Run(async () =>
|
var _ = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
await _ch.AddCurrencyAsync(arg.Author, "Sneaky Game Event", 100, false)
|
await _cs.AddAsync(arg.Author, "Sneaky Game Event", 100, false)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
try { await arg.DeleteAsync(new RequestOptions() { RetryMode = RetryMode.AlwaysFail }).ConfigureAwait(false); }
|
try { await arg.DeleteAsync(new RequestOptions() { RetryMode = RetryMode.AlwaysFail }).ConfigureAwait(false); }
|
||||||
@ -137,7 +137,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
desc, footer: footer)
|
desc, footer: footer)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
await new FlowerReactionEvent(_client, _ch).Start(msg, context, amount);
|
await new FlowerReactionEvent(_client, _cs).Start(msg, context, amount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -152,18 +152,18 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
private readonly ConcurrentHashSet<ulong> _flowerReactionAwardedUsers = new ConcurrentHashSet<ulong>();
|
private readonly ConcurrentHashSet<ulong> _flowerReactionAwardedUsers = new ConcurrentHashSet<ulong>();
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordShardedClient _client;
|
||||||
private readonly CurrencyHandler _ch;
|
private readonly CurrencyService _cs;
|
||||||
|
|
||||||
private IUserMessage StartingMessage { get; set; }
|
private IUserMessage StartingMessage { get; set; }
|
||||||
|
|
||||||
private CancellationTokenSource Source { get; }
|
private CancellationTokenSource Source { get; }
|
||||||
private CancellationToken CancelToken { get; }
|
private CancellationToken CancelToken { get; }
|
||||||
|
|
||||||
public FlowerReactionEvent(DiscordShardedClient client, CurrencyHandler ch)
|
public FlowerReactionEvent(DiscordShardedClient client, CurrencyService cs)
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_client = client;
|
_client = client;
|
||||||
_ch = ch;
|
_cs = cs;
|
||||||
Source = new CancellationTokenSource();
|
Source = new CancellationTokenSource();
|
||||||
CancelToken = Source.Token;
|
CancelToken = Source.Token;
|
||||||
}
|
}
|
||||||
@ -210,7 +210,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
{
|
{
|
||||||
if (r.Emote.Name == "🌸" && r.User.IsSpecified && ((DateTime.UtcNow - r.User.Value.CreatedAt).TotalDays > 5) && _flowerReactionAwardedUsers.Add(r.User.Value.Id))
|
if (r.Emote.Name == "🌸" && r.User.IsSpecified && ((DateTime.UtcNow - r.User.Value.CreatedAt).TotalDays > 5) && _flowerReactionAwardedUsers.Add(r.User.Value.Id))
|
||||||
{
|
{
|
||||||
await _ch.AddCurrencyAsync(r.User.Value, "Flower Reaction Event", amount, false)
|
await _cs.AddAsync(r.User.Value, "Flower Reaction Event", amount, false)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -220,8 +220,8 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
if (num == 10)
|
if (num == 10)
|
||||||
{
|
{
|
||||||
var images = _images.Dice;
|
var images = _images.Dice;
|
||||||
using (var imgOneStream = images[1].Value.ToStream())
|
using (var imgOneStream = images[1].ToStream())
|
||||||
using (var imgZeroStream = images[0].Value.ToStream())
|
using (var imgZeroStream = images[0].ToStream())
|
||||||
{
|
{
|
||||||
Image imgOne = new Image(imgOneStream);
|
Image imgOne = new Image(imgOneStream);
|
||||||
Image imgZero = new Image(imgZeroStream);
|
Image imgZero = new Image(imgZeroStream);
|
||||||
@ -229,7 +229,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
return new[] { imgOne, imgZero }.Merge();
|
return new[] { imgOne, imgZero }.Merge();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
using (var die = _images.Dice[num].Value.ToStream())
|
using (var die = _images.Dice[num].ToStream())
|
||||||
{
|
{
|
||||||
return new Image(die);
|
return new Image(die);
|
||||||
}
|
}
|
||||||
|
@ -18,15 +18,15 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
{
|
{
|
||||||
private readonly IImagesService _images;
|
private readonly IImagesService _images;
|
||||||
private readonly BotConfig _bc;
|
private readonly BotConfig _bc;
|
||||||
private readonly CurrencyHandler _ch;
|
private readonly CurrencyService _cs;
|
||||||
|
|
||||||
private readonly NadekoRandom rng = new NadekoRandom();
|
private readonly NadekoRandom rng = new NadekoRandom();
|
||||||
|
|
||||||
public FlipCoinCommands(IImagesService images, CurrencyHandler ch, BotConfig bc)
|
public FlipCoinCommands(IImagesService images, CurrencyService cs, BotConfig bc)
|
||||||
{
|
{
|
||||||
_images = images;
|
_images = images;
|
||||||
_bc = bc;
|
_bc = bc;
|
||||||
_ch = ch;
|
_cs = cs;
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -74,47 +74,49 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
await Context.Channel.SendFileAsync(imgs.Merge().ToStream(), $"{count} coins.png").ConfigureAwait(false);
|
await Context.Channel.SendFileAsync(imgs.Merge().ToStream(), $"{count} coins.png").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
public enum BetFlipGuess
|
||||||
public async Task Betflip(int amount, string guess)
|
|
||||||
{
|
{
|
||||||
var guessStr = guess.Trim().ToUpperInvariant();
|
H = 1,
|
||||||
if (guessStr != "H" && guessStr != "T" && guessStr != "HEADS" && guessStr != "TAILS")
|
Head = 1,
|
||||||
return;
|
Heads = 1,
|
||||||
|
T = 2,
|
||||||
|
Tail = 2,
|
||||||
|
Tails = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
public async Task Betflip(int amount, BetFlipGuess guess)
|
||||||
|
{
|
||||||
if (amount < _bc.MinimumBetAmount)
|
if (amount < _bc.MinimumBetAmount)
|
||||||
{
|
{
|
||||||
await ReplyErrorLocalized("min_bet_limit", _bc.MinimumBetAmount + _bc.CurrencySign).ConfigureAwait(false);
|
await ReplyErrorLocalized("min_bet_limit", _bc.MinimumBetAmount + _bc.CurrencySign).ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var removed = await _ch.RemoveCurrencyAsync(Context.User, "Betflip Gamble", amount, false).ConfigureAwait(false);
|
var removed = await _cs.RemoveAsync(Context.User, "Betflip Gamble", amount, false).ConfigureAwait(false);
|
||||||
if (!removed)
|
if (!removed)
|
||||||
{
|
{
|
||||||
await ReplyErrorLocalized("not_enough", _bc.CurrencyPluralName).ConfigureAwait(false);
|
await ReplyErrorLocalized("not_enough", _bc.CurrencyPluralName).ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//heads = true
|
BetFlipGuess result;
|
||||||
//tails = false
|
|
||||||
|
|
||||||
//todo this seems stinky, no time to look at it right now
|
|
||||||
var isHeads = guessStr == "HEADS" || guessStr == "H";
|
|
||||||
var result = false;
|
|
||||||
IEnumerable<byte> imageToSend;
|
IEnumerable<byte> imageToSend;
|
||||||
if (rng.Next(0, 2) == 1)
|
if (rng.Next(0, 2) == 1)
|
||||||
{
|
{
|
||||||
imageToSend = _images.Heads;
|
imageToSend = _images.Heads;
|
||||||
result = true;
|
result = BetFlipGuess.Heads;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
imageToSend = _images.Tails;
|
imageToSend = _images.Tails;
|
||||||
|
result = BetFlipGuess.Tails;
|
||||||
}
|
}
|
||||||
|
|
||||||
string str;
|
string str;
|
||||||
if (isHeads == result)
|
if (guess == result)
|
||||||
{
|
{
|
||||||
var toWin = (int)Math.Round(amount * _bc.BetflipMultiplier);
|
var toWin = (int)Math.Round(amount * _bc.BetflipMultiplier);
|
||||||
str = Context.User.Mention + " " + GetText("flip_guess", toWin + _bc.CurrencySign);
|
str = Context.User.Mention + " " + GetText("flip_guess", toWin + _bc.CurrencySign);
|
||||||
await _ch.AddCurrencyAsync(Context.User, "Betflip Gamble", toWin, false).ConfigureAwait(false);
|
await _cs.AddAsync(Context.User, "Betflip Gamble", toWin, false).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -20,8 +20,8 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
public class FlowerShop : NadekoSubmodule
|
public class FlowerShop : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly BotConfig _bc;
|
private readonly BotConfig _bc;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
private readonly CurrencyHandler _ch;
|
private readonly CurrencyService _cs;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordShardedClient _client;
|
||||||
|
|
||||||
public enum Role
|
public enum Role
|
||||||
@ -34,11 +34,11 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
List
|
List
|
||||||
}
|
}
|
||||||
|
|
||||||
public FlowerShop(BotConfig bc, DbHandler db, CurrencyHandler ch, DiscordShardedClient client)
|
public FlowerShop(BotConfig bc, DbService db, CurrencyService cs, DiscordShardedClient client)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
_bc = bc;
|
_bc = bc;
|
||||||
_ch = ch;
|
_cs = cs;
|
||||||
_client = client;
|
_client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (await _ch.RemoveCurrencyAsync(Context.User.Id, $"Shop purchase - {entry.Type}", entry.Price))
|
if (await _cs.RemoveAsync(Context.User.Id, $"Shop purchase - {entry.Type}", entry.Price))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -120,11 +120,11 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_log.Warn(ex);
|
_log.Warn(ex);
|
||||||
await _ch.AddCurrencyAsync(Context.User.Id, $"Shop error refund", entry.Price);
|
await _cs.AddAsync(Context.User.Id, $"Shop error refund", entry.Price);
|
||||||
await ReplyErrorLocalized("shop_role_purchase_error").ConfigureAwait(false);
|
await ReplyErrorLocalized("shop_role_purchase_error").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await _ch.AddCurrencyAsync(entry.AuthorId, $"Shop sell item - {entry.Type}", GetProfitAmount(entry.Price));
|
await _cs.AddAsync(entry.AuthorId, $"Shop sell item - {entry.Type}", GetProfitAmount(entry.Price));
|
||||||
await ReplyConfirmLocalized("shop_role_purchase", Format.Bold(role.Name)).ConfigureAwait(false);
|
await ReplyConfirmLocalized("shop_role_purchase", Format.Bold(role.Name)).ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -144,7 +144,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
|
|
||||||
var item = entry.Items.ToArray()[new NadekoRandom().Next(0, entry.Items.Count)];
|
var item = entry.Items.ToArray()[new NadekoRandom().Next(0, entry.Items.Count)];
|
||||||
|
|
||||||
if (await _ch.RemoveCurrencyAsync(Context.User.Id, $"Shop purchase - {entry.Type}", entry.Price))
|
if (await _cs.RemoveAsync(Context.User.Id, $"Shop purchase - {entry.Type}", entry.Price))
|
||||||
{
|
{
|
||||||
int removed;
|
int removed;
|
||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
@ -163,7 +163,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
.AddField(efb => efb.WithName(GetText("name")).WithValue(entry.Name).WithIsInline(true)))
|
.AddField(efb => efb.WithName(GetText("name")).WithValue(entry.Name).WithIsInline(true)))
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
await _ch.AddCurrencyAsync(entry.AuthorId,
|
await _cs.AddAsync(entry.AuthorId,
|
||||||
$"Shop sell item - {entry.Name}",
|
$"Shop sell item - {entry.Name}",
|
||||||
GetProfitAmount(entry.Price)).ConfigureAwait(false);
|
GetProfitAmount(entry.Price)).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@ -174,7 +174,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
uow._context.Set<ShopEntryItem>().Add(item);
|
uow._context.Set<ShopEntryItem>().Add(item);
|
||||||
uow.Complete();
|
uow.Complete();
|
||||||
|
|
||||||
await _ch.AddCurrencyAsync(Context.User.Id,
|
await _cs.AddAsync(Context.User.Id,
|
||||||
$"Shop error refund - {entry.Name}",
|
$"Shop error refund - {entry.Name}",
|
||||||
entry.Price,
|
entry.Price,
|
||||||
uow).ConfigureAwait(false);
|
uow).ConfigureAwait(false);
|
||||||
|
@ -32,13 +32,13 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
//thanks to judge for helping me with this
|
//thanks to judge for helping me with this
|
||||||
|
|
||||||
private readonly IImagesService _images;
|
private readonly IImagesService _images;
|
||||||
private readonly CurrencyHandler _ch;
|
private readonly CurrencyService _cs;
|
||||||
|
|
||||||
public Slots(IImagesService images, BotConfig bc, CurrencyHandler ch)
|
public Slots(IImagesService images, BotConfig bc, CurrencyService cs)
|
||||||
{
|
{
|
||||||
_images = images;
|
_images = images;
|
||||||
_bc = bc;
|
_bc = bc;
|
||||||
_ch = ch;
|
_cs = cs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SlotMachine
|
public class SlotMachine
|
||||||
@ -157,7 +157,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!await _ch.RemoveCurrencyAsync(Context.User, "Slot Machine", amount, false))
|
if (!await _cs.RemoveAsync(Context.User, "Slot Machine", amount, false))
|
||||||
{
|
{
|
||||||
await ReplyErrorLocalized("not_enough", _bc.CurrencySign).ConfigureAwait(false);
|
await ReplyErrorLocalized("not_enough", _bc.CurrencySign).ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
@ -209,7 +209,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
var msg = GetText("better_luck");
|
var msg = GetText("better_luck");
|
||||||
if (result.Multiplier != 0)
|
if (result.Multiplier != 0)
|
||||||
{
|
{
|
||||||
await _ch.AddCurrencyAsync(Context.User, $"Slot Machine x{result.Multiplier}", amount * result.Multiplier, false);
|
await _cs.AddAsync(Context.User, $"Slot Machine x{result.Multiplier}", amount * result.Multiplier, false);
|
||||||
Interlocked.Add(ref _totalPaidOut, amount * result.Multiplier);
|
Interlocked.Add(ref _totalPaidOut, amount * result.Multiplier);
|
||||||
if (result.Multiplier == 1)
|
if (result.Multiplier == 1)
|
||||||
msg = GetText("slot_single", _bc.CurrencySign, 1);
|
msg = GetText("slot_single", _bc.CurrencySign, 1);
|
||||||
|
@ -57,10 +57,10 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
InsufficientAmount
|
InsufficientAmount
|
||||||
}
|
}
|
||||||
|
|
||||||
public WaifuClaimCommands(BotConfig bc, CurrencyHandler ch, DbHandler db)
|
public WaifuClaimCommands(BotConfig bc, CurrencyService cs, DbService db)
|
||||||
{
|
{
|
||||||
_bc = bc;
|
_bc = bc;
|
||||||
_ch = ch;
|
_cs = cs;
|
||||||
_db = db;
|
_db = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
{
|
{
|
||||||
var claimer = uow.DiscordUsers.GetOrCreate(Context.User);
|
var claimer = uow.DiscordUsers.GetOrCreate(Context.User);
|
||||||
var waifu = uow.DiscordUsers.GetOrCreate(target);
|
var waifu = uow.DiscordUsers.GetOrCreate(target);
|
||||||
if (!await _ch.RemoveCurrencyAsync(Context.User.Id, "Claimed Waifu", amount, uow).ConfigureAwait(false))
|
if (!await _cs.RemoveAsync(Context.User.Id, "Claimed Waifu", amount, uow).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
result = WaifuClaimResult.NotEnoughFunds;
|
result = WaifuClaimResult.NotEnoughFunds;
|
||||||
}
|
}
|
||||||
@ -116,7 +116,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
}
|
}
|
||||||
else if (isAffinity && amount > w.Price * 0.88f)
|
else if (isAffinity && amount > w.Price * 0.88f)
|
||||||
{
|
{
|
||||||
if (!await _ch.RemoveCurrencyAsync(Context.User.Id, "Claimed Waifu", amount, uow).ConfigureAwait(false))
|
if (!await _cs.RemoveAsync(Context.User.Id, "Claimed Waifu", amount, uow).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
result = WaifuClaimResult.NotEnoughFunds;
|
result = WaifuClaimResult.NotEnoughFunds;
|
||||||
}
|
}
|
||||||
@ -138,7 +138,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
}
|
}
|
||||||
else if (amount >= w.Price * 1.1f) // if no affinity
|
else if (amount >= w.Price * 1.1f) // if no affinity
|
||||||
{
|
{
|
||||||
if (!await _ch.RemoveCurrencyAsync(Context.User.Id, "Claimed Waifu", amount, uow).ConfigureAwait(false))
|
if (!await _cs.RemoveAsync(Context.User.Id, "Claimed Waifu", amount, uow).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
result = WaifuClaimResult.NotEnoughFunds;
|
result = WaifuClaimResult.NotEnoughFunds;
|
||||||
}
|
}
|
||||||
@ -230,13 +230,13 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
|
|
||||||
if (w.Affinity?.UserId == Context.User.Id)
|
if (w.Affinity?.UserId == Context.User.Id)
|
||||||
{
|
{
|
||||||
await _ch.AddCurrencyAsync(w.Waifu.UserId, "Waifu Compensation", amount, uow).ConfigureAwait(false);
|
await _cs.AddAsync(w.Waifu.UserId, "Waifu Compensation", amount, uow).ConfigureAwait(false);
|
||||||
w.Price = (int)Math.Floor(w.Price * 0.75f);
|
w.Price = (int)Math.Floor(w.Price * 0.75f);
|
||||||
result = DivorceResult.SucessWithPenalty;
|
result = DivorceResult.SucessWithPenalty;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await _ch.AddCurrencyAsync(Context.User.Id, "Waifu Refund", amount, uow).ConfigureAwait(false);
|
await _cs.AddAsync(Context.User.Id, "Waifu Refund", amount, uow).ConfigureAwait(false);
|
||||||
|
|
||||||
result = DivorceResult.Success;
|
result = DivorceResult.Success;
|
||||||
}
|
}
|
||||||
@ -278,8 +278,8 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
|
|
||||||
private static readonly TimeSpan _affinityLimit = TimeSpan.FromMinutes(30);
|
private static readonly TimeSpan _affinityLimit = TimeSpan.FromMinutes(30);
|
||||||
private readonly BotConfig _bc;
|
private readonly BotConfig _bc;
|
||||||
private readonly CurrencyHandler _ch;
|
private readonly CurrencyService _cs;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
|
@ -13,14 +13,14 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
public partial class Gambling : NadekoTopLevelModule
|
public partial class Gambling : NadekoTopLevelModule
|
||||||
{
|
{
|
||||||
private readonly BotConfig _bc;
|
private readonly BotConfig _bc;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
private readonly CurrencyHandler _currency;
|
private readonly CurrencyService _currency;
|
||||||
|
|
||||||
private string CurrencyName => _bc.CurrencyName;
|
private string CurrencyName => _bc.CurrencyName;
|
||||||
private string CurrencyPluralName => _bc.CurrencyPluralName;
|
private string CurrencyPluralName => _bc.CurrencyPluralName;
|
||||||
private string CurrencySign => _bc.CurrencySign;
|
private string CurrencySign => _bc.CurrencySign;
|
||||||
|
|
||||||
public Gambling(BotConfig bc, DbHandler db, CurrencyHandler currency)
|
public Gambling(BotConfig bc, DbService db, CurrencyService currency)
|
||||||
{
|
{
|
||||||
_bc = bc;
|
_bc = bc;
|
||||||
_db = db;
|
_db = db;
|
||||||
@ -71,13 +71,13 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
{
|
{
|
||||||
if (amount <= 0 || Context.User.Id == receiver.Id)
|
if (amount <= 0 || Context.User.Id == receiver.Id)
|
||||||
return;
|
return;
|
||||||
var success = await _currency.RemoveCurrencyAsync((IGuildUser)Context.User, $"Gift to {receiver.Username} ({receiver.Id}).", amount, false).ConfigureAwait(false);
|
var success = await _currency.RemoveAsync((IGuildUser)Context.User, $"Gift to {receiver.Username} ({receiver.Id}).", amount, false).ConfigureAwait(false);
|
||||||
if (!success)
|
if (!success)
|
||||||
{
|
{
|
||||||
await ReplyErrorLocalized("not_enough", CurrencyPluralName).ConfigureAwait(false);
|
await ReplyErrorLocalized("not_enough", CurrencyPluralName).ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await _currency.AddCurrencyAsync(receiver, $"Gift from {Context.User.Username} ({Context.User.Id}).", amount, true).ConfigureAwait(false);
|
await _currency.AddAsync(receiver, $"Gift from {Context.User.Username} ({Context.User.Id}).", amount, true).ConfigureAwait(false);
|
||||||
await ReplyConfirmLocalized("gifted", amount + CurrencySign, Format.Bold(receiver.ToString()))
|
await ReplyConfirmLocalized("gifted", amount + CurrencySign, Format.Bold(receiver.ToString()))
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@ -97,7 +97,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
if (amount <= 0)
|
if (amount <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
await _currency.AddCurrencyAsync(usrId, $"Awarded by bot owner. ({Context.User.Username}/{Context.User.Id})", amount).ConfigureAwait(false);
|
await _currency.AddAsync(usrId, $"Awarded by bot owner. ({Context.User.Username}/{Context.User.Id})", amount).ConfigureAwait(false);
|
||||||
await ReplyConfirmLocalized("awarded", amount + CurrencySign, $"<@{usrId}>").ConfigureAwait(false);
|
await ReplyConfirmLocalized("awarded", amount + CurrencySign, $"<@{usrId}>").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,7 +110,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
var users = (await Context.Guild.GetUsersAsync())
|
var users = (await Context.Guild.GetUsersAsync())
|
||||||
.Where(u => u.GetRoles().Contains(role))
|
.Where(u => u.GetRoles().Contains(role))
|
||||||
.ToList();
|
.ToList();
|
||||||
await Task.WhenAll(users.Select(u => _currency.AddCurrencyAsync(u.Id,
|
await Task.WhenAll(users.Select(u => _currency.AddAsync(u.Id,
|
||||||
$"Awarded by bot owner to **{role.Name}** role. ({Context.User.Username}/{Context.User.Id})",
|
$"Awarded by bot owner to **{role.Name}** role. ({Context.User.Username}/{Context.User.Id})",
|
||||||
amount)))
|
amount)))
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
@ -129,7 +129,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
if (amount <= 0)
|
if (amount <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (await _currency.RemoveCurrencyAsync(user, $"Taken by bot owner.({Context.User.Username}/{Context.User.Id})", amount, true).ConfigureAwait(false))
|
if (await _currency.RemoveAsync(user, $"Taken by bot owner.({Context.User.Username}/{Context.User.Id})", amount, true).ConfigureAwait(false))
|
||||||
await ReplyConfirmLocalized("take", amount+CurrencySign, Format.Bold(user.ToString())).ConfigureAwait(false);
|
await ReplyConfirmLocalized("take", amount+CurrencySign, Format.Bold(user.ToString())).ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await ReplyErrorLocalized("take_fail", amount + CurrencySign, Format.Bold(user.ToString()), CurrencyPluralName).ConfigureAwait(false);
|
await ReplyErrorLocalized("take_fail", amount + CurrencySign, Format.Bold(user.ToString()), CurrencyPluralName).ConfigureAwait(false);
|
||||||
@ -143,7 +143,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
if (amount <= 0)
|
if (amount <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (await _currency.RemoveCurrencyAsync(usrId, $"Taken by bot owner.({Context.User.Username}/{Context.User.Id})", amount).ConfigureAwait(false))
|
if (await _currency.RemoveAsync(usrId, $"Taken by bot owner.({Context.User.Username}/{Context.User.Id})", amount).ConfigureAwait(false))
|
||||||
await ReplyConfirmLocalized("take", amount + CurrencySign, $"<@{usrId}>").ConfigureAwait(false);
|
await ReplyConfirmLocalized("take", amount + CurrencySign, $"<@{usrId}>").ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await ReplyErrorLocalized("take_fail", amount + CurrencySign, Format.Code(usrId.ToString()), CurrencyPluralName).ConfigureAwait(false);
|
await ReplyErrorLocalized("take_fail", amount + CurrencySign, Format.Code(usrId.ToString()), CurrencyPluralName).ConfigureAwait(false);
|
||||||
@ -210,7 +210,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
if (amount < 1)
|
if (amount < 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!await _currency.RemoveCurrencyAsync(Context.User, "Betroll Gamble", amount, false).ConfigureAwait(false))
|
if (!await _currency.RemoveAsync(Context.User, "Betroll Gamble", amount, false).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
await ReplyErrorLocalized("not_enough", CurrencyPluralName).ConfigureAwait(false);
|
await ReplyErrorLocalized("not_enough", CurrencyPluralName).ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
@ -227,19 +227,19 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
if (rnd < 91)
|
if (rnd < 91)
|
||||||
{
|
{
|
||||||
str += GetText("br_win", (amount * _bc.Betroll67Multiplier) + CurrencySign, 66);
|
str += GetText("br_win", (amount * _bc.Betroll67Multiplier) + CurrencySign, 66);
|
||||||
await _currency.AddCurrencyAsync(Context.User, "Betroll Gamble",
|
await _currency.AddAsync(Context.User, "Betroll Gamble",
|
||||||
(int) (amount * _bc.Betroll67Multiplier), false).ConfigureAwait(false);
|
(int) (amount * _bc.Betroll67Multiplier), false).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else if (rnd < 100)
|
else if (rnd < 100)
|
||||||
{
|
{
|
||||||
str += GetText("br_win", (amount * _bc.Betroll91Multiplier) + CurrencySign, 90);
|
str += GetText("br_win", (amount * _bc.Betroll91Multiplier) + CurrencySign, 90);
|
||||||
await _currency.AddCurrencyAsync(Context.User, "Betroll Gamble",
|
await _currency.AddAsync(Context.User, "Betroll Gamble",
|
||||||
(int) (amount * _bc.Betroll91Multiplier), false).ConfigureAwait(false);
|
(int) (amount * _bc.Betroll91Multiplier), false).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
str += GetText("br_win", (amount * _bc.Betroll100Multiplier) + CurrencySign, 100) + " 👑";
|
str += GetText("br_win", (amount * _bc.Betroll100Multiplier) + CurrencySign, 100) + " 👑";
|
||||||
await _currency.AddCurrencyAsync(Context.User, "Betroll Gamble",
|
await _currency.AddAsync(Context.User, "Betroll Gamble",
|
||||||
(int) (amount * _bc.Betroll100Multiplier), false).ConfigureAwait(false);
|
(int) (amount * _bc.Betroll100Multiplier), false).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
Voting
|
Voting
|
||||||
}
|
}
|
||||||
|
|
||||||
//todo Isolate, this shouldn't print or anything like that.
|
//todo 85 Isolate, this shouldn't print or anything like that.
|
||||||
public class AcrophobiaGame
|
public class AcrophobiaGame
|
||||||
{
|
{
|
||||||
private readonly ITextChannel _channel;
|
private readonly ITextChannel _channel;
|
||||||
|
@ -13,10 +13,10 @@ namespace NadekoBot.Modules.Games
|
|||||||
[Group]
|
[Group]
|
||||||
public class CleverBotCommands : NadekoSubmodule
|
public class CleverBotCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
private readonly GamesService _games;
|
private readonly ChatterBotService _games;
|
||||||
|
|
||||||
public CleverBotCommands(DbHandler db, GamesService games)
|
public CleverBotCommands(DbService db, ChatterBotService games)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
_games = games;
|
_games = games;
|
||||||
@ -29,7 +29,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
{
|
{
|
||||||
var channel = (ITextChannel)Context.Channel;
|
var channel = (ITextChannel)Context.Channel;
|
||||||
|
|
||||||
if (_games.CleverbotGuilds.TryRemove(channel.Guild.Id, out Lazy<ChatterBotSession> throwaway))
|
if (_games.ChatterBotGuilds.TryRemove(channel.Guild.Id, out Lazy<ChatterBotSession> throwaway))
|
||||||
{
|
{
|
||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
||||||
@ -40,7 +40,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_games.CleverbotGuilds.TryAdd(channel.Guild.Id, new Lazy<ChatterBotSession>(() => new ChatterBotSession(Context.Guild.Id), true));
|
_games.ChatterBotGuilds.TryAdd(channel.Guild.Id, new Lazy<ChatterBotSession>(() => new ChatterBotSession(Context.Guild.Id), true));
|
||||||
|
|
||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
||||||
|
@ -24,16 +24,16 @@ namespace NadekoBot.Modules.Games
|
|||||||
[Group]
|
[Group]
|
||||||
public class PlantPickCommands : NadekoSubmodule
|
public class PlantPickCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly CurrencyHandler _ch;
|
private readonly CurrencyService _cs;
|
||||||
private readonly BotConfig _bc;
|
private readonly BotConfig _bc;
|
||||||
private readonly GamesService _games;
|
private readonly GamesService _games;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public PlantPickCommands(BotConfig bc, CurrencyHandler ch, GamesService games,
|
public PlantPickCommands(BotConfig bc, CurrencyService cs, GamesService games,
|
||||||
DbHandler db)
|
DbService db)
|
||||||
{
|
{
|
||||||
_bc = bc;
|
_bc = bc;
|
||||||
_ch = ch;
|
_cs = cs;
|
||||||
_games = games;
|
_games = games;
|
||||||
_db = db;
|
_db = db;
|
||||||
}
|
}
|
||||||
@ -54,7 +54,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
|
|
||||||
await Task.WhenAll(msgs.Where(m => m != null).Select(toDelete => toDelete.DeleteAsync())).ConfigureAwait(false);
|
await Task.WhenAll(msgs.Where(m => m != null).Select(toDelete => toDelete.DeleteAsync())).ConfigureAwait(false);
|
||||||
|
|
||||||
await _ch.AddCurrencyAsync((IGuildUser)Context.User, $"Picked {_bc.CurrencyPluralName}", msgs.Count, false).ConfigureAwait(false);
|
await _cs.AddAsync((IGuildUser)Context.User, $"Picked {_bc.CurrencyPluralName}", msgs.Count, false).ConfigureAwait(false);
|
||||||
var msg = await ReplyConfirmLocalized("picked", msgs.Count + _bc.CurrencySign)
|
var msg = await ReplyConfirmLocalized("picked", msgs.Count + _bc.CurrencySign)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
msg.DeleteAfter(10);
|
msg.DeleteAfter(10);
|
||||||
@ -67,7 +67,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
if (amount < 1)
|
if (amount < 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var removed = await _ch.RemoveCurrencyAsync((IGuildUser)Context.User, $"Planted a {_bc.CurrencyName}", amount, false).ConfigureAwait(false);
|
var removed = await _cs.RemoveAsync((IGuildUser)Context.User, $"Planted a {_bc.CurrencyName}", amount, false).ConfigureAwait(false);
|
||||||
if (!removed)
|
if (!removed)
|
||||||
{
|
{
|
||||||
await ReplyErrorLocalized("not_enough", _bc.CurrencySign).ConfigureAwait(false);
|
await ReplyErrorLocalized("not_enough", _bc.CurrencySign).ConfigureAwait(false);
|
||||||
@ -88,9 +88,9 @@ namespace NadekoBot.Modules.Games
|
|||||||
msgToSend += " " + GetText("pick_sn", Prefix);
|
msgToSend += " " + GetText("pick_sn", Prefix);
|
||||||
|
|
||||||
IUserMessage msg;
|
IUserMessage msg;
|
||||||
using (var toSend = imgData.Value.ToStream())
|
using (var toSend = imgData.Data.ToStream())
|
||||||
{
|
{
|
||||||
msg = await Context.Channel.SendFileAsync(toSend, imgData.Key, msgToSend).ConfigureAwait(false);
|
msg = await Context.Channel.SendFileAsync(toSend, imgData.Name, msgToSend).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
var msgs = new IUserMessage[amount];
|
var msgs = new IUserMessage[amount];
|
||||||
|
@ -3,12 +3,8 @@ using Discord.Commands;
|
|||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using NadekoBot.Attributes;
|
using NadekoBot.Attributes;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services.Games;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Games
|
namespace NadekoBot.Modules.Games
|
||||||
{
|
{
|
||||||
@ -17,12 +13,13 @@ namespace NadekoBot.Modules.Games
|
|||||||
[Group]
|
[Group]
|
||||||
public class PollCommands : NadekoSubmodule
|
public class PollCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
public static ConcurrentDictionary<ulong, Poll> ActivePolls = new ConcurrentDictionary<ulong, Poll>();
|
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordShardedClient _client;
|
||||||
|
private readonly PollService _polls;
|
||||||
|
|
||||||
public PollCommands(DiscordShardedClient client)
|
public PollCommands(DiscordShardedClient client, PollService polls)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
|
_polls = polls;
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -42,8 +39,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task PollStats()
|
public async Task PollStats()
|
||||||
{
|
{
|
||||||
Poll poll;
|
if (!_polls.ActivePolls.TryGetValue(Context.Guild.Id, out var poll))
|
||||||
if (!ActivePolls.TryGetValue(Context.Guild.Id, out poll))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
await Context.Channel.EmbedAsync(poll.GetStats(GetText("current_poll_results")));
|
await Context.Channel.EmbedAsync(poll.GetStats(GetText("current_poll_results")));
|
||||||
@ -51,20 +47,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
|
|
||||||
private async Task InternalStartPoll(string arg, bool isPublic = false)
|
private async Task InternalStartPoll(string arg, bool isPublic = false)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)Context.Channel;
|
if(await _polls.StartPoll((ITextChannel)Context.Channel, Context.Message, arg, isPublic) == false)
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(arg) || !arg.Contains(";"))
|
|
||||||
return;
|
|
||||||
var data = arg.Split(';');
|
|
||||||
if (data.Length < 3)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var poll = new Poll(_client, _strings, Context.Message, data[0], data.Skip(1), isPublic: isPublic);
|
|
||||||
if (ActivePolls.TryAdd(channel.Guild.Id, poll))
|
|
||||||
{
|
|
||||||
await poll.StartPoll().ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
await ReplyErrorLocalized("poll_already_running").ConfigureAwait(false);
|
await ReplyErrorLocalized("poll_already_running").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,151 +58,11 @@ namespace NadekoBot.Modules.Games
|
|||||||
{
|
{
|
||||||
var channel = (ITextChannel)Context.Channel;
|
var channel = (ITextChannel)Context.Channel;
|
||||||
|
|
||||||
Poll poll;
|
_polls.ActivePolls.TryRemove(channel.Guild.Id, out var poll);
|
||||||
ActivePolls.TryRemove(channel.Guild.Id, out poll);
|
|
||||||
await poll.StopPoll().ConfigureAwait(false);
|
await poll.StopPoll().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Poll
|
|
||||||
{
|
|
||||||
private readonly IUserMessage _originalMessage;
|
|
||||||
private readonly IGuild _guild;
|
|
||||||
private string[] answers { get; }
|
|
||||||
private readonly ConcurrentDictionary<ulong, int> _participants = new ConcurrentDictionary<ulong, int>();
|
|
||||||
private readonly string _question;
|
|
||||||
private readonly DiscordShardedClient _client;
|
|
||||||
private readonly NadekoStrings _strings;
|
|
||||||
|
|
||||||
public bool IsPublic { get; }
|
|
||||||
|
|
||||||
public Poll(DiscordShardedClient client, NadekoStrings strings, IUserMessage umsg, string question, IEnumerable<string> enumerable, bool isPublic = false)
|
|
||||||
{
|
|
||||||
_client = client;
|
|
||||||
_strings = strings;
|
|
||||||
|
|
||||||
_originalMessage = umsg;
|
|
||||||
_guild = ((ITextChannel)umsg.Channel).Guild;
|
|
||||||
_question = question;
|
|
||||||
answers = enumerable as string[] ?? enumerable.ToArray();
|
|
||||||
IsPublic = isPublic;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EmbedBuilder GetStats(string title)
|
|
||||||
{
|
|
||||||
var results = _participants.GroupBy(kvp => kvp.Value)
|
|
||||||
.ToDictionary(x => x.Key, x => x.Sum(kvp => 1))
|
|
||||||
.OrderByDescending(kvp => kvp.Value)
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
var eb = new EmbedBuilder().WithTitle(title);
|
|
||||||
|
|
||||||
var sb = new StringBuilder()
|
|
||||||
.AppendLine(Format.Bold(_question))
|
|
||||||
.AppendLine();
|
|
||||||
|
|
||||||
var totalVotesCast = 0;
|
|
||||||
if (results.Length == 0)
|
|
||||||
{
|
|
||||||
sb.AppendLine(GetText("no_votes_cast"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int i = 0; i < results.Length; i++)
|
|
||||||
{
|
|
||||||
var result = results[i];
|
|
||||||
sb.AppendLine(GetText("poll_result",
|
|
||||||
result.Key,
|
|
||||||
Format.Bold(answers[result.Key - 1]),
|
|
||||||
Format.Bold(result.Value.ToString())));
|
|
||||||
totalVotesCast += result.Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
eb.WithDescription(sb.ToString())
|
|
||||||
.WithFooter(efb => efb.WithText(GetText("x_votes_cast", totalVotesCast)));
|
|
||||||
|
|
||||||
return eb;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task StartPoll()
|
|
||||||
{
|
|
||||||
_client.MessageReceived += Vote;
|
|
||||||
var msgToSend = GetText("poll_created", Format.Bold(_originalMessage.Author.Username)) + "\n\n" + Format.Bold(_question) + "\n";
|
|
||||||
var num = 1;
|
|
||||||
msgToSend = answers.Aggregate(msgToSend, (current, answ) => current + $"`{num++}.` **{answ}**\n");
|
|
||||||
if (!IsPublic)
|
|
||||||
msgToSend += "\n" + Format.Bold(GetText("poll_vote_private"));
|
|
||||||
else
|
|
||||||
msgToSend += "\n" + Format.Bold(GetText("poll_vote_public"));
|
|
||||||
await _originalMessage.Channel.SendConfirmAsync(msgToSend).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task StopPoll()
|
|
||||||
{
|
|
||||||
_client.MessageReceived -= Vote;
|
|
||||||
await _originalMessage.Channel.EmbedAsync(GetStats("POLL CLOSED")).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task Vote(SocketMessage imsg)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// has to be a user message
|
|
||||||
var msg = imsg as SocketUserMessage;
|
|
||||||
if (msg == null || msg.Author.IsBot)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// has to be an integer
|
|
||||||
int vote;
|
|
||||||
if (!int.TryParse(imsg.Content, out vote))
|
|
||||||
return;
|
|
||||||
if (vote < 1 || vote > answers.Length)
|
|
||||||
return;
|
|
||||||
|
|
||||||
IMessageChannel ch;
|
|
||||||
if (IsPublic)
|
|
||||||
{
|
|
||||||
//if public, channel must be the same the poll started in
|
|
||||||
if (_originalMessage.Channel.Id != imsg.Channel.Id)
|
|
||||||
return;
|
|
||||||
ch = imsg.Channel;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//if private, channel must be dm channel
|
|
||||||
if ((ch = msg.Channel as IDMChannel) == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// user must be a member of the guild this poll is in
|
|
||||||
var guildUsers = await _guild.GetUsersAsync().ConfigureAwait(false);
|
|
||||||
if (guildUsers.All(u => u.Id != imsg.Author.Id))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//user can vote only once
|
|
||||||
if (_participants.TryAdd(msg.Author.Id, vote))
|
|
||||||
{
|
|
||||||
if (!IsPublic)
|
|
||||||
{
|
|
||||||
await ch.SendConfirmAsync(GetText("thanks_for_voting", Format.Bold(msg.Author.Username))).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var toDelete = await ch.SendConfirmAsync(GetText("poll_voted", Format.Bold(msg.Author.ToString()))).ConfigureAwait(false);
|
|
||||||
toDelete.DeleteAfter(5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetText(string key, params object[] replacements)
|
|
||||||
=> _strings.GetText(key,
|
|
||||||
_guild.Id,
|
|
||||||
typeof(Games).Name.ToLowerInvariant(),
|
|
||||||
replacements);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,7 +6,6 @@ using NadekoBot.Extensions;
|
|||||||
using NadekoBot.Modules.Games.Models;
|
using NadekoBot.Modules.Games.Models;
|
||||||
using NadekoBot.Services.Games;
|
using NadekoBot.Services.Games;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -71,15 +70,10 @@ namespace NadekoBot.Modules.Games
|
|||||||
public async Task Typeadd([Remainder] string text)
|
public async Task Typeadd([Remainder] string text)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)Context.Channel;
|
var channel = (ITextChannel)Context.Channel;
|
||||||
|
if (string.IsNullOrWhiteSpace(text))
|
||||||
|
return;
|
||||||
|
|
||||||
_games.TypingArticles.Add(new TypingArticle
|
_games.AddTypingArticle(Context.User, text);
|
||||||
{
|
|
||||||
Title = $"Text added on {DateTime.UtcNow} by {Context.User}",
|
|
||||||
Text = text.SanitizeMentions(),
|
|
||||||
});
|
|
||||||
|
|
||||||
//todo move this to service
|
|
||||||
File.WriteAllText(_games.TypingArticlesPath, JsonConvert.SerializeObject(_games.TypingArticles));
|
|
||||||
|
|
||||||
await channel.SendConfirmAsync("Added new article for typing game.").ConfigureAwait(false);
|
await channel.SendConfirmAsync("Added new article for typing game.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ namespace NadekoBot.Modules.Games.Trivia
|
|||||||
private readonly NadekoStrings _strings;
|
private readonly NadekoStrings _strings;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordShardedClient _client;
|
||||||
private readonly BotConfig _bc;
|
private readonly BotConfig _bc;
|
||||||
private readonly CurrencyHandler _ch;
|
private readonly CurrencyService _cs;
|
||||||
|
|
||||||
public IGuild Guild { get; }
|
public IGuild Guild { get; }
|
||||||
public ITextChannel Channel { get; }
|
public ITextChannel Channel { get; }
|
||||||
@ -44,14 +44,14 @@ namespace NadekoBot.Modules.Games.Trivia
|
|||||||
public int WinRequirement { get; }
|
public int WinRequirement { get; }
|
||||||
|
|
||||||
public TriviaGame(NadekoStrings strings, DiscordShardedClient client, BotConfig bc,
|
public TriviaGame(NadekoStrings strings, DiscordShardedClient client, BotConfig bc,
|
||||||
CurrencyHandler ch, IGuild guild, ITextChannel channel,
|
CurrencyService cs, IGuild guild, ITextChannel channel,
|
||||||
bool showHints, int winReq, bool isPokemon)
|
bool showHints, int winReq, bool isPokemon)
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_strings = strings;
|
_strings = strings;
|
||||||
_client = client;
|
_client = client;
|
||||||
_bc = bc;
|
_bc = bc;
|
||||||
_ch = ch;
|
_cs = cs;
|
||||||
|
|
||||||
ShowHints = showHints;
|
ShowHints = showHints;
|
||||||
Guild = guild;
|
Guild = guild;
|
||||||
@ -227,7 +227,7 @@ namespace NadekoBot.Modules.Games.Trivia
|
|||||||
}
|
}
|
||||||
var reward = _bc.TriviaCurrencyReward;
|
var reward = _bc.TriviaCurrencyReward;
|
||||||
if (reward > 0)
|
if (reward > 0)
|
||||||
await _ch.AddCurrencyAsync(guildUser, "Won trivia", reward, true).ConfigureAwait(false);
|
await _cs.AddAsync(guildUser, "Won trivia", reward, true).ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,15 +17,15 @@ namespace NadekoBot.Modules.Games
|
|||||||
[Group]
|
[Group]
|
||||||
public class TriviaCommands : NadekoSubmodule
|
public class TriviaCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly CurrencyHandler _ch;
|
private readonly CurrencyService _cs;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordShardedClient _client;
|
||||||
private readonly BotConfig _bc;
|
private readonly BotConfig _bc;
|
||||||
|
|
||||||
public static ConcurrentDictionary<ulong, TriviaGame> RunningTrivias { get; } = new ConcurrentDictionary<ulong, TriviaGame>();
|
public static ConcurrentDictionary<ulong, TriviaGame> RunningTrivias { get; } = new ConcurrentDictionary<ulong, TriviaGame>();
|
||||||
|
|
||||||
public TriviaCommands(DiscordShardedClient client, BotConfig bc, CurrencyHandler ch)
|
public TriviaCommands(DiscordShardedClient client, BotConfig bc, CurrencyService cs)
|
||||||
{
|
{
|
||||||
_ch = ch;
|
_cs = cs;
|
||||||
_client = client;
|
_client = client;
|
||||||
_bc = bc;
|
_bc = bc;
|
||||||
}
|
}
|
||||||
@ -49,7 +49,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
var showHints = !additionalArgs.Contains("nohint");
|
var showHints = !additionalArgs.Contains("nohint");
|
||||||
var isPokemon = additionalArgs.Contains("pokemon");
|
var isPokemon = additionalArgs.Contains("pokemon");
|
||||||
|
|
||||||
var trivia = new TriviaGame(_strings, _client, _bc, _ch, channel.Guild, channel, showHints, winReq, isPokemon);
|
var trivia = new TriviaGame(_strings, _client, _bc, _cs, channel.Guild, channel, showHints, winReq, isPokemon);
|
||||||
if (RunningTrivias.TryAdd(channel.Guild.Id, trivia))
|
if (RunningTrivias.TryAdd(channel.Guild.Id, trivia))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -14,19 +14,21 @@ using System.Collections.Generic;
|
|||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using NadekoBot.Services.Music;
|
using NadekoBot.Services.Music;
|
||||||
|
using NadekoBot.DataStructures;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Music
|
namespace NadekoBot.Modules.Music
|
||||||
{
|
{
|
||||||
|
[NoPublicBot]
|
||||||
public class Music : NadekoTopLevelModule
|
public class Music : NadekoTopLevelModule
|
||||||
{
|
{
|
||||||
private static MusicService _music;
|
private static MusicService _music;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordShardedClient _client;
|
||||||
private readonly IBotCredentials _creds;
|
private readonly IBotCredentials _creds;
|
||||||
private readonly IGoogleApiService _google;
|
private readonly IGoogleApiService _google;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public Music(DiscordShardedClient client, IBotCredentials creds, IGoogleApiService google,
|
public Music(DiscordShardedClient client, IBotCredentials creds, IGoogleApiService google,
|
||||||
DbHandler db, MusicService music)
|
DbService db, MusicService music)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
_creds = creds;
|
_creds = creds;
|
||||||
|
@ -23,14 +23,14 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
public class BlacklistCommands : NadekoSubmodule
|
public class BlacklistCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly BlacklistService _bs;
|
private readonly BlacklistService _bs;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
private readonly IBotCredentials _creds;
|
private readonly IBotCredentials _creds;
|
||||||
|
|
||||||
private ConcurrentHashSet<ulong> BlacklistedUsers => _bs.BlacklistedUsers;
|
private ConcurrentHashSet<ulong> BlacklistedUsers => _bs.BlacklistedUsers;
|
||||||
private ConcurrentHashSet<ulong> BlacklistedGuilds => _bs.BlacklistedGuilds;
|
private ConcurrentHashSet<ulong> BlacklistedGuilds => _bs.BlacklistedGuilds;
|
||||||
private ConcurrentHashSet<ulong> BlacklistedChannels => _bs.BlacklistedChannels;
|
private ConcurrentHashSet<ulong> BlacklistedChannels => _bs.BlacklistedChannels;
|
||||||
|
|
||||||
public BlacklistCommands(BlacklistService bs, DbHandler db, IBotCredentials creds)
|
public BlacklistCommands(BlacklistService bs, DbService db, IBotCredentials creds)
|
||||||
{
|
{
|
||||||
_bs = bs;
|
_bs = bs;
|
||||||
_db = db;
|
_db = db;
|
||||||
|
@ -17,7 +17,7 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
[Group]
|
[Group]
|
||||||
public class CmdCdsCommands : NadekoSubmodule
|
public class CmdCdsCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
private readonly CmdCdService _service;
|
private readonly CmdCdService _service;
|
||||||
|
|
||||||
private ConcurrentDictionary<ulong, ConcurrentHashSet<CommandCooldown>> CommandCooldowns
|
private ConcurrentDictionary<ulong, ConcurrentHashSet<CommandCooldown>> CommandCooldowns
|
||||||
@ -25,7 +25,7 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
private ConcurrentDictionary<ulong, ConcurrentHashSet<ActiveCooldown>> ActiveCooldowns
|
private ConcurrentDictionary<ulong, ConcurrentHashSet<ActiveCooldown>> ActiveCooldowns
|
||||||
=> _service.ActiveCooldowns;
|
=> _service.ActiveCooldowns;
|
||||||
|
|
||||||
public CmdCdsCommands(CmdCdService service, DbHandler db)
|
public CmdCdsCommands(CmdCdService service, DbService db)
|
||||||
{
|
{
|
||||||
_service = service;
|
_service = service;
|
||||||
_db = db;
|
_db = db;
|
||||||
@ -88,40 +88,6 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
else
|
else
|
||||||
await channel.SendTableAsync("", localSet.Select(c => c.CommandName + ": " + c.Seconds + GetText("sec")), s => $"{s,-30}", 2).ConfigureAwait(false);
|
await channel.SendTableAsync("", localSet.Select(c => c.CommandName + ": " + c.Seconds + GetText("sec")), s => $"{s,-30}", 2).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasCooldown(CommandInfo cmd, IGuild guild, IUser user)
|
|
||||||
{
|
|
||||||
if (guild == null)
|
|
||||||
return false;
|
|
||||||
var cmdcds = CommandCooldowns.GetOrAdd(guild.Id, new ConcurrentHashSet<CommandCooldown>());
|
|
||||||
CommandCooldown cdRule;
|
|
||||||
if ((cdRule = cmdcds.FirstOrDefault(cc => cc.CommandName == cmd.Aliases.First().ToLowerInvariant())) != null)
|
|
||||||
{
|
|
||||||
var activeCdsForGuild = ActiveCooldowns.GetOrAdd(guild.Id, new ConcurrentHashSet<ActiveCooldown>());
|
|
||||||
if (activeCdsForGuild.FirstOrDefault(ac => ac.UserId == user.Id && ac.Command == cmd.Aliases.First().ToLowerInvariant()) != null)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
activeCdsForGuild.Add(new ActiveCooldown()
|
|
||||||
{
|
|
||||||
UserId = user.Id,
|
|
||||||
Command = cmd.Aliases.First().ToLowerInvariant(),
|
|
||||||
});
|
|
||||||
var _ = Task.Run(async () =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await Task.Delay(cdRule.Seconds * 1000);
|
|
||||||
activeCdsForGuild.RemoveWhere(ac => ac.Command == cmd.Aliases.First().ToLowerInvariant() && ac.UserId == user.Id);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,10 +15,10 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
[Group]
|
[Group]
|
||||||
public class FilterCommands : NadekoSubmodule
|
public class FilterCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
private readonly FilterService _service;
|
private readonly FilterService _service;
|
||||||
|
|
||||||
public FilterCommands(FilterService service, DbHandler db)
|
public FilterCommands(FilterService service, DbService db)
|
||||||
{
|
{
|
||||||
_service = service;
|
_service = service;
|
||||||
_db = db;
|
_db = db;
|
||||||
|
@ -16,9 +16,9 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
public class GlobalPermissionCommands : NadekoSubmodule
|
public class GlobalPermissionCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private GlobalPermissionService _service;
|
private GlobalPermissionService _service;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public GlobalPermissionCommands(GlobalPermissionService service, DbHandler db)
|
public GlobalPermissionCommands(GlobalPermissionService service, DbService db)
|
||||||
{
|
{
|
||||||
_service = service;
|
_service = service;
|
||||||
_db = db;
|
_db = db;
|
||||||
|
@ -14,10 +14,10 @@ namespace NadekoBot.Modules.Permissions.Commands
|
|||||||
public class ResetPermissionsCommands : NadekoSubmodule
|
public class ResetPermissionsCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly PermissionsService _service;
|
private readonly PermissionsService _service;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
private readonly GlobalPermissionService _globalPerms;
|
private readonly GlobalPermissionService _globalPerms;
|
||||||
|
|
||||||
public ResetPermissionsCommands(PermissionsService service, GlobalPermissionService globalPerms, DbHandler db)
|
public ResetPermissionsCommands(PermissionsService service, GlobalPermissionService globalPerms, DbService db)
|
||||||
{
|
{
|
||||||
_service = service;
|
_service = service;
|
||||||
_db = db;
|
_db = db;
|
||||||
@ -29,7 +29,7 @@ namespace NadekoBot.Modules.Permissions.Commands
|
|||||||
[RequireUserPermission(GuildPermission.Administrator)]
|
[RequireUserPermission(GuildPermission.Administrator)]
|
||||||
public async Task ResetPermissions()
|
public async Task ResetPermissions()
|
||||||
{
|
{
|
||||||
//todo 80 move to service
|
//todo 50 move to service
|
||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
||||||
var config = uow.GuildConfigs.GcWithPermissionsv2For(Context.Guild.Id);
|
var config = uow.GuildConfigs.GcWithPermissionsv2For(Context.Guild.Id);
|
||||||
@ -44,7 +44,7 @@ namespace NadekoBot.Modules.Permissions.Commands
|
|||||||
[OwnerOnly]
|
[OwnerOnly]
|
||||||
public async Task ResetGlobalPermissions()
|
public async Task ResetGlobalPermissions()
|
||||||
{
|
{
|
||||||
//todo 80 move to service
|
//todo 50 move to service
|
||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
||||||
var gc = uow.BotConfig.GetOrCreate();
|
var gc = uow.BotConfig.GetOrCreate();
|
||||||
|
@ -15,10 +15,10 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
{
|
{
|
||||||
public partial class Permissions : NadekoTopLevelModule
|
public partial class Permissions : NadekoTopLevelModule
|
||||||
{
|
{
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
private readonly PermissionsService _service;
|
private readonly PermissionsService _service;
|
||||||
|
|
||||||
public Permissions(PermissionsService service, DbHandler db)
|
public Permissions(PermissionsService service, DbService db)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
_service = service;
|
_service = service;
|
||||||
|
@ -15,16 +15,16 @@ namespace NadekoBot.Modules.Pokemon
|
|||||||
public class Pokemon : NadekoTopLevelModule
|
public class Pokemon : NadekoTopLevelModule
|
||||||
{
|
{
|
||||||
private readonly PokemonService _service;
|
private readonly PokemonService _service;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
private readonly BotConfig _bc;
|
private readonly BotConfig _bc;
|
||||||
private readonly CurrencyHandler _ch;
|
private readonly CurrencyService _cs;
|
||||||
|
|
||||||
public Pokemon(PokemonService pokemonService, DbHandler db, BotConfig bc, CurrencyHandler ch)
|
public Pokemon(PokemonService pokemonService, DbService db, BotConfig bc, CurrencyService cs)
|
||||||
{
|
{
|
||||||
_service = pokemonService;
|
_service = pokemonService;
|
||||||
_db = db;
|
_db = db;
|
||||||
_bc = bc;
|
_bc = bc;
|
||||||
_ch = ch;
|
_cs = cs;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int GetDamage(PokemonType usertype, PokemonType targetType)
|
private int GetDamage(PokemonType usertype, PokemonType targetType)
|
||||||
@ -229,7 +229,7 @@ namespace NadekoBot.Modules.Pokemon
|
|||||||
var target = (targetUser.Id == user.Id) ? "yourself" : targetUser.Mention;
|
var target = (targetUser.Id == user.Id) ? "yourself" : targetUser.Mention;
|
||||||
if (amount > 0)
|
if (amount > 0)
|
||||||
{
|
{
|
||||||
if (!await _ch.RemoveCurrencyAsync(user, $"Poke-Heal {target}", amount, true).ConfigureAwait(false))
|
if (!await _cs.RemoveAsync(user, $"Poke-Heal {target}", amount, true).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
await ReplyErrorLocalized("no_currency", _bc.CurrencySign).ConfigureAwait(false);
|
await ReplyErrorLocalized("no_currency", _bc.CurrencySign).ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
@ -295,7 +295,7 @@ namespace NadekoBot.Modules.Pokemon
|
|||||||
var amount = 1;
|
var amount = 1;
|
||||||
if (amount > 0)
|
if (amount > 0)
|
||||||
{
|
{
|
||||||
if (!await _ch.RemoveCurrencyAsync(user, $"{user} change type to {typeTargeted}", amount, true).ConfigureAwait(false))
|
if (!await _cs.RemoveAsync(user, $"{user} change type to {typeTargeted}", amount, true).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
await ReplyErrorLocalized("no_currency", _bc.CurrencySign).ConfigureAwait(false);
|
await ReplyErrorLocalized("no_currency", _bc.CurrencySign).ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
|
@ -9,7 +9,7 @@ using System.Linq;
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
//todo drawing
|
//todo 50 drawing
|
||||||
namespace NadekoBot.Modules.Searches
|
namespace NadekoBot.Modules.Searches
|
||||||
{
|
{
|
||||||
public partial class Searches
|
public partial class Searches
|
||||||
|
@ -17,10 +17,10 @@ namespace NadekoBot.Modules.Searches
|
|||||||
[Group]
|
[Group]
|
||||||
public class StreamNotificationCommands : NadekoSubmodule
|
public class StreamNotificationCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
private readonly StreamNotificationService _service;
|
private readonly StreamNotificationService _service;
|
||||||
|
|
||||||
public StreamNotificationCommands(DbHandler db, StreamNotificationService service)
|
public StreamNotificationCommands(DbService db, StreamNotificationService service)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
_service = service;
|
_service = service;
|
||||||
|
@ -59,7 +59,7 @@ namespace NadekoBot.Modules.Searches
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_searches.TranslatedChannels.TryRemove(channel.Id, out var throwaway))
|
if (_searches.TranslatedChannels.TryRemove(channel.Id, out _))
|
||||||
{
|
{
|
||||||
await ReplyConfirmLocalized("atl_stopped").ConfigureAwait(false);
|
await ReplyConfirmLocalized("atl_stopped").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
|
@ -20,10 +20,10 @@ namespace NadekoBot.Modules.Utility
|
|||||||
public class CommandMapCommands : NadekoSubmodule
|
public class CommandMapCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly UtilityService _service;
|
private readonly UtilityService _service;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordShardedClient _client;
|
||||||
|
|
||||||
public CommandMapCommands(UtilityService service, DbHandler db, DiscordShardedClient client)
|
public CommandMapCommands(UtilityService service, DbService db, DiscordShardedClient client)
|
||||||
{
|
{
|
||||||
_service = service;
|
_service = service;
|
||||||
_db = db;
|
_db = db;
|
||||||
|
@ -18,13 +18,13 @@ namespace NadekoBot.Modules.Utility
|
|||||||
{
|
{
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordShardedClient _client;
|
||||||
private readonly IStatsService _stats;
|
private readonly IStatsService _stats;
|
||||||
private readonly CommandHandler _ch;
|
private readonly CommandHandler _cmdHandler;
|
||||||
|
|
||||||
public InfoCommands(DiscordShardedClient client, IStatsService stats, CommandHandler ch)
|
public InfoCommands(DiscordShardedClient client, IStatsService stats, CommandHandler ch)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
_stats = stats;
|
_stats = stats;
|
||||||
_ch = ch;
|
_cmdHandler = ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -129,7 +129,7 @@ namespace NadekoBot.Modules.Utility
|
|||||||
int startCount = page * activityPerPage;
|
int startCount = page * activityPerPage;
|
||||||
|
|
||||||
StringBuilder str = new StringBuilder();
|
StringBuilder str = new StringBuilder();
|
||||||
foreach (var kvp in _ch.UserMessagesSent.OrderByDescending(kvp => kvp.Value).Skip(page * activityPerPage).Take(activityPerPage))
|
foreach (var kvp in _cmdHandler.UserMessagesSent.OrderByDescending(kvp => kvp.Value).Skip(page * activityPerPage).Take(activityPerPage))
|
||||||
{
|
{
|
||||||
str.AppendLine(GetText("activity_line",
|
str.AppendLine(GetText("activity_line",
|
||||||
++startCount,
|
++startCount,
|
||||||
@ -141,7 +141,7 @@ namespace NadekoBot.Modules.Utility
|
|||||||
.WithTitle(GetText("activity_page", page + 1))
|
.WithTitle(GetText("activity_page", page + 1))
|
||||||
.WithOkColor()
|
.WithOkColor()
|
||||||
.WithFooter(efb => efb.WithText(GetText("activity_users_total",
|
.WithFooter(efb => efb.WithText(GetText("activity_users_total",
|
||||||
_ch.UserMessagesSent.Count)))
|
_cmdHandler.UserMessagesSent.Count)))
|
||||||
.WithDescription(str.ToString()));
|
.WithDescription(str.ToString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,9 +22,9 @@ namespace NadekoBot.Modules.Utility
|
|||||||
{
|
{
|
||||||
private readonly MessageRepeaterService _service;
|
private readonly MessageRepeaterService _service;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordShardedClient _client;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public RepeatCommands(MessageRepeaterService service, DiscordShardedClient client, DbHandler db)
|
public RepeatCommands(MessageRepeaterService service, DiscordShardedClient client, DbService db)
|
||||||
{
|
{
|
||||||
_service = service;
|
_service = service;
|
||||||
_client = client;
|
_client = client;
|
||||||
|
@ -1,19 +1,12 @@
|
|||||||
using System.Collections.Generic;
|
using System.Threading.Tasks;
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using NadekoBot.Attributes;
|
using NadekoBot.Attributes;
|
||||||
using NadekoBot.Modules.Utility.Models;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using System.Threading;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Immutable;
|
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using Discord;
|
using Discord;
|
||||||
using NLog;
|
using NadekoBot.Services.Utility;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Utility
|
namespace NadekoBot.Modules.Utility
|
||||||
{
|
{
|
||||||
@ -22,27 +15,26 @@ namespace NadekoBot.Modules.Utility
|
|||||||
[Group]
|
[Group]
|
||||||
public class PatreonCommands : NadekoSubmodule
|
public class PatreonCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
//todo rename patreon thingy and move it to be a service, or a part of utility service
|
private readonly PatreonRewardsService _patreon;
|
||||||
private readonly PatreonThingy patreon;
|
|
||||||
private readonly IBotCredentials _creds;
|
private readonly IBotCredentials _creds;
|
||||||
private readonly BotConfig _config;
|
private readonly BotConfig _config;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
private readonly CurrencyHandler _currency;
|
private readonly CurrencyService _currency;
|
||||||
|
|
||||||
public PatreonCommands(IBotCredentials creds, BotConfig config, DbHandler db, CurrencyHandler currency)
|
public PatreonCommands(PatreonRewardsService p, IBotCredentials creds, BotConfig config, DbService db, CurrencyService currency)
|
||||||
{
|
{
|
||||||
_creds = creds;
|
_creds = creds;
|
||||||
_config = config;
|
_config = config;
|
||||||
_db = db;
|
_db = db;
|
||||||
_currency = currency;
|
_currency = currency;
|
||||||
patreon = PatreonThingy.GetInstance(creds, db, currency);
|
_patreon = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[OwnerOnly]
|
[OwnerOnly]
|
||||||
public async Task PatreonRewardsReload()
|
public async Task PatreonRewardsReload()
|
||||||
{
|
{
|
||||||
await patreon.LoadPledges().ConfigureAwait(false);
|
await _patreon.LoadPledges().ConfigureAwait(false);
|
||||||
|
|
||||||
await Context.Channel.SendConfirmAsync("👌").ConfigureAwait(false);
|
await Context.Channel.SendConfirmAsync("👌").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@ -60,7 +52,7 @@ namespace NadekoBot.Modules.Utility
|
|||||||
int amount = 0;
|
int amount = 0;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
amount = await patreon.ClaimReward(Context.User.Id).ConfigureAwait(false);
|
amount = await _patreon.ClaimReward(Context.User.Id).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -72,7 +64,7 @@ namespace NadekoBot.Modules.Utility
|
|||||||
await ReplyConfirmLocalized("clpa_success", amount + _config.CurrencySign).ConfigureAwait(false);
|
await ReplyConfirmLocalized("clpa_success", amount + _config.CurrencySign).ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var rem = (patreon.Interval - (DateTime.UtcNow - patreon.LastUpdate));
|
var rem = (_patreon.Interval - (DateTime.UtcNow - _patreon.LastUpdate));
|
||||||
var helpcmd = Format.Code(NadekoBot.Prefix + "donate");
|
var helpcmd = Format.Code(NadekoBot.Prefix + "donate");
|
||||||
await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
|
await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
|
||||||
.WithDescription(GetText("clpa_fail"))
|
.WithDescription(GetText("clpa_fail"))
|
||||||
@ -85,158 +77,5 @@ namespace NadekoBot.Modules.Utility
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PatreonThingy
|
|
||||||
{
|
|
||||||
//todo quickly hacked while rewriting, fix this
|
|
||||||
private static PatreonThingy _instance = null;
|
|
||||||
public static PatreonThingy GetInstance(IBotCredentials creds, DbHandler db, CurrencyHandler cur)
|
|
||||||
=> _instance ?? (_instance = new PatreonThingy(creds, db, cur));
|
|
||||||
|
|
||||||
private readonly SemaphoreSlim getPledgesLocker = new SemaphoreSlim(1, 1);
|
|
||||||
|
|
||||||
public ImmutableArray<PatreonUserAndReward> Pledges { get; private set; }
|
|
||||||
public DateTime LastUpdate { get; private set; } = DateTime.UtcNow;
|
|
||||||
|
|
||||||
public readonly Timer Updater;
|
|
||||||
private readonly SemaphoreSlim claimLockJustInCase = new SemaphoreSlim(1, 1);
|
|
||||||
private readonly Logger _log;
|
|
||||||
|
|
||||||
public readonly TimeSpan Interval = TimeSpan.FromHours(1);
|
|
||||||
private IBotCredentials _creds;
|
|
||||||
private readonly DbHandler _db;
|
|
||||||
private readonly CurrencyHandler _currency;
|
|
||||||
|
|
||||||
static PatreonThingy() { }
|
|
||||||
private PatreonThingy(IBotCredentials creds, DbHandler db, CurrencyHandler currency)
|
|
||||||
{
|
|
||||||
_creds = creds;
|
|
||||||
_db = db;
|
|
||||||
_currency = currency;
|
|
||||||
if (string.IsNullOrWhiteSpace(creds.PatreonAccessToken))
|
|
||||||
return;
|
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
|
||||||
Updater = new Timer(async (_) => await LoadPledges(), null, TimeSpan.Zero, Interval);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task LoadPledges()
|
|
||||||
{
|
|
||||||
LastUpdate = DateTime.UtcNow;
|
|
||||||
await getPledgesLocker.WaitAsync(1000).ConfigureAwait(false);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var rewards = new List<PatreonPledge>();
|
|
||||||
var users = new List<PatreonUser>();
|
|
||||||
using (var http = new HttpClient())
|
|
||||||
{
|
|
||||||
http.DefaultRequestHeaders.Clear();
|
|
||||||
http.DefaultRequestHeaders.Add("Authorization", "Bearer " + _creds.PatreonAccessToken);
|
|
||||||
var data = new PatreonData()
|
|
||||||
{
|
|
||||||
Links = new PatreonDataLinks()
|
|
||||||
{
|
|
||||||
next = "https://api.patreon.com/oauth2/api/campaigns/334038/pledges"
|
|
||||||
}
|
|
||||||
};
|
|
||||||
do
|
|
||||||
{
|
|
||||||
var res = await http.GetStringAsync(data.Links.next)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
data = JsonConvert.DeserializeObject<PatreonData>(res);
|
|
||||||
var pledgers = data.Data.Where(x => x["type"].ToString() == "pledge");
|
|
||||||
rewards.AddRange(pledgers.Select(x => JsonConvert.DeserializeObject<PatreonPledge>(x.ToString()))
|
|
||||||
.Where(x => x.attributes.declined_since == null));
|
|
||||||
users.AddRange(data.Included
|
|
||||||
.Where(x => x["type"].ToString() == "user")
|
|
||||||
.Select(x => JsonConvert.DeserializeObject<PatreonUser>(x.ToString())));
|
|
||||||
} while (!string.IsNullOrWhiteSpace(data.Links.next));
|
|
||||||
}
|
|
||||||
Pledges = rewards.Join(users, (r) => r.relationships?.patron?.data?.id, (u) => u.id, (x, y) => new PatreonUserAndReward()
|
|
||||||
{
|
|
||||||
User = y,
|
|
||||||
Reward = x,
|
|
||||||
}).ToImmutableArray();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_log.Warn(ex);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
var _ = Task.Run(async () =>
|
|
||||||
{
|
|
||||||
await Task.Delay(TimeSpan.FromMinutes(5)).ConfigureAwait(false);
|
|
||||||
getPledgesLocker.Release();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<int> ClaimReward(ulong userId)
|
|
||||||
{
|
|
||||||
await claimLockJustInCase.WaitAsync();
|
|
||||||
var now = DateTime.UtcNow;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var data = Pledges.FirstOrDefault(x => x.User.attributes?.social_connections?.discord?.user_id == userId.ToString());
|
|
||||||
|
|
||||||
if (data == null)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
var amount = data.Reward.attributes.amount_cents;
|
|
||||||
|
|
||||||
using (var uow = _db.UnitOfWork)
|
|
||||||
{
|
|
||||||
var users = uow._context.Set<RewardedUser>();
|
|
||||||
var usr = users.FirstOrDefault(x => x.PatreonUserId == data.User.id);
|
|
||||||
|
|
||||||
if (usr == null)
|
|
||||||
{
|
|
||||||
users.Add(new RewardedUser()
|
|
||||||
{
|
|
||||||
UserId = userId,
|
|
||||||
PatreonUserId = data.User.id,
|
|
||||||
LastReward = now,
|
|
||||||
AmountRewardedThisMonth = amount,
|
|
||||||
});
|
|
||||||
|
|
||||||
await _currency.AddCurrencyAsync(userId, "Patreon reward - new", amount, uow).ConfigureAwait(false);
|
|
||||||
|
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
|
||||||
return amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (usr.LastReward.Month != now.Month)
|
|
||||||
{
|
|
||||||
usr.LastReward = now;
|
|
||||||
usr.AmountRewardedThisMonth = amount;
|
|
||||||
usr.PatreonUserId = data.User.id;
|
|
||||||
|
|
||||||
await _currency.AddCurrencyAsync(userId, "Patreon reward - recurring", amount, uow).ConfigureAwait(false);
|
|
||||||
|
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
|
||||||
return amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( usr.AmountRewardedThisMonth < amount)
|
|
||||||
{
|
|
||||||
var toAward = amount - usr.AmountRewardedThisMonth;
|
|
||||||
|
|
||||||
usr.LastReward = now;
|
|
||||||
usr.AmountRewardedThisMonth = amount;
|
|
||||||
usr.PatreonUserId = data.User.id;
|
|
||||||
|
|
||||||
await _currency.AddCurrencyAsync(usr.UserId, "Patreon reward - update", toAward, uow).ConfigureAwait(false);
|
|
||||||
|
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
|
||||||
return toAward;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
claimLockJustInCase.Release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -17,9 +17,9 @@ namespace NadekoBot.Modules.Utility
|
|||||||
[Group]
|
[Group]
|
||||||
public class QuoteCommands : NadekoSubmodule
|
public class QuoteCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public QuoteCommands(DbHandler db)
|
public QuoteCommands(DbService db)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
}
|
}
|
||||||
|
@ -18,9 +18,9 @@ namespace NadekoBot.Modules.Utility
|
|||||||
public class RemindCommands : NadekoSubmodule
|
public class RemindCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly RemindService _service;
|
private readonly RemindService _service;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public RemindCommands(RemindService service, DbHandler db)
|
public RemindCommands(RemindService service, DbService db)
|
||||||
{
|
{
|
||||||
_service = service;
|
_service = service;
|
||||||
_db = db;
|
_db = db;
|
||||||
|
@ -494,7 +494,6 @@ namespace NadekoBot.Services.Utility
|
|||||||
}
|
}
|
||||||
else if (s.Embeds.Any())
|
else if (s.Embeds.Any())
|
||||||
{
|
{
|
||||||
//todo probably just go through all properties and check if they are set, if they are, add them
|
|
||||||
msg += "EMBEDS: " + string.Join("\n--------\n", s.Embeds.Select(x => $"Description: {x.Description}"));
|
msg += "EMBEDS: " + string.Join("\n--------\n", s.Embeds.Select(x => $"Description: {x.Description}"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ using NadekoBot.Services.Games;
|
|||||||
using NadekoBot.Services.Administration;
|
using NadekoBot.Services.Administration;
|
||||||
using NadekoBot.Services.Permissions;
|
using NadekoBot.Services.Permissions;
|
||||||
using NadekoBot.Services.Utility;
|
using NadekoBot.Services.Utility;
|
||||||
|
using NadekoBot.Services.Help;
|
||||||
|
|
||||||
namespace NadekoBot
|
namespace NadekoBot
|
||||||
{
|
{
|
||||||
@ -45,7 +46,7 @@ namespace NadekoBot
|
|||||||
|
|
||||||
public ImmutableArray<GuildConfig> AllGuildConfigs { get; }
|
public ImmutableArray<GuildConfig> AllGuildConfigs { get; }
|
||||||
public BotConfig BotConfig { get; }
|
public BotConfig BotConfig { get; }
|
||||||
public DbHandler Db { get; }
|
public DbService Db { get; }
|
||||||
public CommandService CommandService { get; }
|
public CommandService CommandService { get; }
|
||||||
|
|
||||||
public DiscordShardedClient Client { get; }
|
public DiscordShardedClient Client { get; }
|
||||||
@ -60,7 +61,7 @@ namespace NadekoBot
|
|||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
Credentials = new BotCredentials();
|
Credentials = new BotCredentials();
|
||||||
Db = new DbHandler(Credentials);
|
Db = new DbService(Credentials);
|
||||||
|
|
||||||
using (var uow = Db.UnitOfWork)
|
using (var uow = Db.UnitOfWork)
|
||||||
{
|
{
|
||||||
@ -99,7 +100,7 @@ namespace NadekoBot
|
|||||||
var commandHandler = new CommandHandler(Client, CommandService, Credentials, this);
|
var commandHandler = new CommandHandler(Client, CommandService, Credentials, this);
|
||||||
var stats = new StatsService(Client, commandHandler, Credentials);
|
var stats = new StatsService(Client, commandHandler, Credentials);
|
||||||
var images = new ImagesService();
|
var images = new ImagesService();
|
||||||
var currencyHandler = new CurrencyHandler(BotConfig, Db);
|
var currencyHandler = new CurrencyService(BotConfig, Db);
|
||||||
|
|
||||||
//module services
|
//module services
|
||||||
//todo 90 - autodiscover, DI, and add instead of manual like this
|
//todo 90 - autodiscover, DI, and add instead of manual like this
|
||||||
@ -109,27 +110,36 @@ namespace NadekoBot
|
|||||||
var repeaterService = new MessageRepeaterService(Client, AllGuildConfigs);
|
var repeaterService = new MessageRepeaterService(Client, AllGuildConfigs);
|
||||||
var converterService = new ConverterService(Db);
|
var converterService = new ConverterService(Db);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Searches
|
#region Searches
|
||||||
var searchesService = new SearchesService(Client, googleApiService, Db);
|
var searchesService = new SearchesService(Client, googleApiService, Db);
|
||||||
var streamNotificationService = new StreamNotificationService(Db, Client, strings);
|
var streamNotificationService = new StreamNotificationService(Db, Client, strings);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
var clashService = new ClashOfClansService(Client, Db, localization, strings);
|
var clashService = new ClashOfClansService(Client, Db, localization, strings);
|
||||||
var musicService = new MusicService(googleApiService, strings, localization, Db, soundcloudApiService, Credentials);
|
var musicService = new MusicService(googleApiService, strings, localization, Db, soundcloudApiService, Credentials, AllGuildConfigs);
|
||||||
var crService = new CustomReactionsService(Db, Client);
|
var crService = new CustomReactionsService(Db, Client);
|
||||||
|
var helpService = new HelpService(BotConfig);
|
||||||
|
|
||||||
|
#region Games
|
||||||
var gamesService = new GamesService(Client, BotConfig, AllGuildConfigs, strings, images);
|
var gamesService = new GamesService(Client, BotConfig, AllGuildConfigs, strings, images);
|
||||||
|
var chatterBotService = new ChatterBotService(Client, AllGuildConfigs);
|
||||||
|
var pollService = new PollService(Client, strings);
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region administration
|
#region administration
|
||||||
var administrationService = new AdministrationService(AllGuildConfigs, commandHandler);
|
var administrationService = new AdministrationService(AllGuildConfigs, commandHandler);
|
||||||
var greetSettingsService = new GreetSettingsService(Client, AllGuildConfigs, Db);
|
var greetSettingsService = new GreetSettingsService(Client, AllGuildConfigs, Db);
|
||||||
var selfService = new SelfService(this, commandHandler, Db, BotConfig);
|
var selfService = new SelfService(Client, this, commandHandler, Db, BotConfig, localization, strings, Credentials);
|
||||||
var vcRoleService = new VcRoleService(Client, AllGuildConfigs);
|
var vcRoleService = new VcRoleService(Client, AllGuildConfigs, Db);
|
||||||
var vPlusTService = new VplusTService(Client, AllGuildConfigs, strings, Db);
|
var vPlusTService = new VplusTService(Client, AllGuildConfigs, strings, Db);
|
||||||
var muteService = new MuteService(Client, AllGuildConfigs, Db);
|
var muteService = new MuteService(Client, AllGuildConfigs, Db);
|
||||||
var ratelimitService = new RatelimitService(Client, AllGuildConfigs);
|
var ratelimitService = new SlowmodeService(AllGuildConfigs);
|
||||||
var protectionService = new ProtectionService(Client, AllGuildConfigs, muteService);
|
var protectionService = new ProtectionService(Client, AllGuildConfigs, muteService);
|
||||||
var playingRotateService = new PlayingRotateService(Client, BotConfig, musicService);
|
var playingRotateService = new PlayingRotateService(Client, BotConfig, musicService);
|
||||||
var gameVcService = new GameVoiceChannelService(Client, Db, AllGuildConfigs);
|
var gameVcService = new GameVoiceChannelService(Client, Db, AllGuildConfigs);
|
||||||
var autoAssignRoleService = new AutoAssignRoleService(Client, AllGuildConfigs);
|
var autoAssignRoleService = new AutoAssignRoleService(Client, AllGuildConfigs);
|
||||||
var permissionsService = new PermissionsService(Db);
|
var permissionsService = new PermissionsService(Db, BotConfig);
|
||||||
var blacklistService = new BlacklistService(BotConfig);
|
var blacklistService = new BlacklistService(BotConfig);
|
||||||
var cmdcdsService = new CmdCdService(AllGuildConfigs);
|
var cmdcdsService = new CmdCdService(AllGuildConfigs);
|
||||||
var filterService = new FilterService(AllGuildConfigs);
|
var filterService = new FilterService(AllGuildConfigs);
|
||||||
@ -148,9 +158,9 @@ namespace NadekoBot
|
|||||||
.Add<NadekoStrings>(strings)
|
.Add<NadekoStrings>(strings)
|
||||||
.Add<DiscordShardedClient>(Client)
|
.Add<DiscordShardedClient>(Client)
|
||||||
.Add<BotConfig>(BotConfig)
|
.Add<BotConfig>(BotConfig)
|
||||||
.Add<CurrencyHandler>(currencyHandler)
|
.Add<CurrencyService>(currencyHandler)
|
||||||
.Add<CommandHandler>(commandHandler)
|
.Add<CommandHandler>(commandHandler)
|
||||||
.Add<DbHandler>(Db)
|
.Add<DbService>(Db)
|
||||||
//modules
|
//modules
|
||||||
.Add<UtilityService>(utilityService)
|
.Add<UtilityService>(utilityService)
|
||||||
.Add(remindService)
|
.Add(remindService)
|
||||||
@ -162,7 +172,10 @@ namespace NadekoBot
|
|||||||
.Add<MusicService>(musicService)
|
.Add<MusicService>(musicService)
|
||||||
.Add<GreetSettingsService>(greetSettingsService)
|
.Add<GreetSettingsService>(greetSettingsService)
|
||||||
.Add<CustomReactionsService>(crService)
|
.Add<CustomReactionsService>(crService)
|
||||||
|
.Add<HelpService>(helpService)
|
||||||
.Add<GamesService>(gamesService)
|
.Add<GamesService>(gamesService)
|
||||||
|
.Add(chatterBotService)
|
||||||
|
.Add(pollService)
|
||||||
.Add<AdministrationService>(administrationService)
|
.Add<AdministrationService>(administrationService)
|
||||||
.Add(selfService)
|
.Add(selfService)
|
||||||
.Add(vcRoleService)
|
.Add(vcRoleService)
|
||||||
@ -228,9 +241,13 @@ namespace NadekoBot
|
|||||||
await commandHandler.StartHandling().ConfigureAwait(false);
|
await commandHandler.StartHandling().ConfigureAwait(false);
|
||||||
|
|
||||||
var _ = await CommandService.AddModulesAsync(this.GetType().GetTypeInfo().Assembly);
|
var _ = await CommandService.AddModulesAsync(this.GetType().GetTypeInfo().Assembly);
|
||||||
#if !GLOBAL_NADEKO
|
#if GLOBAL_NADEKO
|
||||||
//todo uncomment this
|
//unload modules which are not available on the public bot
|
||||||
//await CommandService.AddModuleAsync<Music>().ConfigureAwait(false);
|
CommandService
|
||||||
|
.Modules
|
||||||
|
.ToArray()
|
||||||
|
.Where(x => x.Preconditions.Any(y => y.GetType() == typeof(NoPublicBot)))
|
||||||
|
.ForEach(x => CommandService.RemoveModuleAsync(x));
|
||||||
#endif
|
#endif
|
||||||
Ready = true;
|
Ready = true;
|
||||||
_log.Info(await stats.Print().ConfigureAwait(false));
|
_log.Info(await stats.Print().ConfigureAwait(false));
|
||||||
|
@ -29,11 +29,8 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Remove="data\**\*;credentials.json;credentials_example.json" />
|
<Compile Remove="data\**\*;credentials.json;credentials_example.json" />
|
||||||
<Compile Remove="Modules\Administration\**" />
|
<Compile Remove="Modules\Administration\**" />
|
||||||
<Compile Remove="Modules\NSFW\**" />
|
|
||||||
<EmbeddedResource Remove="Modules\Administration\**" />
|
<EmbeddedResource Remove="Modules\Administration\**" />
|
||||||
<EmbeddedResource Remove="Modules\NSFW\**" />
|
|
||||||
<None Remove="Modules\Administration\**" />
|
<None Remove="Modules\Administration\**" />
|
||||||
<None Remove="Modules\NSFW\**" />
|
|
||||||
<Compile Remove="Modules\Gambling\Commands\Lucky7Commands.cs" />
|
<Compile Remove="Modules\Gambling\Commands\Lucky7Commands.cs" />
|
||||||
<Compile Include="Modules\Administration\Administration.cs" />
|
<Compile Include="Modules\Administration\Administration.cs" />
|
||||||
<Compile Include="Modules\Administration\Commands\AutoAssignRoleCommands.cs" />
|
<Compile Include="Modules\Administration\Commands\AutoAssignRoleCommands.cs" />
|
||||||
@ -87,6 +84,7 @@
|
|||||||
<PackageReference Include="Microsoft.Extensions.PlatformAbstractions" Version="1.1.0" />
|
<PackageReference Include="Microsoft.Extensions.PlatformAbstractions" Version="1.1.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="10.0.2" />
|
<PackageReference Include="Newtonsoft.Json" Version="10.0.2" />
|
||||||
<PackageReference Include="NLog" Version="5.0.0-beta03" />
|
<PackageReference Include="NLog" Version="5.0.0-beta03" />
|
||||||
|
<PackageReference Include="System.ValueTuple" Version="4.4.0-preview1-25305-02" />
|
||||||
<PackageReference Include="System.Xml.XPath" Version="4.3.0" />
|
<PackageReference Include="System.Xml.XPath" Version="4.3.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
@ -102,5 +100,6 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Modules\Music\Classes\" />
|
<Folder Include="Modules\Music\Classes\" />
|
||||||
|
<Folder Include="Modules\Utility\Models\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -15,10 +15,10 @@ namespace NadekoBot.Services.Administration
|
|||||||
public readonly ConcurrentHashSet<ulong> GameVoiceChannels = new ConcurrentHashSet<ulong>();
|
public readonly ConcurrentHashSet<ulong> GameVoiceChannels = new ConcurrentHashSet<ulong>();
|
||||||
|
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordShardedClient _client;
|
||||||
|
|
||||||
public GameVoiceChannelService(DiscordShardedClient client, DbHandler db, IEnumerable<GuildConfig> gcs)
|
public GameVoiceChannelService(DiscordShardedClient client, DbService db, IEnumerable<GuildConfig> gcs)
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_db = db;
|
_db = db;
|
||||||
|
@ -26,9 +26,9 @@ namespace NadekoBot.Services.Administration
|
|||||||
|
|
||||||
private readonly Logger _log = LogManager.GetCurrentClassLogger();
|
private readonly Logger _log = LogManager.GetCurrentClassLogger();
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordShardedClient _client;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public MuteService(DiscordShardedClient client, IEnumerable<GuildConfig> gcs, DbHandler db)
|
public MuteService(DiscordShardedClient client, IEnumerable<GuildConfig> gcs, DbService db)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
_db = db;
|
_db = db;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
|
using NadekoBot.DataStructures.ModuleBehaviors;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using NLog;
|
using NLog;
|
||||||
@ -6,22 +7,22 @@ using System;
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Discord;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace NadekoBot.Services.Administration
|
namespace NadekoBot.Services.Administration
|
||||||
{
|
{
|
||||||
public class RatelimitService
|
public class SlowmodeService : IEarlyBlocker
|
||||||
{
|
{
|
||||||
public ConcurrentDictionary<ulong, Ratelimiter> RatelimitingChannels = new ConcurrentDictionary<ulong, Ratelimiter>();
|
public ConcurrentDictionary<ulong, Ratelimiter> RatelimitingChannels = new ConcurrentDictionary<ulong, Ratelimiter>();
|
||||||
public ConcurrentDictionary<ulong, HashSet<ulong>> IgnoredRoles = new ConcurrentDictionary<ulong, HashSet<ulong>>();
|
public ConcurrentDictionary<ulong, HashSet<ulong>> IgnoredRoles = new ConcurrentDictionary<ulong, HashSet<ulong>>();
|
||||||
public ConcurrentDictionary<ulong, HashSet<ulong>> IgnoredUsers = new ConcurrentDictionary<ulong, HashSet<ulong>>();
|
public ConcurrentDictionary<ulong, HashSet<ulong>> IgnoredUsers = new ConcurrentDictionary<ulong, HashSet<ulong>>();
|
||||||
|
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
private readonly DiscordShardedClient _client;
|
|
||||||
|
|
||||||
public RatelimitService(DiscordShardedClient client, IEnumerable<GuildConfig> gcs)
|
public SlowmodeService(IEnumerable<GuildConfig> gcs)
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_client = client;
|
|
||||||
|
|
||||||
IgnoredRoles = new ConcurrentDictionary<ulong, HashSet<ulong>>(
|
IgnoredRoles = new ConcurrentDictionary<ulong, HashSet<ulong>>(
|
||||||
gcs.ToDictionary(x => x.GuildId,
|
gcs.ToDictionary(x => x.GuildId,
|
||||||
@ -30,24 +31,33 @@ namespace NadekoBot.Services.Administration
|
|||||||
IgnoredUsers = new ConcurrentDictionary<ulong, HashSet<ulong>>(
|
IgnoredUsers = new ConcurrentDictionary<ulong, HashSet<ulong>>(
|
||||||
gcs.ToDictionary(x => x.GuildId,
|
gcs.ToDictionary(x => x.GuildId,
|
||||||
x => new HashSet<ulong>(x.SlowmodeIgnoredUsers.Select(y => y.UserId))));
|
x => new HashSet<ulong>(x.SlowmodeIgnoredUsers.Select(y => y.UserId))));
|
||||||
|
}
|
||||||
|
|
||||||
_client.MessageReceived += async (umsg) =>
|
public async Task<bool> TryBlockEarly(DiscordShardedClient client, IGuild guild, IUserMessage usrMsg)
|
||||||
|
{
|
||||||
|
if (guild == null)
|
||||||
|
return false;
|
||||||
|
try
|
||||||
{
|
{
|
||||||
try
|
var channel = usrMsg?.Channel as SocketTextChannel;
|
||||||
|
|
||||||
|
if (channel == null || usrMsg == null || usrMsg.IsAuthor(client))
|
||||||
|
return false;
|
||||||
|
if (!RatelimitingChannels.TryGetValue(channel.Id, out Ratelimiter limiter))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (limiter.CheckUserRatelimit(usrMsg.Author.Id, channel.Guild.Id, usrMsg.Author as SocketGuildUser))
|
||||||
{
|
{
|
||||||
var usrMsg = umsg as SocketUserMessage;
|
await usrMsg.DeleteAsync();
|
||||||
var channel = usrMsg?.Channel as SocketTextChannel;
|
return true;
|
||||||
|
|
||||||
if (channel == null || usrMsg == null || usrMsg.IsAuthor(client))
|
|
||||||
return;
|
|
||||||
if (!RatelimitingChannels.TryGetValue(channel.Id, out Ratelimiter limiter))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (limiter.CheckUserRatelimit(usrMsg.Author.Id, channel.Guild.Id, usrMsg.Author as SocketGuildUser))
|
|
||||||
await usrMsg.DeleteAsync();
|
|
||||||
}
|
}
|
||||||
catch (Exception ex) { _log.Warn(ex); }
|
}
|
||||||
};
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_log.Warn(ex);
|
||||||
|
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ namespace NadekoBot.Services.Administration
|
|||||||
{
|
{
|
||||||
public class Ratelimiter
|
public class Ratelimiter
|
||||||
{
|
{
|
||||||
private readonly RatelimitService _svc;
|
private readonly SlowmodeService _svc;
|
||||||
|
|
||||||
public class RatelimitedUser
|
public class RatelimitedUser
|
||||||
{
|
{
|
||||||
@ -22,7 +22,7 @@ namespace NadekoBot.Services.Administration
|
|||||||
public int MaxMessages { get; set; }
|
public int MaxMessages { get; set; }
|
||||||
public int PerSeconds { get; set; }
|
public int PerSeconds { get; set; }
|
||||||
|
|
||||||
public Ratelimiter(RatelimitService svc)
|
public Ratelimiter(SlowmodeService svc)
|
||||||
{
|
{
|
||||||
_svc = svc;
|
_svc = svc;
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,43 @@
|
|||||||
using NadekoBot.Services.Database.Models;
|
using Discord;
|
||||||
|
using NadekoBot.DataStructures;
|
||||||
|
using NadekoBot.DataStructures.ModuleBehaviors;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
|
using NadekoBot.Services.Database.Models;
|
||||||
|
using NLog;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace NadekoBot.Services.Administration
|
namespace NadekoBot.Services.Administration
|
||||||
{
|
{
|
||||||
public class SelfService
|
public class SelfService : ILateExecutor
|
||||||
{
|
{
|
||||||
public volatile bool ForwardDMs;
|
public volatile bool ForwardDMs;
|
||||||
public volatile bool ForwardDMsToAllOwners;
|
public volatile bool ForwardDMsToAllOwners;
|
||||||
|
|
||||||
private readonly NadekoBot _bot;
|
private readonly NadekoBot _bot;
|
||||||
private readonly CommandHandler _cmdHandler;
|
private readonly CommandHandler _cmdHandler;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
|
private readonly Logger _log;
|
||||||
|
private readonly ILocalization _localization;
|
||||||
|
private readonly NadekoStrings _strings;
|
||||||
|
private readonly DiscordShardedClient _client;
|
||||||
|
private readonly IBotCredentials _creds;
|
||||||
|
private ImmutableArray<AsyncLazy<IDMChannel>> ownerChannels = new ImmutableArray<AsyncLazy<IDMChannel>>();
|
||||||
|
|
||||||
public SelfService(NadekoBot bot, CommandHandler cmdHandler, DbHandler db,
|
public SelfService(DiscordShardedClient client, NadekoBot bot, CommandHandler cmdHandler, DbService db,
|
||||||
BotConfig bc)
|
BotConfig bc, ILocalization localization, NadekoStrings strings, IBotCredentials creds)
|
||||||
{
|
{
|
||||||
_bot = bot;
|
_bot = bot;
|
||||||
_cmdHandler = cmdHandler;
|
_cmdHandler = cmdHandler;
|
||||||
_db = db;
|
_db = db;
|
||||||
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
|
_localization = localization;
|
||||||
|
_strings = strings;
|
||||||
|
_client = client;
|
||||||
|
_creds = creds;
|
||||||
|
|
||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
||||||
@ -37,6 +57,112 @@ namespace NadekoBot.Services.Administration
|
|||||||
await Task.Delay(400).ConfigureAwait(false);
|
await Task.Delay(400).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var ___ = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
while (!bot.Ready)
|
||||||
|
await Task.Delay(1000);
|
||||||
|
|
||||||
|
await Task.Delay(5000);
|
||||||
|
|
||||||
|
_client.Guilds.SelectMany(g => g.Users);
|
||||||
|
|
||||||
|
LoadOwnerChannels();
|
||||||
|
|
||||||
|
if (!ownerChannels.Any())
|
||||||
|
_log.Warn("No owner channels created! Make sure you've specified correct OwnerId in the credentials.json file.");
|
||||||
|
else
|
||||||
|
_log.Info($"Created {ownerChannels.Length} out of {_creds.OwnerIds.Length} owner message channels.");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadOwnerChannels()
|
||||||
|
{
|
||||||
|
var hs = new HashSet<ulong>(_creds.OwnerIds);
|
||||||
|
var channels = new Dictionary<ulong, AsyncLazy<IDMChannel>>();
|
||||||
|
|
||||||
|
foreach (var s in _client.Shards)
|
||||||
|
{
|
||||||
|
if (hs.Count == 0)
|
||||||
|
break;
|
||||||
|
foreach (var g in s.Guilds)
|
||||||
|
{
|
||||||
|
if (hs.Count == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
foreach (var u in g.Users)
|
||||||
|
{
|
||||||
|
if (hs.Remove(u.Id))
|
||||||
|
{
|
||||||
|
channels.Add(u.Id, new AsyncLazy<IDMChannel>(async () => await u.CreateDMChannelAsync()));
|
||||||
|
if (hs.Count == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ownerChannels = channels.OrderBy(x => _creds.OwnerIds.IndexOf(x.Key))
|
||||||
|
.Select(x => x.Value)
|
||||||
|
.ToImmutableArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
// forwards dms
|
||||||
|
public async Task LateExecute(DiscordShardedClient client, IGuild guild, IUserMessage msg)
|
||||||
|
{
|
||||||
|
if (msg.Channel is IDMChannel && ForwardDMs && ownerChannels.Length > 0)
|
||||||
|
{
|
||||||
|
var title = _strings.GetText("dm_from",
|
||||||
|
_localization.DefaultCultureInfo,
|
||||||
|
"Administration".ToLowerInvariant()) +
|
||||||
|
$" [{msg.Author}]({msg.Author.Id})";
|
||||||
|
|
||||||
|
var attachamentsTxt = _strings.GetText("attachments",
|
||||||
|
_localization.DefaultCultureInfo,
|
||||||
|
"Administration".ToLowerInvariant());
|
||||||
|
|
||||||
|
var toSend = msg.Content;
|
||||||
|
|
||||||
|
if (msg.Attachments.Count > 0)
|
||||||
|
{
|
||||||
|
toSend += $"\n\n{Format.Code(attachamentsTxt)}:\n" +
|
||||||
|
string.Join("\n", msg.Attachments.Select(a => a.ProxyUrl));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ForwardDMsToAllOwners)
|
||||||
|
{
|
||||||
|
var allOwnerChannels = await Task.WhenAll(ownerChannels
|
||||||
|
.Select(x => x.Value))
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
foreach (var ownerCh in allOwnerChannels.Where(ch => ch.Recipient.Id != msg.Author.Id))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await ownerCh.SendConfirmAsync(title, toSend).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
_log.Warn("Can't contact owner with id {0}", ownerCh.Recipient.Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var firstOwnerChannel = await ownerChannels[0];
|
||||||
|
if (firstOwnerChannel.Recipient.Id != msg.Author.Id)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await firstOwnerChannel.SendConfirmAsync(title, toSend).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,20 +13,25 @@ namespace NadekoBot.Services.Administration
|
|||||||
public class VcRoleService
|
public class VcRoleService
|
||||||
{
|
{
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
|
private readonly DbService _db;
|
||||||
|
private readonly DiscordShardedClient _client;
|
||||||
|
|
||||||
public ConcurrentDictionary<ulong, ConcurrentDictionary<ulong, IRole>> VcRoles { get; }
|
public ConcurrentDictionary<ulong, ConcurrentDictionary<ulong, IRole>> VcRoles { get; }
|
||||||
|
|
||||||
public VcRoleService(DiscordShardedClient client, IEnumerable<GuildConfig> gcs)
|
public VcRoleService(DiscordShardedClient client, IEnumerable<GuildConfig> gcs, DbService db)
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
|
_db = db;
|
||||||
|
_client = client;
|
||||||
|
|
||||||
client.UserVoiceStateUpdated += ClientOnUserVoiceStateUpdated;
|
_client.UserVoiceStateUpdated += ClientOnUserVoiceStateUpdated;
|
||||||
VcRoles = new ConcurrentDictionary<ulong, ConcurrentDictionary<ulong, IRole>>();
|
VcRoles = new ConcurrentDictionary<ulong, ConcurrentDictionary<ulong, IRole>>();
|
||||||
|
var missingRoles = new List<VcRoleInfo>();
|
||||||
foreach (var gconf in gcs)
|
foreach (var gconf in gcs)
|
||||||
{
|
{
|
||||||
var g = client.GetGuild(gconf.GuildId);
|
var g = _client.GetGuild(gconf.GuildId);
|
||||||
if (g == null)
|
if (g == null)
|
||||||
continue; //todo delete everything from db if guild doesn't exist?
|
continue;
|
||||||
|
|
||||||
var infos = new ConcurrentDictionary<ulong, IRole>();
|
var infos = new ConcurrentDictionary<ulong, IRole>();
|
||||||
VcRoles.TryAdd(gconf.GuildId, infos);
|
VcRoles.TryAdd(gconf.GuildId, infos);
|
||||||
@ -34,11 +39,21 @@ namespace NadekoBot.Services.Administration
|
|||||||
{
|
{
|
||||||
var role = g.GetRole(ri.RoleId);
|
var role = g.GetRole(ri.RoleId);
|
||||||
if (role == null)
|
if (role == null)
|
||||||
continue; //todo remove this entry from db
|
{
|
||||||
|
missingRoles.Add(ri);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
infos.TryAdd(ri.VoiceChannelId, role);
|
infos.TryAdd(ri.VoiceChannelId, role);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(missingRoles.Any())
|
||||||
|
using (var uow = _db.UnitOfWork)
|
||||||
|
{
|
||||||
|
_log.Warn($"Removing {missingRoles.Count} missing roles from {nameof(VcRoleService)}");
|
||||||
|
uow._context.RemoveRange(missingRoles);
|
||||||
|
uow.Complete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task ClientOnUserVoiceStateUpdated(SocketUser usr, SocketVoiceState oldState,
|
private Task ClientOnUserVoiceStateUpdated(SocketUser usr, SocketVoiceState oldState,
|
||||||
|
@ -22,11 +22,11 @@ namespace NadekoBot.Services.Administration
|
|||||||
private readonly ConcurrentDictionary<ulong, SemaphoreSlim> _guildLockObjects = new ConcurrentDictionary<ulong, SemaphoreSlim>();
|
private readonly ConcurrentDictionary<ulong, SemaphoreSlim> _guildLockObjects = new ConcurrentDictionary<ulong, SemaphoreSlim>();
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordShardedClient _client;
|
||||||
private readonly NadekoStrings _strings;
|
private readonly NadekoStrings _strings;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
|
|
||||||
public VplusTService(DiscordShardedClient client, IEnumerable<GuildConfig> gcs, NadekoStrings strings,
|
public VplusTService(DiscordShardedClient client, IEnumerable<GuildConfig> gcs, NadekoStrings strings,
|
||||||
DbHandler db)
|
DbService db)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
_strings = strings;
|
_strings = strings;
|
||||||
|
@ -18,14 +18,14 @@ namespace NadekoBot.Services.ClashOfClans
|
|||||||
public class ClashOfClansService
|
public class ClashOfClansService
|
||||||
{
|
{
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordShardedClient _client;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
private readonly ILocalization _localization;
|
private readonly ILocalization _localization;
|
||||||
private readonly NadekoStrings _strings;
|
private readonly NadekoStrings _strings;
|
||||||
private readonly Timer checkWarTimer;
|
private readonly Timer checkWarTimer;
|
||||||
|
|
||||||
public ConcurrentDictionary<ulong, List<ClashWar>> ClashWars { get; set; }
|
public ConcurrentDictionary<ulong, List<ClashWar>> ClashWars { get; set; }
|
||||||
|
|
||||||
public ClashOfClansService(DiscordShardedClient client, DbHandler db, ILocalization localization, NadekoStrings strings)
|
public ClashOfClansService(DiscordShardedClient client, DbService db, ILocalization localization, NadekoStrings strings)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
_db = db;
|
_db = db;
|
||||||
|
@ -87,20 +87,6 @@ namespace NadekoBot.Services
|
|||||||
|
|
||||||
public Task StartHandling()
|
public Task StartHandling()
|
||||||
{
|
{
|
||||||
var _ = Task.Run(async () =>
|
|
||||||
{
|
|
||||||
await Task.Delay(5000).ConfigureAwait(false);
|
|
||||||
|
|
||||||
_client.Guilds.SelectMany(g => g.Users);
|
|
||||||
|
|
||||||
LoadOwnerChannels();
|
|
||||||
|
|
||||||
if (!ownerChannels.Any())
|
|
||||||
_log.Warn("No owner channels created! Make sure you've specified correct OwnerId in the credentials.json file.");
|
|
||||||
else
|
|
||||||
_log.Info($"Created {ownerChannels.Length} out of {_creds.OwnerIds.Length} owner message channels.");
|
|
||||||
});
|
|
||||||
|
|
||||||
_client.MessageReceived += MessageReceivedHandler;
|
_client.MessageReceived += MessageReceivedHandler;
|
||||||
_client.MessageUpdated += (oldmsg, newMsg, channel) =>
|
_client.MessageUpdated += (oldmsg, newMsg, channel) =>
|
||||||
{
|
{
|
||||||
@ -126,80 +112,6 @@ namespace NadekoBot.Services
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadOwnerChannels()
|
|
||||||
{
|
|
||||||
var hs = new HashSet<ulong>(_creds.OwnerIds);
|
|
||||||
var channels = new Dictionary<ulong, AsyncLazy<IDMChannel>>();
|
|
||||||
|
|
||||||
foreach (var s in _client.Shards)
|
|
||||||
{
|
|
||||||
if(hs.Count == 0)
|
|
||||||
break;
|
|
||||||
foreach (var g in s.Guilds)
|
|
||||||
{
|
|
||||||
if(hs.Count == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
foreach (var u in g.Users)
|
|
||||||
{
|
|
||||||
if(hs.Remove(u.Id))
|
|
||||||
{
|
|
||||||
channels.Add(u.Id, new AsyncLazy<IDMChannel>(async () => await u.CreateDMChannelAsync()));
|
|
||||||
if(hs.Count == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ownerChannels = channels.OrderBy(x => _creds.OwnerIds.IndexOf(x.Key))
|
|
||||||
.Select(x => x.Value)
|
|
||||||
.ToImmutableArray();
|
|
||||||
}
|
|
||||||
////todo cleverbot
|
|
||||||
//private async Task<bool> TryRunCleverbot(IUserMessage usrMsg, SocketGuild guild)
|
|
||||||
//{
|
|
||||||
// if (guild == null)
|
|
||||||
// return false;
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// var message = Games.CleverBotCommands.PrepareMessage(usrMsg, out Games.ChatterBotSession cbs);
|
|
||||||
// if (message == null || cbs == null)
|
|
||||||
// return false;
|
|
||||||
|
|
||||||
// PermissionCache pc = Permissions.GetCache(guild.Id);
|
|
||||||
// if (!pc.Permissions.CheckPermissions(usrMsg,
|
|
||||||
// NadekoBot.Prefix + "cleverbot",
|
|
||||||
// typeof(Games).Name,
|
|
||||||
// out int index))
|
|
||||||
// {
|
|
||||||
// //todo print in guild actually
|
|
||||||
// var returnMsg =
|
|
||||||
// $"Permission number #{index + 1} **{pc.Permissions[index].GetCommand(guild)}** is preventing this action.";
|
|
||||||
// _log.Info(returnMsg);
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// var cleverbotExecuted = await Games.CleverBotCommands.TryAsk(cbs, (ITextChannel)usrMsg.Channel, message).ConfigureAwait(false);
|
|
||||||
// if (cleverbotExecuted)
|
|
||||||
// {
|
|
||||||
// _log.Info($@"CleverBot Executed
|
|
||||||
//Server: {guild.Name} [{guild.Id}]
|
|
||||||
//Channel: {usrMsg.Channel?.Name} [{usrMsg.Channel?.Id}]
|
|
||||||
//UserId: {usrMsg.Author} [{usrMsg.Author.Id}]
|
|
||||||
//Message: {usrMsg.Content}");
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// catch (Exception ex) { _log.Warn(ex, "Error in cleverbot"); }
|
|
||||||
// return false;
|
|
||||||
//}
|
|
||||||
////todo blacklisting
|
|
||||||
//private bool IsBlacklisted(IGuild guild, IUserMessage usrMsg) =>
|
|
||||||
// (guild != null && BlacklistCommands.BlacklistedGuilds.Contains(guild.Id)) ||
|
|
||||||
// BlacklistCommands.BlacklistedChannels.Contains(usrMsg.Channel.Id) ||
|
|
||||||
// BlacklistCommands.BlacklistedUsers.Contains(usrMsg.Author.Id);
|
|
||||||
|
|
||||||
private const float _oneThousandth = 1.0f / 1000;
|
private const float _oneThousandth = 1.0f / 1000;
|
||||||
|
|
||||||
private Task LogSuccessfulExecution(IUserMessage usrMsg, bool exec, ITextChannel channel, params int[] execPoints)
|
private Task LogSuccessfulExecution(IUserMessage usrMsg, bool exec, ITextChannel channel, params int[] execPoints)
|
||||||
@ -233,166 +145,66 @@ namespace NadekoBot.Services
|
|||||||
//exec.Result.ErrorReason // {4}
|
//exec.Result.ErrorReason // {4}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
////todo invite filtering
|
|
||||||
//private async Task<bool> InviteFiltered(IGuild guild, IUserMessage usrMsg)
|
|
||||||
//{
|
|
||||||
// if ((Permissions.FilterCommands.InviteFilteringChannels.Contains(usrMsg.Channel.Id) ||
|
|
||||||
// Permissions.FilterCommands.InviteFilteringServers.Contains(guild.Id)) &&
|
|
||||||
// usrMsg.Content.IsDiscordInvite())
|
|
||||||
// {
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// await usrMsg.DeleteAsync().ConfigureAwait(false);
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// catch (HttpException ex)
|
|
||||||
// {
|
|
||||||
// _log.Warn("I do not have permission to filter invites in channel with id " + usrMsg.Channel.Id, ex);
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return false;
|
|
||||||
//}
|
|
||||||
|
|
||||||
////todo word filtering
|
private async Task MessageReceivedHandler(SocketMessage msg)
|
||||||
//private async Task<bool> WordFiltered(IGuild guild, IUserMessage usrMsg)
|
|
||||||
//{
|
|
||||||
// var filteredChannelWords = Permissions.FilterCommands.FilteredWordsForChannel(usrMsg.Channel.Id, guild.Id) ?? new ConcurrentHashSet<string>();
|
|
||||||
// var filteredServerWords = Permissions.FilterCommands.FilteredWordsForServer(guild.Id) ?? new ConcurrentHashSet<string>();
|
|
||||||
// var wordsInMessage = usrMsg.Content.ToLowerInvariant().Split(' ');
|
|
||||||
// if (filteredChannelWords.Count != 0 || filteredServerWords.Count != 0)
|
|
||||||
// {
|
|
||||||
// foreach (var word in wordsInMessage)
|
|
||||||
// {
|
|
||||||
// if (filteredChannelWords.Contains(word) ||
|
|
||||||
// filteredServerWords.Contains(word))
|
|
||||||
// {
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// await usrMsg.DeleteAsync().ConfigureAwait(false);
|
|
||||||
// }
|
|
||||||
// catch (HttpException ex)
|
|
||||||
// {
|
|
||||||
// _log.Warn("I do not have permission to filter words in channel with id " + usrMsg.Channel.Id, ex);
|
|
||||||
// }
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return false;
|
|
||||||
//}
|
|
||||||
|
|
||||||
private Task MessageReceivedHandler(SocketMessage msg)
|
|
||||||
{
|
{
|
||||||
var _ = Task.Run(async () =>
|
await Task.Yield();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
try
|
if (msg.Author.IsBot || !_bot.Ready) //no bots, wait until bot connected and initialized
|
||||||
{
|
return;
|
||||||
if (msg.Author.IsBot || !_bot.Ready) //no bots, wait until bot connected and initialized
|
|
||||||
return;
|
|
||||||
|
|
||||||
var usrMsg = msg as SocketUserMessage;
|
if (!(msg is SocketUserMessage usrMsg))
|
||||||
if (usrMsg == null) //has to be an user message, not system/other messages.
|
return;
|
||||||
return;
|
|
||||||
|
|
||||||
if (usrMsg.Author.Id == 193022505026453504)
|
|
||||||
return;
|
|
||||||
#if !GLOBAL_NADEKO
|
#if !GLOBAL_NADEKO
|
||||||
// track how many messagges each user is sending
|
// track how many messagges each user is sending
|
||||||
UserMessagesSent.AddOrUpdate(usrMsg.Author.Id, 1, (key, old) => ++old);
|
UserMessagesSent.AddOrUpdate(usrMsg.Author.Id, 1, (key, old) => ++old);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var channel = msg.Channel as SocketTextChannel;
|
var channel = msg.Channel as ISocketMessageChannel;
|
||||||
var guild = channel?.Guild;
|
var guild = (msg.Channel as SocketTextChannel)?.Guild;
|
||||||
|
|
||||||
await TryRunCommand(guild, channel, usrMsg);
|
await TryRunCommand(guild, channel, usrMsg);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_log.Warn("Error in CommandHandler");
|
||||||
|
_log.Warn(ex);
|
||||||
|
if (ex.InnerException != null)
|
||||||
{
|
{
|
||||||
_log.Warn("Error in CommandHandler");
|
_log.Warn("Inner Exception of the error in CommandHandler");
|
||||||
_log.Warn(ex);
|
_log.Warn(ex.InnerException);
|
||||||
if (ex.InnerException != null)
|
|
||||||
{
|
|
||||||
_log.Warn("Inner Exception of the error in CommandHandler");
|
|
||||||
_log.Warn(ex.InnerException);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task TryRunCommand(SocketGuild guild, ITextChannel channel, IUserMessage usrMsg)
|
public async Task TryRunCommand(SocketGuild guild, ISocketMessageChannel channel, IUserMessage usrMsg)
|
||||||
{
|
{
|
||||||
var execTime = Environment.TickCount;
|
var execTime = Environment.TickCount;
|
||||||
|
|
||||||
foreach (var svc in _services)
|
foreach (var svc in _services)
|
||||||
{
|
{
|
||||||
if (svc is IBlockingExecutor _executor &&
|
if (svc is IEarlyBlocker blocker &&
|
||||||
await _executor.TryExecute(_client, guild, usrMsg))
|
await blocker.TryBlockEarly(_client, guild, usrMsg).ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
_log.Info("Blocked User: [{0}] Message: [{1}] Service: [{2}]", usrMsg.Author, usrMsg.Content, svc.GetType().Name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var exec2 = Environment.TickCount - execTime;
|
||||||
|
|
||||||
|
|
||||||
|
foreach (var svc in _services)
|
||||||
|
{
|
||||||
|
if (svc is IEarlyBlockingExecutor exec &&
|
||||||
|
await exec.TryExecuteEarly(_client, guild, usrMsg).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
_log.Info("User [{0}] executed [{1}] in [{2}]", usrMsg.Author, usrMsg.Content, svc.GetType().Name);
|
_log.Info("User [{0}] executed [{1}] in [{2}]", usrMsg.Author, usrMsg.Content, svc.GetType().Name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////todo word and invite filtering
|
|
||||||
//if (guild != null && guild.OwnerId != usrMsg.Author.Id)
|
|
||||||
//{
|
|
||||||
// if (await InviteFiltered(guild, usrMsg).ConfigureAwait(false))
|
|
||||||
// return;
|
|
||||||
|
|
||||||
// if (await WordFiltered(guild, usrMsg).ConfigureAwait(false))
|
|
||||||
// return;
|
|
||||||
//}
|
|
||||||
|
|
||||||
////todo blacklisting
|
|
||||||
//if (IsBlacklisted(guild, usrMsg))
|
|
||||||
// return;
|
|
||||||
|
|
||||||
//var cleverBotRan = await Task.Run(() => TryRunCleverbot(usrMsg, guild)).ConfigureAwait(false);
|
|
||||||
//if (cleverBotRan)
|
|
||||||
// return;
|
|
||||||
|
|
||||||
var exec2 = Environment.TickCount - execTime;
|
|
||||||
|
|
||||||
////todo custom reactions
|
|
||||||
//// maybe this message is a custom reaction
|
|
||||||
//// todo log custom reaction executions. return struct with info
|
|
||||||
//var cr = await Task.Run(() => CustomReactions.TryGetCustomReaction(usrMsg)).ConfigureAwait(false);
|
|
||||||
//if (cr != null) //if it was, don't execute the command
|
|
||||||
//{
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// if (guild != null)
|
|
||||||
// {
|
|
||||||
// PermissionCache pc = Permissions.GetCache(guild.Id);
|
|
||||||
|
|
||||||
// if (!pc.Permissions.CheckPermissions(usrMsg, cr.Trigger, "ActualCustomReactions",
|
|
||||||
// out int index))
|
|
||||||
// {
|
|
||||||
// //todo print in guild actually
|
|
||||||
// var returnMsg =
|
|
||||||
// $"Permission number #{index + 1} **{pc.Permissions[index].GetCommand(guild)}** is preventing this action.";
|
|
||||||
// _log.Info(returnMsg);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// await cr.Send(usrMsg).ConfigureAwait(false);
|
|
||||||
|
|
||||||
// if (cr.AutoDeleteTrigger)
|
|
||||||
// {
|
|
||||||
// try { await usrMsg.DeleteAsync().ConfigureAwait(false); } catch { }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// _log.Warn("Sending CREmbed failed");
|
|
||||||
// _log.Warn(ex);
|
|
||||||
// }
|
|
||||||
// return;
|
|
||||||
//}
|
|
||||||
|
|
||||||
var exec3 = Environment.TickCount - execTime;
|
var exec3 = Environment.TickCount - execTime;
|
||||||
|
|
||||||
string messageContent = usrMsg.Content;
|
string messageContent = usrMsg.Content;
|
||||||
@ -436,13 +248,13 @@ namespace NadekoBot.Services
|
|||||||
var exec = await Task.Run(() => ExecuteCommandAsync(new CommandContext(_client, usrMsg), NadekoBot.Prefix.Length, _services, MultiMatchHandling.Best)).ConfigureAwait(false);
|
var exec = await Task.Run(() => ExecuteCommandAsync(new CommandContext(_client, usrMsg), NadekoBot.Prefix.Length, _services, MultiMatchHandling.Best)).ConfigureAwait(false);
|
||||||
execTime = Environment.TickCount - execTime;
|
execTime = Environment.TickCount - execTime;
|
||||||
|
|
||||||
////todo permissions
|
////todo commandHandler
|
||||||
//if (exec.Result.IsSuccess)
|
if (exec)
|
||||||
//{
|
{
|
||||||
// await CommandExecuted(usrMsg, exec.CommandInfo).ConfigureAwait(false);
|
// await CommandExecuted(usrMsg, exec.CommandInfo).ConfigureAwait(false);
|
||||||
// await LogSuccessfulExecution(usrMsg, exec, channel, exec2, exec3, execTime).ConfigureAwait(false);
|
await LogSuccessfulExecution(usrMsg, exec, channel as ITextChannel, exec2, exec3, execTime).ConfigureAwait(false);
|
||||||
// return;
|
return;
|
||||||
//}
|
}
|
||||||
//else if (!exec.Result.IsSuccess && exec.Result.Error != CommandError.UnknownCommand)
|
//else if (!exec.Result.IsSuccess && exec.Result.Error != CommandError.UnknownCommand)
|
||||||
//{
|
//{
|
||||||
// LogErroredExecution(usrMsg, exec, channel, exec2, exec3, execTime);
|
// LogErroredExecution(usrMsg, exec, channel, exec2, exec3, execTime);
|
||||||
@ -453,20 +265,20 @@ namespace NadekoBot.Services
|
|||||||
// }
|
// }
|
||||||
// return;
|
// return;
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
if (exec)
|
||||||
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usrMsg.Channel is IPrivateChannel)
|
foreach (var svc in _services)
|
||||||
{
|
{
|
||||||
// rofl, gotta do this to prevent dm help message being sent to
|
if (svc is ILateExecutor exec)
|
||||||
// users who are voting on private polls (sending a number in a DM)
|
{
|
||||||
if (int.TryParse(usrMsg.Content, out int vote)) return;
|
await exec.LateExecute(_client, guild, usrMsg).ConfigureAwait(false);
|
||||||
|
}
|
||||||
////todo help
|
|
||||||
//await usrMsg.Channel.SendMessageAsync(Help.DMHelpString).ConfigureAwait(false);
|
|
||||||
|
|
||||||
////todo selfcommands
|
|
||||||
//await SelfCommands.HandleDmForwarding(usrMsg, ownerChannels).ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<bool> ExecuteCommandAsync(CommandContext context, int argPos, IServiceProvider serviceProvider, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception)
|
public Task<bool> ExecuteCommandAsync(CommandContext context, int argPos, IServiceProvider serviceProvider, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception)
|
||||||
@ -540,16 +352,16 @@ namespace NadekoBot.Services
|
|||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
|
|
||||||
////////future
|
//////future
|
||||||
//////int price;
|
////int price;
|
||||||
//////if (Permissions.CommandCostCommands.CommandCosts.TryGetValue(cmd.Aliases.First().Trim().ToLowerInvariant(), out price) && price > 0)
|
////if (Permissions.CommandCostCommands.CommandCosts.TryGetValue(cmd.Aliases.First().Trim().ToLowerInvariant(), out price) && price > 0)
|
||||||
//////{
|
////{
|
||||||
////// var success = await _ch.RemoveCurrencyAsync(context.User.Id, $"Running {cmd.Name} command.", price).ConfigureAwait(false);
|
//// var success = await _cs.RemoveCurrencyAsync(context.User.Id, $"Running {cmd.Name} command.", price).ConfigureAwait(false);
|
||||||
////// if (!success)
|
//// if (!success)
|
||||||
////// {
|
//// {
|
||||||
////// return new ExecuteCommandResult(cmd, pc, SearchResult.FromError(CommandError.Exception, $"Insufficient funds. You need {price}{NadekoBot.BotConfig.CurrencySign} to run this command."));
|
//// return new ExecuteCommandResult(cmd, pc, SearchResult.FromError(CommandError.Exception, $"Insufficient funds. You need {price}{NadekoBot.BotConfig.CurrencySign} to run this command."));
|
||||||
////// }
|
//// }
|
||||||
//////}
|
////}
|
||||||
}
|
}
|
||||||
|
|
||||||
////todo perms
|
////todo perms
|
||||||
@ -564,11 +376,18 @@ namespace NadekoBot.Services
|
|||||||
// GlobalCommandsCooldown constant (miliseconds)
|
// GlobalCommandsCooldown constant (miliseconds)
|
||||||
if (!UsersOnShortCooldown.Add(context.Message.Author.Id))
|
if (!UsersOnShortCooldown.Add(context.Message.Author.Id))
|
||||||
return false;
|
return false;
|
||||||
//return SearchResult.FromError(CommandError.Exception, "You are on a global cooldown.");
|
//return SearchResult.FromError(CommandError.Exception, "You are on a global cooldown.");
|
||||||
|
|
||||||
////todo cmdcds
|
var commandName = cmd.Aliases.First();
|
||||||
//if (CmdCdsCommands.HasCooldown(cmd, context.Guild, context.User))
|
foreach (var svc in _services)
|
||||||
// return new ExecuteCommandResult(cmd, null, SearchResult.FromError(CommandError.Exception, "That command is on a cooldown for you."));
|
{
|
||||||
|
if (svc is ILateBlocker exec &&
|
||||||
|
await exec.TryBlockLate(_client, context.Message, context.Guild, context.Channel, context.User, cmd.Module.GetTopLevelModule().Name, commandName).ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
_log.Info("Late blocking User [{0}] Command: [{1}] in [{2}]", context.User, commandName, svc.GetType().Name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await commands[i].ExecuteAsync(context, parseResult, serviceProvider);
|
await commands[i].ExecuteAsync(context, parseResult, serviceProvider);
|
||||||
return true;
|
return true;
|
||||||
|
@ -7,20 +7,20 @@ using NadekoBot.Services.Database;
|
|||||||
|
|
||||||
namespace NadekoBot.Services
|
namespace NadekoBot.Services
|
||||||
{
|
{
|
||||||
public class CurrencyHandler
|
public class CurrencyService
|
||||||
{
|
{
|
||||||
private readonly BotConfig _config;
|
private readonly BotConfig _config;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public CurrencyHandler(BotConfig config, DbHandler db)
|
public CurrencyService(BotConfig config, DbService db)
|
||||||
{
|
{
|
||||||
_config = config;
|
_config = config;
|
||||||
_db = db;
|
_db = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> RemoveCurrencyAsync(IUser author, string reason, long amount, bool sendMessage)
|
public async Task<bool> RemoveAsync(IUser author, string reason, long amount, bool sendMessage)
|
||||||
{
|
{
|
||||||
var success = await RemoveCurrencyAsync(author.Id, reason, amount);
|
var success = await RemoveAsync(author.Id, reason, amount);
|
||||||
|
|
||||||
if (success && sendMessage)
|
if (success && sendMessage)
|
||||||
try { await author.SendErrorAsync($"`You lost:` {amount} {_config.CurrencySign}\n`Reason:` {reason}").ConfigureAwait(false); } catch { }
|
try { await author.SendErrorAsync($"`You lost:` {amount} {_config.CurrencySign}\n`Reason:` {reason}").ConfigureAwait(false); } catch { }
|
||||||
@ -28,12 +28,11 @@ namespace NadekoBot.Services
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> RemoveCurrencyAsync(ulong authorId, string reason, long amount, IUnitOfWork uow = null)
|
public async Task<bool> RemoveAsync(ulong authorId, string reason, long amount, IUnitOfWork uow = null)
|
||||||
{
|
{
|
||||||
if (amount < 0)
|
if (amount < 0)
|
||||||
throw new ArgumentNullException(nameof(amount));
|
throw new ArgumentNullException(nameof(amount));
|
||||||
|
|
||||||
|
|
||||||
if (uow == null)
|
if (uow == null)
|
||||||
{
|
{
|
||||||
using (uow = _db.UnitOfWork)
|
using (uow = _db.UnitOfWork)
|
||||||
@ -61,15 +60,15 @@ namespace NadekoBot.Services
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task AddCurrencyAsync(IUser author, string reason, long amount, bool sendMessage)
|
public async Task AddAsync(IUser author, string reason, long amount, bool sendMessage)
|
||||||
{
|
{
|
||||||
await AddCurrencyAsync(author.Id, reason, amount);
|
await AddAsync(author.Id, reason, amount);
|
||||||
|
|
||||||
if (sendMessage)
|
if (sendMessage)
|
||||||
try { await author.SendConfirmAsync($"`You received:` {amount} {_config.CurrencySign}\n`Reason:` {reason}").ConfigureAwait(false); } catch { }
|
try { await author.SendConfirmAsync($"`You received:` {amount} {_config.CurrencySign}\n`Reason:` {reason}").ConfigureAwait(false); } catch { }
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task AddCurrencyAsync(ulong receiverId, string reason, long amount, IUnitOfWork uow = null)
|
public async Task AddAsync(ulong receiverId, string reason, long amount, IUnitOfWork uow = null)
|
||||||
{
|
{
|
||||||
if (amount < 0)
|
if (amount < 0)
|
||||||
throw new ArgumentNullException(nameof(amount));
|
throw new ArgumentNullException(nameof(amount));
|
||||||
|
@ -11,7 +11,7 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace NadekoBot.Services.CustomReactions
|
namespace NadekoBot.Services.CustomReactions
|
||||||
{
|
{
|
||||||
public class CustomReactionsService : IBlockingExecutor
|
public class CustomReactionsService : IEarlyBlockingExecutor
|
||||||
{
|
{
|
||||||
public CustomReaction[] GlobalReactions = new CustomReaction[] { };
|
public CustomReaction[] GlobalReactions = new CustomReaction[] { };
|
||||||
public ConcurrentDictionary<ulong, CustomReaction[]> GuildReactions { get; } = new ConcurrentDictionary<ulong, CustomReaction[]>();
|
public ConcurrentDictionary<ulong, CustomReaction[]> GuildReactions { get; } = new ConcurrentDictionary<ulong, CustomReaction[]>();
|
||||||
@ -19,10 +19,10 @@ namespace NadekoBot.Services.CustomReactions
|
|||||||
public ConcurrentDictionary<string, uint> ReactionStats { get; } = new ConcurrentDictionary<string, uint>();
|
public ConcurrentDictionary<string, uint> ReactionStats { get; } = new ConcurrentDictionary<string, uint>();
|
||||||
|
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordShardedClient _client;
|
||||||
|
|
||||||
public CustomReactionsService(DbHandler db, DiscordShardedClient client)
|
public CustomReactionsService(DbService db, DiscordShardedClient client)
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_db = db;
|
_db = db;
|
||||||
@ -90,16 +90,15 @@ namespace NadekoBot.Services.CustomReactions
|
|||||||
return greaction;
|
return greaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> TryExecute(DiscordShardedClient client, IGuild guild, IUserMessage msg)
|
public async Task<bool> TryExecuteEarly(DiscordShardedClient client, IGuild guild, IUserMessage msg)
|
||||||
{
|
{
|
||||||
//todo custom reactions
|
|
||||||
// maybe this message is a custom reaction
|
// maybe this message is a custom reaction
|
||||||
// todo log custom reaction executions. return struct with info
|
|
||||||
var cr = await Task.Run(() => TryGetCustomReaction(msg)).ConfigureAwait(false);
|
var cr = await Task.Run(() => TryGetCustomReaction(msg)).ConfigureAwait(false);
|
||||||
if (cr != null) //if it was, don't execute the command
|
if (cr != null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
//todo permissions
|
||||||
//if (guild != null)
|
//if (guild != null)
|
||||||
//{
|
//{
|
||||||
// PermissionCache pc = Permissions.GetCache(guild.Id);
|
// PermissionCache pc = Permissions.GetCache(guild.Id);
|
||||||
@ -107,7 +106,6 @@ namespace NadekoBot.Services.CustomReactions
|
|||||||
// if (!pc.Permissions.CheckPermissions(usrMsg, cr.Trigger, "ActualCustomReactions",
|
// if (!pc.Permissions.CheckPermissions(usrMsg, cr.Trigger, "ActualCustomReactions",
|
||||||
// out int index))
|
// out int index))
|
||||||
// {
|
// {
|
||||||
// //todo print in guild actually
|
|
||||||
// var returnMsg =
|
// var returnMsg =
|
||||||
// $"Permission number #{index + 1} **{pc.Permissions[index].GetCommand(guild)}** is preventing this action.";
|
// $"Permission number #{index + 1} **{pc.Permissions[index].GetCommand(guild)}** is preventing this action.";
|
||||||
// _log.Info(returnMsg);
|
// _log.Info(returnMsg);
|
||||||
|
@ -64,6 +64,7 @@ Nadeko Support Server: https://discord.gg/nadekobot";
|
|||||||
public List<StartupCommand> StartupCommands { get; set; }
|
public List<StartupCommand> StartupCommands { get; set; }
|
||||||
public HashSet<BlockedCmdOrMdl> BlockedCommands { get; set; }
|
public HashSet<BlockedCmdOrMdl> BlockedCommands { get; set; }
|
||||||
public HashSet<BlockedCmdOrMdl> BlockedModules { get; set; }
|
public HashSet<BlockedCmdOrMdl> BlockedModules { get; set; }
|
||||||
|
public int PermissionVersion { get; set; } = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BlockedCmdOrMdl : DbEntity
|
public class BlockedCmdOrMdl : DbEntity
|
||||||
|
@ -126,10 +126,6 @@ namespace NadekoBot.Services.Database.Repositories.Impl
|
|||||||
.Where(gc => gc.RootPermission != null)
|
.Where(gc => gc.RootPermission != null)
|
||||||
.Include(gc => gc.RootPermission);
|
.Include(gc => gc.RootPermission);
|
||||||
|
|
||||||
//todo this is possibly a disaster for performance
|
|
||||||
//What i could do instead is count the number of permissions in the permission table for this guild
|
|
||||||
// and make a for loop with those.
|
|
||||||
// or just select permissions for this guild and manually chain them
|
|
||||||
for (int i = 0; i < 60; i++)
|
for (int i = 0; i < 60; i++)
|
||||||
{
|
{
|
||||||
query = query.ThenInclude(gc => gc.Next);
|
query = query.ThenInclude(gc => gc.Next);
|
||||||
|
@ -3,17 +3,15 @@ using NadekoBot.Services.Database;
|
|||||||
|
|
||||||
namespace NadekoBot.Services
|
namespace NadekoBot.Services
|
||||||
{
|
{
|
||||||
public class DbHandler
|
public class DbService
|
||||||
{
|
{
|
||||||
private readonly DbContextOptions options;
|
private readonly DbContextOptions options;
|
||||||
|
|
||||||
private string connectionString { get; }
|
private readonly string _connectionString;
|
||||||
|
|
||||||
static DbHandler() { }
|
public DbService(IBotCredentials creds)
|
||||||
|
|
||||||
public DbHandler(IBotCredentials creds)
|
|
||||||
{
|
{
|
||||||
connectionString = creds.Db.ConnectionString;
|
_connectionString = creds.Db.ConnectionString;
|
||||||
var optionsBuilder = new DbContextOptionsBuilder();
|
var optionsBuilder = new DbContextOptionsBuilder();
|
||||||
optionsBuilder.UseSqlite(creds.Db.ConnectionString);
|
optionsBuilder.UseSqlite(creds.Db.ConnectionString);
|
||||||
options = optionsBuilder.Options;
|
options = optionsBuilder.Options;
|
||||||
|
120
src/NadekoBot/Services/Games/ChatterbotService.cs
Normal file
120
src/NadekoBot/Services/Games/ChatterbotService.cs
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
using Discord;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using NadekoBot.DataStructures.ModuleBehaviors;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
|
using NadekoBot.Services.Database.Models;
|
||||||
|
using NLog;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NadekoBot.Services.Games
|
||||||
|
{
|
||||||
|
public class ChatterBotService : IEarlyBlockingExecutor
|
||||||
|
{
|
||||||
|
private readonly DiscordShardedClient _client;
|
||||||
|
private readonly Logger _log;
|
||||||
|
|
||||||
|
public ConcurrentDictionary<ulong, Lazy<ChatterBotSession>> ChatterBotGuilds { get; }
|
||||||
|
|
||||||
|
public ChatterBotService(DiscordShardedClient client, IEnumerable<GuildConfig> gcs)
|
||||||
|
{
|
||||||
|
_client = client;
|
||||||
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
|
ChatterBotGuilds = new ConcurrentDictionary<ulong, Lazy<ChatterBotSession>>(
|
||||||
|
gcs.Where(gc => gc.CleverbotEnabled)
|
||||||
|
.ToDictionary(gc => gc.GuildId, gc => new Lazy<ChatterBotSession>(() => new ChatterBotSession(gc.GuildId), true)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public string PrepareMessage(IUserMessage msg, out ChatterBotSession cleverbot)
|
||||||
|
{
|
||||||
|
var channel = msg.Channel as ITextChannel;
|
||||||
|
cleverbot = null;
|
||||||
|
|
||||||
|
if (channel == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (!ChatterBotGuilds.TryGetValue(channel.Guild.Id, out Lazy<ChatterBotSession> lazyCleverbot))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
cleverbot = lazyCleverbot.Value;
|
||||||
|
|
||||||
|
var nadekoId = _client.CurrentUser.Id;
|
||||||
|
var normalMention = $"<@{nadekoId}> ";
|
||||||
|
var nickMention = $"<@!{nadekoId}> ";
|
||||||
|
string message;
|
||||||
|
if (msg.Content.StartsWith(normalMention))
|
||||||
|
{
|
||||||
|
message = msg.Content.Substring(normalMention.Length).Trim();
|
||||||
|
}
|
||||||
|
else if (msg.Content.StartsWith(nickMention))
|
||||||
|
{
|
||||||
|
message = msg.Content.Substring(nickMention.Length).Trim();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> TryAsk(ChatterBotSession cleverbot, ITextChannel channel, string message)
|
||||||
|
{
|
||||||
|
await channel.TriggerTypingAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
var response = await cleverbot.Think(message).ConfigureAwait(false);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await channel.SendConfirmAsync(response.SanitizeMentions()).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
await channel.SendConfirmAsync(response.SanitizeMentions()).ConfigureAwait(false); // try twice :\
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> TryExecuteEarly(DiscordShardedClient client, IGuild guild, IUserMessage usrMsg)
|
||||||
|
{
|
||||||
|
if (guild == null)
|
||||||
|
return false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var message = PrepareMessage(usrMsg, out ChatterBotSession cbs);
|
||||||
|
if (message == null || cbs == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
//todo permissions
|
||||||
|
//PermissionCache pc = Permissions.GetCache(guild.Id);
|
||||||
|
//if (!pc.Permissions.CheckPermissions(usrMsg,
|
||||||
|
// NadekoBot.Prefix + "cleverbot",
|
||||||
|
// "Games".ToLowerInvariant(),
|
||||||
|
// out int index))
|
||||||
|
//{
|
||||||
|
// //todo print in guild actually
|
||||||
|
// var returnMsg =
|
||||||
|
// $"Permission number #{index + 1} **{pc.Permissions[index].GetCommand(guild)}** is preventing this action.";
|
||||||
|
// _log.Info(returnMsg);
|
||||||
|
// return true;
|
||||||
|
//}
|
||||||
|
|
||||||
|
var cleverbotExecuted = await TryAsk(cbs, (ITextChannel)usrMsg.Channel, message).ConfigureAwait(false);
|
||||||
|
if (cleverbotExecuted)
|
||||||
|
{
|
||||||
|
_log.Info($@"CleverBot Executed
|
||||||
|
Server: {guild.Name} [{guild.Id}]
|
||||||
|
Channel: {usrMsg.Channel?.Name} [{usrMsg.Channel?.Id}]
|
||||||
|
UserId: {usrMsg.Author} [{usrMsg.Author.Id}]
|
||||||
|
Message: {usrMsg.Content}");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex) { _log.Warn(ex, "Error in cleverbot"); }
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -28,8 +28,6 @@ namespace NadekoBot.Services.Games
|
|||||||
private readonly IImagesService _images;
|
private readonly IImagesService _images;
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
|
|
||||||
public ConcurrentDictionary<ulong, Lazy<ChatterBotSession>> CleverbotGuilds { get; }
|
|
||||||
|
|
||||||
public readonly string TypingArticlesPath = "data/typing_articles2.json";
|
public readonly string TypingArticlesPath = "data/typing_articles2.json";
|
||||||
public List<TypingArticle> TypingArticles { get; } = new List<TypingArticle>();
|
public List<TypingArticle> TypingArticles { get; } = new List<TypingArticle>();
|
||||||
|
|
||||||
@ -52,11 +50,6 @@ namespace NadekoBot.Services.Games
|
|||||||
|
|
||||||
}, null, TimeSpan.FromDays(1), TimeSpan.FromDays(1));
|
}, null, TimeSpan.FromDays(1), TimeSpan.FromDays(1));
|
||||||
|
|
||||||
//cleverbot
|
|
||||||
CleverbotGuilds = new ConcurrentDictionary<ulong, Lazy<ChatterBotSession>>(
|
|
||||||
gcs.Where(gc => gc.CleverbotEnabled)
|
|
||||||
.ToDictionary(gc => gc.GuildId, gc => new Lazy<ChatterBotSession>(() => new ChatterBotSession(gc.GuildId), true)));
|
|
||||||
|
|
||||||
//plantpick
|
//plantpick
|
||||||
client.MessageReceived += PotentialFlowerGeneration;
|
client.MessageReceived += PotentialFlowerGeneration;
|
||||||
GenerationChannels = new ConcurrentHashSet<ulong>(gcs
|
GenerationChannels = new ConcurrentHashSet<ulong>(gcs
|
||||||
@ -73,55 +66,15 @@ namespace NadekoBot.Services.Games
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AddTypingArticle(IUser user, string text)
|
||||||
public string PrepareMessage(IUserMessage msg, out ChatterBotSession cleverbot)
|
|
||||||
{
|
{
|
||||||
var channel = msg.Channel as ITextChannel;
|
TypingArticles.Add(new TypingArticle
|
||||||
cleverbot = null;
|
|
||||||
|
|
||||||
if (channel == null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
Lazy<ChatterBotSession> lazyCleverbot;
|
|
||||||
if (!CleverbotGuilds.TryGetValue(channel.Guild.Id, out lazyCleverbot))
|
|
||||||
return null;
|
|
||||||
|
|
||||||
cleverbot = lazyCleverbot.Value;
|
|
||||||
|
|
||||||
var nadekoId = _client.CurrentUser.Id;
|
|
||||||
var normalMention = $"<@{nadekoId}> ";
|
|
||||||
var nickMention = $"<@!{nadekoId}> ";
|
|
||||||
string message;
|
|
||||||
if (msg.Content.StartsWith(normalMention))
|
|
||||||
{
|
{
|
||||||
message = msg.Content.Substring(normalMention.Length).Trim();
|
Title = $"Text added on {DateTime.UtcNow} by {user}",
|
||||||
}
|
Text = text.SanitizeMentions(),
|
||||||
else if (msg.Content.StartsWith(nickMention))
|
});
|
||||||
{
|
|
||||||
message = msg.Content.Substring(nickMention.Length).Trim();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return message;
|
File.WriteAllText(TypingArticlesPath, JsonConvert.SerializeObject(TypingArticles));
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> TryAsk(ChatterBotSession cleverbot, ITextChannel channel, string message)
|
|
||||||
{
|
|
||||||
await channel.TriggerTypingAsync().ConfigureAwait(false);
|
|
||||||
|
|
||||||
var response = await cleverbot.Think(message).ConfigureAwait(false);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await channel.SendConfirmAsync(response.SanitizeMentions()).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
await channel.SendConfirmAsync(response.SanitizeMentions()).ConfigureAwait(false); // try twice :\
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConcurrentHashSet<ulong> GenerationChannels { get; }
|
public ConcurrentHashSet<ulong> GenerationChannels { get; }
|
||||||
@ -130,7 +83,9 @@ namespace NadekoBot.Services.Games
|
|||||||
//channelId/last generation
|
//channelId/last generation
|
||||||
public ConcurrentDictionary<ulong, DateTime> LastGenerations { get; } = new ConcurrentDictionary<ulong, DateTime>();
|
public ConcurrentDictionary<ulong, DateTime> LastGenerations { get; } = new ConcurrentDictionary<ulong, DateTime>();
|
||||||
|
|
||||||
public KeyValuePair<string, ImmutableArray<byte>> GetRandomCurrencyImage()
|
private ConcurrentDictionary<ulong, object> _locks { get; } = new ConcurrentDictionary<ulong, object>();
|
||||||
|
|
||||||
|
public (string Name, ImmutableArray<byte> Data) GetRandomCurrencyImage()
|
||||||
{
|
{
|
||||||
var rng = new NadekoRandom();
|
var rng = new NadekoRandom();
|
||||||
return _images.Currency[rng.Next(0, _images.Currency.Length)];
|
return _images.Currency[rng.Next(0, _images.Currency.Length)];
|
||||||
@ -139,68 +94,61 @@ namespace NadekoBot.Services.Games
|
|||||||
private string GetText(ITextChannel ch, string key, params object[] rep)
|
private string GetText(ITextChannel ch, string key, params object[] rep)
|
||||||
=> _strings.GetText(key, ch.GuildId, "Games".ToLowerInvariant(), rep);
|
=> _strings.GetText(key, ch.GuildId, "Games".ToLowerInvariant(), rep);
|
||||||
|
|
||||||
private Task PotentialFlowerGeneration(SocketMessage imsg)
|
private async Task PotentialFlowerGeneration(SocketMessage imsg)
|
||||||
{
|
{
|
||||||
var msg = imsg as SocketUserMessage;
|
var msg = imsg as SocketUserMessage;
|
||||||
if (msg == null || msg.Author.IsBot)
|
if (msg == null || msg.Author.IsBot)
|
||||||
return Task.CompletedTask;
|
return;
|
||||||
|
|
||||||
var channel = imsg.Channel as ITextChannel;
|
var channel = imsg.Channel as ITextChannel;
|
||||||
if (channel == null)
|
if (channel == null)
|
||||||
return Task.CompletedTask;
|
return;
|
||||||
|
|
||||||
if (!GenerationChannels.Contains(channel.Id))
|
if (!GenerationChannels.Contains(channel.Id))
|
||||||
return Task.CompletedTask;
|
return;
|
||||||
|
|
||||||
var _ = Task.Run(async () =>
|
try
|
||||||
{
|
{
|
||||||
try
|
var lastGeneration = LastGenerations.GetOrAdd(channel.Id, DateTime.MinValue);
|
||||||
|
var rng = new NadekoRandom();
|
||||||
|
|
||||||
|
if (DateTime.Now - TimeSpan.FromSeconds(_bc.CurrencyGenerationCooldown) < lastGeneration) //recently generated in this channel, don't generate again
|
||||||
|
return;
|
||||||
|
|
||||||
|
var num = rng.Next(1, 101) + _bc.CurrencyGenerationChance * 100;
|
||||||
|
if (num > 100 && LastGenerations.TryUpdate(channel.Id, DateTime.Now, lastGeneration))
|
||||||
{
|
{
|
||||||
var lastGeneration = LastGenerations.GetOrAdd(channel.Id, DateTime.MinValue);
|
var dropAmount = _bc.CurrencyDropAmount;
|
||||||
var rng = new NadekoRandom();
|
|
||||||
|
|
||||||
//todo i'm stupid :rofl: wtg kwoth. real async programming :100: :ok_hand: :100: :100: :thumbsup:
|
if (dropAmount > 0)
|
||||||
if (DateTime.Now - TimeSpan.FromSeconds(_bc.CurrencyGenerationCooldown) < lastGeneration) //recently generated in this channel, don't generate again
|
|
||||||
return;
|
|
||||||
|
|
||||||
var num = rng.Next(1, 101) + _bc.CurrencyGenerationChance * 100;
|
|
||||||
|
|
||||||
if (num > 100)
|
|
||||||
{
|
{
|
||||||
LastGenerations.AddOrUpdate(channel.Id, DateTime.Now, (id, old) => DateTime.Now);
|
var msgs = new IUserMessage[dropAmount];
|
||||||
|
var prefix = NadekoBot.Prefix;
|
||||||
var dropAmount = _bc.CurrencyDropAmount;
|
var toSend = dropAmount == 1
|
||||||
|
? GetText(channel, "curgen_sn", _bc.CurrencySign)
|
||||||
if (dropAmount > 0)
|
+ " " + GetText(channel, "pick_sn", prefix)
|
||||||
|
: GetText(channel, "curgen_pl", dropAmount, _bc.CurrencySign)
|
||||||
|
+ " " + GetText(channel, "pick_pl", prefix);
|
||||||
|
var file = GetRandomCurrencyImage();
|
||||||
|
using (var fileStream = file.Data.ToStream())
|
||||||
{
|
{
|
||||||
var msgs = new IUserMessage[dropAmount];
|
var sent = await channel.SendFileAsync(
|
||||||
var prefix = NadekoBot.Prefix;
|
fileStream,
|
||||||
var toSend = dropAmount == 1
|
file.Name,
|
||||||
? GetText(channel, "curgen_sn", _bc.CurrencySign)
|
toSend).ConfigureAwait(false);
|
||||||
+ " " + GetText(channel, "pick_sn", prefix)
|
|
||||||
: GetText(channel, "curgen_pl", dropAmount, _bc.CurrencySign)
|
|
||||||
+ " " + GetText(channel, "pick_pl", prefix);
|
|
||||||
var file = GetRandomCurrencyImage();
|
|
||||||
using (var fileStream = file.Value.ToStream())
|
|
||||||
{
|
|
||||||
var sent = await channel.SendFileAsync(
|
|
||||||
fileStream,
|
|
||||||
file.Key,
|
|
||||||
toSend).ConfigureAwait(false);
|
|
||||||
|
|
||||||
msgs[0] = sent;
|
msgs[0] = sent;
|
||||||
}
|
|
||||||
|
|
||||||
PlantedFlowers.AddOrUpdate(channel.Id, msgs.ToList(), (id, old) => { old.AddRange(msgs); return old; });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PlantedFlowers.AddOrUpdate(channel.Id, msgs.ToList(), (id, old) => { old.AddRange(msgs); return old; });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
}
|
||||||
{
|
catch (Exception ex)
|
||||||
LogManager.GetCurrentClassLogger().Warn(ex);
|
{
|
||||||
}
|
LogManager.GetCurrentClassLogger().Warn(ex);
|
||||||
});
|
}
|
||||||
return Task.CompletedTask;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
158
src/NadekoBot/Services/Games/Poll.cs
Normal file
158
src/NadekoBot/Services/Games/Poll.cs
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
using Discord;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NadekoBot.Services.Games
|
||||||
|
{
|
||||||
|
//todo 75 rewrite
|
||||||
|
public class Poll
|
||||||
|
{
|
||||||
|
private readonly IUserMessage _originalMessage;
|
||||||
|
private readonly IGuild _guild;
|
||||||
|
private string[] answers { get; }
|
||||||
|
private readonly ConcurrentDictionary<ulong, int> _participants = new ConcurrentDictionary<ulong, int>();
|
||||||
|
private readonly string _question;
|
||||||
|
private readonly DiscordShardedClient _client;
|
||||||
|
private readonly NadekoStrings _strings;
|
||||||
|
private bool running = false;
|
||||||
|
private HashSet<ulong> _guildUsers;
|
||||||
|
|
||||||
|
public event Action<ulong> OnEnded = delegate { };
|
||||||
|
|
||||||
|
public bool IsPublic { get; }
|
||||||
|
|
||||||
|
public Poll(DiscordShardedClient client, NadekoStrings strings, IUserMessage umsg, string question, IEnumerable<string> enumerable, bool isPublic = false)
|
||||||
|
{
|
||||||
|
_client = client;
|
||||||
|
_strings = strings;
|
||||||
|
|
||||||
|
_originalMessage = umsg;
|
||||||
|
_guild = ((ITextChannel)umsg.Channel).Guild;
|
||||||
|
_question = question;
|
||||||
|
answers = enumerable as string[] ?? enumerable.ToArray();
|
||||||
|
IsPublic = isPublic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EmbedBuilder GetStats(string title)
|
||||||
|
{
|
||||||
|
var results = _participants.GroupBy(kvp => kvp.Value)
|
||||||
|
.ToDictionary(x => x.Key, x => x.Sum(kvp => 1))
|
||||||
|
.OrderByDescending(kvp => kvp.Value)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
var eb = new EmbedBuilder().WithTitle(title);
|
||||||
|
|
||||||
|
var sb = new StringBuilder()
|
||||||
|
.AppendLine(Format.Bold(_question))
|
||||||
|
.AppendLine();
|
||||||
|
|
||||||
|
var totalVotesCast = 0;
|
||||||
|
if (results.Length == 0)
|
||||||
|
{
|
||||||
|
sb.AppendLine(GetText("no_votes_cast"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < results.Length; i++)
|
||||||
|
{
|
||||||
|
var result = results[i];
|
||||||
|
sb.AppendLine(GetText("poll_result",
|
||||||
|
result.Key,
|
||||||
|
Format.Bold(answers[result.Key - 1]),
|
||||||
|
Format.Bold(result.Value.ToString())));
|
||||||
|
totalVotesCast += result.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
eb.WithDescription(sb.ToString())
|
||||||
|
.WithFooter(efb => efb.WithText(GetText("x_votes_cast", totalVotesCast)));
|
||||||
|
|
||||||
|
return eb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task StartPoll()
|
||||||
|
{
|
||||||
|
var msgToSend = GetText("poll_created", Format.Bold(_originalMessage.Author.Username)) + "\n\n" + Format.Bold(_question) + "\n";
|
||||||
|
var num = 1;
|
||||||
|
msgToSend = answers.Aggregate(msgToSend, (current, answ) => current + $"`{num++}.` **{answ}**\n");
|
||||||
|
if (!IsPublic)
|
||||||
|
msgToSend += "\n" + Format.Bold(GetText("poll_vote_private"));
|
||||||
|
else
|
||||||
|
msgToSend += "\n" + Format.Bold(GetText("poll_vote_public"));
|
||||||
|
|
||||||
|
if (!IsPublic)
|
||||||
|
_guildUsers = new HashSet<ulong>((await _guild.GetUsersAsync().ConfigureAwait(false)).Select(x => x.Id));
|
||||||
|
|
||||||
|
await _originalMessage.Channel.SendConfirmAsync(msgToSend).ConfigureAwait(false);
|
||||||
|
running = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task StopPoll()
|
||||||
|
{
|
||||||
|
running = false;
|
||||||
|
OnEnded(_guild.Id);
|
||||||
|
await _originalMessage.Channel.EmbedAsync(GetStats("POLL CLOSED")).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> TryVote(IUserMessage msg)
|
||||||
|
{
|
||||||
|
// has to be a user message
|
||||||
|
if (msg == null || msg.Author.IsBot || !running)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// has to be an integer
|
||||||
|
if (!int.TryParse(msg.Content, out int vote))
|
||||||
|
return false;
|
||||||
|
if (vote < 1 || vote > answers.Length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
IMessageChannel ch;
|
||||||
|
if (IsPublic)
|
||||||
|
{
|
||||||
|
//if public, channel must be the same the poll started in
|
||||||
|
if (_originalMessage.Channel.Id != msg.Channel.Id)
|
||||||
|
return false;
|
||||||
|
ch = msg.Channel;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//if private, channel must be dm channel
|
||||||
|
if ((ch = msg.Channel as IDMChannel) == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// user must be a member of the guild this poll is in
|
||||||
|
if (!_guildUsers.Contains(msg.Author.Id))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//user can vote only once
|
||||||
|
if (_participants.TryAdd(msg.Author.Id, vote))
|
||||||
|
{
|
||||||
|
if (!IsPublic)
|
||||||
|
{
|
||||||
|
await ch.SendConfirmAsync(GetText("thanks_for_voting", Format.Bold(msg.Author.Username))).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var toDelete = await ch.SendConfirmAsync(GetText("poll_voted", Format.Bold(msg.Author.ToString()))).ConfigureAwait(false);
|
||||||
|
toDelete.DeleteAfter(5);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetText(string key, params object[] replacements)
|
||||||
|
=> _strings.GetText(key,
|
||||||
|
_guild.Id,
|
||||||
|
"Games".ToLowerInvariant(),
|
||||||
|
replacements);
|
||||||
|
}
|
||||||
|
}
|
78
src/NadekoBot/Services/Games/PollService.cs
Normal file
78
src/NadekoBot/Services/Games/PollService.cs
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
using NadekoBot.DataStructures.ModuleBehaviors;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Discord;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using NLog;
|
||||||
|
|
||||||
|
namespace NadekoBot.Services.Games
|
||||||
|
{
|
||||||
|
public class PollService : IEarlyBlockingExecutor
|
||||||
|
{
|
||||||
|
public ConcurrentDictionary<ulong, Poll> ActivePolls = new ConcurrentDictionary<ulong, Poll>();
|
||||||
|
private readonly Logger _log;
|
||||||
|
private readonly DiscordShardedClient _client;
|
||||||
|
private readonly NadekoStrings _strings;
|
||||||
|
|
||||||
|
public PollService(DiscordShardedClient client, NadekoStrings strings)
|
||||||
|
{
|
||||||
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
|
_client = client;
|
||||||
|
_strings = strings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool?> StartPoll(ITextChannel channel, IUserMessage msg, string arg, bool isPublic = false)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(arg) || !arg.Contains(";"))
|
||||||
|
return null;
|
||||||
|
var data = arg.Split(';');
|
||||||
|
if (data.Length < 3)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var poll = new Poll(_client, _strings, msg, data[0], data.Skip(1), isPublic: isPublic);
|
||||||
|
if (ActivePolls.TryAdd(channel.Guild.Id, poll))
|
||||||
|
{
|
||||||
|
poll.OnEnded += (gid) =>
|
||||||
|
{
|
||||||
|
ActivePolls.TryRemove(gid, out _);
|
||||||
|
};
|
||||||
|
|
||||||
|
await poll.StartPoll().ConfigureAwait(false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> TryExecuteEarly(DiscordShardedClient client, IGuild guild, IUserMessage msg)
|
||||||
|
{
|
||||||
|
if (guild == null)
|
||||||
|
{
|
||||||
|
foreach (var kvp in ActivePolls)
|
||||||
|
{
|
||||||
|
if (!kvp.Value.IsPublic)
|
||||||
|
{
|
||||||
|
if (await kvp.Value.TryVote(msg).ConfigureAwait(false))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ActivePolls.TryGetValue(guild.Id, out var poll))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await poll.TryVote(msg).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_log.Warn(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -14,13 +14,13 @@ namespace NadekoBot.Services
|
|||||||
{
|
{
|
||||||
public class GreetSettingsService
|
public class GreetSettingsService
|
||||||
{
|
{
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public readonly ConcurrentDictionary<ulong, GreetSettings> GuildConfigsCache;
|
public readonly ConcurrentDictionary<ulong, GreetSettings> GuildConfigsCache;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordShardedClient _client;
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
|
|
||||||
public GreetSettingsService(DiscordShardedClient client, IEnumerable<GuildConfig> guildConfigs, DbHandler db)
|
public GreetSettingsService(DiscordShardedClient client, IEnumerable<GuildConfig> guildConfigs, DbService db)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
_client = client;
|
_client = client;
|
||||||
|
32
src/NadekoBot/Services/Help/HelpService.cs
Normal file
32
src/NadekoBot/Services/Help/HelpService.cs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
using NadekoBot.DataStructures.ModuleBehaviors;
|
||||||
|
using NadekoBot.Services.Database.Models;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Discord;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace NadekoBot.Services.Help
|
||||||
|
{
|
||||||
|
public class HelpService : ILateExecutor
|
||||||
|
{
|
||||||
|
private readonly BotConfig _bc;
|
||||||
|
|
||||||
|
public HelpService(BotConfig bc)
|
||||||
|
{
|
||||||
|
_bc = bc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task LateExecute(DiscordShardedClient client, IGuild guild, IUserMessage msg)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if(guild == null)
|
||||||
|
await msg.Channel.SendMessageAsync(_bc.DMHelpString).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
//ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
|
|
||||||
namespace NadekoBot.Services
|
namespace NadekoBot.Services
|
||||||
@ -9,8 +8,8 @@ namespace NadekoBot.Services
|
|||||||
ImmutableArray<byte> Heads { get; }
|
ImmutableArray<byte> Heads { get; }
|
||||||
ImmutableArray<byte> Tails { get; }
|
ImmutableArray<byte> Tails { get; }
|
||||||
|
|
||||||
ImmutableArray<KeyValuePair<string, ImmutableArray<byte>>> Currency { get; }
|
ImmutableArray<(string, ImmutableArray<byte>)> Currency { get; }
|
||||||
ImmutableArray<KeyValuePair<string, ImmutableArray<byte>>> Dice { get; }
|
ImmutableArray<ImmutableArray<byte>> Dice { get; }
|
||||||
|
|
||||||
ImmutableArray<byte> SlotBackground { get; }
|
ImmutableArray<byte> SlotBackground { get; }
|
||||||
ImmutableArray<ImmutableArray<byte>> SlotEmojis { get; }
|
ImmutableArray<ImmutableArray<byte>> SlotEmojis { get; }
|
||||||
|
@ -162,7 +162,7 @@ namespace NadekoBot.Services.Impl
|
|||||||
|
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
//todo AsyncEnumerable
|
|
||||||
public async Task<IReadOnlyDictionary<string, TimeSpan>> GetVideoDurationsAsync(IEnumerable<string> videoIds)
|
public async Task<IReadOnlyDictionary<string, TimeSpan>> GetVideoDurationsAsync(IEnumerable<string> videoIds)
|
||||||
{
|
{
|
||||||
var videoIdsList = videoIds as List<string> ?? videoIds.ToList();
|
var videoIdsList = videoIds as List<string> ?? videoIds.ToList();
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
using NLog;
|
using NLog;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@ -31,10 +30,9 @@ namespace NadekoBot.Services.Impl
|
|||||||
public ImmutableArray<byte> Heads { get; private set; }
|
public ImmutableArray<byte> Heads { get; private set; }
|
||||||
public ImmutableArray<byte> Tails { get; private set; }
|
public ImmutableArray<byte> Tails { get; private set; }
|
||||||
|
|
||||||
//todo C#7 tuples
|
public ImmutableArray<(string, ImmutableArray<byte>)> Currency { get; private set; }
|
||||||
public ImmutableArray<KeyValuePair<string, ImmutableArray<byte>>> Currency { get; private set; }
|
|
||||||
|
|
||||||
public ImmutableArray<KeyValuePair<string, ImmutableArray<byte>>> Dice { get; private set; }
|
public ImmutableArray<ImmutableArray<byte>> Dice { get; private set; }
|
||||||
|
|
||||||
public ImmutableArray<byte> SlotBackground { get; private set; }
|
public ImmutableArray<byte> SlotBackground { get; private set; }
|
||||||
public ImmutableArray<ImmutableArray<byte>> SlotNumbers { get; private set; }
|
public ImmutableArray<ImmutableArray<byte>> SlotNumbers { get; private set; }
|
||||||
@ -59,15 +57,12 @@ namespace NadekoBot.Services.Impl
|
|||||||
Tails = File.ReadAllBytes(_tailsPath).ToImmutableArray();
|
Tails = File.ReadAllBytes(_tailsPath).ToImmutableArray();
|
||||||
|
|
||||||
Currency = Directory.GetFiles(_currencyImagesPath)
|
Currency = Directory.GetFiles(_currencyImagesPath)
|
||||||
.Select(x => new KeyValuePair<string, ImmutableArray<byte>>(
|
.Select(x => (Path.GetFileName(x), File.ReadAllBytes(x).ToImmutableArray()))
|
||||||
Path.GetFileName(x),
|
|
||||||
File.ReadAllBytes(x).ToImmutableArray()))
|
|
||||||
.ToImmutableArray();
|
.ToImmutableArray();
|
||||||
|
|
||||||
Dice = Directory.GetFiles(_diceImagesPath)
|
Dice = Directory.GetFiles(_diceImagesPath)
|
||||||
.OrderBy(x => int.Parse(Path.GetFileNameWithoutExtension(x)))
|
.OrderBy(x => int.Parse(Path.GetFileNameWithoutExtension(x)))
|
||||||
.Select(x => new KeyValuePair<string, ImmutableArray<byte>>(x,
|
.Select(x => File.ReadAllBytes(x).ToImmutableArray())
|
||||||
File.ReadAllBytes(x).ToImmutableArray()))
|
|
||||||
.ToImmutableArray();
|
.ToImmutableArray();
|
||||||
|
|
||||||
SlotBackground = File.ReadAllBytes(_slotBackgroundPath).ToImmutableArray();
|
SlotBackground = File.ReadAllBytes(_slotBackgroundPath).ToImmutableArray();
|
||||||
|
@ -10,13 +10,13 @@ namespace NadekoBot.Services
|
|||||||
public class Localization : ILocalization
|
public class Localization : ILocalization
|
||||||
{
|
{
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public ConcurrentDictionary<ulong, CultureInfo> GuildCultureInfos { get; }
|
public ConcurrentDictionary<ulong, CultureInfo> GuildCultureInfos { get; }
|
||||||
public CultureInfo DefaultCultureInfo { get; private set; } = CultureInfo.CurrentCulture;
|
public CultureInfo DefaultCultureInfo { get; private set; } = CultureInfo.CurrentCulture;
|
||||||
|
|
||||||
private Localization() { }
|
private Localization() { }
|
||||||
public Localization(string defaultCulture, IDictionary<ulong, string> cultureInfoNames, DbHandler db)
|
public Localization(string defaultCulture, IDictionary<ulong, string> cultureInfoNames, DbService db)
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_db = db;
|
_db = db;
|
||||||
|
@ -61,7 +61,7 @@ namespace NadekoBot.Services
|
|||||||
}
|
}
|
||||||
|
|
||||||
public string GetText(string key, ulong guildId, string lowerModuleTypeName, params object[] replacements) =>
|
public string GetText(string key, ulong guildId, string lowerModuleTypeName, params object[] replacements) =>
|
||||||
GetText(key, _localization.GetCultureInfo(guildId), lowerModuleTypeName);
|
GetText(key, _localization.GetCultureInfo(guildId), lowerModuleTypeName, replacements);
|
||||||
|
|
||||||
public string GetText(string key, CultureInfo cultureInfo, string lowerModuleTypeName)
|
public string GetText(string key, CultureInfo cultureInfo, string lowerModuleTypeName)
|
||||||
{
|
{
|
||||||
|
@ -10,6 +10,7 @@ using NLog;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using VideoLibrary;
|
using VideoLibrary;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace NadekoBot.Services.Music
|
namespace NadekoBot.Services.Music
|
||||||
{
|
{
|
||||||
@ -20,16 +21,17 @@ namespace NadekoBot.Services.Music
|
|||||||
private readonly IGoogleApiService _google;
|
private readonly IGoogleApiService _google;
|
||||||
private readonly NadekoStrings _strings;
|
private readonly NadekoStrings _strings;
|
||||||
private readonly ILocalization _localization;
|
private readonly ILocalization _localization;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
private readonly SoundCloudApiService _sc;
|
private readonly SoundCloudApiService _sc;
|
||||||
private readonly IBotCredentials _creds;
|
private readonly IBotCredentials _creds;
|
||||||
|
private readonly ConcurrentDictionary<ulong, float> _defaultVolumes;
|
||||||
|
|
||||||
public ConcurrentDictionary<ulong, MusicPlayer> MusicPlayers { get; } = new ConcurrentDictionary<ulong, MusicPlayer>();
|
public ConcurrentDictionary<ulong, MusicPlayer> MusicPlayers { get; } = new ConcurrentDictionary<ulong, MusicPlayer>();
|
||||||
|
|
||||||
public MusicService(IGoogleApiService google,
|
public MusicService(IGoogleApiService google,
|
||||||
NadekoStrings strings, ILocalization localization, DbHandler db,
|
NadekoStrings strings, ILocalization localization, DbService db,
|
||||||
SoundCloudApiService sc, IBotCredentials creds)
|
SoundCloudApiService sc, IBotCredentials creds, IEnumerable<GuildConfig> gcs)
|
||||||
{
|
{
|
||||||
_google = google;
|
_google = google;
|
||||||
_strings = strings;
|
_strings = strings;
|
||||||
@ -41,6 +43,8 @@ namespace NadekoBot.Services.Music
|
|||||||
|
|
||||||
try { Directory.Delete(MusicDataPath, true); } catch { }
|
try { Directory.Delete(MusicDataPath, true); } catch { }
|
||||||
|
|
||||||
|
_defaultVolumes = new ConcurrentDictionary<ulong, float>(gcs.ToDictionary(x => x.GuildId, x => x.DefaultMusicVolume));
|
||||||
|
|
||||||
Directory.CreateDirectory(MusicDataPath);
|
Directory.CreateDirectory(MusicDataPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,12 +61,14 @@ namespace NadekoBot.Services.Music
|
|||||||
|
|
||||||
return MusicPlayers.GetOrAdd(guildId, server =>
|
return MusicPlayers.GetOrAdd(guildId, server =>
|
||||||
{
|
{
|
||||||
float vol;// SpecificConfigurations.Default.Of(server.Id).DefaultMusicVolume;
|
var vol = _defaultVolumes.GetOrAdd(guildId, (id) =>
|
||||||
using (var uow = _db.UnitOfWork)
|
|
||||||
{
|
{
|
||||||
//todo move to cached variable
|
using (var uow = _db.UnitOfWork)
|
||||||
vol = uow.GuildConfigs.For(guildId, set => set).DefaultMusicVolume;
|
{
|
||||||
}
|
return uow.GuildConfigs.For(guildId, set => set).DefaultMusicVolume;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
var mp = new MusicPlayer(voiceCh, textCh, vol, _google);
|
var mp = new MusicPlayer(voiceCh, textCh, vol, _google);
|
||||||
IUserMessage playingMessage = null;
|
IUserMessage playingMessage = null;
|
||||||
IUserMessage lastFinishedMessage = null;
|
IUserMessage lastFinishedMessage = null;
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.DataStructures.ModuleBehaviors;
|
||||||
|
using NadekoBot.Services.Database.Models;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Discord;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace NadekoBot.Services.Permissions
|
namespace NadekoBot.Services.Permissions
|
||||||
{
|
{
|
||||||
public class BlacklistService
|
public class BlacklistService : IEarlyBlocker
|
||||||
{
|
{
|
||||||
public ConcurrentHashSet<ulong> BlacklistedUsers { get; set; }
|
public ConcurrentHashSet<ulong> BlacklistedUsers { get; }
|
||||||
public ConcurrentHashSet<ulong> BlacklistedGuilds { get; set; }
|
public ConcurrentHashSet<ulong> BlacklistedGuilds { get; }
|
||||||
public ConcurrentHashSet<ulong> BlacklistedChannels { get; set; }
|
public ConcurrentHashSet<ulong> BlacklistedChannels { get; }
|
||||||
|
|
||||||
public BlacklistService(BotConfig bc)
|
public BlacklistService(BotConfig bc)
|
||||||
{
|
{
|
||||||
@ -17,5 +21,10 @@ namespace NadekoBot.Services.Permissions
|
|||||||
BlacklistedGuilds = new ConcurrentHashSet<ulong>(blacklist.Where(bi => bi.Type == BlacklistType.Server).Select(c => c.ItemId));
|
BlacklistedGuilds = new ConcurrentHashSet<ulong>(blacklist.Where(bi => bi.Type == BlacklistType.Server).Select(c => c.ItemId));
|
||||||
BlacklistedChannels = new ConcurrentHashSet<ulong>(blacklist.Where(bi => bi.Type == BlacklistType.Channel).Select(c => c.ItemId));
|
BlacklistedChannels = new ConcurrentHashSet<ulong>(blacklist.Where(bi => bi.Type == BlacklistType.Channel).Select(c => c.ItemId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Task<bool> TryBlockEarly(DiscordShardedClient client, IGuild guild, IUserMessage usrMsg)
|
||||||
|
=> Task.FromResult((guild != null && BlacklistedGuilds.Contains(guild.Id)) ||
|
||||||
|
BlacklistedChannels.Contains(usrMsg.Channel.Id) ||
|
||||||
|
BlacklistedUsers.Contains(usrMsg.Author.Id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.DataStructures.ModuleBehaviors;
|
||||||
|
using NadekoBot.Services.Database.Models;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Discord;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace NadekoBot.Services.Permissions
|
namespace NadekoBot.Services.Permissions
|
||||||
{
|
{
|
||||||
public class CmdCdService
|
public class CmdCdService : ILateBlocker
|
||||||
{
|
{
|
||||||
public ConcurrentDictionary<ulong, ConcurrentHashSet<CommandCooldown>> CommandCooldowns { get; }
|
public ConcurrentDictionary<ulong, ConcurrentHashSet<CommandCooldown>> CommandCooldowns { get; }
|
||||||
public ConcurrentDictionary<ulong, ConcurrentHashSet<ActiveCooldown>> ActiveCooldowns { get; } = new ConcurrentDictionary<ulong, ConcurrentHashSet<ActiveCooldown>>();
|
public ConcurrentDictionary<ulong, ConcurrentHashSet<ActiveCooldown>> ActiveCooldowns { get; } = new ConcurrentDictionary<ulong, ConcurrentHashSet<ActiveCooldown>>();
|
||||||
@ -16,6 +20,41 @@ namespace NadekoBot.Services.Permissions
|
|||||||
gcs.ToDictionary(k => k.GuildId,
|
gcs.ToDictionary(k => k.GuildId,
|
||||||
v => new ConcurrentHashSet<CommandCooldown>(v.CommandCooldowns)));
|
v => new ConcurrentHashSet<CommandCooldown>(v.CommandCooldowns)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Task<bool> TryBlockLate(DiscordShardedClient client, IUserMessage msg, IGuild guild,
|
||||||
|
IMessageChannel channel, IUser user, string moduleName, string commandName)
|
||||||
|
{
|
||||||
|
if (guild == null)
|
||||||
|
return Task.FromResult(false);
|
||||||
|
var cmdcds = CommandCooldowns.GetOrAdd(guild.Id, new ConcurrentHashSet<CommandCooldown>());
|
||||||
|
CommandCooldown cdRule;
|
||||||
|
if ((cdRule = cmdcds.FirstOrDefault(cc => cc.CommandName == commandName.ToLowerInvariant())) != null)
|
||||||
|
{
|
||||||
|
var activeCdsForGuild = ActiveCooldowns.GetOrAdd(guild.Id, new ConcurrentHashSet<ActiveCooldown>());
|
||||||
|
if (activeCdsForGuild.FirstOrDefault(ac => ac.UserId == user.Id && ac.Command == commandName.ToLowerInvariant()) != null)
|
||||||
|
{
|
||||||
|
return Task.FromResult(true);
|
||||||
|
}
|
||||||
|
activeCdsForGuild.Add(new ActiveCooldown()
|
||||||
|
{
|
||||||
|
UserId = user.Id,
|
||||||
|
Command = commandName.ToLowerInvariant(),
|
||||||
|
});
|
||||||
|
var _ = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Task.Delay(cdRule.Seconds * 1000);
|
||||||
|
activeCdsForGuild.RemoveWhere(ac => ac.Command == commandName.ToLowerInvariant() && ac.UserId == user.Id);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Task.FromResult(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ActiveCooldown
|
public class ActiveCooldown
|
||||||
|
@ -1,12 +1,21 @@
|
|||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.DataStructures.ModuleBehaviors;
|
||||||
|
using NadekoBot.Services.Database.Models;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Discord;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
|
using Discord.Net;
|
||||||
|
using NLog;
|
||||||
|
|
||||||
namespace NadekoBot.Services.Permissions
|
namespace NadekoBot.Services.Permissions
|
||||||
{
|
{
|
||||||
public class FilterService
|
public class FilterService : IEarlyBlocker
|
||||||
{
|
{
|
||||||
|
private readonly Logger _log;
|
||||||
|
|
||||||
public ConcurrentHashSet<ulong> InviteFilteringChannels { get; }
|
public ConcurrentHashSet<ulong> InviteFilteringChannels { get; }
|
||||||
public ConcurrentHashSet<ulong> InviteFilteringServers { get; }
|
public ConcurrentHashSet<ulong> InviteFilteringServers { get; }
|
||||||
|
|
||||||
@ -34,6 +43,8 @@ namespace NadekoBot.Services.Permissions
|
|||||||
|
|
||||||
public FilterService(IEnumerable<GuildConfig> gcs)
|
public FilterService(IEnumerable<GuildConfig> gcs)
|
||||||
{
|
{
|
||||||
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
InviteFilteringServers = new ConcurrentHashSet<ulong>(gcs.Where(gc => gc.FilterInvites).Select(gc => gc.GuildId));
|
InviteFilteringServers = new ConcurrentHashSet<ulong>(gcs.Where(gc => gc.FilterInvites).Select(gc => gc.GuildId));
|
||||||
InviteFilteringChannels = new ConcurrentHashSet<ulong>(gcs.SelectMany(gc => gc.FilterInvitesChannelIds.Select(fci => fci.ChannelId)));
|
InviteFilteringChannels = new ConcurrentHashSet<ulong>(gcs.SelectMany(gc => gc.FilterInvitesChannelIds.Select(fci => fci.ChannelId)));
|
||||||
|
|
||||||
@ -46,5 +57,61 @@ namespace NadekoBot.Services.Permissions
|
|||||||
|
|
||||||
WordFilteringChannels = new ConcurrentHashSet<ulong>(gcs.SelectMany(gc => gc.FilterWordsChannelIds.Select(fwci => fwci.ChannelId)));
|
WordFilteringChannels = new ConcurrentHashSet<ulong>(gcs.SelectMany(gc => gc.FilterWordsChannelIds.Select(fwci => fwci.ChannelId)));
|
||||||
}
|
}
|
||||||
|
//todo ignore guild admin
|
||||||
|
public async Task<bool> TryBlockEarly(DiscordShardedClient client, IGuild guild, IUserMessage msg)
|
||||||
|
=> await FilterInvites(client, guild, msg) || await FilterWords(client, guild, msg);
|
||||||
|
|
||||||
|
public async Task<bool> FilterWords(DiscordShardedClient client, IGuild guild, IUserMessage usrMsg)
|
||||||
|
{
|
||||||
|
if (guild is null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var filteredChannelWords = FilteredWordsForChannel(usrMsg.Channel.Id, guild.Id) ?? new ConcurrentHashSet<string>();
|
||||||
|
var filteredServerWords = FilteredWordsForServer(guild.Id) ?? new ConcurrentHashSet<string>();
|
||||||
|
var wordsInMessage = usrMsg.Content.ToLowerInvariant().Split(' ');
|
||||||
|
if (filteredChannelWords.Count != 0 || filteredServerWords.Count != 0)
|
||||||
|
{
|
||||||
|
foreach (var word in wordsInMessage)
|
||||||
|
{
|
||||||
|
if (filteredChannelWords.Contains(word) ||
|
||||||
|
filteredServerWords.Contains(word))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await usrMsg.DeleteAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (HttpException ex)
|
||||||
|
{
|
||||||
|
_log.Warn("I do not have permission to filter words in channel with id " + usrMsg.Channel.Id, ex);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> FilterInvites(DiscordShardedClient client, IGuild guild, IUserMessage usrMsg)
|
||||||
|
{
|
||||||
|
if (guild is null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ((InviteFilteringChannels.Contains(usrMsg.Channel.Id) ||
|
||||||
|
InviteFilteringServers.Contains(guild.Id)) &&
|
||||||
|
usrMsg.Content.IsDiscordInvite())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await usrMsg.DeleteAsync().ConfigureAwait(false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (HttpException ex)
|
||||||
|
{
|
||||||
|
_log.Warn("I do not have permission to filter invites in channel with id " + usrMsg.Channel.Id, ex);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using NadekoBot.DataStructures.ModuleBehaviors;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using NLog;
|
using NLog;
|
||||||
using System;
|
using System;
|
||||||
@ -6,25 +7,27 @@ using System.Collections.Concurrent;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Discord;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
|
||||||
namespace NadekoBot.Services.Permissions
|
namespace NadekoBot.Services.Permissions
|
||||||
{
|
{
|
||||||
public class PermissionsService
|
public class PermissionsService : ILateBlocker
|
||||||
{
|
{
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
|
|
||||||
//guildid, root permission
|
//guildid, root permission
|
||||||
public ConcurrentDictionary<ulong, PermissionCache> Cache { get; } =
|
public ConcurrentDictionary<ulong, PermissionCache> Cache { get; } =
|
||||||
new ConcurrentDictionary<ulong, PermissionCache>();
|
new ConcurrentDictionary<ulong, PermissionCache>();
|
||||||
|
|
||||||
public PermissionsService(DbHandler db)
|
public PermissionsService(DbService db, BotConfig bc)
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_db = db;
|
_db = db;
|
||||||
|
|
||||||
var sw = Stopwatch.StartNew();
|
var sw = Stopwatch.StartNew();
|
||||||
TryMigratePermissions();
|
TryMigratePermissions(bc);
|
||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
||||||
foreach (var x in uow.GuildConfigs.Permissionsv2ForAll())
|
foreach (var x in uow.GuildConfigs.Permissionsv2ForAll())
|
||||||
@ -59,61 +62,67 @@ namespace NadekoBot.Services.Permissions
|
|||||||
return pc;
|
return pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TryMigratePermissions()
|
private void TryMigratePermissions(BotConfig bc)
|
||||||
{
|
{
|
||||||
var log = LogManager.GetCurrentClassLogger();
|
var log = LogManager.GetCurrentClassLogger();
|
||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
||||||
var oldCache = new ConcurrentDictionary<ulong, OldPermissionCache>(uow.GuildConfigs
|
if (bc.PermissionVersion <= 1)
|
||||||
.OldPermissionsForAll()
|
|
||||||
.Where(x => x.RootPermission != null) // there is a check inside already, but just in case
|
|
||||||
.ToDictionary(k => k.GuildId,
|
|
||||||
v => new OldPermissionCache()
|
|
||||||
{
|
|
||||||
RootPermission = v.RootPermission,
|
|
||||||
Verbose = v.VerbosePermissions,
|
|
||||||
PermRole = v.PermissionRole
|
|
||||||
}));
|
|
||||||
|
|
||||||
if (oldCache.Any())
|
|
||||||
{
|
{
|
||||||
log.Info("Old permissions found. Performing one-time migration to v2.");
|
log.Info("Permission version is 1, upgrading to 2.");
|
||||||
var i = 0;
|
var oldCache = new ConcurrentDictionary<ulong, OldPermissionCache>(uow.GuildConfigs
|
||||||
foreach (var oc in oldCache)
|
.OldPermissionsForAll()
|
||||||
{
|
.Where(x => x.RootPermission != null) // there is a check inside already, but just in case
|
||||||
if (i % 3 == 0)
|
.ToDictionary(k => k.GuildId,
|
||||||
log.Info("Migrating Permissions #" + i + " - GuildId: " + oc.Key);
|
v => new OldPermissionCache()
|
||||||
i++;
|
|
||||||
var gc = uow.GuildConfigs.GcWithPermissionsv2For(oc.Key);
|
|
||||||
|
|
||||||
var oldPerms = oc.Value.RootPermission.AsEnumerable().Reverse().ToList();
|
|
||||||
uow._context.Set<Permission>().RemoveRange(oldPerms);
|
|
||||||
gc.RootPermission = null;
|
|
||||||
if (oldPerms.Count > 2)
|
|
||||||
{
|
|
||||||
|
|
||||||
var newPerms = oldPerms.Take(oldPerms.Count - 1)
|
|
||||||
.Select(x => x.Tov2())
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var allowPerm = Permissionv2.AllowAllPerm;
|
|
||||||
var firstPerm = newPerms[0];
|
|
||||||
if (allowPerm.State != firstPerm.State ||
|
|
||||||
allowPerm.PrimaryTarget != firstPerm.PrimaryTarget ||
|
|
||||||
allowPerm.SecondaryTarget != firstPerm.SecondaryTarget ||
|
|
||||||
allowPerm.PrimaryTargetId != firstPerm.PrimaryTargetId ||
|
|
||||||
allowPerm.SecondaryTargetName != firstPerm.SecondaryTargetName)
|
|
||||||
newPerms.Insert(0, Permissionv2.AllowAllPerm);
|
|
||||||
Cache.TryAdd(oc.Key, new PermissionCache
|
|
||||||
{
|
{
|
||||||
Permissions = new PermissionsCollection<Permissionv2>(newPerms),
|
RootPermission = v.RootPermission,
|
||||||
Verbose = gc.VerbosePermissions,
|
Verbose = v.VerbosePermissions,
|
||||||
PermRole = gc.PermissionRole,
|
PermRole = v.PermissionRole
|
||||||
});
|
}));
|
||||||
gc.Permissions = newPerms;
|
|
||||||
|
if (oldCache.Any())
|
||||||
|
{
|
||||||
|
log.Info("Old permissions found. Performing one-time migration to v2.");
|
||||||
|
var i = 0;
|
||||||
|
foreach (var oc in oldCache)
|
||||||
|
{
|
||||||
|
if (i % 3 == 0)
|
||||||
|
log.Info("Migrating Permissions #" + i + " - GuildId: " + oc.Key);
|
||||||
|
i++;
|
||||||
|
var gc = uow.GuildConfigs.GcWithPermissionsv2For(oc.Key);
|
||||||
|
|
||||||
|
var oldPerms = oc.Value.RootPermission.AsEnumerable().Reverse().ToList();
|
||||||
|
uow._context.Set<Permission>().RemoveRange(oldPerms);
|
||||||
|
gc.RootPermission = null;
|
||||||
|
if (oldPerms.Count > 2)
|
||||||
|
{
|
||||||
|
|
||||||
|
var newPerms = oldPerms.Take(oldPerms.Count - 1)
|
||||||
|
.Select(x => x.Tov2())
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var allowPerm = Permissionv2.AllowAllPerm;
|
||||||
|
var firstPerm = newPerms[0];
|
||||||
|
if (allowPerm.State != firstPerm.State ||
|
||||||
|
allowPerm.PrimaryTarget != firstPerm.PrimaryTarget ||
|
||||||
|
allowPerm.SecondaryTarget != firstPerm.SecondaryTarget ||
|
||||||
|
allowPerm.PrimaryTargetId != firstPerm.PrimaryTargetId ||
|
||||||
|
allowPerm.SecondaryTargetName != firstPerm.SecondaryTargetName)
|
||||||
|
newPerms.Insert(0, Permissionv2.AllowAllPerm);
|
||||||
|
Cache.TryAdd(oc.Key, new PermissionCache
|
||||||
|
{
|
||||||
|
Permissions = new PermissionsCollection<Permissionv2>(newPerms),
|
||||||
|
Verbose = gc.VerbosePermissions,
|
||||||
|
PermRole = gc.PermissionRole,
|
||||||
|
});
|
||||||
|
gc.Permissions = newPerms;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
log.Info("Permission migration to v2 is done.");
|
||||||
}
|
}
|
||||||
log.Info("Permission migration to v2 is done.");
|
|
||||||
|
uow.BotConfig.GetOrCreate().PermissionVersion = 2;
|
||||||
uow.Complete();
|
uow.Complete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -151,5 +160,39 @@ namespace NadekoBot.Services.Permissions
|
|||||||
return old;
|
return old;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<bool> TryBlockLate(DiscordShardedClient client, IUserMessage msg, IGuild guild, IMessageChannel channel, IUser user, string moduleName, string commandName)
|
||||||
|
{
|
||||||
|
await Task.Yield();
|
||||||
|
if (guild == null)
|
||||||
|
{
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var resetCommand = commandName == "resetperms";
|
||||||
|
|
||||||
|
//todo perms
|
||||||
|
PermissionCache pc = GetCache(guild.Id);
|
||||||
|
if (!resetCommand && !pc.Permissions.CheckPermissions(msg, commandName, moduleName, out int index))
|
||||||
|
{
|
||||||
|
var returnMsg = $"Permission number #{index + 1} **{pc.Permissions[index].GetCommand((SocketGuild)guild)}** is preventing this action.";
|
||||||
|
return true;
|
||||||
|
//return new ExecuteCommandResult(cmd, pc, SearchResult.FromError(CommandError.Exception, returnMsg));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (moduleName == "Permissions")
|
||||||
|
{
|
||||||
|
var roles = (user as SocketGuildUser)?.Roles ?? ((IGuildUser)user).RoleIds.Select(x => guild.GetRole(x)).Where(x => x != null);
|
||||||
|
if (!roles.Any(r => r.Name.Trim().ToLowerInvariant() == pc.PermRole.Trim().ToLowerInvariant()) && user.Id != ((IGuildUser)user).Guild.OwnerId)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
//return new ExecuteCommandResult(cmd, pc, SearchResult.FromError(CommandError.Exception, $"You need the **{pc.PermRole}** role in order to use permission commands."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ namespace NadekoBot.Services.Searches
|
|||||||
{
|
{
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordShardedClient _client;
|
||||||
private readonly IGoogleApiService _google;
|
private readonly IGoogleApiService _google;
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
|
|
||||||
public ConcurrentDictionary<ulong, bool> TranslatedChannels { get; } = new ConcurrentDictionary<ulong, bool>();
|
public ConcurrentDictionary<ulong, bool> TranslatedChannels { get; } = new ConcurrentDictionary<ulong, bool>();
|
||||||
@ -31,7 +31,7 @@ namespace NadekoBot.Services.Searches
|
|||||||
public List<WoWJoke> WowJokes { get; } = new List<WoWJoke>();
|
public List<WoWJoke> WowJokes { get; } = new List<WoWJoke>();
|
||||||
public List<MagicItem> MagicItems { get; } = new List<MagicItem>();
|
public List<MagicItem> MagicItems { get; } = new List<MagicItem>();
|
||||||
|
|
||||||
public SearchesService(DiscordShardedClient client, IGoogleApiService google, DbHandler db)
|
public SearchesService(DiscordShardedClient client, IGoogleApiService google, DbService db)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
_google = google;
|
_google = google;
|
||||||
|
@ -19,11 +19,11 @@ namespace NadekoBot.Services.Searches
|
|||||||
private bool firstStreamNotifPass { get; set; } = true;
|
private bool firstStreamNotifPass { get; set; } = true;
|
||||||
private readonly ConcurrentDictionary<string, StreamStatus> _cachedStatuses = new ConcurrentDictionary<string, StreamStatus>();
|
private readonly ConcurrentDictionary<string, StreamStatus> _cachedStatuses = new ConcurrentDictionary<string, StreamStatus>();
|
||||||
|
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordShardedClient _client;
|
||||||
private readonly NadekoStrings _strings;
|
private readonly NadekoStrings _strings;
|
||||||
|
|
||||||
public StreamNotificationService(DbHandler db, DiscordShardedClient client, NadekoStrings strings)
|
public StreamNotificationService(DbService db, DiscordShardedClient client, NadekoStrings strings)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
_client = client;
|
_client = client;
|
||||||
|
@ -17,9 +17,9 @@ namespace NadekoBot.Services.Utility
|
|||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
private Timer _timer;
|
private Timer _timer;
|
||||||
private readonly TimeSpan _updateInterval = new TimeSpan(12, 0, 0);
|
private readonly TimeSpan _updateInterval = new TimeSpan(12, 0, 0);
|
||||||
private readonly DbHandler _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public ConverterService(DbHandler db)
|
public ConverterService(DbService db)
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_db = db;
|
_db = db;
|
||||||
|
@ -7,6 +7,7 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace NadekoBot.Services.Utility
|
namespace NadekoBot.Services.Utility
|
||||||
{
|
{
|
||||||
|
//todo 50 rewrite
|
||||||
public class MessageRepeaterService
|
public class MessageRepeaterService
|
||||||
{
|
{
|
||||||
//messagerepeater
|
//messagerepeater
|
||||||
@ -23,7 +24,6 @@ namespace NadekoBot.Services.Utility
|
|||||||
#else
|
#else
|
||||||
await Task.Delay(30000).ConfigureAwait(false);
|
await Task.Delay(30000).ConfigureAwait(false);
|
||||||
#endif
|
#endif
|
||||||
//todo this is pretty terrible :kms: no time
|
|
||||||
Repeaters = new ConcurrentDictionary<ulong, ConcurrentQueue<RepeatRunner>>(gcs
|
Repeaters = new ConcurrentDictionary<ulong, ConcurrentQueue<RepeatRunner>>(gcs
|
||||||
.ToDictionary(gc => gc.GuildId,
|
.ToDictionary(gc => gc.GuildId,
|
||||||
gc => new ConcurrentQueue<RepeatRunner>(gc.GuildRepeaters
|
gc => new ConcurrentQueue<RepeatRunner>(gc.GuildRepeaters
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Utility.Models
|
namespace NadekoBot.Services.Utility.Patreon
|
||||||
{
|
{
|
||||||
public class PatreonData
|
public class PatreonData
|
||||||
{
|
{
|
@ -1,4 +1,4 @@
|
|||||||
namespace NadekoBot.Modules.Utility.Models
|
namespace NadekoBot.Services.Utility.Patreon
|
||||||
{
|
{
|
||||||
public class Attributes
|
public class Attributes
|
||||||
{
|
{
|
@ -1,4 +1,4 @@
|
|||||||
namespace NadekoBot.Modules.Utility.Models
|
namespace NadekoBot.Services.Utility.Patreon
|
||||||
{
|
{
|
||||||
public class DiscordConnection
|
public class DiscordConnection
|
||||||
{
|
{
|
162
src/NadekoBot/Services/Utility/PatreonRewardsService.cs
Normal file
162
src/NadekoBot/Services/Utility/PatreonRewardsService.cs
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
using NadekoBot.Services.Database.Models;
|
||||||
|
using NadekoBot.Services.Utility.Patreon;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using NLog;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NadekoBot.Services.Utility
|
||||||
|
{
|
||||||
|
public class PatreonRewardsService
|
||||||
|
{
|
||||||
|
private readonly SemaphoreSlim getPledgesLocker = new SemaphoreSlim(1, 1);
|
||||||
|
|
||||||
|
public ImmutableArray<PatreonUserAndReward> Pledges { get; private set; }
|
||||||
|
public DateTime LastUpdate { get; private set; } = DateTime.UtcNow;
|
||||||
|
|
||||||
|
public readonly Timer Updater;
|
||||||
|
private readonly SemaphoreSlim claimLockJustInCase = new SemaphoreSlim(1, 1);
|
||||||
|
private readonly Logger _log;
|
||||||
|
|
||||||
|
public readonly TimeSpan Interval = TimeSpan.FromHours(1);
|
||||||
|
private IBotCredentials _creds;
|
||||||
|
private readonly DbService _db;
|
||||||
|
private readonly CurrencyService _currency;
|
||||||
|
|
||||||
|
private PatreonRewardsService(IBotCredentials creds, DbService db, CurrencyService currency)
|
||||||
|
{
|
||||||
|
_creds = creds;
|
||||||
|
_db = db;
|
||||||
|
_currency = currency;
|
||||||
|
if (string.IsNullOrWhiteSpace(creds.PatreonAccessToken))
|
||||||
|
return;
|
||||||
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
|
Updater = new Timer(async (_) => await LoadPledges(), null, TimeSpan.Zero, Interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task LoadPledges()
|
||||||
|
{
|
||||||
|
LastUpdate = DateTime.UtcNow;
|
||||||
|
await getPledgesLocker.WaitAsync(1000).ConfigureAwait(false);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var rewards = new List<PatreonPledge>();
|
||||||
|
var users = new List<PatreonUser>();
|
||||||
|
using (var http = new HttpClient())
|
||||||
|
{
|
||||||
|
http.DefaultRequestHeaders.Clear();
|
||||||
|
http.DefaultRequestHeaders.Add("Authorization", "Bearer " + _creds.PatreonAccessToken);
|
||||||
|
var data = new PatreonData()
|
||||||
|
{
|
||||||
|
Links = new PatreonDataLinks()
|
||||||
|
{
|
||||||
|
next = "https://api.patreon.com/oauth2/api/campaigns/334038/pledges"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
do
|
||||||
|
{
|
||||||
|
var res = await http.GetStringAsync(data.Links.next)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
data = JsonConvert.DeserializeObject<PatreonData>(res);
|
||||||
|
var pledgers = data.Data.Where(x => x["type"].ToString() == "pledge");
|
||||||
|
rewards.AddRange(pledgers.Select(x => JsonConvert.DeserializeObject<PatreonPledge>(x.ToString()))
|
||||||
|
.Where(x => x.attributes.declined_since == null));
|
||||||
|
users.AddRange(data.Included
|
||||||
|
.Where(x => x["type"].ToString() == "user")
|
||||||
|
.Select(x => JsonConvert.DeserializeObject<PatreonUser>(x.ToString())));
|
||||||
|
} while (!string.IsNullOrWhiteSpace(data.Links.next));
|
||||||
|
}
|
||||||
|
Pledges = rewards.Join(users, (r) => r.relationships?.patron?.data?.id, (u) => u.id, (x, y) => new PatreonUserAndReward()
|
||||||
|
{
|
||||||
|
User = y,
|
||||||
|
Reward = x,
|
||||||
|
}).ToImmutableArray();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_log.Warn(ex);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
var _ = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await Task.Delay(TimeSpan.FromMinutes(5)).ConfigureAwait(false);
|
||||||
|
getPledgesLocker.Release();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> ClaimReward(ulong userId)
|
||||||
|
{
|
||||||
|
await claimLockJustInCase.WaitAsync();
|
||||||
|
var now = DateTime.UtcNow;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var data = Pledges.FirstOrDefault(x => x.User.attributes?.social_connections?.discord?.user_id == userId.ToString());
|
||||||
|
|
||||||
|
if (data == null)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
var amount = data.Reward.attributes.amount_cents;
|
||||||
|
|
||||||
|
using (var uow = _db.UnitOfWork)
|
||||||
|
{
|
||||||
|
var users = uow._context.Set<RewardedUser>();
|
||||||
|
var usr = users.FirstOrDefault(x => x.PatreonUserId == data.User.id);
|
||||||
|
|
||||||
|
if (usr == null)
|
||||||
|
{
|
||||||
|
users.Add(new RewardedUser()
|
||||||
|
{
|
||||||
|
UserId = userId,
|
||||||
|
PatreonUserId = data.User.id,
|
||||||
|
LastReward = now,
|
||||||
|
AmountRewardedThisMonth = amount,
|
||||||
|
});
|
||||||
|
|
||||||
|
await _currency.AddAsync(userId, "Patreon reward - new", amount, uow).ConfigureAwait(false);
|
||||||
|
|
||||||
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usr.LastReward.Month != now.Month)
|
||||||
|
{
|
||||||
|
usr.LastReward = now;
|
||||||
|
usr.AmountRewardedThisMonth = amount;
|
||||||
|
usr.PatreonUserId = data.User.id;
|
||||||
|
|
||||||
|
await _currency.AddAsync(userId, "Patreon reward - recurring", amount, uow).ConfigureAwait(false);
|
||||||
|
|
||||||
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usr.AmountRewardedThisMonth < amount)
|
||||||
|
{
|
||||||
|
var toAward = amount - usr.AmountRewardedThisMonth;
|
||||||
|
|
||||||
|
usr.LastReward = now;
|
||||||
|
usr.AmountRewardedThisMonth = amount;
|
||||||
|
usr.PatreonUserId = data.User.id;
|
||||||
|
|
||||||
|
await _currency.AddAsync(usr.UserId, "Patreon reward - update", toAward, uow).ConfigureAwait(false);
|
||||||
|
|
||||||
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
|
return toAward;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
claimLockJustInCase.Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user