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>
|
||||
/// Implemented by modules which can execute something and prevent further commands from being executed.
|
||||
/// </summary>
|
||||
public interface IBlockingExecutor
|
||||
public interface IEarlyBlockingExecutor
|
||||
{
|
||||
/// <summary>
|
||||
/// Try to execute some logic within some module's service.
|
||||
/// </summary>
|
||||
/// <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");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Repeaters_ChannelId",
|
||||
name: "IX_Repeaters_channelId",
|
||||
table: "Repeaters",
|
||||
column: "ChannelId",
|
||||
unique: true);
|
||||
|
@ -30,7 +30,7 @@ namespace NadekoBot.Migrations
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Repeaters_ChannelId",
|
||||
name: "IX_Repeaters_channelId",
|
||||
table: "Repeaters",
|
||||
column: "ChannelId",
|
||||
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)
|
||||
{
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "1.1.0-rtm-22752");
|
||||
.HasAnnotation("ProductVersion", "1.1.1");
|
||||
|
||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiRaidSetting", b =>
|
||||
{
|
||||
@ -165,6 +165,8 @@ namespace NadekoBot.Migrations
|
||||
|
||||
b.Property<string>("OkColor");
|
||||
|
||||
b.Property<int>("PermissionVersion");
|
||||
|
||||
b.Property<string>("RemindMessageFormat");
|
||||
|
||||
b.Property<bool>("RotatingStatuses");
|
||||
|
@ -15,10 +15,10 @@ namespace NadekoBot.Modules.Administration
|
||||
public partial class Administration : NadekoTopLevelModule
|
||||
{
|
||||
private IGuild _nadekoSupportServer;
|
||||
private readonly DbHandler _db;
|
||||
private readonly DbService _db;
|
||||
private readonly AdministrationService _admin;
|
||||
|
||||
public Administration(DbHandler db, AdministrationService admin)
|
||||
public Administration(DbService db, AdministrationService admin)
|
||||
{
|
||||
_db = db;
|
||||
_admin = admin;
|
||||
|
@ -14,10 +14,10 @@ namespace NadekoBot.Modules.Administration
|
||||
[Group]
|
||||
public class AutoAssignRoleCommands : NadekoSubmodule
|
||||
{
|
||||
private readonly DbHandler _db;
|
||||
private readonly DbService _db;
|
||||
private readonly AutoAssignRoleService _service;
|
||||
|
||||
public AutoAssignRoleCommands(AutoAssignRoleService service, DbHandler db)
|
||||
public AutoAssignRoleCommands(AutoAssignRoleService service, DbService db)
|
||||
{
|
||||
_db = db;
|
||||
_service = service;
|
||||
|
@ -12,10 +12,10 @@ namespace NadekoBot.Modules.Administration
|
||||
[Group]
|
||||
public class GameChannelCommands : NadekoSubmodule
|
||||
{
|
||||
private readonly DbHandler _db;
|
||||
private readonly DbService _db;
|
||||
private readonly GameVoiceChannelService _service;
|
||||
|
||||
public GameChannelCommands(GameVoiceChannelService service, DbHandler db)
|
||||
public GameChannelCommands(GameVoiceChannelService service, DbService db)
|
||||
{
|
||||
_db = db;
|
||||
_service = service;
|
||||
|
@ -22,9 +22,9 @@ namespace NadekoBot.Modules.Administration
|
||||
public class Migration : NadekoSubmodule
|
||||
{
|
||||
private const int CURRENT_VERSION = 1;
|
||||
private readonly DbHandler _db;
|
||||
private readonly DbService _db;
|
||||
|
||||
public Migration(DbHandler db)
|
||||
public Migration(DbService db)
|
||||
{
|
||||
_db = db;
|
||||
}
|
||||
|
@ -14,9 +14,9 @@ namespace NadekoBot.Modules.Administration
|
||||
public class MuteCommands : NadekoSubmodule
|
||||
{
|
||||
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;
|
||||
_db = db;
|
||||
|
@ -14,10 +14,10 @@ namespace NadekoBot.Modules.Administration
|
||||
public class PlayingRotateCommands : NadekoSubmodule
|
||||
{
|
||||
private static readonly object _locker = new object();
|
||||
private readonly DbHandler _db;
|
||||
private readonly DbService _db;
|
||||
private readonly PlayingRotateService _service;
|
||||
|
||||
public PlayingRotateCommands(PlayingRotateService service, DbHandler db)
|
||||
public PlayingRotateCommands(PlayingRotateService service, DbService db)
|
||||
{
|
||||
_db = db;
|
||||
_service = service;
|
||||
|
@ -19,9 +19,9 @@ namespace NadekoBot.Modules.Administration
|
||||
{
|
||||
private readonly ProtectionService _service;
|
||||
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;
|
||||
_mute = mute;
|
||||
|
@ -15,12 +15,12 @@ namespace NadekoBot.Modules.Administration
|
||||
public partial class Administration
|
||||
{
|
||||
[Group]
|
||||
public class RatelimitCommands : NadekoSubmodule
|
||||
public class SlowModeCommands : NadekoSubmodule
|
||||
{
|
||||
private readonly RatelimitService _service;
|
||||
private readonly DbHandler _db;
|
||||
private readonly SlowmodeService _service;
|
||||
private readonly DbService _db;
|
||||
|
||||
public RatelimitCommands(RatelimitService service, DbHandler db)
|
||||
public SlowModeCommands(SlowmodeService service, DbService db)
|
||||
{
|
||||
_service = service;
|
||||
_db = db;
|
||||
|
@ -18,9 +18,9 @@ namespace NadekoBot.Modules.Administration
|
||||
[Group]
|
||||
public class SelfAssignedRolesCommands : NadekoSubmodule
|
||||
{
|
||||
private readonly DbHandler _db;
|
||||
private readonly DbService _db;
|
||||
|
||||
public SelfAssignedRolesCommands(DbHandler db)
|
||||
public SelfAssignedRolesCommands(DbService db)
|
||||
{
|
||||
_db = db;
|
||||
}
|
||||
|
@ -21,14 +21,14 @@ namespace NadekoBot.Modules.Administration
|
||||
[Group]
|
||||
public class SelfCommands : NadekoSubmodule
|
||||
{
|
||||
private readonly DbHandler _db;
|
||||
private readonly DbService _db;
|
||||
|
||||
private static readonly object _locker = new object();
|
||||
private readonly SelfService _service;
|
||||
private readonly DiscordShardedClient _client;
|
||||
private readonly IImagesService _images;
|
||||
|
||||
public SelfCommands(DbHandler db, SelfService service, DiscordShardedClient client,
|
||||
public SelfCommands(DbService db, SelfService service, DiscordShardedClient client,
|
||||
IImagesService images)
|
||||
{
|
||||
_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]
|
||||
[OwnerOnly]
|
||||
public async Task ConnectShard(int shardid)
|
||||
|
@ -14,9 +14,9 @@ namespace NadekoBot.Modules.Administration
|
||||
public class ServerGreetCommands : NadekoSubmodule
|
||||
{
|
||||
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;
|
||||
_db = db;
|
||||
|
@ -19,10 +19,10 @@ namespace NadekoBot.Modules.Administration
|
||||
[Group]
|
||||
public class UserPunishCommands : NadekoSubmodule
|
||||
{
|
||||
private readonly DbHandler _db;
|
||||
private readonly DbService _db;
|
||||
private readonly MuteService _muteService;
|
||||
|
||||
public UserPunishCommands(DbHandler db, MuteService muteService)
|
||||
public UserPunishCommands(DbService db, MuteService muteService)
|
||||
{
|
||||
_db = db;
|
||||
_muteService = muteService;
|
||||
|
@ -19,9 +19,9 @@ namespace NadekoBot.Modules.Administration
|
||||
public class VcRoleCommands : NadekoSubmodule
|
||||
{
|
||||
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;
|
||||
_db = db;
|
||||
@ -31,7 +31,7 @@ namespace NadekoBot.Modules.Administration
|
||||
[RequireUserPermission(GuildPermission.ManageRoles)]
|
||||
[RequireUserPermission(GuildPermission.ManageChannels)]
|
||||
[RequireBotPermission(GuildPermission.ManageRoles)]
|
||||
//todo discord.net [RequireBotPermission(GuildPermission.ManageChannels)]
|
||||
//todo 999 discord.net [RequireBotPermission(GuildPermission.ManageChannels)]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task VcRole([Remainder]IRole role = null)
|
||||
{
|
||||
|
@ -18,9 +18,9 @@ namespace NadekoBot.Modules.Administration
|
||||
public class VoicePlusTextCommands : NadekoSubmodule
|
||||
{
|
||||
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;
|
||||
_db = db;
|
||||
|
@ -15,11 +15,11 @@ namespace NadekoBot.Modules.CustomReactions
|
||||
public class CustomReactions : NadekoTopLevelModule
|
||||
{
|
||||
private readonly IBotCredentials _creds;
|
||||
private readonly DbHandler _db;
|
||||
private readonly DbService _db;
|
||||
private readonly CustomReactionsService _crs;
|
||||
private readonly DiscordShardedClient _client;
|
||||
|
||||
public CustomReactions(IBotCredentials creds, DbHandler db, CustomReactionsService crs,
|
||||
public CustomReactions(IBotCredentials creds, DbService db, CustomReactionsService crs,
|
||||
DiscordShardedClient client)
|
||||
{
|
||||
_creds = creds;
|
||||
@ -239,7 +239,7 @@ namespace NadekoBot.Modules.CustomReactions
|
||||
if ((toDelete.GuildId == null || toDelete.GuildId == 0) && Context.Guild == null)
|
||||
{
|
||||
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();
|
||||
success = true;
|
||||
}
|
||||
|
@ -21,16 +21,16 @@ namespace NadekoBot.Modules.Gambling
|
||||
public class AnimalRacing : NadekoSubmodule
|
||||
{
|
||||
private readonly BotConfig _bc;
|
||||
private readonly CurrencyHandler _ch;
|
||||
private readonly CurrencyService _cs;
|
||||
private readonly DiscordShardedClient _client;
|
||||
|
||||
|
||||
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;
|
||||
_ch = ch;
|
||||
_cs = cs;
|
||||
_client = client;
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
public async Task Race()
|
||||
{
|
||||
var ar = new AnimalRace(Context.Guild.Id, (ITextChannel)Context.Channel, Prefix,
|
||||
_bc, _ch, _client,_localization, _strings);
|
||||
_bc, _cs, _client,_localization, _strings);
|
||||
|
||||
if (ar.Fail)
|
||||
await ReplyErrorLocalized("race_failed_starting").ConfigureAwait(false);
|
||||
@ -63,7 +63,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
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
|
||||
public class AnimalRace
|
||||
{
|
||||
@ -81,7 +81,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
|
||||
private readonly ITextChannel _raceChannel;
|
||||
private readonly BotConfig _bc;
|
||||
private readonly CurrencyHandler _ch;
|
||||
private readonly CurrencyService _cs;
|
||||
private readonly DiscordShardedClient _client;
|
||||
private readonly ILocalization _localization;
|
||||
private readonly NadekoStrings _strings;
|
||||
@ -89,12 +89,12 @@ namespace NadekoBot.Modules.Gambling
|
||||
public bool Started { get; private set; }
|
||||
|
||||
public AnimalRace(ulong serverId, ITextChannel channel, string prefix, BotConfig bc,
|
||||
CurrencyHandler ch, DiscordShardedClient client, ILocalization localization,
|
||||
CurrencyService cs, DiscordShardedClient client, ILocalization localization,
|
||||
NadekoStrings strings)
|
||||
{
|
||||
_prefix = prefix;
|
||||
_bc = bc;
|
||||
_ch = ch;
|
||||
_cs = cs;
|
||||
_log = LogManager.GetCurrentClassLogger();
|
||||
_serverId = serverId;
|
||||
_raceChannel = channel;
|
||||
@ -144,7 +144,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
var p = _participants.FirstOrDefault();
|
||||
|
||||
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();
|
||||
return;
|
||||
}
|
||||
@ -232,7 +232,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
{
|
||||
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);
|
||||
await _raceChannel.SendConfirmAsync(GetText("animal_race"),
|
||||
Format.Bold(GetText("animal_race_won_money", winner.User.Mention,
|
||||
@ -287,7 +287,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
return;
|
||||
}
|
||||
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);
|
||||
return;
|
||||
|
@ -36,13 +36,13 @@ namespace NadekoBot.Modules.Gambling
|
||||
private string _secretCode = string.Empty;
|
||||
private readonly DiscordShardedClient _client;
|
||||
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;
|
||||
_bc = bc;
|
||||
_ch = ch;
|
||||
_cs = cs;
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
@ -111,7 +111,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
{
|
||||
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);
|
||||
|
||||
try { await arg.DeleteAsync(new RequestOptions() { RetryMode = RetryMode.AlwaysFail }).ConfigureAwait(false); }
|
||||
@ -137,7 +137,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
desc, footer: footer)
|
||||
.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 Logger _log;
|
||||
private readonly DiscordShardedClient _client;
|
||||
private readonly CurrencyHandler _ch;
|
||||
private readonly CurrencyService _cs;
|
||||
|
||||
private IUserMessage StartingMessage { get; set; }
|
||||
|
||||
private CancellationTokenSource Source { get; }
|
||||
private CancellationToken CancelToken { get; }
|
||||
|
||||
public FlowerReactionEvent(DiscordShardedClient client, CurrencyHandler ch)
|
||||
public FlowerReactionEvent(DiscordShardedClient client, CurrencyService cs)
|
||||
{
|
||||
_log = LogManager.GetCurrentClassLogger();
|
||||
_client = client;
|
||||
_ch = ch;
|
||||
_cs = cs;
|
||||
Source = new CancellationTokenSource();
|
||||
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))
|
||||
{
|
||||
await _ch.AddCurrencyAsync(r.User.Value, "Flower Reaction Event", amount, false)
|
||||
await _cs.AddAsync(r.User.Value, "Flower Reaction Event", amount, false)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
@ -220,8 +220,8 @@ namespace NadekoBot.Modules.Gambling
|
||||
if (num == 10)
|
||||
{
|
||||
var images = _images.Dice;
|
||||
using (var imgOneStream = images[1].Value.ToStream())
|
||||
using (var imgZeroStream = images[0].Value.ToStream())
|
||||
using (var imgOneStream = images[1].ToStream())
|
||||
using (var imgZeroStream = images[0].ToStream())
|
||||
{
|
||||
Image imgOne = new Image(imgOneStream);
|
||||
Image imgZero = new Image(imgZeroStream);
|
||||
@ -229,7 +229,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
return new[] { imgOne, imgZero }.Merge();
|
||||
}
|
||||
}
|
||||
using (var die = _images.Dice[num].Value.ToStream())
|
||||
using (var die = _images.Dice[num].ToStream())
|
||||
{
|
||||
return new Image(die);
|
||||
}
|
||||
|
@ -18,15 +18,15 @@ namespace NadekoBot.Modules.Gambling
|
||||
{
|
||||
private readonly IImagesService _images;
|
||||
private readonly BotConfig _bc;
|
||||
private readonly CurrencyHandler _ch;
|
||||
private readonly CurrencyService _cs;
|
||||
|
||||
private readonly NadekoRandom rng = new NadekoRandom();
|
||||
|
||||
public FlipCoinCommands(IImagesService images, CurrencyHandler ch, BotConfig bc)
|
||||
public FlipCoinCommands(IImagesService images, CurrencyService cs, BotConfig bc)
|
||||
{
|
||||
_images = images;
|
||||
_bc = bc;
|
||||
_ch = ch;
|
||||
_cs = cs;
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
@ -74,47 +74,49 @@ namespace NadekoBot.Modules.Gambling
|
||||
await Context.Channel.SendFileAsync(imgs.Merge().ToStream(), $"{count} coins.png").ConfigureAwait(false);
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
public async Task Betflip(int amount, string guess)
|
||||
public enum BetFlipGuess
|
||||
{
|
||||
var guessStr = guess.Trim().ToUpperInvariant();
|
||||
if (guessStr != "H" && guessStr != "T" && guessStr != "HEADS" && guessStr != "TAILS")
|
||||
return;
|
||||
H = 1,
|
||||
Head = 1,
|
||||
Heads = 1,
|
||||
T = 2,
|
||||
Tail = 2,
|
||||
Tails = 2
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
public async Task Betflip(int amount, BetFlipGuess guess)
|
||||
{
|
||||
if (amount < _bc.MinimumBetAmount)
|
||||
{
|
||||
await ReplyErrorLocalized("min_bet_limit", _bc.MinimumBetAmount + _bc.CurrencySign).ConfigureAwait(false);
|
||||
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)
|
||||
{
|
||||
await ReplyErrorLocalized("not_enough", _bc.CurrencyPluralName).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
//heads = true
|
||||
//tails = false
|
||||
|
||||
//todo this seems stinky, no time to look at it right now
|
||||
var isHeads = guessStr == "HEADS" || guessStr == "H";
|
||||
var result = false;
|
||||
BetFlipGuess result;
|
||||
IEnumerable<byte> imageToSend;
|
||||
if (rng.Next(0, 2) == 1)
|
||||
{
|
||||
imageToSend = _images.Heads;
|
||||
result = true;
|
||||
result = BetFlipGuess.Heads;
|
||||
}
|
||||
else
|
||||
{
|
||||
imageToSend = _images.Tails;
|
||||
result = BetFlipGuess.Tails;
|
||||
}
|
||||
|
||||
string str;
|
||||
if (isHeads == result)
|
||||
if (guess == result)
|
||||
{
|
||||
var toWin = (int)Math.Round(amount * _bc.BetflipMultiplier);
|
||||
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
|
||||
{
|
||||
|
@ -20,8 +20,8 @@ namespace NadekoBot.Modules.Gambling
|
||||
public class FlowerShop : NadekoSubmodule
|
||||
{
|
||||
private readonly BotConfig _bc;
|
||||
private readonly DbHandler _db;
|
||||
private readonly CurrencyHandler _ch;
|
||||
private readonly DbService _db;
|
||||
private readonly CurrencyService _cs;
|
||||
private readonly DiscordShardedClient _client;
|
||||
|
||||
public enum Role
|
||||
@ -34,11 +34,11 @@ namespace NadekoBot.Modules.Gambling
|
||||
List
|
||||
}
|
||||
|
||||
public FlowerShop(BotConfig bc, DbHandler db, CurrencyHandler ch, DiscordShardedClient client)
|
||||
public FlowerShop(BotConfig bc, DbService db, CurrencyService cs, DiscordShardedClient client)
|
||||
{
|
||||
_db = db;
|
||||
_bc = bc;
|
||||
_ch = ch;
|
||||
_cs = cs;
|
||||
_client = client;
|
||||
}
|
||||
|
||||
@ -111,7 +111,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
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
|
||||
{
|
||||
@ -120,11 +120,11 @@ namespace NadekoBot.Modules.Gambling
|
||||
catch (Exception 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);
|
||||
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);
|
||||
return;
|
||||
}
|
||||
@ -144,7 +144,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
|
||||
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;
|
||||
using (var uow = _db.UnitOfWork)
|
||||
@ -163,7 +163,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
.AddField(efb => efb.WithName(GetText("name")).WithValue(entry.Name).WithIsInline(true)))
|
||||
.ConfigureAwait(false);
|
||||
|
||||
await _ch.AddCurrencyAsync(entry.AuthorId,
|
||||
await _cs.AddAsync(entry.AuthorId,
|
||||
$"Shop sell item - {entry.Name}",
|
||||
GetProfitAmount(entry.Price)).ConfigureAwait(false);
|
||||
}
|
||||
@ -174,7 +174,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
uow._context.Set<ShopEntryItem>().Add(item);
|
||||
uow.Complete();
|
||||
|
||||
await _ch.AddCurrencyAsync(Context.User.Id,
|
||||
await _cs.AddAsync(Context.User.Id,
|
||||
$"Shop error refund - {entry.Name}",
|
||||
entry.Price,
|
||||
uow).ConfigureAwait(false);
|
||||
|
@ -32,13 +32,13 @@ namespace NadekoBot.Modules.Gambling
|
||||
//thanks to judge for helping me with this
|
||||
|
||||
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;
|
||||
_bc = bc;
|
||||
_ch = ch;
|
||||
_cs = cs;
|
||||
}
|
||||
|
||||
public class SlotMachine
|
||||
@ -157,7 +157,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
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);
|
||||
return;
|
||||
@ -209,7 +209,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
var msg = GetText("better_luck");
|
||||
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);
|
||||
if (result.Multiplier == 1)
|
||||
msg = GetText("slot_single", _bc.CurrencySign, 1);
|
||||
|
@ -57,10 +57,10 @@ namespace NadekoBot.Modules.Gambling
|
||||
InsufficientAmount
|
||||
}
|
||||
|
||||
public WaifuClaimCommands(BotConfig bc, CurrencyHandler ch, DbHandler db)
|
||||
public WaifuClaimCommands(BotConfig bc, CurrencyService cs, DbService db)
|
||||
{
|
||||
_bc = bc;
|
||||
_ch = ch;
|
||||
_cs = cs;
|
||||
_db = db;
|
||||
}
|
||||
|
||||
@ -91,7 +91,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
{
|
||||
var claimer = uow.DiscordUsers.GetOrCreate(Context.User);
|
||||
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;
|
||||
}
|
||||
@ -116,7 +116,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
}
|
||||
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;
|
||||
}
|
||||
@ -138,7 +138,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
}
|
||||
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;
|
||||
}
|
||||
@ -230,13 +230,13 @@ namespace NadekoBot.Modules.Gambling
|
||||
|
||||
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);
|
||||
result = DivorceResult.SucessWithPenalty;
|
||||
}
|
||||
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;
|
||||
}
|
||||
@ -278,8 +278,8 @@ namespace NadekoBot.Modules.Gambling
|
||||
|
||||
private static readonly TimeSpan _affinityLimit = TimeSpan.FromMinutes(30);
|
||||
private readonly BotConfig _bc;
|
||||
private readonly CurrencyHandler _ch;
|
||||
private readonly DbHandler _db;
|
||||
private readonly CurrencyService _cs;
|
||||
private readonly DbService _db;
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
|
@ -13,14 +13,14 @@ namespace NadekoBot.Modules.Gambling
|
||||
public partial class Gambling : NadekoTopLevelModule
|
||||
{
|
||||
private readonly BotConfig _bc;
|
||||
private readonly DbHandler _db;
|
||||
private readonly CurrencyHandler _currency;
|
||||
private readonly DbService _db;
|
||||
private readonly CurrencyService _currency;
|
||||
|
||||
private string CurrencyName => _bc.CurrencyName;
|
||||
private string CurrencyPluralName => _bc.CurrencyPluralName;
|
||||
private string CurrencySign => _bc.CurrencySign;
|
||||
|
||||
public Gambling(BotConfig bc, DbHandler db, CurrencyHandler currency)
|
||||
public Gambling(BotConfig bc, DbService db, CurrencyService currency)
|
||||
{
|
||||
_bc = bc;
|
||||
_db = db;
|
||||
@ -71,13 +71,13 @@ namespace NadekoBot.Modules.Gambling
|
||||
{
|
||||
if (amount <= 0 || Context.User.Id == receiver.Id)
|
||||
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)
|
||||
{
|
||||
await ReplyErrorLocalized("not_enough", CurrencyPluralName).ConfigureAwait(false);
|
||||
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()))
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
@ -97,7 +97,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
if (amount <= 0)
|
||||
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);
|
||||
}
|
||||
|
||||
@ -110,7 +110,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
var users = (await Context.Guild.GetUsersAsync())
|
||||
.Where(u => u.GetRoles().Contains(role))
|
||||
.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})",
|
||||
amount)))
|
||||
.ConfigureAwait(false);
|
||||
@ -129,7 +129,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
if (amount <= 0)
|
||||
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);
|
||||
else
|
||||
await ReplyErrorLocalized("take_fail", amount + CurrencySign, Format.Bold(user.ToString()), CurrencyPluralName).ConfigureAwait(false);
|
||||
@ -143,7 +143,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
if (amount <= 0)
|
||||
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);
|
||||
else
|
||||
await ReplyErrorLocalized("take_fail", amount + CurrencySign, Format.Code(usrId.ToString()), CurrencyPluralName).ConfigureAwait(false);
|
||||
@ -210,7 +210,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
if (amount < 1)
|
||||
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);
|
||||
return;
|
||||
@ -227,19 +227,19 @@ namespace NadekoBot.Modules.Gambling
|
||||
if (rnd < 91)
|
||||
{
|
||||
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);
|
||||
}
|
||||
else if (rnd < 100)
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ namespace NadekoBot.Modules.Games
|
||||
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
|
||||
{
|
||||
private readonly ITextChannel _channel;
|
||||
|
@ -13,10 +13,10 @@ namespace NadekoBot.Modules.Games
|
||||
[Group]
|
||||
public class CleverBotCommands : NadekoSubmodule
|
||||
{
|
||||
private readonly DbHandler _db;
|
||||
private readonly GamesService _games;
|
||||
private readonly DbService _db;
|
||||
private readonly ChatterBotService _games;
|
||||
|
||||
public CleverBotCommands(DbHandler db, GamesService games)
|
||||
public CleverBotCommands(DbService db, ChatterBotService games)
|
||||
{
|
||||
_db = db;
|
||||
_games = games;
|
||||
@ -29,7 +29,7 @@ namespace NadekoBot.Modules.Games
|
||||
{
|
||||
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)
|
||||
{
|
||||
@ -40,7 +40,7 @@ namespace NadekoBot.Modules.Games
|
||||
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)
|
||||
{
|
||||
|
@ -24,16 +24,16 @@ namespace NadekoBot.Modules.Games
|
||||
[Group]
|
||||
public class PlantPickCommands : NadekoSubmodule
|
||||
{
|
||||
private readonly CurrencyHandler _ch;
|
||||
private readonly CurrencyService _cs;
|
||||
private readonly BotConfig _bc;
|
||||
private readonly GamesService _games;
|
||||
private readonly DbHandler _db;
|
||||
private readonly DbService _db;
|
||||
|
||||
public PlantPickCommands(BotConfig bc, CurrencyHandler ch, GamesService games,
|
||||
DbHandler db)
|
||||
public PlantPickCommands(BotConfig bc, CurrencyService cs, GamesService games,
|
||||
DbService db)
|
||||
{
|
||||
_bc = bc;
|
||||
_ch = ch;
|
||||
_cs = cs;
|
||||
_games = games;
|
||||
_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 _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)
|
||||
.ConfigureAwait(false);
|
||||
msg.DeleteAfter(10);
|
||||
@ -67,7 +67,7 @@ namespace NadekoBot.Modules.Games
|
||||
if (amount < 1)
|
||||
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)
|
||||
{
|
||||
await ReplyErrorLocalized("not_enough", _bc.CurrencySign).ConfigureAwait(false);
|
||||
@ -88,9 +88,9 @@ namespace NadekoBot.Modules.Games
|
||||
msgToSend += " " + GetText("pick_sn", Prefix);
|
||||
|
||||
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];
|
||||
|
@ -3,12 +3,8 @@ using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using NadekoBot.Attributes;
|
||||
using NadekoBot.Extensions;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using NadekoBot.Services;
|
||||
using NadekoBot.Services.Games;
|
||||
|
||||
namespace NadekoBot.Modules.Games
|
||||
{
|
||||
@ -17,12 +13,13 @@ namespace NadekoBot.Modules.Games
|
||||
[Group]
|
||||
public class PollCommands : NadekoSubmodule
|
||||
{
|
||||
public static ConcurrentDictionary<ulong, Poll> ActivePolls = new ConcurrentDictionary<ulong, Poll>();
|
||||
private readonly DiscordShardedClient _client;
|
||||
private readonly PollService _polls;
|
||||
|
||||
public PollCommands(DiscordShardedClient client)
|
||||
public PollCommands(DiscordShardedClient client, PollService polls)
|
||||
{
|
||||
_client = client;
|
||||
_polls = polls;
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
@ -42,8 +39,7 @@ namespace NadekoBot.Modules.Games
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task PollStats()
|
||||
{
|
||||
Poll poll;
|
||||
if (!ActivePolls.TryGetValue(Context.Guild.Id, out poll))
|
||||
if (!_polls.ActivePolls.TryGetValue(Context.Guild.Id, out var poll))
|
||||
return;
|
||||
|
||||
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)
|
||||
{
|
||||
var channel = (ITextChannel)Context.Channel;
|
||||
|
||||
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
|
||||
if(await _polls.StartPoll((ITextChannel)Context.Channel, Context.Message, arg, isPublic) == false)
|
||||
await ReplyErrorLocalized("poll_already_running").ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@ -75,151 +58,11 @@ namespace NadekoBot.Modules.Games
|
||||
{
|
||||
var channel = (ITextChannel)Context.Channel;
|
||||
|
||||
Poll poll;
|
||||
ActivePolls.TryRemove(channel.Guild.Id, out poll);
|
||||
_polls.ActivePolls.TryRemove(channel.Guild.Id, out var poll);
|
||||
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.Services.Games;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@ -71,15 +70,10 @@ namespace NadekoBot.Modules.Games
|
||||
public async Task Typeadd([Remainder] string text)
|
||||
{
|
||||
var channel = (ITextChannel)Context.Channel;
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
return;
|
||||
|
||||
_games.TypingArticles.Add(new TypingArticle
|
||||
{
|
||||
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));
|
||||
_games.AddTypingArticle(Context.User, text);
|
||||
|
||||
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 DiscordShardedClient _client;
|
||||
private readonly BotConfig _bc;
|
||||
private readonly CurrencyHandler _ch;
|
||||
private readonly CurrencyService _cs;
|
||||
|
||||
public IGuild Guild { get; }
|
||||
public ITextChannel Channel { get; }
|
||||
@ -44,14 +44,14 @@ namespace NadekoBot.Modules.Games.Trivia
|
||||
public int WinRequirement { get; }
|
||||
|
||||
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)
|
||||
{
|
||||
_log = LogManager.GetCurrentClassLogger();
|
||||
_strings = strings;
|
||||
_client = client;
|
||||
_bc = bc;
|
||||
_ch = ch;
|
||||
_cs = cs;
|
||||
|
||||
ShowHints = showHints;
|
||||
Guild = guild;
|
||||
@ -227,7 +227,7 @@ namespace NadekoBot.Modules.Games.Trivia
|
||||
}
|
||||
var reward = _bc.TriviaCurrencyReward;
|
||||
if (reward > 0)
|
||||
await _ch.AddCurrencyAsync(guildUser, "Won trivia", reward, true).ConfigureAwait(false);
|
||||
await _cs.AddAsync(guildUser, "Won trivia", reward, true).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -17,15 +17,15 @@ namespace NadekoBot.Modules.Games
|
||||
[Group]
|
||||
public class TriviaCommands : NadekoSubmodule
|
||||
{
|
||||
private readonly CurrencyHandler _ch;
|
||||
private readonly CurrencyService _cs;
|
||||
private readonly DiscordShardedClient _client;
|
||||
private readonly BotConfig _bc;
|
||||
|
||||
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;
|
||||
_bc = bc;
|
||||
}
|
||||
@ -49,7 +49,7 @@ namespace NadekoBot.Modules.Games
|
||||
var showHints = !additionalArgs.Contains("nohint");
|
||||
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))
|
||||
{
|
||||
try
|
||||
|
@ -14,19 +14,21 @@ using System.Collections.Generic;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
using System.Threading;
|
||||
using NadekoBot.Services.Music;
|
||||
using NadekoBot.DataStructures;
|
||||
|
||||
namespace NadekoBot.Modules.Music
|
||||
{
|
||||
[NoPublicBot]
|
||||
public class Music : NadekoTopLevelModule
|
||||
{
|
||||
private static MusicService _music;
|
||||
private readonly DiscordShardedClient _client;
|
||||
private readonly IBotCredentials _creds;
|
||||
private readonly IGoogleApiService _google;
|
||||
private readonly DbHandler _db;
|
||||
private readonly DbService _db;
|
||||
|
||||
public Music(DiscordShardedClient client, IBotCredentials creds, IGoogleApiService google,
|
||||
DbHandler db, MusicService music)
|
||||
DbService db, MusicService music)
|
||||
{
|
||||
_client = client;
|
||||
_creds = creds;
|
||||
|
@ -23,14 +23,14 @@ namespace NadekoBot.Modules.Permissions
|
||||
public class BlacklistCommands : NadekoSubmodule
|
||||
{
|
||||
private readonly BlacklistService _bs;
|
||||
private readonly DbHandler _db;
|
||||
private readonly DbService _db;
|
||||
private readonly IBotCredentials _creds;
|
||||
|
||||
private ConcurrentHashSet<ulong> BlacklistedUsers => _bs.BlacklistedUsers;
|
||||
private ConcurrentHashSet<ulong> BlacklistedGuilds => _bs.BlacklistedGuilds;
|
||||
private ConcurrentHashSet<ulong> BlacklistedChannels => _bs.BlacklistedChannels;
|
||||
|
||||
public BlacklistCommands(BlacklistService bs, DbHandler db, IBotCredentials creds)
|
||||
public BlacklistCommands(BlacklistService bs, DbService db, IBotCredentials creds)
|
||||
{
|
||||
_bs = bs;
|
||||
_db = db;
|
||||
|
@ -17,7 +17,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
[Group]
|
||||
public class CmdCdsCommands : NadekoSubmodule
|
||||
{
|
||||
private readonly DbHandler _db;
|
||||
private readonly DbService _db;
|
||||
private readonly CmdCdService _service;
|
||||
|
||||
private ConcurrentDictionary<ulong, ConcurrentHashSet<CommandCooldown>> CommandCooldowns
|
||||
@ -25,7 +25,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
private ConcurrentDictionary<ulong, ConcurrentHashSet<ActiveCooldown>> ActiveCooldowns
|
||||
=> _service.ActiveCooldowns;
|
||||
|
||||
public CmdCdsCommands(CmdCdService service, DbHandler db)
|
||||
public CmdCdsCommands(CmdCdService service, DbService db)
|
||||
{
|
||||
_service = service;
|
||||
_db = db;
|
||||
@ -88,40 +88,6 @@ namespace NadekoBot.Modules.Permissions
|
||||
else
|
||||
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]
|
||||
public class FilterCommands : NadekoSubmodule
|
||||
{
|
||||
private readonly DbHandler _db;
|
||||
private readonly DbService _db;
|
||||
private readonly FilterService _service;
|
||||
|
||||
public FilterCommands(FilterService service, DbHandler db)
|
||||
public FilterCommands(FilterService service, DbService db)
|
||||
{
|
||||
_service = service;
|
||||
_db = db;
|
||||
|
@ -16,9 +16,9 @@ namespace NadekoBot.Modules.Permissions
|
||||
public class GlobalPermissionCommands : NadekoSubmodule
|
||||
{
|
||||
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;
|
||||
_db = db;
|
||||
|
@ -14,10 +14,10 @@ namespace NadekoBot.Modules.Permissions.Commands
|
||||
public class ResetPermissionsCommands : NadekoSubmodule
|
||||
{
|
||||
private readonly PermissionsService _service;
|
||||
private readonly DbHandler _db;
|
||||
private readonly DbService _db;
|
||||
private readonly GlobalPermissionService _globalPerms;
|
||||
|
||||
public ResetPermissionsCommands(PermissionsService service, GlobalPermissionService globalPerms, DbHandler db)
|
||||
public ResetPermissionsCommands(PermissionsService service, GlobalPermissionService globalPerms, DbService db)
|
||||
{
|
||||
_service = service;
|
||||
_db = db;
|
||||
@ -29,7 +29,7 @@ namespace NadekoBot.Modules.Permissions.Commands
|
||||
[RequireUserPermission(GuildPermission.Administrator)]
|
||||
public async Task ResetPermissions()
|
||||
{
|
||||
//todo 80 move to service
|
||||
//todo 50 move to service
|
||||
using (var uow = _db.UnitOfWork)
|
||||
{
|
||||
var config = uow.GuildConfigs.GcWithPermissionsv2For(Context.Guild.Id);
|
||||
@ -44,7 +44,7 @@ namespace NadekoBot.Modules.Permissions.Commands
|
||||
[OwnerOnly]
|
||||
public async Task ResetGlobalPermissions()
|
||||
{
|
||||
//todo 80 move to service
|
||||
//todo 50 move to service
|
||||
using (var uow = _db.UnitOfWork)
|
||||
{
|
||||
var gc = uow.BotConfig.GetOrCreate();
|
||||
|
@ -15,10 +15,10 @@ namespace NadekoBot.Modules.Permissions
|
||||
{
|
||||
public partial class Permissions : NadekoTopLevelModule
|
||||
{
|
||||
private readonly DbHandler _db;
|
||||
private readonly DbService _db;
|
||||
private readonly PermissionsService _service;
|
||||
|
||||
public Permissions(PermissionsService service, DbHandler db)
|
||||
public Permissions(PermissionsService service, DbService db)
|
||||
{
|
||||
_db = db;
|
||||
_service = service;
|
||||
|
@ -15,16 +15,16 @@ namespace NadekoBot.Modules.Pokemon
|
||||
public class Pokemon : NadekoTopLevelModule
|
||||
{
|
||||
private readonly PokemonService _service;
|
||||
private readonly DbHandler _db;
|
||||
private readonly DbService _db;
|
||||
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;
|
||||
_db = db;
|
||||
_bc = bc;
|
||||
_ch = ch;
|
||||
_cs = cs;
|
||||
}
|
||||
|
||||
private int GetDamage(PokemonType usertype, PokemonType targetType)
|
||||
@ -229,7 +229,7 @@ namespace NadekoBot.Modules.Pokemon
|
||||
var target = (targetUser.Id == user.Id) ? "yourself" : targetUser.Mention;
|
||||
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);
|
||||
return;
|
||||
@ -295,7 +295,7 @@ namespace NadekoBot.Modules.Pokemon
|
||||
var amount = 1;
|
||||
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);
|
||||
return;
|
||||
|
@ -9,7 +9,7 @@ using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
//todo drawing
|
||||
//todo 50 drawing
|
||||
namespace NadekoBot.Modules.Searches
|
||||
{
|
||||
public partial class Searches
|
||||
|
@ -17,10 +17,10 @@ namespace NadekoBot.Modules.Searches
|
||||
[Group]
|
||||
public class StreamNotificationCommands : NadekoSubmodule
|
||||
{
|
||||
private readonly DbHandler _db;
|
||||
private readonly DbService _db;
|
||||
private readonly StreamNotificationService _service;
|
||||
|
||||
public StreamNotificationCommands(DbHandler db, StreamNotificationService service)
|
||||
public StreamNotificationCommands(DbService db, StreamNotificationService service)
|
||||
{
|
||||
_db = db;
|
||||
_service = service;
|
||||
|
@ -59,7 +59,7 @@ namespace NadekoBot.Modules.Searches
|
||||
return;
|
||||
}
|
||||
|
||||
if (_searches.TranslatedChannels.TryRemove(channel.Id, out var throwaway))
|
||||
if (_searches.TranslatedChannels.TryRemove(channel.Id, out _))
|
||||
{
|
||||
await ReplyConfirmLocalized("atl_stopped").ConfigureAwait(false);
|
||||
return;
|
||||
|
@ -20,10 +20,10 @@ namespace NadekoBot.Modules.Utility
|
||||
public class CommandMapCommands : NadekoSubmodule
|
||||
{
|
||||
private readonly UtilityService _service;
|
||||
private readonly DbHandler _db;
|
||||
private readonly DbService _db;
|
||||
private readonly DiscordShardedClient _client;
|
||||
|
||||
public CommandMapCommands(UtilityService service, DbHandler db, DiscordShardedClient client)
|
||||
public CommandMapCommands(UtilityService service, DbService db, DiscordShardedClient client)
|
||||
{
|
||||
_service = service;
|
||||
_db = db;
|
||||
|
@ -18,13 +18,13 @@ namespace NadekoBot.Modules.Utility
|
||||
{
|
||||
private readonly DiscordShardedClient _client;
|
||||
private readonly IStatsService _stats;
|
||||
private readonly CommandHandler _ch;
|
||||
private readonly CommandHandler _cmdHandler;
|
||||
|
||||
public InfoCommands(DiscordShardedClient client, IStatsService stats, CommandHandler ch)
|
||||
{
|
||||
_client = client;
|
||||
_stats = stats;
|
||||
_ch = ch;
|
||||
_cmdHandler = ch;
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
@ -129,7 +129,7 @@ namespace NadekoBot.Modules.Utility
|
||||
int startCount = page * activityPerPage;
|
||||
|
||||
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",
|
||||
++startCount,
|
||||
@ -141,7 +141,7 @@ namespace NadekoBot.Modules.Utility
|
||||
.WithTitle(GetText("activity_page", page + 1))
|
||||
.WithOkColor()
|
||||
.WithFooter(efb => efb.WithText(GetText("activity_users_total",
|
||||
_ch.UserMessagesSent.Count)))
|
||||
_cmdHandler.UserMessagesSent.Count)))
|
||||
.WithDescription(str.ToString()));
|
||||
}
|
||||
}
|
||||
|
@ -22,9 +22,9 @@ namespace NadekoBot.Modules.Utility
|
||||
{
|
||||
private readonly MessageRepeaterService _service;
|
||||
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;
|
||||
_client = client;
|
||||
|
@ -1,19 +1,12 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading.Tasks;
|
||||
using Discord.Commands;
|
||||
using NadekoBot.Attributes;
|
||||
using NadekoBot.Modules.Utility.Models;
|
||||
using Newtonsoft.Json;
|
||||
using System.Threading;
|
||||
using System;
|
||||
using System.Collections.Immutable;
|
||||
using NadekoBot.Services;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
using NadekoBot.Extensions;
|
||||
using Discord;
|
||||
using NLog;
|
||||
using NadekoBot.Services.Utility;
|
||||
|
||||
namespace NadekoBot.Modules.Utility
|
||||
{
|
||||
@ -22,27 +15,26 @@ namespace NadekoBot.Modules.Utility
|
||||
[Group]
|
||||
public class PatreonCommands : NadekoSubmodule
|
||||
{
|
||||
//todo rename patreon thingy and move it to be a service, or a part of utility service
|
||||
private readonly PatreonThingy patreon;
|
||||
private readonly PatreonRewardsService _patreon;
|
||||
private readonly IBotCredentials _creds;
|
||||
private readonly BotConfig _config;
|
||||
private readonly DbHandler _db;
|
||||
private readonly CurrencyHandler _currency;
|
||||
private readonly DbService _db;
|
||||
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;
|
||||
_config = config;
|
||||
_db = db;
|
||||
_currency = currency;
|
||||
patreon = PatreonThingy.GetInstance(creds, db, currency);
|
||||
_patreon = p;
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[OwnerOnly]
|
||||
public async Task PatreonRewardsReload()
|
||||
{
|
||||
await patreon.LoadPledges().ConfigureAwait(false);
|
||||
await _patreon.LoadPledges().ConfigureAwait(false);
|
||||
|
||||
await Context.Channel.SendConfirmAsync("👌").ConfigureAwait(false);
|
||||
}
|
||||
@ -60,7 +52,7 @@ namespace NadekoBot.Modules.Utility
|
||||
int amount = 0;
|
||||
try
|
||||
{
|
||||
amount = await patreon.ClaimReward(Context.User.Id).ConfigureAwait(false);
|
||||
amount = await _patreon.ClaimReward(Context.User.Id).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -72,7 +64,7 @@ namespace NadekoBot.Modules.Utility
|
||||
await ReplyConfirmLocalized("clpa_success", amount + _config.CurrencySign).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
var rem = (patreon.Interval - (DateTime.UtcNow - patreon.LastUpdate));
|
||||
var rem = (_patreon.Interval - (DateTime.UtcNow - _patreon.LastUpdate));
|
||||
var helpcmd = Format.Code(NadekoBot.Prefix + "donate");
|
||||
await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
|
||||
.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]
|
||||
public class QuoteCommands : NadekoSubmodule
|
||||
{
|
||||
private readonly DbHandler _db;
|
||||
private readonly DbService _db;
|
||||
|
||||
public QuoteCommands(DbHandler db)
|
||||
public QuoteCommands(DbService db)
|
||||
{
|
||||
_db = db;
|
||||
}
|
||||
|
@ -18,9 +18,9 @@ namespace NadekoBot.Modules.Utility
|
||||
public class RemindCommands : NadekoSubmodule
|
||||
{
|
||||
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;
|
||||
_db = db;
|
||||
|
@ -494,7 +494,6 @@ namespace NadekoBot.Services.Utility
|
||||
}
|
||||
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}"));
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ using NadekoBot.Services.Games;
|
||||
using NadekoBot.Services.Administration;
|
||||
using NadekoBot.Services.Permissions;
|
||||
using NadekoBot.Services.Utility;
|
||||
using NadekoBot.Services.Help;
|
||||
|
||||
namespace NadekoBot
|
||||
{
|
||||
@ -45,7 +46,7 @@ namespace NadekoBot
|
||||
|
||||
public ImmutableArray<GuildConfig> AllGuildConfigs { get; }
|
||||
public BotConfig BotConfig { get; }
|
||||
public DbHandler Db { get; }
|
||||
public DbService Db { get; }
|
||||
public CommandService CommandService { get; }
|
||||
|
||||
public DiscordShardedClient Client { get; }
|
||||
@ -60,7 +61,7 @@ namespace NadekoBot
|
||||
_log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
Credentials = new BotCredentials();
|
||||
Db = new DbHandler(Credentials);
|
||||
Db = new DbService(Credentials);
|
||||
|
||||
using (var uow = Db.UnitOfWork)
|
||||
{
|
||||
@ -99,7 +100,7 @@ namespace NadekoBot
|
||||
var commandHandler = new CommandHandler(Client, CommandService, Credentials, this);
|
||||
var stats = new StatsService(Client, commandHandler, Credentials);
|
||||
var images = new ImagesService();
|
||||
var currencyHandler = new CurrencyHandler(BotConfig, Db);
|
||||
var currencyHandler = new CurrencyService(BotConfig, Db);
|
||||
|
||||
//module services
|
||||
//todo 90 - autodiscover, DI, and add instead of manual like this
|
||||
@ -109,27 +110,36 @@ namespace NadekoBot
|
||||
var repeaterService = new MessageRepeaterService(Client, AllGuildConfigs);
|
||||
var converterService = new ConverterService(Db);
|
||||
#endregion
|
||||
|
||||
#region Searches
|
||||
var searchesService = new SearchesService(Client, googleApiService, Db);
|
||||
var streamNotificationService = new StreamNotificationService(Db, Client, strings);
|
||||
#endregion
|
||||
|
||||
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 helpService = new HelpService(BotConfig);
|
||||
|
||||
#region Games
|
||||
var gamesService = new GamesService(Client, BotConfig, AllGuildConfigs, strings, images);
|
||||
var chatterBotService = new ChatterBotService(Client, AllGuildConfigs);
|
||||
var pollService = new PollService(Client, strings);
|
||||
#endregion
|
||||
|
||||
#region administration
|
||||
var administrationService = new AdministrationService(AllGuildConfigs, commandHandler);
|
||||
var greetSettingsService = new GreetSettingsService(Client, AllGuildConfigs, Db);
|
||||
var selfService = new SelfService(this, commandHandler, Db, BotConfig);
|
||||
var vcRoleService = new VcRoleService(Client, AllGuildConfigs);
|
||||
var selfService = new SelfService(Client, this, commandHandler, Db, BotConfig, localization, strings, Credentials);
|
||||
var vcRoleService = new VcRoleService(Client, AllGuildConfigs, Db);
|
||||
var vPlusTService = new VplusTService(Client, AllGuildConfigs, strings, 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 playingRotateService = new PlayingRotateService(Client, BotConfig, musicService);
|
||||
var gameVcService = new GameVoiceChannelService(Client, Db, AllGuildConfigs);
|
||||
var autoAssignRoleService = new AutoAssignRoleService(Client, AllGuildConfigs);
|
||||
var permissionsService = new PermissionsService(Db);
|
||||
var permissionsService = new PermissionsService(Db, BotConfig);
|
||||
var blacklistService = new BlacklistService(BotConfig);
|
||||
var cmdcdsService = new CmdCdService(AllGuildConfigs);
|
||||
var filterService = new FilterService(AllGuildConfigs);
|
||||
@ -148,9 +158,9 @@ namespace NadekoBot
|
||||
.Add<NadekoStrings>(strings)
|
||||
.Add<DiscordShardedClient>(Client)
|
||||
.Add<BotConfig>(BotConfig)
|
||||
.Add<CurrencyHandler>(currencyHandler)
|
||||
.Add<CurrencyService>(currencyHandler)
|
||||
.Add<CommandHandler>(commandHandler)
|
||||
.Add<DbHandler>(Db)
|
||||
.Add<DbService>(Db)
|
||||
//modules
|
||||
.Add<UtilityService>(utilityService)
|
||||
.Add(remindService)
|
||||
@ -162,7 +172,10 @@ namespace NadekoBot
|
||||
.Add<MusicService>(musicService)
|
||||
.Add<GreetSettingsService>(greetSettingsService)
|
||||
.Add<CustomReactionsService>(crService)
|
||||
.Add<HelpService>(helpService)
|
||||
.Add<GamesService>(gamesService)
|
||||
.Add(chatterBotService)
|
||||
.Add(pollService)
|
||||
.Add<AdministrationService>(administrationService)
|
||||
.Add(selfService)
|
||||
.Add(vcRoleService)
|
||||
@ -228,9 +241,13 @@ namespace NadekoBot
|
||||
await commandHandler.StartHandling().ConfigureAwait(false);
|
||||
|
||||
var _ = await CommandService.AddModulesAsync(this.GetType().GetTypeInfo().Assembly);
|
||||
#if !GLOBAL_NADEKO
|
||||
//todo uncomment this
|
||||
//await CommandService.AddModuleAsync<Music>().ConfigureAwait(false);
|
||||
#if GLOBAL_NADEKO
|
||||
//unload modules which are not available on the public bot
|
||||
CommandService
|
||||
.Modules
|
||||
.ToArray()
|
||||
.Where(x => x.Preconditions.Any(y => y.GetType() == typeof(NoPublicBot)))
|
||||
.ForEach(x => CommandService.RemoveModuleAsync(x));
|
||||
#endif
|
||||
Ready = true;
|
||||
_log.Info(await stats.Print().ConfigureAwait(false));
|
||||
|
@ -29,11 +29,8 @@
|
||||
<ItemGroup>
|
||||
<Compile Remove="data\**\*;credentials.json;credentials_example.json" />
|
||||
<Compile Remove="Modules\Administration\**" />
|
||||
<Compile Remove="Modules\NSFW\**" />
|
||||
<EmbeddedResource Remove="Modules\Administration\**" />
|
||||
<EmbeddedResource Remove="Modules\NSFW\**" />
|
||||
<None Remove="Modules\Administration\**" />
|
||||
<None Remove="Modules\NSFW\**" />
|
||||
<Compile Remove="Modules\Gambling\Commands\Lucky7Commands.cs" />
|
||||
<Compile Include="Modules\Administration\Administration.cs" />
|
||||
<Compile Include="Modules\Administration\Commands\AutoAssignRoleCommands.cs" />
|
||||
@ -87,6 +84,7 @@
|
||||
<PackageReference Include="Microsoft.Extensions.PlatformAbstractions" Version="1.1.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="10.0.2" />
|
||||
<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" />
|
||||
</ItemGroup>
|
||||
|
||||
@ -102,5 +100,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Modules\Music\Classes\" />
|
||||
<Folder Include="Modules\Utility\Models\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
@ -15,10 +15,10 @@ namespace NadekoBot.Services.Administration
|
||||
public readonly ConcurrentHashSet<ulong> GameVoiceChannels = new ConcurrentHashSet<ulong>();
|
||||
|
||||
private readonly Logger _log;
|
||||
private readonly DbHandler _db;
|
||||
private readonly DbService _db;
|
||||
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();
|
||||
_db = db;
|
||||
|
@ -26,9 +26,9 @@ namespace NadekoBot.Services.Administration
|
||||
|
||||
private readonly Logger _log = LogManager.GetCurrentClassLogger();
|
||||
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;
|
||||
_db = db;
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Discord.WebSocket;
|
||||
using NadekoBot.DataStructures.ModuleBehaviors;
|
||||
using NadekoBot.Extensions;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
using NLog;
|
||||
@ -6,22 +7,22 @@ using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Discord;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NadekoBot.Services.Administration
|
||||
{
|
||||
public class RatelimitService
|
||||
public class SlowmodeService : IEarlyBlocker
|
||||
{
|
||||
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>> IgnoredUsers = new ConcurrentDictionary<ulong, HashSet<ulong>>();
|
||||
|
||||
private readonly Logger _log;
|
||||
private readonly DiscordShardedClient _client;
|
||||
|
||||
public RatelimitService(DiscordShardedClient client, IEnumerable<GuildConfig> gcs)
|
||||
public SlowmodeService(IEnumerable<GuildConfig> gcs)
|
||||
{
|
||||
_log = LogManager.GetCurrentClassLogger();
|
||||
_client = client;
|
||||
|
||||
IgnoredRoles = new ConcurrentDictionary<ulong, HashSet<ulong>>(
|
||||
gcs.ToDictionary(x => x.GuildId,
|
||||
@ -30,24 +31,33 @@ namespace NadekoBot.Services.Administration
|
||||
IgnoredUsers = new ConcurrentDictionary<ulong, HashSet<ulong>>(
|
||||
gcs.ToDictionary(x => x.GuildId,
|
||||
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;
|
||||
var channel = usrMsg?.Channel as SocketTextChannel;
|
||||
|
||||
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();
|
||||
await usrMsg.DeleteAsync();
|
||||
return true;
|
||||
}
|
||||
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
|
||||
{
|
||||
private readonly RatelimitService _svc;
|
||||
private readonly SlowmodeService _svc;
|
||||
|
||||
public class RatelimitedUser
|
||||
{
|
||||
@ -22,7 +22,7 @@ namespace NadekoBot.Services.Administration
|
||||
public int MaxMessages { get; set; }
|
||||
public int PerSeconds { get; set; }
|
||||
|
||||
public Ratelimiter(RatelimitService svc)
|
||||
public Ratelimiter(SlowmodeService 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 Discord.WebSocket;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NadekoBot.Services.Administration
|
||||
{
|
||||
public class SelfService
|
||||
public class SelfService : ILateExecutor
|
||||
{
|
||||
public volatile bool ForwardDMs;
|
||||
public volatile bool ForwardDMsToAllOwners;
|
||||
|
||||
private readonly NadekoBot _bot;
|
||||
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,
|
||||
BotConfig bc)
|
||||
public SelfService(DiscordShardedClient client, NadekoBot bot, CommandHandler cmdHandler, DbService db,
|
||||
BotConfig bc, ILocalization localization, NadekoStrings strings, IBotCredentials creds)
|
||||
{
|
||||
_bot = bot;
|
||||
_cmdHandler = cmdHandler;
|
||||
_db = db;
|
||||
_log = LogManager.GetCurrentClassLogger();
|
||||
_localization = localization;
|
||||
_strings = strings;
|
||||
_client = client;
|
||||
_creds = creds;
|
||||
|
||||
using (var uow = _db.UnitOfWork)
|
||||
{
|
||||
@ -37,6 +57,112 @@ namespace NadekoBot.Services.Administration
|
||||
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
|
||||
{
|
||||
private readonly Logger _log;
|
||||
private readonly DbService _db;
|
||||
private readonly DiscordShardedClient _client;
|
||||
|
||||
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();
|
||||
_db = db;
|
||||
_client = client;
|
||||
|
||||
client.UserVoiceStateUpdated += ClientOnUserVoiceStateUpdated;
|
||||
_client.UserVoiceStateUpdated += ClientOnUserVoiceStateUpdated;
|
||||
VcRoles = new ConcurrentDictionary<ulong, ConcurrentDictionary<ulong, IRole>>();
|
||||
var missingRoles = new List<VcRoleInfo>();
|
||||
foreach (var gconf in gcs)
|
||||
{
|
||||
var g = client.GetGuild(gconf.GuildId);
|
||||
var g = _client.GetGuild(gconf.GuildId);
|
||||
if (g == null)
|
||||
continue; //todo delete everything from db if guild doesn't exist?
|
||||
continue;
|
||||
|
||||
var infos = new ConcurrentDictionary<ulong, IRole>();
|
||||
VcRoles.TryAdd(gconf.GuildId, infos);
|
||||
@ -34,11 +39,21 @@ namespace NadekoBot.Services.Administration
|
||||
{
|
||||
var role = g.GetRole(ri.RoleId);
|
||||
if (role == null)
|
||||
continue; //todo remove this entry from db
|
||||
{
|
||||
missingRoles.Add(ri);
|
||||
continue;
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -22,11 +22,11 @@ namespace NadekoBot.Services.Administration
|
||||
private readonly ConcurrentDictionary<ulong, SemaphoreSlim> _guildLockObjects = new ConcurrentDictionary<ulong, SemaphoreSlim>();
|
||||
private readonly DiscordShardedClient _client;
|
||||
private readonly NadekoStrings _strings;
|
||||
private readonly DbHandler _db;
|
||||
private readonly DbService _db;
|
||||
private readonly Logger _log;
|
||||
|
||||
public VplusTService(DiscordShardedClient client, IEnumerable<GuildConfig> gcs, NadekoStrings strings,
|
||||
DbHandler db)
|
||||
DbService db)
|
||||
{
|
||||
_client = client;
|
||||
_strings = strings;
|
||||
|
@ -18,14 +18,14 @@ namespace NadekoBot.Services.ClashOfClans
|
||||
public class ClashOfClansService
|
||||
{
|
||||
private readonly DiscordShardedClient _client;
|
||||
private readonly DbHandler _db;
|
||||
private readonly DbService _db;
|
||||
private readonly ILocalization _localization;
|
||||
private readonly NadekoStrings _strings;
|
||||
private readonly Timer checkWarTimer;
|
||||
|
||||
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;
|
||||
_db = db;
|
||||
|
@ -87,20 +87,6 @@ namespace NadekoBot.Services
|
||||
|
||||
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.MessageUpdated += (oldmsg, newMsg, channel) =>
|
||||
{
|
||||
@ -126,80 +112,6 @@ namespace NadekoBot.Services
|
||||
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 Task LogSuccessfulExecution(IUserMessage usrMsg, bool exec, ITextChannel channel, params int[] execPoints)
|
||||
@ -233,166 +145,66 @@ namespace NadekoBot.Services
|
||||
//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<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)
|
||||
private async 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 (usrMsg == null) //has to be an user message, not system/other messages.
|
||||
return;
|
||||
|
||||
if (usrMsg.Author.Id == 193022505026453504)
|
||||
return;
|
||||
if (!(msg is SocketUserMessage usrMsg))
|
||||
return;
|
||||
#if !GLOBAL_NADEKO
|
||||
// track how many messagges each user is sending
|
||||
UserMessagesSent.AddOrUpdate(usrMsg.Author.Id, 1, (key, old) => ++old);
|
||||
// track how many messagges each user is sending
|
||||
UserMessagesSent.AddOrUpdate(usrMsg.Author.Id, 1, (key, old) => ++old);
|
||||
#endif
|
||||
|
||||
var channel = msg.Channel as SocketTextChannel;
|
||||
var guild = channel?.Guild;
|
||||
var channel = msg.Channel as ISocketMessageChannel;
|
||||
var guild = (msg.Channel as SocketTextChannel)?.Guild;
|
||||
|
||||
await TryRunCommand(guild, channel, usrMsg);
|
||||
}
|
||||
catch (Exception ex)
|
||||
await TryRunCommand(guild, channel, usrMsg);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_log.Warn("Error in CommandHandler");
|
||||
_log.Warn(ex);
|
||||
if (ex.InnerException != null)
|
||||
{
|
||||
_log.Warn("Error in CommandHandler");
|
||||
_log.Warn(ex);
|
||||
if (ex.InnerException != null)
|
||||
{
|
||||
_log.Warn("Inner Exception of the error in CommandHandler");
|
||||
_log.Warn(ex.InnerException);
|
||||
}
|
||||
_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;
|
||||
|
||||
foreach (var svc in _services)
|
||||
{
|
||||
if (svc is IBlockingExecutor _executor &&
|
||||
await _executor.TryExecute(_client, guild, usrMsg))
|
||||
if (svc is IEarlyBlocker blocker &&
|
||||
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);
|
||||
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;
|
||||
|
||||
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);
|
||||
execTime = Environment.TickCount - execTime;
|
||||
|
||||
////todo permissions
|
||||
//if (exec.Result.IsSuccess)
|
||||
//{
|
||||
////todo commandHandler
|
||||
if (exec)
|
||||
{
|
||||
// await CommandExecuted(usrMsg, exec.CommandInfo).ConfigureAwait(false);
|
||||
// await LogSuccessfulExecution(usrMsg, exec, channel, exec2, exec3, execTime).ConfigureAwait(false);
|
||||
// return;
|
||||
//}
|
||||
await LogSuccessfulExecution(usrMsg, exec, channel as ITextChannel, exec2, exec3, execTime).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
//else if (!exec.Result.IsSuccess && exec.Result.Error != CommandError.UnknownCommand)
|
||||
//{
|
||||
// LogErroredExecution(usrMsg, exec, channel, exec2, exec3, execTime);
|
||||
@ -453,20 +265,20 @@ namespace NadekoBot.Services
|
||||
// }
|
||||
// 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
|
||||
// users who are voting on private polls (sending a number in a DM)
|
||||
if (int.TryParse(usrMsg.Content, out int vote)) return;
|
||||
|
||||
////todo help
|
||||
//await usrMsg.Channel.SendMessageAsync(Help.DMHelpString).ConfigureAwait(false);
|
||||
|
||||
////todo selfcommands
|
||||
//await SelfCommands.HandleDmForwarding(usrMsg, ownerChannels).ConfigureAwait(false);
|
||||
if (svc is ILateExecutor exec)
|
||||
{
|
||||
await exec.LateExecute(_client, guild, usrMsg).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Task<bool> ExecuteCommandAsync(CommandContext context, int argPos, IServiceProvider serviceProvider, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception)
|
||||
@ -540,16 +352,16 @@ namespace NadekoBot.Services
|
||||
// }
|
||||
//}
|
||||
|
||||
////////future
|
||||
//////int price;
|
||||
//////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);
|
||||
////// if (!success)
|
||||
////// {
|
||||
////// return new ExecuteCommandResult(cmd, pc, SearchResult.FromError(CommandError.Exception, $"Insufficient funds. You need {price}{NadekoBot.BotConfig.CurrencySign} to run this command."));
|
||||
////// }
|
||||
//////}
|
||||
//////future
|
||||
////int price;
|
||||
////if (Permissions.CommandCostCommands.CommandCosts.TryGetValue(cmd.Aliases.First().Trim().ToLowerInvariant(), out price) && price > 0)
|
||||
////{
|
||||
//// var success = await _cs.RemoveCurrencyAsync(context.User.Id, $"Running {cmd.Name} command.", price).ConfigureAwait(false);
|
||||
//// if (!success)
|
||||
//// {
|
||||
//// return new ExecuteCommandResult(cmd, pc, SearchResult.FromError(CommandError.Exception, $"Insufficient funds. You need {price}{NadekoBot.BotConfig.CurrencySign} to run this command."));
|
||||
//// }
|
||||
////}
|
||||
}
|
||||
|
||||
////todo perms
|
||||
@ -564,11 +376,18 @@ namespace NadekoBot.Services
|
||||
// GlobalCommandsCooldown constant (miliseconds)
|
||||
if (!UsersOnShortCooldown.Add(context.Message.Author.Id))
|
||||
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
|
||||
//if (CmdCdsCommands.HasCooldown(cmd, context.Guild, context.User))
|
||||
// return new ExecuteCommandResult(cmd, null, SearchResult.FromError(CommandError.Exception, "That command is on a cooldown for you."));
|
||||
var commandName = cmd.Aliases.First();
|
||||
foreach (var svc in _services)
|
||||
{
|
||||
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);
|
||||
return true;
|
||||
|
@ -7,20 +7,20 @@ using NadekoBot.Services.Database;
|
||||
|
||||
namespace NadekoBot.Services
|
||||
{
|
||||
public class CurrencyHandler
|
||||
public class CurrencyService
|
||||
{
|
||||
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;
|
||||
_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)
|
||||
try { await author.SendErrorAsync($"`You lost:` {amount} {_config.CurrencySign}\n`Reason:` {reason}").ConfigureAwait(false); } catch { }
|
||||
@ -28,12 +28,11 @@ namespace NadekoBot.Services
|
||||
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)
|
||||
throw new ArgumentNullException(nameof(amount));
|
||||
|
||||
|
||||
if (uow == null)
|
||||
{
|
||||
using (uow = _db.UnitOfWork)
|
||||
@ -61,15 +60,15 @@ namespace NadekoBot.Services
|
||||
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)
|
||||
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)
|
||||
throw new ArgumentNullException(nameof(amount));
|
||||
|
@ -11,7 +11,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace NadekoBot.Services.CustomReactions
|
||||
{
|
||||
public class CustomReactionsService : IBlockingExecutor
|
||||
public class CustomReactionsService : IEarlyBlockingExecutor
|
||||
{
|
||||
public CustomReaction[] GlobalReactions = new 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>();
|
||||
|
||||
private readonly Logger _log;
|
||||
private readonly DbHandler _db;
|
||||
private readonly DbService _db;
|
||||
private readonly DiscordShardedClient _client;
|
||||
|
||||
public CustomReactionsService(DbHandler db, DiscordShardedClient client)
|
||||
public CustomReactionsService(DbService db, DiscordShardedClient client)
|
||||
{
|
||||
_log = LogManager.GetCurrentClassLogger();
|
||||
_db = db;
|
||||
@ -90,16 +90,15 @@ namespace NadekoBot.Services.CustomReactions
|
||||
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
|
||||
// todo log custom reaction executions. return struct with info
|
||||
var cr = await Task.Run(() => TryGetCustomReaction(msg)).ConfigureAwait(false);
|
||||
if (cr != null) //if it was, don't execute the command
|
||||
if (cr != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
//todo permissions
|
||||
//if (guild != null)
|
||||
//{
|
||||
// PermissionCache pc = Permissions.GetCache(guild.Id);
|
||||
@ -107,7 +106,6 @@ namespace NadekoBot.Services.CustomReactions
|
||||
// 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);
|
||||
|
@ -64,6 +64,7 @@ Nadeko Support Server: https://discord.gg/nadekobot";
|
||||
public List<StartupCommand> StartupCommands { get; set; }
|
||||
public HashSet<BlockedCmdOrMdl> BlockedCommands { get; set; }
|
||||
public HashSet<BlockedCmdOrMdl> BlockedModules { get; set; }
|
||||
public int PermissionVersion { get; set; } = 1;
|
||||
}
|
||||
|
||||
public class BlockedCmdOrMdl : DbEntity
|
||||
|
@ -126,10 +126,6 @@ namespace NadekoBot.Services.Database.Repositories.Impl
|
||||
.Where(gc => gc.RootPermission != null)
|
||||
.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++)
|
||||
{
|
||||
query = query.ThenInclude(gc => gc.Next);
|
||||
|
@ -3,17 +3,15 @@ using NadekoBot.Services.Database;
|
||||
|
||||
namespace NadekoBot.Services
|
||||
{
|
||||
public class DbHandler
|
||||
public class DbService
|
||||
{
|
||||
private readonly DbContextOptions options;
|
||||
|
||||
private string connectionString { get; }
|
||||
private readonly string _connectionString;
|
||||
|
||||
static DbHandler() { }
|
||||
|
||||
public DbHandler(IBotCredentials creds)
|
||||
public DbService(IBotCredentials creds)
|
||||
{
|
||||
connectionString = creds.Db.ConnectionString;
|
||||
_connectionString = creds.Db.ConnectionString;
|
||||
var optionsBuilder = new DbContextOptionsBuilder();
|
||||
optionsBuilder.UseSqlite(creds.Db.ConnectionString);
|
||||
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 Logger _log;
|
||||
|
||||
public ConcurrentDictionary<ulong, Lazy<ChatterBotSession>> CleverbotGuilds { get; }
|
||||
|
||||
public readonly string TypingArticlesPath = "data/typing_articles2.json";
|
||||
public List<TypingArticle> TypingArticles { get; } = new List<TypingArticle>();
|
||||
|
||||
@ -52,11 +50,6 @@ namespace NadekoBot.Services.Games
|
||||
|
||||
}, 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
|
||||
client.MessageReceived += PotentialFlowerGeneration;
|
||||
GenerationChannels = new ConcurrentHashSet<ulong>(gcs
|
||||
@ -73,55 +66,15 @@ namespace NadekoBot.Services.Games
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public string PrepareMessage(IUserMessage msg, out ChatterBotSession cleverbot)
|
||||
public void AddTypingArticle(IUser user, string text)
|
||||
{
|
||||
var channel = msg.Channel as ITextChannel;
|
||||
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))
|
||||
TypingArticles.Add(new TypingArticle
|
||||
{
|
||||
message = msg.Content.Substring(normalMention.Length).Trim();
|
||||
}
|
||||
else if (msg.Content.StartsWith(nickMention))
|
||||
{
|
||||
message = msg.Content.Substring(nickMention.Length).Trim();
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
Title = $"Text added on {DateTime.UtcNow} by {user}",
|
||||
Text = text.SanitizeMentions(),
|
||||
});
|
||||
|
||||
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;
|
||||
File.WriteAllText(TypingArticlesPath, JsonConvert.SerializeObject(TypingArticles));
|
||||
}
|
||||
|
||||
public ConcurrentHashSet<ulong> GenerationChannels { get; }
|
||||
@ -130,7 +83,9 @@ namespace NadekoBot.Services.Games
|
||||
//channelId/last generation
|
||||
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();
|
||||
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)
|
||||
=> _strings.GetText(key, ch.GuildId, "Games".ToLowerInvariant(), rep);
|
||||
|
||||
private Task PotentialFlowerGeneration(SocketMessage imsg)
|
||||
private async Task PotentialFlowerGeneration(SocketMessage imsg)
|
||||
{
|
||||
var msg = imsg as SocketUserMessage;
|
||||
if (msg == null || msg.Author.IsBot)
|
||||
return Task.CompletedTask;
|
||||
return;
|
||||
|
||||
var channel = imsg.Channel as ITextChannel;
|
||||
if (channel == null)
|
||||
return Task.CompletedTask;
|
||||
return;
|
||||
|
||||
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 rng = new NadekoRandom();
|
||||
var dropAmount = _bc.CurrencyDropAmount;
|
||||
|
||||
//todo i'm stupid :rofl: wtg kwoth. real async programming :100: :ok_hand: :100: :100: :thumbsup:
|
||||
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)
|
||||
if (dropAmount > 0)
|
||||
{
|
||||
LastGenerations.AddOrUpdate(channel.Id, DateTime.Now, (id, old) => DateTime.Now);
|
||||
|
||||
var dropAmount = _bc.CurrencyDropAmount;
|
||||
|
||||
if (dropAmount > 0)
|
||||
var msgs = new IUserMessage[dropAmount];
|
||||
var prefix = NadekoBot.Prefix;
|
||||
var toSend = dropAmount == 1
|
||||
? GetText(channel, "curgen_sn", _bc.CurrencySign)
|
||||
+ " " + 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 prefix = NadekoBot.Prefix;
|
||||
var toSend = dropAmount == 1
|
||||
? GetText(channel, "curgen_sn", _bc.CurrencySign)
|
||||
+ " " + 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);
|
||||
var sent = await channel.SendFileAsync(
|
||||
fileStream,
|
||||
file.Name,
|
||||
toSend).ConfigureAwait(false);
|
||||
|
||||
msgs[0] = sent;
|
||||
}
|
||||
|
||||
PlantedFlowers.AddOrUpdate(channel.Id, msgs.ToList(), (id, old) => { old.AddRange(msgs); return old; });
|
||||
msgs[0] = sent;
|
||||
}
|
||||
|
||||
PlantedFlowers.AddOrUpdate(channel.Id, msgs.ToList(), (id, old) => { old.AddRange(msgs); return old; });
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.GetCurrentClassLogger().Warn(ex);
|
||||
}
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogManager.GetCurrentClassLogger().Warn(ex);
|
||||
}
|
||||
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
|
||||
{
|
||||
private readonly DbHandler _db;
|
||||
private readonly DbService _db;
|
||||
|
||||
public readonly ConcurrentDictionary<ulong, GreetSettings> GuildConfigsCache;
|
||||
private readonly DiscordShardedClient _client;
|
||||
private readonly Logger _log;
|
||||
|
||||
public GreetSettingsService(DiscordShardedClient client, IEnumerable<GuildConfig> guildConfigs, DbHandler db)
|
||||
public GreetSettingsService(DiscordShardedClient client, IEnumerable<GuildConfig> guildConfigs, DbService db)
|
||||
{
|
||||
_db = db;
|
||||
_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.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace NadekoBot.Services
|
||||
@ -9,8 +8,8 @@ namespace NadekoBot.Services
|
||||
ImmutableArray<byte> Heads { get; }
|
||||
ImmutableArray<byte> Tails { get; }
|
||||
|
||||
ImmutableArray<KeyValuePair<string, ImmutableArray<byte>>> Currency { get; }
|
||||
ImmutableArray<KeyValuePair<string, ImmutableArray<byte>>> Dice { get; }
|
||||
ImmutableArray<(string, ImmutableArray<byte>)> Currency { get; }
|
||||
ImmutableArray<ImmutableArray<byte>> Dice { get; }
|
||||
|
||||
ImmutableArray<byte> SlotBackground { get; }
|
||||
ImmutableArray<ImmutableArray<byte>> SlotEmojis { get; }
|
||||
|
@ -162,7 +162,7 @@ namespace NadekoBot.Services.Impl
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
//todo AsyncEnumerable
|
||||
|
||||
public async Task<IReadOnlyDictionary<string, TimeSpan>> GetVideoDurationsAsync(IEnumerable<string> videoIds)
|
||||
{
|
||||
var videoIdsList = videoIds as List<string> ?? videoIds.ToList();
|
||||
|
@ -1,6 +1,5 @@
|
||||
using NLog;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
@ -31,10 +30,9 @@ namespace NadekoBot.Services.Impl
|
||||
public ImmutableArray<byte> Heads { get; private set; }
|
||||
public ImmutableArray<byte> Tails { get; private set; }
|
||||
|
||||
//todo C#7 tuples
|
||||
public ImmutableArray<KeyValuePair<string, ImmutableArray<byte>>> Currency { get; private set; }
|
||||
public ImmutableArray<(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<ImmutableArray<byte>> SlotNumbers { get; private set; }
|
||||
@ -59,15 +57,12 @@ namespace NadekoBot.Services.Impl
|
||||
Tails = File.ReadAllBytes(_tailsPath).ToImmutableArray();
|
||||
|
||||
Currency = Directory.GetFiles(_currencyImagesPath)
|
||||
.Select(x => new KeyValuePair<string, ImmutableArray<byte>>(
|
||||
Path.GetFileName(x),
|
||||
File.ReadAllBytes(x).ToImmutableArray()))
|
||||
.Select(x => (Path.GetFileName(x), File.ReadAllBytes(x).ToImmutableArray()))
|
||||
.ToImmutableArray();
|
||||
|
||||
Dice = Directory.GetFiles(_diceImagesPath)
|
||||
.OrderBy(x => int.Parse(Path.GetFileNameWithoutExtension(x)))
|
||||
.Select(x => new KeyValuePair<string, ImmutableArray<byte>>(x,
|
||||
File.ReadAllBytes(x).ToImmutableArray()))
|
||||
.Select(x => File.ReadAllBytes(x).ToImmutableArray())
|
||||
.ToImmutableArray();
|
||||
|
||||
SlotBackground = File.ReadAllBytes(_slotBackgroundPath).ToImmutableArray();
|
||||
|
@ -10,13 +10,13 @@ namespace NadekoBot.Services
|
||||
public class Localization : ILocalization
|
||||
{
|
||||
private readonly Logger _log;
|
||||
private readonly DbHandler _db;
|
||||
private readonly DbService _db;
|
||||
|
||||
public ConcurrentDictionary<ulong, CultureInfo> GuildCultureInfos { get; }
|
||||
public CultureInfo DefaultCultureInfo { get; private set; } = CultureInfo.CurrentCulture;
|
||||
|
||||
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();
|
||||
_db = db;
|
||||
|
@ -61,7 +61,7 @@ namespace NadekoBot.Services
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -10,6 +10,7 @@ using NLog;
|
||||
using System.IO;
|
||||
using VideoLibrary;
|
||||
using System.Net.Http;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NadekoBot.Services.Music
|
||||
{
|
||||
@ -20,16 +21,17 @@ namespace NadekoBot.Services.Music
|
||||
private readonly IGoogleApiService _google;
|
||||
private readonly NadekoStrings _strings;
|
||||
private readonly ILocalization _localization;
|
||||
private readonly DbHandler _db;
|
||||
private readonly DbService _db;
|
||||
private readonly Logger _log;
|
||||
private readonly SoundCloudApiService _sc;
|
||||
private readonly IBotCredentials _creds;
|
||||
private readonly ConcurrentDictionary<ulong, float> _defaultVolumes;
|
||||
|
||||
public ConcurrentDictionary<ulong, MusicPlayer> MusicPlayers { get; } = new ConcurrentDictionary<ulong, MusicPlayer>();
|
||||
|
||||
public MusicService(IGoogleApiService google,
|
||||
NadekoStrings strings, ILocalization localization, DbHandler db,
|
||||
SoundCloudApiService sc, IBotCredentials creds)
|
||||
NadekoStrings strings, ILocalization localization, DbService db,
|
||||
SoundCloudApiService sc, IBotCredentials creds, IEnumerable<GuildConfig> gcs)
|
||||
{
|
||||
_google = google;
|
||||
_strings = strings;
|
||||
@ -41,6 +43,8 @@ namespace NadekoBot.Services.Music
|
||||
|
||||
try { Directory.Delete(MusicDataPath, true); } catch { }
|
||||
|
||||
_defaultVolumes = new ConcurrentDictionary<ulong, float>(gcs.ToDictionary(x => x.GuildId, x => x.DefaultMusicVolume));
|
||||
|
||||
Directory.CreateDirectory(MusicDataPath);
|
||||
}
|
||||
|
||||
@ -57,12 +61,14 @@ namespace NadekoBot.Services.Music
|
||||
|
||||
return MusicPlayers.GetOrAdd(guildId, server =>
|
||||
{
|
||||
float vol;// SpecificConfigurations.Default.Of(server.Id).DefaultMusicVolume;
|
||||
using (var uow = _db.UnitOfWork)
|
||||
var vol = _defaultVolumes.GetOrAdd(guildId, (id) =>
|
||||
{
|
||||
//todo move to cached variable
|
||||
vol = uow.GuildConfigs.For(guildId, set => set).DefaultMusicVolume;
|
||||
}
|
||||
using (var uow = _db.UnitOfWork)
|
||||
{
|
||||
return uow.GuildConfigs.For(guildId, set => set).DefaultMusicVolume;
|
||||
}
|
||||
});
|
||||
|
||||
var mp = new MusicPlayer(voiceCh, textCh, vol, _google);
|
||||
IUserMessage playingMessage = 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.Linq;
|
||||
using Discord;
|
||||
using Discord.WebSocket;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NadekoBot.Services.Permissions
|
||||
{
|
||||
public class BlacklistService
|
||||
public class BlacklistService : IEarlyBlocker
|
||||
{
|
||||
public ConcurrentHashSet<ulong> BlacklistedUsers { get; set; }
|
||||
public ConcurrentHashSet<ulong> BlacklistedGuilds { get; set; }
|
||||
public ConcurrentHashSet<ulong> BlacklistedChannels { get; set; }
|
||||
public ConcurrentHashSet<ulong> BlacklistedUsers { get; }
|
||||
public ConcurrentHashSet<ulong> BlacklistedGuilds { get; }
|
||||
public ConcurrentHashSet<ulong> BlacklistedChannels { get; }
|
||||
|
||||
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));
|
||||
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.Generic;
|
||||
using System.Linq;
|
||||
using Discord;
|
||||
using Discord.WebSocket;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NadekoBot.Services.Permissions
|
||||
{
|
||||
public class CmdCdService
|
||||
public class CmdCdService : ILateBlocker
|
||||
{
|
||||
public ConcurrentDictionary<ulong, ConcurrentHashSet<CommandCooldown>> CommandCooldowns { get; }
|
||||
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,
|
||||
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
|
||||
|
@ -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.Generic;
|
||||
using System.Linq;
|
||||
using Discord;
|
||||
using Discord.WebSocket;
|
||||
using System.Threading.Tasks;
|
||||
using NadekoBot.Extensions;
|
||||
using Discord.Net;
|
||||
using NLog;
|
||||
|
||||
namespace NadekoBot.Services.Permissions
|
||||
{
|
||||
public class FilterService
|
||||
public class FilterService : IEarlyBlocker
|
||||
{
|
||||
private readonly Logger _log;
|
||||
|
||||
public ConcurrentHashSet<ulong> InviteFilteringChannels { get; }
|
||||
public ConcurrentHashSet<ulong> InviteFilteringServers { get; }
|
||||
|
||||
@ -34,6 +43,8 @@ namespace NadekoBot.Services.Permissions
|
||||
|
||||
public FilterService(IEnumerable<GuildConfig> gcs)
|
||||
{
|
||||
_log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
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)));
|
||||
|
||||
@ -46,5 +57,61 @@ namespace NadekoBot.Services.Permissions
|
||||
|
||||
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 NadekoBot.DataStructures.ModuleBehaviors;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
using NLog;
|
||||
using System;
|
||||
@ -6,25 +7,27 @@ using System.Collections.Concurrent;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Discord;
|
||||
using Discord.WebSocket;
|
||||
|
||||
namespace NadekoBot.Services.Permissions
|
||||
{
|
||||
public class PermissionsService
|
||||
public class PermissionsService : ILateBlocker
|
||||
{
|
||||
private readonly DbHandler _db;
|
||||
private readonly DbService _db;
|
||||
private readonly Logger _log;
|
||||
|
||||
//guildid, root permission
|
||||
public ConcurrentDictionary<ulong, PermissionCache> Cache { get; } =
|
||||
new ConcurrentDictionary<ulong, PermissionCache>();
|
||||
|
||||
public PermissionsService(DbHandler db)
|
||||
public PermissionsService(DbService db, BotConfig bc)
|
||||
{
|
||||
_log = LogManager.GetCurrentClassLogger();
|
||||
_db = db;
|
||||
|
||||
var sw = Stopwatch.StartNew();
|
||||
TryMigratePermissions();
|
||||
TryMigratePermissions(bc);
|
||||
using (var uow = _db.UnitOfWork)
|
||||
{
|
||||
foreach (var x in uow.GuildConfigs.Permissionsv2ForAll())
|
||||
@ -59,61 +62,67 @@ namespace NadekoBot.Services.Permissions
|
||||
return pc;
|
||||
}
|
||||
|
||||
private void TryMigratePermissions()
|
||||
private void TryMigratePermissions(BotConfig bc)
|
||||
{
|
||||
var log = LogManager.GetCurrentClassLogger();
|
||||
using (var uow = _db.UnitOfWork)
|
||||
{
|
||||
var oldCache = new ConcurrentDictionary<ulong, OldPermissionCache>(uow.GuildConfigs
|
||||
.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())
|
||||
if (bc.PermissionVersion <= 1)
|
||||
{
|
||||
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
|
||||
log.Info("Permission version is 1, upgrading to 2.");
|
||||
var oldCache = new ConcurrentDictionary<ulong, OldPermissionCache>(uow.GuildConfigs
|
||||
.OldPermissionsForAll()
|
||||
.Where(x => x.RootPermission != null) // there is a check inside already, but just in case
|
||||
.ToDictionary(k => k.GuildId,
|
||||
v => new OldPermissionCache()
|
||||
{
|
||||
Permissions = new PermissionsCollection<Permissionv2>(newPerms),
|
||||
Verbose = gc.VerbosePermissions,
|
||||
PermRole = gc.PermissionRole,
|
||||
});
|
||||
gc.Permissions = newPerms;
|
||||
RootPermission = v.RootPermission,
|
||||
Verbose = v.VerbosePermissions,
|
||||
PermRole = v.PermissionRole
|
||||
}));
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
@ -151,5 +160,39 @@ namespace NadekoBot.Services.Permissions
|
||||
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 IGoogleApiService _google;
|
||||
private readonly DbHandler _db;
|
||||
private readonly DbService _db;
|
||||
private readonly Logger _log;
|
||||
|
||||
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<MagicItem> MagicItems { get; } = new List<MagicItem>();
|
||||
|
||||
public SearchesService(DiscordShardedClient client, IGoogleApiService google, DbHandler db)
|
||||
public SearchesService(DiscordShardedClient client, IGoogleApiService google, DbService db)
|
||||
{
|
||||
_client = client;
|
||||
_google = google;
|
||||
|
@ -19,11 +19,11 @@ namespace NadekoBot.Services.Searches
|
||||
private bool firstStreamNotifPass { get; set; } = true;
|
||||
private readonly ConcurrentDictionary<string, StreamStatus> _cachedStatuses = new ConcurrentDictionary<string, StreamStatus>();
|
||||
|
||||
private readonly DbHandler _db;
|
||||
private readonly DbService _db;
|
||||
private readonly DiscordShardedClient _client;
|
||||
private readonly NadekoStrings _strings;
|
||||
|
||||
public StreamNotificationService(DbHandler db, DiscordShardedClient client, NadekoStrings strings)
|
||||
public StreamNotificationService(DbService db, DiscordShardedClient client, NadekoStrings strings)
|
||||
{
|
||||
_db = db;
|
||||
_client = client;
|
||||
|
@ -17,9 +17,9 @@ namespace NadekoBot.Services.Utility
|
||||
private readonly Logger _log;
|
||||
private Timer _timer;
|
||||
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();
|
||||
_db = db;
|
||||
|
@ -7,6 +7,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace NadekoBot.Services.Utility
|
||||
{
|
||||
//todo 50 rewrite
|
||||
public class MessageRepeaterService
|
||||
{
|
||||
//messagerepeater
|
||||
@ -23,7 +24,6 @@ namespace NadekoBot.Services.Utility
|
||||
#else
|
||||
await Task.Delay(30000).ConfigureAwait(false);
|
||||
#endif
|
||||
//todo this is pretty terrible :kms: no time
|
||||
Repeaters = new ConcurrentDictionary<ulong, ConcurrentQueue<RepeatRunner>>(gcs
|
||||
.ToDictionary(gc => gc.GuildId,
|
||||
gc => new ConcurrentQueue<RepeatRunner>(gc.GuildRepeaters
|
||||
|
@ -1,6 +1,6 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace NadekoBot.Modules.Utility.Models
|
||||
namespace NadekoBot.Services.Utility.Patreon
|
||||
{
|
||||
public class PatreonData
|
||||
{
|
@ -1,4 +1,4 @@
|
||||
namespace NadekoBot.Modules.Utility.Models
|
||||
namespace NadekoBot.Services.Utility.Patreon
|
||||
{
|
||||
public class Attributes
|
||||
{
|
@ -1,4 +1,4 @@
|
||||
namespace NadekoBot.Modules.Utility.Models
|
||||
namespace NadekoBot.Services.Utility.Patreon
|
||||
{
|
||||
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