Revert "1.9 2017/11/30"
This commit is contained in:
parent
be9352bc03
commit
0589728f58
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 15
|
# Visual Studio 15
|
||||||
VisualStudioVersion = 15.0.26730.3
|
VisualStudioVersion = 15.0.26430.12
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{04929013-5BAB-42B0-B9B2-8F2BB8F16AF2}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{04929013-5BAB-42B0-B9B2-8F2BB8F16AF2}"
|
||||||
EndProject
|
EndProject
|
||||||
@ -33,7 +33,4 @@ Global
|
|||||||
GlobalSection(NestedProjects) = preSolution
|
GlobalSection(NestedProjects) = preSolution
|
||||||
{45EC1473-C678-4857-A544-07DFE0D0B478} = {04929013-5BAB-42B0-B9B2-8F2BB8F16AF2}
|
{45EC1473-C678-4857-A544-07DFE0D0B478} = {04929013-5BAB-42B0-B9B2-8F2BB8F16AF2}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
|
||||||
SolutionGuid = {5F3F555C-855F-4BE8-B526-D062D3E8ACA4}
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"sdk": { "version": "2.0.0" }
|
"sdk": { "version": "1.0.1" }
|
||||||
}
|
}
|
@ -2,11 +2,12 @@
|
|||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using NadekoBot.Services.Impl;
|
using NadekoBot.Services.Impl;
|
||||||
|
|
||||||
namespace NadekoBot.Common.Attributes
|
namespace NadekoBot.Common.Attributes
|
||||||
{
|
{
|
||||||
public class Aliases : AliasAttribute
|
public class Aliases : AliasAttribute
|
||||||
{
|
{
|
||||||
public Aliases([CallerMemberName] string memberName = "") : base(Localization.LoadCommand(memberName.ToLowerInvariant()).Cmd.Split(' ').Skip(1).ToArray())
|
public Aliases([CallerMemberName] string memberName = "") : base(Localization.LoadCommandString(memberName.ToLowerInvariant() + "_cmd").Split(' ').Skip(1).ToArray())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ namespace NadekoBot.Common.Attributes
|
|||||||
{
|
{
|
||||||
public class Description : SummaryAttribute
|
public class Description : SummaryAttribute
|
||||||
{
|
{
|
||||||
public Description([CallerMemberName] string memberName="") : base(Localization.LoadCommand(memberName.ToLowerInvariant()).Desc)
|
public Description([CallerMemberName] string memberName="") : base(Localization.LoadCommandString(memberName.ToLowerInvariant() + "_desc"))
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ namespace NadekoBot.Common.Attributes
|
|||||||
{
|
{
|
||||||
public class NadekoCommand : CommandAttribute
|
public class NadekoCommand : CommandAttribute
|
||||||
{
|
{
|
||||||
public NadekoCommand([CallerMemberName] string memberName="") : base(Localization.LoadCommand(memberName.ToLowerInvariant()).Cmd)
|
public NadekoCommand([CallerMemberName] string memberName="") : base(Localization.LoadCommandString(memberName.ToLowerInvariant() + "_cmd").Split(' ')[0])
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ namespace NadekoBot.Common.Attributes
|
|||||||
{
|
{
|
||||||
public class Usage : RemarksAttribute
|
public class Usage : RemarksAttribute
|
||||||
{
|
{
|
||||||
public Usage([CallerMemberName] string memberName="") : base(Localization.LoadCommand(memberName.ToLowerInvariant()).Usage)
|
public Usage([CallerMemberName] string memberName="") : base(Localization.LoadCommandString(memberName.ToLowerInvariant()+"_usage"))
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
namespace NadekoBot.Common
|
|
||||||
{
|
|
||||||
public class CommandData
|
|
||||||
{
|
|
||||||
public string Cmd { get; set; }
|
|
||||||
public string Usage { get; set; }
|
|
||||||
public string Desc { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
1949
src/NadekoBot/Migrations/20170913022654_total-xp.Designer.cs
generated
1949
src/NadekoBot/Migrations/20170913022654_total-xp.Designer.cs
generated
File diff suppressed because it is too large
Load Diff
@ -1,27 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
namespace NadekoBot.Migrations
|
|
||||||
{
|
|
||||||
public partial class totalxp : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<int>(
|
|
||||||
name: "TotalXp",
|
|
||||||
table: "DiscordUser",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: 0);
|
|
||||||
|
|
||||||
migrationBuilder.Sql(MigrationQueries.TotalXp);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "TotalXp",
|
|
||||||
table: "DiscordUser");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -1,25 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
|
||||||
|
|
||||||
namespace NadekoBot.Migrations
|
|
||||||
{
|
|
||||||
public partial class clubadmins : Migration
|
|
||||||
{
|
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.AddColumn<bool>(
|
|
||||||
name: "IsClubAdmin",
|
|
||||||
table: "DiscordUser",
|
|
||||||
nullable: false,
|
|
||||||
defaultValue: false);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Down(MigrationBuilder migrationBuilder)
|
|
||||||
{
|
|
||||||
migrationBuilder.DropColumn(
|
|
||||||
name: "IsClubAdmin",
|
|
||||||
table: "DiscordUser");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -34,9 +34,5 @@ INSERT INTO DiscordUser
|
|||||||
FROM DiscordUser_tmp;
|
FROM DiscordUser_tmp;
|
||||||
|
|
||||||
DROP TABLE DiscordUser_tmp;";
|
DROP TABLE DiscordUser_tmp;";
|
||||||
public static string TotalXp { get; } =
|
|
||||||
@"UPDATE DiscordUser
|
|
||||||
SET TotalXp = ifnull((SELECT SUM(Xp) FROM UserXpStats WHERE UserId = DiscordUser.UserId), 0)";
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -462,18 +462,14 @@ namespace NadekoBot.Migrations
|
|||||||
|
|
||||||
b.Property<string>("Discriminator");
|
b.Property<string>("Discriminator");
|
||||||
|
|
||||||
b.Property<bool>("IsClubAdmin");
|
|
||||||
|
|
||||||
b.Property<DateTime>("LastLevelUp")
|
b.Property<DateTime>("LastLevelUp")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasDefaultValue(new DateTime(2017, 9, 15, 5, 48, 8, 660, DateTimeKind.Local));
|
.HasDefaultValue(new DateTime(2017, 9, 11, 22, 0, 31, 236, DateTimeKind.Local));
|
||||||
|
|
||||||
b.Property<DateTime>("LastXpGain");
|
b.Property<DateTime>("LastXpGain");
|
||||||
|
|
||||||
b.Property<int>("NotifyOnLevelUp");
|
b.Property<int>("NotifyOnLevelUp");
|
||||||
|
|
||||||
b.Property<int>("TotalXp");
|
|
||||||
|
|
||||||
b.Property<ulong>("UserId");
|
b.Property<ulong>("UserId");
|
||||||
|
|
||||||
b.Property<string>("Username");
|
b.Property<string>("Username");
|
||||||
@ -1366,7 +1362,7 @@ namespace NadekoBot.Migrations
|
|||||||
|
|
||||||
b.Property<DateTime>("LastLevelUp")
|
b.Property<DateTime>("LastLevelUp")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasDefaultValue(new DateTime(2017, 9, 15, 5, 48, 8, 665, DateTimeKind.Local));
|
.HasDefaultValue(new DateTime(2017, 9, 11, 22, 0, 31, 238, DateTimeKind.Local));
|
||||||
|
|
||||||
b.Property<int>("NotifyOnLevelUp");
|
b.Property<int>("NotifyOnLevelUp");
|
||||||
|
|
||||||
|
@ -30,9 +30,8 @@ namespace NadekoBot.Modules.Administration
|
|||||||
private readonly IImagesService _images;
|
private readonly IImagesService _images;
|
||||||
private readonly MusicService _music;
|
private readonly MusicService _music;
|
||||||
private readonly IBotConfigProvider _bc;
|
private readonly IBotConfigProvider _bc;
|
||||||
private readonly NadekoBot _bot;
|
|
||||||
|
|
||||||
public SelfCommands(DbService db, NadekoBot bot, DiscordSocketClient client,
|
public SelfCommands(DbService db, DiscordSocketClient client,
|
||||||
MusicService music, IImagesService images, IBotConfigProvider bc)
|
MusicService music, IImagesService images, IBotConfigProvider bc)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
@ -40,7 +39,6 @@ namespace NadekoBot.Modules.Administration
|
|||||||
_images = images;
|
_images = images;
|
||||||
_music = music;
|
_music = music;
|
||||||
_bc = bc;
|
_bc = bc;
|
||||||
_bot = bot;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -351,7 +349,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[OwnerOnly]
|
[OwnerOnly]
|
||||||
public async Task SetGame([Remainder] string game = null)
|
public async Task SetGame([Remainder] string game = null)
|
||||||
{
|
{
|
||||||
await _bot.SetGameAsync(game).ConfigureAwait(false);
|
await _client.SetGameAsync(game).ConfigureAwait(false);
|
||||||
|
|
||||||
await ReplyConfirmLocalized("set_game").ConfigureAwait(false);
|
await ReplyConfirmLocalized("set_game").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ using NadekoBot.Modules.Music.Services;
|
|||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using NLog;
|
using NLog;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration.Services
|
namespace NadekoBot.Modules.Administration.Services
|
||||||
{
|
{
|
||||||
@ -17,7 +16,6 @@ namespace NadekoBot.Modules.Administration.Services
|
|||||||
private readonly DiscordSocketClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly MusicService _music;
|
private readonly MusicService _music;
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
private readonly IDataCache _cache;
|
|
||||||
private readonly Replacer _rep;
|
private readonly Replacer _rep;
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
private readonly IBotConfigProvider _bcp;
|
private readonly IBotConfigProvider _bcp;
|
||||||
@ -29,60 +27,50 @@ namespace NadekoBot.Modules.Administration.Services
|
|||||||
public int Index { get; set; }
|
public int Index { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlayingRotateService(DiscordSocketClient client, IBotConfigProvider bcp,
|
public PlayingRotateService(DiscordSocketClient client, IBotConfigProvider bcp, MusicService music, DbService db)
|
||||||
MusicService music, DbService db, IDataCache cache, NadekoBot bot)
|
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
_bcp = bcp;
|
_bcp = bcp;
|
||||||
_music = music;
|
_music = music;
|
||||||
_db = db;
|
_db = db;
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_cache = cache;
|
_rep = new ReplacementBuilder()
|
||||||
|
.WithClient(client)
|
||||||
|
.WithStats(client)
|
||||||
|
.WithMusic(music)
|
||||||
|
.Build();
|
||||||
|
|
||||||
if (client.ShardId == 0)
|
_t = new Timer(async (objState) =>
|
||||||
{
|
{
|
||||||
|
try
|
||||||
_rep = new ReplacementBuilder()
|
|
||||||
.WithClient(client)
|
|
||||||
.WithStats(client)
|
|
||||||
.WithMusic(music)
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
_t = new Timer(async (objState) =>
|
|
||||||
{
|
{
|
||||||
try
|
bcp.Reload();
|
||||||
{
|
|
||||||
bcp.Reload();
|
|
||||||
|
|
||||||
var state = (TimerState)objState;
|
var state = (TimerState)objState;
|
||||||
if (!BotConfig.RotatingStatuses)
|
if (!BotConfig.RotatingStatuses)
|
||||||
return;
|
return;
|
||||||
if (state.Index >= BotConfig.RotatingStatusMessages.Count)
|
if (state.Index >= BotConfig.RotatingStatusMessages.Count)
|
||||||
state.Index = 0;
|
state.Index = 0;
|
||||||
|
|
||||||
if (!BotConfig.RotatingStatusMessages.Any())
|
if (!BotConfig.RotatingStatusMessages.Any())
|
||||||
return;
|
return;
|
||||||
var status = BotConfig.RotatingStatusMessages[state.Index++].Status;
|
var status = BotConfig.RotatingStatusMessages[state.Index++].Status;
|
||||||
if (string.IsNullOrWhiteSpace(status))
|
if (string.IsNullOrWhiteSpace(status))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
status = _rep.Replace(status);
|
status = _rep.Replace(status);
|
||||||
|
|
||||||
try
|
try { await client.SetGameAsync(status).ConfigureAwait(false); }
|
||||||
{
|
|
||||||
await bot.SetGameAsync(status).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_log.Warn(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_log.Warn("Rotating playing status errored.\n" + ex);
|
_log.Warn(ex);
|
||||||
}
|
}
|
||||||
}, new TimerState(), TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
|
}
|
||||||
}
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_log.Warn("Rotating playing status errored.\n" + ex);
|
||||||
|
}
|
||||||
|
}, new TimerState(), TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,8 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
|
|
||||||
if (channel == null)
|
if (channel == null)
|
||||||
{
|
{
|
||||||
await _service.AddGcr(cr).ConfigureAwait(false);
|
Array.Resize(ref _service.GlobalReactions, _service.GlobalReactions.Length + 1);
|
||||||
|
_service.GlobalReactions[_service.GlobalReactions.Length - 1] = cr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -236,7 +237,8 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
if ((toDelete.GuildId == null || toDelete.GuildId == 0) && Context.Guild == null)
|
if ((toDelete.GuildId == null || toDelete.GuildId == 0) && Context.Guild == null)
|
||||||
{
|
{
|
||||||
uow.CustomReactions.Remove(toDelete);
|
uow.CustomReactions.Remove(toDelete);
|
||||||
await _service.DelGcr(toDelete.Id);
|
//todo 91 i can dramatically improve performance of this, if Ids are ordered.
|
||||||
|
_service.GlobalReactions = _service.GlobalReactions.Where(cr => cr?.Id != toDelete.Id).ToArray();
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
else if ((toDelete.GuildId != null && toDelete.GuildId != 0) && Context.Guild.Id == toDelete.GuildId)
|
else if ((toDelete.GuildId != null && toDelete.GuildId != 0) && Context.Guild.Id == toDelete.GuildId)
|
||||||
|
@ -15,7 +15,6 @@ using NadekoBot.Modules.CustomReactions.Extensions;
|
|||||||
using NadekoBot.Modules.Permissions.Common;
|
using NadekoBot.Modules.Permissions.Common;
|
||||||
using NadekoBot.Modules.Permissions.Services;
|
using NadekoBot.Modules.Permissions.Services;
|
||||||
using NadekoBot.Services.Impl;
|
using NadekoBot.Services.Impl;
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace NadekoBot.Modules.CustomReactions.Services
|
namespace NadekoBot.Modules.CustomReactions.Services
|
||||||
{
|
{
|
||||||
@ -33,11 +32,9 @@ namespace NadekoBot.Modules.CustomReactions.Services
|
|||||||
private readonly CommandHandler _cmd;
|
private readonly CommandHandler _cmd;
|
||||||
private readonly IBotConfigProvider _bc;
|
private readonly IBotConfigProvider _bc;
|
||||||
private readonly NadekoStrings _strings;
|
private readonly NadekoStrings _strings;
|
||||||
private readonly IDataCache _cache;
|
|
||||||
|
|
||||||
public CustomReactionsService(PermissionService perms, DbService db, NadekoStrings strings,
|
public CustomReactionsService(PermissionService perms, DbService db, NadekoStrings strings,
|
||||||
DiscordSocketClient client, CommandHandler cmd, IBotConfigProvider bc, IUnitOfWork uow,
|
DiscordSocketClient client, CommandHandler cmd, IBotConfigProvider bc, IUnitOfWork uow)
|
||||||
IDataCache cache)
|
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_db = db;
|
_db = db;
|
||||||
@ -46,38 +43,12 @@ namespace NadekoBot.Modules.CustomReactions.Services
|
|||||||
_cmd = cmd;
|
_cmd = cmd;
|
||||||
_bc = bc;
|
_bc = bc;
|
||||||
_strings = strings;
|
_strings = strings;
|
||||||
_cache = cache;
|
|
||||||
|
|
||||||
var sub = _cache.Redis.GetSubscriber();
|
|
||||||
sub.Subscribe("gcr.added", (ch, msg) =>
|
|
||||||
{
|
|
||||||
Array.Resize(ref GlobalReactions, GlobalReactions.Length + 1);
|
|
||||||
GlobalReactions[GlobalReactions.Length - 1] = JsonConvert.DeserializeObject<CustomReaction>(msg);
|
|
||||||
}, StackExchange.Redis.CommandFlags.FireAndForget);
|
|
||||||
sub.Subscribe("gcr.deleted", (ch, msg) =>
|
|
||||||
{
|
|
||||||
var id = int.Parse(msg);
|
|
||||||
GlobalReactions = GlobalReactions.Where(cr => cr?.Id != id).ToArray();
|
|
||||||
}, StackExchange.Redis.CommandFlags.FireAndForget);
|
|
||||||
|
|
||||||
var items = uow.CustomReactions.GetAll();
|
var items = uow.CustomReactions.GetAll();
|
||||||
|
|
||||||
GuildReactions = new ConcurrentDictionary<ulong, CustomReaction[]>(items.Where(g => g.GuildId != null && g.GuildId != 0).GroupBy(k => k.GuildId.Value).ToDictionary(g => g.Key, g => g.ToArray()));
|
GuildReactions = new ConcurrentDictionary<ulong, CustomReaction[]>(items.Where(g => g.GuildId != null && g.GuildId != 0).GroupBy(k => k.GuildId.Value).ToDictionary(g => g.Key, g => g.ToArray()));
|
||||||
GlobalReactions = items.Where(g => g.GuildId == null || g.GuildId == 0).ToArray();
|
GlobalReactions = items.Where(g => g.GuildId == null || g.GuildId == 0).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task AddGcr(CustomReaction cr)
|
|
||||||
{
|
|
||||||
var sub = _cache.Redis.GetSubscriber();
|
|
||||||
return sub.PublishAsync("gcr.added", JsonConvert.SerializeObject(cr));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task DelGcr(int id)
|
|
||||||
{
|
|
||||||
var sub = _cache.Redis.GetSubscriber();
|
|
||||||
return sub.PublishAsync("gcr.deleted", id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ClearStats() => ReactionStats.Clear();
|
public void ClearStats() => ReactionStats.Clear();
|
||||||
|
|
||||||
public CustomReaction TryGetCustomReaction(IUserMessage umsg)
|
public CustomReaction TryGetCustomReaction(IUserMessage umsg)
|
||||||
|
@ -331,7 +331,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
var embed = new EmbedBuilder().WithOkColor();
|
var embed = new EmbedBuilder().WithOkColor();
|
||||||
|
|
||||||
if (entry.Type == ShopEntryType.Role)
|
if (entry.Type == ShopEntryType.Role)
|
||||||
return embed.AddField(efb => efb.WithName(GetText("name")).WithValue(GetText("shop_role", Format.Bold(Context.Guild.GetRole(entry.RoleId)?.Name ?? "MISSING_ROLE"))).WithIsInline(true))
|
return embed.AddField(efb => efb.WithName(GetText("name")).WithValue(GetText("shop_role", Format.Bold(entry.RoleName))).WithIsInline(true))
|
||||||
.AddField(efb => efb.WithName(GetText("price")).WithValue(entry.Price.ToString()).WithIsInline(true))
|
.AddField(efb => efb.WithName(GetText("price")).WithValue(entry.Price.ToString()).WithIsInline(true))
|
||||||
.AddField(efb => efb.WithName(GetText("type")).WithValue(entry.Type.ToString()).WithIsInline(true));
|
.AddField(efb => efb.WithName(GetText("type")).WithValue(entry.Type.ToString()).WithIsInline(true));
|
||||||
else if (entry.Type == ShopEntryType.List)
|
else if (entry.Type == ShopEntryType.List)
|
||||||
@ -349,7 +349,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
{
|
{
|
||||||
if (entry.Type == ShopEntryType.Role)
|
if (entry.Type == ShopEntryType.Role)
|
||||||
{
|
{
|
||||||
return GetText("shop_role", Format.Bold(Context.Guild.GetRole(entry.RoleId)?.Name ?? "MISSING_ROLE"));
|
return GetText("shop_role", Format.Bold(entry.RoleName));
|
||||||
}
|
}
|
||||||
else if (entry.Type == ShopEntryType.List)
|
else if (entry.Type == ShopEntryType.List)
|
||||||
{
|
{
|
||||||
|
@ -38,7 +38,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
public async Task EightBall([Remainder] string question = null)
|
public async Task _8Ball([Remainder] string question = null)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(question))
|
if (string.IsNullOrWhiteSpace(question))
|
||||||
return;
|
return;
|
||||||
|
@ -3,6 +3,7 @@ using System;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Music.Common
|
namespace NadekoBot.Modules.Music.Common
|
||||||
{
|
{
|
||||||
@ -17,16 +18,27 @@ namespace NadekoBot.Modules.Music.Common
|
|||||||
|
|
||||||
public string SongUri { get; private set; }
|
public string SongUri { get; private set; }
|
||||||
|
|
||||||
|
//private volatile bool restart = false;
|
||||||
|
|
||||||
public SongBuffer(string songUri, string skipTo, bool isLocal)
|
public SongBuffer(string songUri, string skipTo, bool isLocal)
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
|
//_log.Warn(songUri);
|
||||||
this.SongUri = songUri;
|
this.SongUri = songUri;
|
||||||
this._isLocal = isLocal;
|
this._isLocal = isLocal;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
this.p = StartFFmpegProcess(SongUri, 0);
|
this.p = StartFFmpegProcess(SongUri, 0);
|
||||||
|
var t = Task.Run(() =>
|
||||||
|
{
|
||||||
|
this.p.BeginErrorReadLine();
|
||||||
|
this.p.ErrorDataReceived += P_ErrorDataReceived;
|
||||||
|
this.p.WaitForExit();
|
||||||
|
});
|
||||||
|
|
||||||
this._outStream = this.p.StandardOutput.BaseStream;
|
this._outStream = this.p.StandardOutput.BaseStream;
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (System.ComponentModel.Win32Exception)
|
catch (System.ComponentModel.Win32Exception)
|
||||||
{
|
{
|
||||||
@ -56,14 +68,113 @@ Check the guides for your platform on how to setup ffmpeg correctly:
|
|||||||
Arguments = args,
|
Arguments = args,
|
||||||
UseShellExecute = false,
|
UseShellExecute = false,
|
||||||
RedirectStandardOutput = true,
|
RedirectStandardOutput = true,
|
||||||
RedirectStandardError = false,
|
RedirectStandardError = true,
|
||||||
CreateNoWindow = true,
|
CreateNoWindow = true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void P_ErrorDataReceived(object sender, DataReceivedEventArgs e)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(e.Data))
|
||||||
|
return;
|
||||||
|
_log.Error(">>> " + e.Data);
|
||||||
|
if (e.Data?.Contains("Error in the pull function") == true)
|
||||||
|
{
|
||||||
|
_log.Error("Ignore this.");
|
||||||
|
//restart = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private readonly object locker = new object();
|
private readonly object locker = new object();
|
||||||
private readonly bool _isLocal;
|
private readonly bool _isLocal;
|
||||||
|
|
||||||
|
public Task<bool> StartBuffering(CancellationToken cancelToken)
|
||||||
|
{
|
||||||
|
var toReturn = new TaskCompletionSource<bool>();
|
||||||
|
var _ = Task.Run(() =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
////int maxLoopsPerSec = 25;
|
||||||
|
//var sw = Stopwatch.StartNew();
|
||||||
|
////var delay = 1000 / maxLoopsPerSec;
|
||||||
|
//int currentLoops = 0;
|
||||||
|
//int _bytesSent = 0;
|
||||||
|
//try
|
||||||
|
//{
|
||||||
|
// //do
|
||||||
|
// //{
|
||||||
|
// // if (restart)
|
||||||
|
// // {
|
||||||
|
// // var cur = _bytesSent / 3840 / (1000 / 20.0f);
|
||||||
|
// // _log.Info("Restarting");
|
||||||
|
// // try { this.p.StandardOutput.Dispose(); } catch { }
|
||||||
|
// // try { this.p.Dispose(); } catch { }
|
||||||
|
// // this.p = StartFFmpegProcess(SongUri, cur);
|
||||||
|
// // }
|
||||||
|
// // restart = false;
|
||||||
|
// ++currentLoops;
|
||||||
|
// byte[] buffer = new byte[readSize];
|
||||||
|
// int bytesRead = 1;
|
||||||
|
// while (!cancelToken.IsCancellationRequested && !this.p.HasExited)
|
||||||
|
// {
|
||||||
|
// bytesRead = await p.StandardOutput.BaseStream.ReadAsync(buffer, 0, readSize, cancelToken).ConfigureAwait(false);
|
||||||
|
// _bytesSent += bytesRead;
|
||||||
|
// if (bytesRead == 0)
|
||||||
|
// break;
|
||||||
|
// bool written;
|
||||||
|
// do
|
||||||
|
// {
|
||||||
|
// lock (locker)
|
||||||
|
// written = _outStream.Write(buffer, 0, bytesRead);
|
||||||
|
// if (!written)
|
||||||
|
// await Task.Delay(2000, cancelToken);
|
||||||
|
// }
|
||||||
|
// while (!written && !cancelToken.IsCancellationRequested);
|
||||||
|
// lock (locker)
|
||||||
|
// if (_outStream.Length > 200_000 || bytesRead == 0)
|
||||||
|
// if (toReturn.TrySetResult(true))
|
||||||
|
// _log.Info("Prebuffering finished in {0}", sw.Elapsed.TotalSeconds.ToString("F2"));
|
||||||
|
|
||||||
|
// //_log.Info(_outStream.Length);
|
||||||
|
// await Task.Delay(10);
|
||||||
|
// }
|
||||||
|
// //if (cancelToken.IsCancellationRequested)
|
||||||
|
// // _log.Info("Song canceled");
|
||||||
|
// //else if (p.HasExited)
|
||||||
|
// // _log.Info("Song buffered completely (FFmpeg exited)");
|
||||||
|
// //else if (bytesRead == 0)
|
||||||
|
// // _log.Info("Nothing read");
|
||||||
|
// //}
|
||||||
|
// //while (restart && !cancelToken.IsCancellationRequested);
|
||||||
|
//return Task.CompletedTask;
|
||||||
|
toReturn.TrySetResult(true);
|
||||||
|
}
|
||||||
|
catch (System.ComponentModel.Win32Exception)
|
||||||
|
{
|
||||||
|
_log.Error(@"You have not properly installed or configured FFMPEG.
|
||||||
|
Please install and configure FFMPEG to play music.
|
||||||
|
Check the guides for your platform on how to setup ffmpeg correctly:
|
||||||
|
Windows Guide: https://goo.gl/OjKk8F
|
||||||
|
Linux Guide: https://goo.gl/ShjCUo");
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException) { }
|
||||||
|
catch (InvalidOperationException) { } // when ffmpeg is disposed
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_log.Info(ex);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (toReturn.TrySetResult(false))
|
||||||
|
_log.Info("Prebuffering failed");
|
||||||
|
}
|
||||||
|
}, cancelToken);
|
||||||
|
|
||||||
|
return toReturn.Task;
|
||||||
|
}
|
||||||
|
|
||||||
public int Read(byte[] b, int offset, int toRead)
|
public int Read(byte[] b, int offset, int toRead)
|
||||||
{
|
{
|
||||||
lock (locker)
|
lock (locker)
|
||||||
@ -93,3 +204,214 @@ Check the guides for your platform on how to setup ffmpeg correctly:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//namespace NadekoBot.Services.Music
|
||||||
|
//{
|
||||||
|
// /// <summary>
|
||||||
|
// /// Create a buffer for a song file. It will create multiples files to ensure, that radio don't fill up disk space.
|
||||||
|
// /// It also help for large music by deleting files that are already seen.
|
||||||
|
// /// </summary>
|
||||||
|
// class SongBuffer : Stream
|
||||||
|
// {
|
||||||
|
// public SongBuffer(MusicPlayer musicPlayer, string basename, SongInfo songInfo, int skipTo, int maxFileSize)
|
||||||
|
// {
|
||||||
|
// MusicPlayer = musicPlayer;
|
||||||
|
// Basename = basename;
|
||||||
|
// SongInfo = songInfo;
|
||||||
|
// SkipTo = skipTo;
|
||||||
|
// MaxFileSize = maxFileSize;
|
||||||
|
// CurrentFileStream = new FileStream(this.GetNextFile(), FileMode.OpenOrCreate, FileAccess.Read, FileShare.Write);
|
||||||
|
// _log = LogManager.GetCurrentClassLogger();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// MusicPlayer MusicPlayer { get; }
|
||||||
|
|
||||||
|
// private string Basename { get; }
|
||||||
|
|
||||||
|
// private SongInfo SongInfo { get; }
|
||||||
|
|
||||||
|
// private int SkipTo { get; }
|
||||||
|
|
||||||
|
// private int MaxFileSize { get; } = 2.MiB();
|
||||||
|
|
||||||
|
// private long FileNumber = -1;
|
||||||
|
|
||||||
|
// private long NextFileToRead = 0;
|
||||||
|
|
||||||
|
// public bool BufferingCompleted { get; private set; } = false;
|
||||||
|
|
||||||
|
// private ulong CurrentBufferSize = 0;
|
||||||
|
|
||||||
|
// private FileStream CurrentFileStream;
|
||||||
|
// private Logger _log;
|
||||||
|
|
||||||
|
// public Task BufferSong(CancellationToken cancelToken) =>
|
||||||
|
// Task.Run(async () =>
|
||||||
|
// {
|
||||||
|
// Process p = null;
|
||||||
|
// FileStream outStream = null;
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// p = Process.Start(new ProcessStartInfo
|
||||||
|
// {
|
||||||
|
// FileName = "ffmpeg",
|
||||||
|
// Arguments = $"-ss {SkipTo} -i {SongInfo.Uri} -f s16le -ar 48000 -vn -ac 2 pipe:1 -loglevel quiet",
|
||||||
|
// UseShellExecute = false,
|
||||||
|
// RedirectStandardOutput = true,
|
||||||
|
// RedirectStandardError = false,
|
||||||
|
// CreateNoWindow = true,
|
||||||
|
// });
|
||||||
|
|
||||||
|
// byte[] buffer = new byte[81920];
|
||||||
|
// int currentFileSize = 0;
|
||||||
|
// ulong prebufferSize = 100ul.MiB();
|
||||||
|
|
||||||
|
// outStream = new FileStream(Basename + "-" + ++FileNumber, FileMode.Append, FileAccess.Write, FileShare.Read);
|
||||||
|
// while (!p.HasExited) //Also fix low bandwidth
|
||||||
|
// {
|
||||||
|
// int bytesRead = await p.StandardOutput.BaseStream.ReadAsync(buffer, 0, buffer.Length, cancelToken).ConfigureAwait(false);
|
||||||
|
// if (currentFileSize >= MaxFileSize)
|
||||||
|
// {
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// outStream.Dispose();
|
||||||
|
// }
|
||||||
|
// catch { }
|
||||||
|
// outStream = new FileStream(Basename + "-" + ++FileNumber, FileMode.Append, FileAccess.Write, FileShare.Read);
|
||||||
|
// currentFileSize = bytesRead;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// currentFileSize += bytesRead;
|
||||||
|
// }
|
||||||
|
// CurrentBufferSize += Convert.ToUInt64(bytesRead);
|
||||||
|
// await outStream.WriteAsync(buffer, 0, bytesRead, cancelToken).ConfigureAwait(false);
|
||||||
|
// while (CurrentBufferSize > prebufferSize)
|
||||||
|
// await Task.Delay(100, cancelToken);
|
||||||
|
// }
|
||||||
|
// BufferingCompleted = true;
|
||||||
|
// }
|
||||||
|
// catch (System.ComponentModel.Win32Exception)
|
||||||
|
// {
|
||||||
|
// var oldclr = Console.ForegroundColor;
|
||||||
|
// Console.ForegroundColor = ConsoleColor.Red;
|
||||||
|
// Console.WriteLine(@"You have not properly installed or configured FFMPEG.
|
||||||
|
//Please install and configure FFMPEG to play music.
|
||||||
|
//Check the guides for your platform on how to setup ffmpeg correctly:
|
||||||
|
// Windows Guide: https://goo.gl/OjKk8F
|
||||||
|
// Linux Guide: https://goo.gl/ShjCUo");
|
||||||
|
// Console.ForegroundColor = oldclr;
|
||||||
|
// }
|
||||||
|
// catch (Exception ex)
|
||||||
|
// {
|
||||||
|
// Console.WriteLine($"Buffering stopped: {ex.Message}");
|
||||||
|
// }
|
||||||
|
// finally
|
||||||
|
// {
|
||||||
|
// if (outStream != null)
|
||||||
|
// outStream.Dispose();
|
||||||
|
// if (p != null)
|
||||||
|
// {
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// p.Kill();
|
||||||
|
// }
|
||||||
|
// catch { }
|
||||||
|
// p.Dispose();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// /// <summary>
|
||||||
|
// /// Return the next file to read, and delete the old one
|
||||||
|
// /// </summary>
|
||||||
|
// /// <returns>Name of the file to read</returns>
|
||||||
|
// private string GetNextFile()
|
||||||
|
// {
|
||||||
|
// string filename = Basename + "-" + NextFileToRead;
|
||||||
|
|
||||||
|
// if (NextFileToRead != 0)
|
||||||
|
// {
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// CurrentBufferSize -= Convert.ToUInt64(new FileInfo(Basename + "-" + (NextFileToRead - 1)).Length);
|
||||||
|
// File.Delete(Basename + "-" + (NextFileToRead - 1));
|
||||||
|
// }
|
||||||
|
// catch { }
|
||||||
|
// }
|
||||||
|
// NextFileToRead++;
|
||||||
|
// return filename;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private bool IsNextFileReady()
|
||||||
|
// {
|
||||||
|
// return NextFileToRead <= FileNumber;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private void CleanFiles()
|
||||||
|
// {
|
||||||
|
// for (long i = NextFileToRead - 1; i <= FileNumber; i++)
|
||||||
|
// {
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// File.Delete(Basename + "-" + i);
|
||||||
|
// }
|
||||||
|
// catch { }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //Stream part
|
||||||
|
|
||||||
|
// public override bool CanRead => true;
|
||||||
|
|
||||||
|
// public override bool CanSeek => false;
|
||||||
|
|
||||||
|
// public override bool CanWrite => false;
|
||||||
|
|
||||||
|
// public override long Length => (long)CurrentBufferSize;
|
||||||
|
|
||||||
|
// public override long Position { get; set; } = 0;
|
||||||
|
|
||||||
|
// public override void Flush() { }
|
||||||
|
|
||||||
|
// public override int Read(byte[] buffer, int offset, int count)
|
||||||
|
// {
|
||||||
|
// int read = CurrentFileStream.Read(buffer, offset, count);
|
||||||
|
// if (read < count)
|
||||||
|
// {
|
||||||
|
// if (!BufferingCompleted || IsNextFileReady())
|
||||||
|
// {
|
||||||
|
// CurrentFileStream.Dispose();
|
||||||
|
// CurrentFileStream = new FileStream(GetNextFile(), FileMode.OpenOrCreate, FileAccess.Read, FileShare.Write);
|
||||||
|
// read += CurrentFileStream.Read(buffer, read + offset, count - read);
|
||||||
|
// }
|
||||||
|
// if (read < count)
|
||||||
|
// Array.Clear(buffer, read, count - read);
|
||||||
|
// }
|
||||||
|
// return read;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override long Seek(long offset, SeekOrigin origin)
|
||||||
|
// {
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override void SetLength(long value)
|
||||||
|
// {
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public override void Write(byte[] buffer, int offset, int count)
|
||||||
|
// {
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public new void Dispose()
|
||||||
|
// {
|
||||||
|
// CurrentFileStream.Dispose();
|
||||||
|
// MusicPlayer.SongCancelSource.Cancel();
|
||||||
|
// CleanFiles();
|
||||||
|
// base.Dispose();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
@ -16,13 +16,9 @@ using NadekoBot.Modules.NSFW.Exceptions;
|
|||||||
|
|
||||||
namespace NadekoBot.Modules.NSFW
|
namespace NadekoBot.Modules.NSFW
|
||||||
{
|
{
|
||||||
// thanks to halitalf for adding autoboob and autobutt features :D
|
|
||||||
public class NSFW : NadekoTopLevelModule<SearchesService>
|
public class NSFW : NadekoTopLevelModule<SearchesService>
|
||||||
{
|
{
|
||||||
private static readonly ConcurrentDictionary<ulong, Timer> _autoHentaiTimers = new ConcurrentDictionary<ulong, Timer>();
|
private static readonly ConcurrentDictionary<ulong, Timer> _autoHentaiTimers = new ConcurrentDictionary<ulong, Timer>();
|
||||||
private static readonly ConcurrentDictionary<ulong, Timer> _autoBoobTimers = new ConcurrentDictionary<ulong, Timer>();
|
|
||||||
private static readonly ConcurrentDictionary<ulong, Timer> _autoButtTimers = new ConcurrentDictionary<ulong, Timer>();
|
|
||||||
|
|
||||||
private static readonly ConcurrentHashSet<ulong> _hentaiBombBlacklist = new ConcurrentHashSet<ulong>();
|
private static readonly ConcurrentHashSet<ulong> _hentaiBombBlacklist = new ConcurrentHashSet<ulong>();
|
||||||
|
|
||||||
private async Task InternalHentai(IMessageChannel channel, string tag, bool noError)
|
private async Task InternalHentai(IMessageChannel channel, string tag, bool noError)
|
||||||
@ -53,34 +49,10 @@ namespace NadekoBot.Modules.NSFW
|
|||||||
.WithDescription($"[{GetText("tag")}: {tag}]({img})"))
|
.WithDescription($"[{GetText("tag")}: {tag}]({img})"))
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
private async Task InternalBoobs(IMessageChannel Channel)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
JToken obj;
|
|
||||||
obj = JArray.Parse(await _service.Http.GetStringAsync($"http://api.oboobs.ru/boobs/{new NadekoRandom().Next(0, 10330)}").ConfigureAwait(false))[0];
|
|
||||||
await Channel.SendMessageAsync($"http://media.oboobs.ru/{obj["preview"]}").ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
await Channel.SendErrorAsync(ex.Message).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task InternalButts(IMessageChannel Channel)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
JToken obj;
|
|
||||||
obj = JArray.Parse(await _service.Http.GetStringAsync($"http://api.obutts.ru/butts/{new NadekoRandom().Next(0, 4335)}").ConfigureAwait(false))[0];
|
|
||||||
await Channel.SendMessageAsync($"http://media.obutts.ru/{obj["preview"]}").ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
await Channel.SendErrorAsync(ex.Message).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
public Task Hentai([Remainder] string tag = null) =>
|
||||||
|
InternalHentai(Context.Channel, tag, false);
|
||||||
#if !GLOBAL_NADEKO
|
#if !GLOBAL_NADEKO
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireUserPermission(ChannelPermission.ManageMessages)]
|
[RequireUserPermission(ChannelPermission.ManageMessages)]
|
||||||
@ -93,7 +65,7 @@ namespace NadekoBot.Modules.NSFW
|
|||||||
if (!_autoHentaiTimers.TryRemove(Context.Channel.Id, out t)) return;
|
if (!_autoHentaiTimers.TryRemove(Context.Channel.Id, out t)) return;
|
||||||
|
|
||||||
t.Change(Timeout.Infinite, Timeout.Infinite); //proper way to disable the timer
|
t.Change(Timeout.Infinite, Timeout.Infinite); //proper way to disable the timer
|
||||||
await ReplyConfirmLocalized("stopped").ConfigureAwait(false);
|
await ReplyConfirmLocalized("autohentai_stopped").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,90 +99,8 @@ namespace NadekoBot.Modules.NSFW
|
|||||||
interval,
|
interval,
|
||||||
string.Join(", ", tagsArr)).ConfigureAwait(false);
|
string.Join(", ", tagsArr)).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
|
||||||
[RequireUserPermission(ChannelPermission.ManageMessages)]
|
|
||||||
public async Task AutoBoobs(int interval = 0)
|
|
||||||
{
|
|
||||||
Timer t;
|
|
||||||
|
|
||||||
if (interval == 0)
|
|
||||||
{
|
|
||||||
if (!_autoBoobTimers.TryRemove(Context.Channel.Id, out t)) return;
|
|
||||||
|
|
||||||
t.Change(Timeout.Infinite, Timeout.Infinite); //proper way to disable the timer
|
|
||||||
await ReplyConfirmLocalized("stopped").ConfigureAwait(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (interval < 20)
|
|
||||||
return;
|
|
||||||
|
|
||||||
t = new Timer(async (state) =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await InternalBoobs(Context.Channel).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
}, null, interval * 1000, interval * 1000);
|
|
||||||
|
|
||||||
_autoBoobTimers.AddOrUpdate(Context.Channel.Id, t, (key, old) =>
|
|
||||||
{
|
|
||||||
old.Change(Timeout.Infinite, Timeout.Infinite);
|
|
||||||
return t;
|
|
||||||
});
|
|
||||||
|
|
||||||
await ReplyConfirmLocalized("started", interval).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
|
||||||
[RequireUserPermission(ChannelPermission.ManageMessages)]
|
|
||||||
public async Task AutoButts(int interval = 0)
|
|
||||||
{
|
|
||||||
Timer t;
|
|
||||||
|
|
||||||
if (interval == 0)
|
|
||||||
{
|
|
||||||
if (!_autoButtTimers.TryRemove(Context.Channel.Id, out t)) return;
|
|
||||||
|
|
||||||
t.Change(Timeout.Infinite, Timeout.Infinite); //proper way to disable the timer
|
|
||||||
await ReplyConfirmLocalized("stopped").ConfigureAwait(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (interval < 20)
|
|
||||||
return;
|
|
||||||
|
|
||||||
t = new Timer(async (state) =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await InternalButts(Context.Channel).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
}, null, interval * 1000, interval * 1000);
|
|
||||||
|
|
||||||
_autoButtTimers.AddOrUpdate(Context.Channel.Id, t, (key, old) =>
|
|
||||||
{
|
|
||||||
old.Change(Timeout.Infinite, Timeout.Infinite);
|
|
||||||
return t;
|
|
||||||
});
|
|
||||||
|
|
||||||
await ReplyConfirmLocalized("started", interval).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
|
||||||
public Task Hentai([Remainder] string tag = null) =>
|
|
||||||
InternalHentai(Context.Channel, tag, false);
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
public async Task HentaiBomb([Remainder] string tag = null)
|
public async Task HentaiBomb([Remainder] string tag = null)
|
||||||
{
|
{
|
||||||
@ -309,7 +199,7 @@ namespace NadekoBot.Modules.NSFW
|
|||||||
tag = tag.Trim().ToLowerInvariant();
|
tag = tag.Trim().ToLowerInvariant();
|
||||||
var added = _service.ToggleBlacklistedTag(Context.Guild.Id, tag);
|
var added = _service.ToggleBlacklistedTag(Context.Guild.Id, tag);
|
||||||
|
|
||||||
if (added)
|
if(added)
|
||||||
await ReplyConfirmLocalized("blacklisted_tag_add", tag).ConfigureAwait(false);
|
await ReplyConfirmLocalized("blacklisted_tag_add", tag).ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await ReplyConfirmLocalized("blacklisted_tag_remove", tag).ConfigureAwait(false);
|
await ReplyConfirmLocalized("blacklisted_tag_remove", tag).ConfigureAwait(false);
|
||||||
|
@ -135,11 +135,11 @@ namespace NadekoBot.Modules.Permissions.Services
|
|||||||
{
|
{
|
||||||
var oldPrefixes = new[] { ".", ";", "!!", "!m", "!", "+", "-", "$", ">" };
|
var oldPrefixes = new[] { ".", ";", "!!", "!m", "!", "+", "-", "$", ">" };
|
||||||
uow._context.Database.ExecuteSqlCommand(
|
uow._context.Database.ExecuteSqlCommand(
|
||||||
@"UPDATE Permissionv2
|
$@"UPDATE {nameof(Permissionv2)}
|
||||||
SET secondaryTargetName=trim(substr(secondaryTargetName, 3))
|
SET secondaryTargetName=trim(substr(secondaryTargetName, 3))
|
||||||
WHERE secondaryTargetName LIKE '!!%' OR secondaryTargetName LIKE '!m%';
|
WHERE secondaryTargetName LIKE '!!%' OR secondaryTargetName LIKE '!m%';
|
||||||
|
|
||||||
UPDATE Permissionv2
|
UPDATE {nameof(Permissionv2)}
|
||||||
SET secondaryTargetName=substr(secondaryTargetName, 2)
|
SET secondaryTargetName=substr(secondaryTargetName, 2)
|
||||||
WHERE secondaryTargetName LIKE '.%' OR
|
WHERE secondaryTargetName LIKE '.%' OR
|
||||||
secondaryTargetName LIKE '~%' OR
|
secondaryTargetName LIKE '~%' OR
|
||||||
|
@ -76,13 +76,11 @@ namespace NadekoBot.Modules.Searches.Common
|
|||||||
if (images.Length == 0)
|
if (images.Length == 0)
|
||||||
return null;
|
return null;
|
||||||
var toReturn = images[_rng.Next(images.Length)];
|
var toReturn = images[_rng.Next(images.Length)];
|
||||||
#if !GLOBAL_NADEKO
|
|
||||||
foreach (var dledImg in images)
|
foreach (var dledImg in images)
|
||||||
{
|
{
|
||||||
if(dledImg != toReturn)
|
if(dledImg != toReturn)
|
||||||
_cache.Add(dledImg);
|
_cache.Add(dledImg);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,14 +11,10 @@ namespace NadekoBot.Modules.Searches.Services
|
|||||||
public class AnimeSearchService : INService
|
public class AnimeSearchService : INService
|
||||||
{
|
{
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
private readonly IDataCache _cache;
|
|
||||||
private readonly HttpClient _http;
|
|
||||||
|
|
||||||
public AnimeSearchService(IDataCache cache)
|
public AnimeSearchService()
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_cache = cache;
|
|
||||||
_http = new HttpClient();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<AnimeResult> GetAnimeData(string query)
|
public async Task<AnimeResult> GetAnimeData(string query)
|
||||||
@ -29,16 +25,11 @@ namespace NadekoBot.Modules.Searches.Services
|
|||||||
{
|
{
|
||||||
|
|
||||||
var link = "https://aniapi.nadekobot.me/anime/" + Uri.EscapeDataString(query.Replace("/", " "));
|
var link = "https://aniapi.nadekobot.me/anime/" + Uri.EscapeDataString(query.Replace("/", " "));
|
||||||
link = link.ToLowerInvariant();
|
using (var http = new HttpClient())
|
||||||
var (ok, data) = await _cache.TryGetAnimeDataAsync(link).ConfigureAwait(false);
|
|
||||||
if (!ok)
|
|
||||||
{
|
{
|
||||||
data = await _http.GetStringAsync(link).ConfigureAwait(false);
|
var res = await http.GetStringAsync(link).ConfigureAwait(false);
|
||||||
await _cache.SetAnimeDataAsync(link, data).ConfigureAwait(false);
|
return JsonConvert.DeserializeObject<AnimeResult>(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return JsonConvert.DeserializeObject<AnimeResult>(data);
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@ -53,17 +44,12 @@ namespace NadekoBot.Modules.Searches.Services
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
var link = "https://aniapi.nadekobot.me/manga/" + Uri.EscapeDataString(query.Replace("/", " "));
|
var link = "https://aniapi.nadekobot.me/manga/" + Uri.EscapeDataString(query.Replace("/", " "));
|
||||||
link = link.ToLowerInvariant();
|
using (var http = new HttpClient())
|
||||||
var (ok, data) = await _cache.TryGetAnimeDataAsync(link).ConfigureAwait(false);
|
|
||||||
if (!ok)
|
|
||||||
{
|
{
|
||||||
data = await _http.GetStringAsync(link).ConfigureAwait(false);
|
var res = await http.GetStringAsync(link).ConfigureAwait(false);
|
||||||
await _cache.SetAnimeDataAsync(link, data).ConfigureAwait(false);
|
return JsonConvert.DeserializeObject<MangaResult>(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return JsonConvert.DeserializeObject<MangaResult>(data);
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
@ -26,27 +26,6 @@ namespace NadekoBot.Modules.Xp
|
|||||||
_client = client;
|
_client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
|
||||||
public async Task ClubAdmin([Remainder]IUser toAdmin)
|
|
||||||
{
|
|
||||||
bool admin;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
admin = _service.ToggleAdmin(Context.User, toAdmin);
|
|
||||||
}
|
|
||||||
catch (InvalidOperationException)
|
|
||||||
{
|
|
||||||
await ReplyErrorLocalized("club_admin_error").ConfigureAwait(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(admin)
|
|
||||||
await ReplyConfirmLocalized("club_admin_add", Format.Bold(toAdmin.ToString())).ConfigureAwait(false);
|
|
||||||
else
|
|
||||||
await ReplyConfirmLocalized("club_admin_remove", Format.Bold(toAdmin.ToString())).ConfigureAwait(false);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
public async Task ClubCreate([Remainder]string clubName)
|
public async Task ClubCreate([Remainder]string clubName)
|
||||||
{
|
{
|
||||||
@ -118,14 +97,7 @@ namespace NadekoBot.Modules.Xp
|
|||||||
.AddField("Level Req.", club.MinimumLevelReq.ToString(), true)
|
.AddField("Level Req.", club.MinimumLevelReq.ToString(), true)
|
||||||
.AddField("Members", string.Join("\n", club.Users
|
.AddField("Members", string.Join("\n", club.Users
|
||||||
.Skip(page * 10)
|
.Skip(page * 10)
|
||||||
.Take(10)
|
.Take(10)), false);
|
||||||
.OrderByDescending(x => x.IsClubAdmin)
|
|
||||||
.Select(x =>
|
|
||||||
{
|
|
||||||
if (x.IsClubAdmin)
|
|
||||||
return x.ToString() + "⭐";
|
|
||||||
return x.ToString();
|
|
||||||
})), false);
|
|
||||||
|
|
||||||
if (Uri.IsWellFormedUriString(club.ImageUrl, UriKind.Absolute))
|
if (Uri.IsWellFormedUriString(club.ImageUrl, UriKind.Absolute))
|
||||||
return embed.WithThumbnailUrl(club.ImageUrl);
|
return embed.WithThumbnailUrl(club.ImageUrl);
|
||||||
@ -140,7 +112,7 @@ namespace NadekoBot.Modules.Xp
|
|||||||
if (--page < 0)
|
if (--page < 0)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
||||||
var club = _service.GetClubWithBansAndApplications(Context.User.Id);
|
var club = _service.GetBansAndApplications(Context.User.Id);
|
||||||
if (club == null)
|
if (club == null)
|
||||||
return ReplyErrorLocalized("club_not_exists");
|
return ReplyErrorLocalized("club_not_exists");
|
||||||
|
|
||||||
@ -159,8 +131,7 @@ namespace NadekoBot.Modules.Xp
|
|||||||
|
|
||||||
return new EmbedBuilder()
|
return new EmbedBuilder()
|
||||||
.WithTitle(GetText("club_bans_for", club.ToString()))
|
.WithTitle(GetText("club_bans_for", club.ToString()))
|
||||||
.WithDescription(toShow)
|
.WithDescription(toShow);
|
||||||
.WithOkColor();
|
|
||||||
|
|
||||||
}, bans.Length / 10);
|
}, bans.Length / 10);
|
||||||
}
|
}
|
||||||
@ -172,11 +143,11 @@ namespace NadekoBot.Modules.Xp
|
|||||||
if (--page < 0)
|
if (--page < 0)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
||||||
var club = _service.GetClubWithBansAndApplications(Context.User.Id);
|
var club = _service.GetBansAndApplications(Context.User.Id);
|
||||||
if (club == null)
|
if (club == null)
|
||||||
return ReplyErrorLocalized("club_not_exists");
|
return ReplyErrorLocalized("club_not_exists");
|
||||||
|
|
||||||
var apps = club
|
var bans = club
|
||||||
.Applicants
|
.Applicants
|
||||||
.Select(x => x.User)
|
.Select(x => x.User)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
@ -184,17 +155,16 @@ namespace NadekoBot.Modules.Xp
|
|||||||
return Context.Channel.SendPaginatedConfirmAsync(_client, page,
|
return Context.Channel.SendPaginatedConfirmAsync(_client, page,
|
||||||
curPage =>
|
curPage =>
|
||||||
{
|
{
|
||||||
var toShow = string.Join("\n", apps
|
var toShow = string.Join("\n", bans
|
||||||
.Skip(page * 10)
|
.Skip(page * 10)
|
||||||
.Take(10)
|
.Take(10)
|
||||||
.Select(x => x.ToString()));
|
.Select(x => x.ToString()));
|
||||||
|
|
||||||
return new EmbedBuilder()
|
return new EmbedBuilder()
|
||||||
.WithTitle(GetText("club_apps_for", club.ToString()))
|
.WithTitle(GetText("club_apps_for", club.ToString()))
|
||||||
.WithDescription(toShow)
|
.WithDescription(toShow);
|
||||||
.WithOkColor();
|
|
||||||
|
|
||||||
}, apps.Length / 10);
|
}, bans.Length / 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -312,7 +282,7 @@ namespace NadekoBot.Modules.Xp
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await ReplyErrorLocalized("club_disband_error").ConfigureAwait(false);
|
await ReplyErrorLocalized("club_disaband_error").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,11 +27,10 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
{
|
{
|
||||||
var du = uow.DiscordUsers.GetOrCreate(user);
|
var du = uow.DiscordUsers.GetOrCreate(user);
|
||||||
uow._context.SaveChanges();
|
uow._context.SaveChanges();
|
||||||
var xp = new LevelStats(du.TotalXp);
|
var xp = new LevelStats(uow.Xp.GetTotalUserXp(user.Id));
|
||||||
|
|
||||||
if (xp.Level >= 5 && du.Club == null)
|
if (xp.Level >= 5 && du.Club == null)
|
||||||
{
|
{
|
||||||
du.IsClubAdmin = true;
|
|
||||||
du.Club = new ClubInfo()
|
du.Club = new ClubInfo()
|
||||||
{
|
{
|
||||||
Name = clubName,
|
Name = clubName,
|
||||||
@ -53,27 +52,6 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ToggleAdmin(IUser owner, IUser toAdmin)
|
|
||||||
{
|
|
||||||
bool newState;
|
|
||||||
using (var uow = _db.UnitOfWork)
|
|
||||||
{
|
|
||||||
var club = uow.Clubs.GetByOwner(owner.Id);
|
|
||||||
var adminUser = uow.DiscordUsers.GetOrCreate(toAdmin);
|
|
||||||
|
|
||||||
if (club.OwnerId == adminUser.Id)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (club == null || club.Owner.UserId != owner.Id ||
|
|
||||||
!club.Users.Contains(adminUser))
|
|
||||||
throw new InvalidOperationException();
|
|
||||||
|
|
||||||
newState = adminUser.IsClubAdmin = !adminUser.IsClubAdmin;
|
|
||||||
uow.Complete();
|
|
||||||
}
|
|
||||||
return newState;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ClubInfo GetClubByMember(IUser user)
|
public ClubInfo GetClubByMember(IUser user)
|
||||||
{
|
{
|
||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
@ -129,7 +107,7 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
uow._context.SaveChanges();
|
uow._context.SaveChanges();
|
||||||
|
|
||||||
if (du.Club != null
|
if (du.Club != null
|
||||||
|| new LevelStats(du.TotalXp).Level < club.MinimumLevelReq
|
|| new LevelStats(uow.Xp.GetTotalUserXp(user.Id)).Level < club.MinimumLevelReq
|
||||||
|| club.Bans.Any(x => x.UserId == du.Id)
|
|| club.Bans.Any(x => x.UserId == du.Id)
|
||||||
|| club.Applicants.Any(x => x.UserId == du.Id))
|
|| club.Applicants.Any(x => x.UserId == du.Id))
|
||||||
{
|
{
|
||||||
@ -156,7 +134,11 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
discordUser = null;
|
discordUser = null;
|
||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
||||||
var club = uow.Clubs.GetByOwnerOrAdmin(clubOwnerUserId);
|
var club = uow.Clubs.GetByOwner(clubOwnerUserId,
|
||||||
|
set => set.Include(x => x.Applicants)
|
||||||
|
.ThenInclude(x => x.Club)
|
||||||
|
.Include(x => x.Applicants)
|
||||||
|
.ThenInclude(x => x.User));
|
||||||
if (club == null)
|
if (club == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -165,7 +147,6 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
applicant.User.Club = club;
|
applicant.User.Club = club;
|
||||||
applicant.User.IsClubAdmin = false;
|
|
||||||
club.Applicants.Remove(applicant);
|
club.Applicants.Remove(applicant);
|
||||||
|
|
||||||
//remove that user's all other applications
|
//remove that user's all other applications
|
||||||
@ -178,11 +159,15 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClubInfo GetClubWithBansAndApplications(ulong ownerUserId)
|
public ClubInfo GetBansAndApplications(ulong ownerUserId)
|
||||||
{
|
{
|
||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
||||||
return uow.Clubs.GetByOwnerOrAdmin(ownerUserId);
|
return uow.Clubs.GetByOwner(ownerUserId,
|
||||||
|
x => x.Include(y => y.Bans)
|
||||||
|
.ThenInclude(y => y.User)
|
||||||
|
.Include(y => y.Applicants)
|
||||||
|
.ThenInclude(y => y.User));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,7 +180,6 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
du.Club = null;
|
du.Club = null;
|
||||||
du.IsClubAdmin = false;
|
|
||||||
uow.Complete();
|
uow.Complete();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -237,7 +221,9 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
{
|
{
|
||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
||||||
club = uow.Clubs.GetByOwnerOrAdmin(ownerUserId);
|
club = uow.Clubs.GetByOwner(ownerUserId,
|
||||||
|
set => set.Include(x => x.Applicants)
|
||||||
|
.ThenInclude(x => x.User));
|
||||||
if (club == null)
|
if (club == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -270,7 +256,9 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
{
|
{
|
||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
||||||
club = uow.Clubs.GetByOwnerOrAdmin(ownerUserId);
|
club = uow.Clubs.GetByOwner(ownerUserId,
|
||||||
|
set => set.Include(x => x.Bans)
|
||||||
|
.ThenInclude(x => x.User));
|
||||||
if (club == null)
|
if (club == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -289,7 +277,7 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
{
|
{
|
||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
||||||
club = uow.Clubs.GetByOwnerOrAdmin(ownerUserId);
|
club = uow.Clubs.GetByOwner(ownerUserId);
|
||||||
if (club == null)
|
if (club == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -36,7 +36,6 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
private readonly IImagesService _images;
|
private readonly IImagesService _images;
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
private readonly NadekoStrings _strings;
|
private readonly NadekoStrings _strings;
|
||||||
private readonly IDataCache _cache;
|
|
||||||
private readonly FontCollection _fonts = new FontCollection();
|
private readonly FontCollection _fonts = new FontCollection();
|
||||||
public const int XP_REQUIRED_LVL_1 = 36;
|
public const int XP_REQUIRED_LVL_1 = 36;
|
||||||
|
|
||||||
@ -55,6 +54,9 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
private readonly ConcurrentQueue<UserCacheItem> _addMessageXp
|
private readonly ConcurrentQueue<UserCacheItem> _addMessageXp
|
||||||
= new ConcurrentQueue<UserCacheItem>();
|
= new ConcurrentQueue<UserCacheItem>();
|
||||||
|
|
||||||
|
private readonly ConcurrentDictionary<string, byte[]> _imageStreams
|
||||||
|
= new ConcurrentDictionary<string, byte[]>();
|
||||||
|
|
||||||
private readonly Timer updateXpTimer;
|
private readonly Timer updateXpTimer;
|
||||||
private readonly HttpClient http = new HttpClient();
|
private readonly HttpClient http = new HttpClient();
|
||||||
private FontFamily _usernameFontFamily;
|
private FontFamily _usernameFontFamily;
|
||||||
@ -67,7 +69,7 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
|
|
||||||
public XpService(CommandHandler cmd, IBotConfigProvider bc,
|
public XpService(CommandHandler cmd, IBotConfigProvider bc,
|
||||||
IEnumerable<GuildConfig> allGuildConfigs, IImagesService images,
|
IEnumerable<GuildConfig> allGuildConfigs, IImagesService images,
|
||||||
DbService db, NadekoStrings strings, IDataCache cache)
|
DbService db, NadekoStrings strings)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
_cmd = cmd;
|
_cmd = cmd;
|
||||||
@ -75,7 +77,6 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
_images = images;
|
_images = images;
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_strings = strings;
|
_strings = strings;
|
||||||
_cache = cache;
|
|
||||||
|
|
||||||
//load settings
|
//load settings
|
||||||
allGuildConfigs = allGuildConfigs.Where(x => x.XpSettings != null);
|
allGuildConfigs = allGuildConfigs.Where(x => x.XpSettings != null);
|
||||||
@ -144,13 +145,12 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
|
|
||||||
du.LastXpGain = DateTime.UtcNow;
|
du.LastXpGain = DateTime.UtcNow;
|
||||||
|
|
||||||
var globalXp = du.TotalXp;
|
var globalXp = uow.Xp.GetTotalUserXp(item.Key.User.Id);
|
||||||
var oldGlobalLevelData = new LevelStats(globalXp);
|
var oldGlobalLevelData = new LevelStats(globalXp);
|
||||||
var newGlobalLevelData = new LevelStats(globalXp + xp);
|
var newGlobalLevelData = new LevelStats(globalXp + xp);
|
||||||
|
|
||||||
var oldGuildLevelData = new LevelStats(usr.Xp + usr.AwardedXp);
|
var oldGuildLevelData = new LevelStats(usr.Xp + usr.AwardedXp);
|
||||||
usr.Xp += xp;
|
usr.Xp += xp;
|
||||||
du.TotalXp += xp;
|
|
||||||
if (du.Club != null)
|
if (du.Club != null)
|
||||||
du.Club.Xp += xp;
|
du.Club.Xp += xp;
|
||||||
var newGuildLevelData = new LevelStats(usr.Xp + usr.AwardedXp);
|
var newGuildLevelData = new LevelStats(usr.Xp + usr.AwardedXp);
|
||||||
@ -308,11 +308,11 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DiscordUser[] GetUserXps(int page)
|
public (ulong UserId, int TotalXp)[] GetUserXps(int page)
|
||||||
{
|
{
|
||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
||||||
return uow.DiscordUsers.GetUsersXpLeaderboardFor(page);
|
return uow.Xp.GetUsersFor(page);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,6 +403,17 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
return _rewardedUsers.Add(userId);
|
return _rewardedUsers.Add(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LevelStats GetGlobalUserStats(ulong userId)
|
||||||
|
{
|
||||||
|
int totalXp;
|
||||||
|
using (var uow = _db.UnitOfWork)
|
||||||
|
{
|
||||||
|
totalXp = uow.Xp.GetTotalUserXp(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new LevelStats(totalXp);
|
||||||
|
}
|
||||||
|
|
||||||
public FullUserStats GetUserStats(IGuildUser user)
|
public FullUserStats GetUserStats(IGuildUser user)
|
||||||
{
|
{
|
||||||
DiscordUser du;
|
DiscordUser du;
|
||||||
@ -414,8 +425,8 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
{
|
{
|
||||||
du = uow.DiscordUsers.GetOrCreate(user);
|
du = uow.DiscordUsers.GetOrCreate(user);
|
||||||
stats = uow.Xp.GetOrCreateUser(user.GuildId, user.Id);
|
stats = uow.Xp.GetOrCreateUser(user.GuildId, user.Id);
|
||||||
totalXp = du.TotalXp;
|
totalXp = uow.Xp.GetTotalUserXp(user.Id);
|
||||||
globalRank = uow.DiscordUsers.GetUserGlobalRanking(user.Id);
|
globalRank = uow.Xp.GetUserGlobalRanking(user.Id);
|
||||||
guildRank = uow.Xp.GetUserGuildRanking(user.Id, user.GuildId);
|
guildRank = uow.Xp.GetUserGuildRanking(user.Id, user.GuildId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -539,7 +550,7 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<MemoryStream> GenerateImageAsync(IGuildUser user)
|
public Task<Image<Rgba32>> GenerateImageAsync(IGuildUser user)
|
||||||
{
|
{
|
||||||
return GenerateImageAsync(GetUserStats(user));
|
return GenerateImageAsync(GetUserStats(user));
|
||||||
}
|
}
|
||||||
@ -555,166 +566,170 @@ namespace NadekoBot.Modules.Xp.Services
|
|||||||
_timeFont = _fonts.Find("Whitney-Bold").CreateFont(20);
|
_timeFont = _fonts.Find("Whitney-Bold").CreateFont(20);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<MemoryStream> GenerateImageAsync(FullUserStats stats) => Task.Run(async () =>
|
public Task<Image<Rgba32>> GenerateImageAsync(FullUserStats stats) => Task.Run(async () =>
|
||||||
{
|
{
|
||||||
using (var img = Image.Load(_images.XpCard.ToArray()))
|
var img = Image.Load(_images.XpCard.ToArray());
|
||||||
|
|
||||||
|
var username = stats.User.ToString();
|
||||||
|
var usernameFont = _usernameFontFamily
|
||||||
|
.CreateFont(username.Length <= 6
|
||||||
|
? 50
|
||||||
|
: 50 - username.Length);
|
||||||
|
|
||||||
|
img.DrawText("@" + username, usernameFont, Rgba32.White,
|
||||||
|
new PointF(130, 5));
|
||||||
|
|
||||||
|
// level
|
||||||
|
|
||||||
|
img.DrawText(stats.Global.Level.ToString(), _levelFont, Rgba32.White,
|
||||||
|
new PointF(47, 137));
|
||||||
|
|
||||||
|
img.DrawText(stats.Guild.Level.ToString(), _levelFont, Rgba32.White,
|
||||||
|
new PointF(47, 285));
|
||||||
|
|
||||||
|
//club name
|
||||||
|
|
||||||
|
var clubName = stats.User.Club?.ToString() ?? "-";
|
||||||
|
|
||||||
|
var clubFont = _clubFontFamily
|
||||||
|
.CreateFont(clubName.Length <= 8
|
||||||
|
? 35
|
||||||
|
: 35 - (clubName.Length / 2));
|
||||||
|
|
||||||
|
img.DrawText(clubName, clubFont, Rgba32.White,
|
||||||
|
new PointF(650 - clubName.Length * 10, 40));
|
||||||
|
|
||||||
|
var pen = new Pen<Rgba32>(Rgba32.Black, 1);
|
||||||
|
var brush = Brushes.Solid<Rgba32>(Rgba32.White);
|
||||||
|
var xpBgBrush = Brushes.Solid<Rgba32>(new Rgba32(0, 0, 0, 0.4f));
|
||||||
|
|
||||||
|
var global = stats.Global;
|
||||||
|
var guild = stats.Guild;
|
||||||
|
|
||||||
|
//xp bar
|
||||||
|
|
||||||
|
img.FillPolygon(xpBgBrush, new[] {
|
||||||
|
new PointF(321, 104),
|
||||||
|
new PointF(321 + (450 * (global.LevelXp / (float)global.RequiredXp)), 104),
|
||||||
|
new PointF(286 + (450 * (global.LevelXp / (float)global.RequiredXp)), 235),
|
||||||
|
new PointF(286, 235),
|
||||||
|
});
|
||||||
|
img.DrawText($"{global.LevelXp}/{global.RequiredXp}", _xpFont, brush, pen,
|
||||||
|
new PointF(430, 130));
|
||||||
|
|
||||||
|
img.FillPolygon(xpBgBrush, new[] {
|
||||||
|
new PointF(282, 248),
|
||||||
|
new PointF(282 + (450 * (guild.LevelXp / (float)guild.RequiredXp)), 248),
|
||||||
|
new PointF(247 + (450 * (guild.LevelXp / (float)guild.RequiredXp)), 379),
|
||||||
|
new PointF(247, 379),
|
||||||
|
});
|
||||||
|
img.DrawText($"{guild.LevelXp}/{guild.RequiredXp}", _xpFont, brush, pen,
|
||||||
|
new PointF(400, 270));
|
||||||
|
|
||||||
|
if (stats.FullGuildStats.AwardedXp != 0)
|
||||||
{
|
{
|
||||||
|
var sign = stats.FullGuildStats.AwardedXp > 0
|
||||||
var username = stats.User.ToString();
|
? "+ "
|
||||||
var usernameFont = _usernameFontFamily
|
: "";
|
||||||
.CreateFont(username.Length <= 6
|
img.DrawText($"({sign}{stats.FullGuildStats.AwardedXp})", _awardedFont, brush, pen,
|
||||||
? 50
|
new PointF(445 - (Math.Max(0, (stats.FullGuildStats.AwardedXp.ToString().Length - 2)) * 5), 335));
|
||||||
: 50 - username.Length);
|
|
||||||
|
|
||||||
img.DrawText("@" + username, usernameFont, Rgba32.White,
|
|
||||||
new PointF(130, 5));
|
|
||||||
|
|
||||||
// level
|
|
||||||
|
|
||||||
img.DrawText(stats.Global.Level.ToString(), _levelFont, Rgba32.White,
|
|
||||||
new PointF(47, 137));
|
|
||||||
|
|
||||||
img.DrawText(stats.Guild.Level.ToString(), _levelFont, Rgba32.White,
|
|
||||||
new PointF(47, 285));
|
|
||||||
|
|
||||||
//club name
|
|
||||||
|
|
||||||
var clubName = stats.User.Club?.ToString() ?? "-";
|
|
||||||
|
|
||||||
var clubFont = _clubFontFamily
|
|
||||||
.CreateFont(clubName.Length <= 8
|
|
||||||
? 35
|
|
||||||
: 35 - (clubName.Length / 2));
|
|
||||||
|
|
||||||
img.DrawText(clubName, clubFont, Rgba32.White,
|
|
||||||
new PointF(650 - clubName.Length * 10, 40));
|
|
||||||
|
|
||||||
var pen = new Pen<Rgba32>(Rgba32.Black, 1);
|
|
||||||
var brush = Brushes.Solid<Rgba32>(Rgba32.White);
|
|
||||||
var xpBgBrush = Brushes.Solid<Rgba32>(new Rgba32(0, 0, 0, 0.4f));
|
|
||||||
|
|
||||||
var global = stats.Global;
|
|
||||||
var guild = stats.Guild;
|
|
||||||
|
|
||||||
//xp bar
|
|
||||||
|
|
||||||
img.FillPolygon(xpBgBrush, new[] {
|
|
||||||
new PointF(321, 104),
|
|
||||||
new PointF(321 + (450 * (global.LevelXp / (float)global.RequiredXp)), 104),
|
|
||||||
new PointF(286 + (450 * (global.LevelXp / (float)global.RequiredXp)), 235),
|
|
||||||
new PointF(286, 235),
|
|
||||||
});
|
|
||||||
img.DrawText($"{global.LevelXp}/{global.RequiredXp}", _xpFont, brush, pen,
|
|
||||||
new PointF(430, 130));
|
|
||||||
|
|
||||||
img.FillPolygon(xpBgBrush, new[] {
|
|
||||||
new PointF(282, 248),
|
|
||||||
new PointF(282 + (450 * (guild.LevelXp / (float)guild.RequiredXp)), 248),
|
|
||||||
new PointF(247 + (450 * (guild.LevelXp / (float)guild.RequiredXp)), 379),
|
|
||||||
new PointF(247, 379),
|
|
||||||
});
|
|
||||||
img.DrawText($"{guild.LevelXp}/{guild.RequiredXp}", _xpFont, brush, pen,
|
|
||||||
new PointF(400, 270));
|
|
||||||
|
|
||||||
if (stats.FullGuildStats.AwardedXp != 0)
|
|
||||||
{
|
|
||||||
var sign = stats.FullGuildStats.AwardedXp > 0
|
|
||||||
? "+ "
|
|
||||||
: "";
|
|
||||||
img.DrawText($"({sign}{stats.FullGuildStats.AwardedXp})", _awardedFont, brush, pen,
|
|
||||||
new PointF(445 - (Math.Max(0, (stats.FullGuildStats.AwardedXp.ToString().Length - 2)) * 5), 335));
|
|
||||||
}
|
|
||||||
|
|
||||||
//ranking
|
|
||||||
|
|
||||||
img.DrawText(stats.GlobalRanking.ToString(), _rankFont, Rgba32.White,
|
|
||||||
new PointF(148, 170));
|
|
||||||
|
|
||||||
img.DrawText(stats.GuildRanking.ToString(), _rankFont, Rgba32.White,
|
|
||||||
new PointF(148, 317));
|
|
||||||
|
|
||||||
//time on this level
|
|
||||||
|
|
||||||
string GetTimeSpent(DateTime time)
|
|
||||||
{
|
|
||||||
var offset = DateTime.UtcNow - time;
|
|
||||||
return $"{offset.Days}d{offset.Hours}h{offset.Minutes}m";
|
|
||||||
}
|
|
||||||
|
|
||||||
img.DrawText(GetTimeSpent(stats.User.LastLevelUp), _timeFont, Rgba32.White,
|
|
||||||
new PointF(50, 197));
|
|
||||||
|
|
||||||
img.DrawText(GetTimeSpent(stats.FullGuildStats.LastLevelUp), _timeFont, Rgba32.White,
|
|
||||||
new PointF(50, 344));
|
|
||||||
|
|
||||||
//avatar
|
|
||||||
|
|
||||||
if (stats.User.AvatarId != null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var avatarUrl = stats.User.RealAvatarUrl();
|
|
||||||
|
|
||||||
var (succ, data) = await _cache.TryGetImageDataAsync(avatarUrl);
|
|
||||||
if (!succ)
|
|
||||||
{
|
|
||||||
using (var temp = await http.GetStreamAsync(avatarUrl))
|
|
||||||
using (var tempDraw = Image.Load(temp).Resize(69, 70))
|
|
||||||
{
|
|
||||||
ApplyRoundedCorners(tempDraw, 35);
|
|
||||||
data = tempDraw.ToStream().ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
await _cache.SetImageDataAsync(avatarUrl, data);
|
|
||||||
}
|
|
||||||
var toDraw = Image.Load(data);
|
|
||||||
|
|
||||||
|
|
||||||
img.DrawImage(toDraw,
|
|
||||||
1,
|
|
||||||
new Size(69, 70),
|
|
||||||
new Point(32, 10));
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_log.Warn(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//club image
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(stats.User.Club?.ImageUrl))
|
|
||||||
{
|
|
||||||
var imgUrl = stats.User.Club.ImageUrl;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var (succ, data) = await _cache.TryGetImageDataAsync(imgUrl);
|
|
||||||
if (!succ)
|
|
||||||
{
|
|
||||||
using (var temp = await http.GetStreamAsync(imgUrl))
|
|
||||||
using (var tempDraw = Image.Load(temp).Resize(45, 45))
|
|
||||||
{
|
|
||||||
ApplyRoundedCorners(tempDraw, 22.5f);
|
|
||||||
data = tempDraw.ToStream().ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
await _cache.SetImageDataAsync(imgUrl, data);
|
|
||||||
}
|
|
||||||
var toDraw = Image.Load(data);
|
|
||||||
|
|
||||||
img.DrawImage(toDraw,
|
|
||||||
1,
|
|
||||||
new Size(45, 45),
|
|
||||||
new Point(722, 25));
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_log.Warn(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return img.Resize(432, 211).ToStream();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//ranking
|
||||||
|
|
||||||
|
img.DrawText(stats.GlobalRanking.ToString(), _rankFont, Rgba32.White,
|
||||||
|
new PointF(148, 170));
|
||||||
|
|
||||||
|
img.DrawText(stats.GuildRanking.ToString(), _rankFont, Rgba32.White,
|
||||||
|
new PointF(148, 317));
|
||||||
|
|
||||||
|
//time on this level
|
||||||
|
|
||||||
|
string GetTimeSpent(DateTime time)
|
||||||
|
{
|
||||||
|
var offset = DateTime.UtcNow - time;
|
||||||
|
return $"{offset.Days}d{offset.Hours}h{offset.Minutes}m";
|
||||||
|
}
|
||||||
|
|
||||||
|
img.DrawText(GetTimeSpent(stats.User.LastLevelUp), _timeFont, Rgba32.White,
|
||||||
|
new PointF(50, 197));
|
||||||
|
|
||||||
|
img.DrawText(GetTimeSpent(stats.FullGuildStats.LastLevelUp), _timeFont, Rgba32.White,
|
||||||
|
new PointF(50, 344));
|
||||||
|
|
||||||
|
//avatar
|
||||||
|
|
||||||
|
if (stats.User.AvatarId != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var avatarUrl = stats.User.RealAvatarUrl();
|
||||||
|
|
||||||
|
byte[] s;
|
||||||
|
if (!_imageStreams.TryGetValue(avatarUrl, out s))
|
||||||
|
{
|
||||||
|
using (var temp = await http.GetStreamAsync(avatarUrl))
|
||||||
|
{
|
||||||
|
var tempDraw = Image.Load(temp);
|
||||||
|
tempDraw = tempDraw.Resize(69, 70);
|
||||||
|
ApplyRoundedCorners(tempDraw, 35);
|
||||||
|
s = tempDraw.ToStream().ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
_imageStreams.AddOrUpdate(avatarUrl, s, (k, v) => s);
|
||||||
|
}
|
||||||
|
var toDraw = Image.Load(s);
|
||||||
|
|
||||||
|
|
||||||
|
img.DrawImage(toDraw,
|
||||||
|
1,
|
||||||
|
new Size(69, 70),
|
||||||
|
new Point(32, 10));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_log.Warn(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//club image
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(stats.User.Club?.ImageUrl))
|
||||||
|
{
|
||||||
|
var imgUrl = stats.User.Club.ImageUrl;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
byte[] s;
|
||||||
|
if (!_imageStreams.TryGetValue(imgUrl, out s))
|
||||||
|
{
|
||||||
|
using (var temp = await http.GetStreamAsync(imgUrl))
|
||||||
|
{
|
||||||
|
var tempDraw = Image.Load(temp);
|
||||||
|
tempDraw = tempDraw.Resize(45, 45);
|
||||||
|
ApplyRoundedCorners(tempDraw, 22.5f);
|
||||||
|
s = tempDraw.ToStream().ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
_imageStreams.AddOrUpdate(imgUrl, s, (k, v) => s);
|
||||||
|
}
|
||||||
|
var toDraw = Image.Load(s);
|
||||||
|
|
||||||
|
img.DrawImage(toDraw,
|
||||||
|
1,
|
||||||
|
new Size(45, 45),
|
||||||
|
new Point(722, 25));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_log.Warn(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var arr = img.ToStream().ToArray();
|
||||||
|
|
||||||
|
//_log.Info("{0:F2} KB", arr.Length * 1.0f / 1.KB());
|
||||||
|
|
||||||
|
return img;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using NadekoBot.Common;
|
|
||||||
using NadekoBot.Common.Attributes;
|
using NadekoBot.Common.Attributes;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Modules.Xp.Common;
|
using NadekoBot.Modules.Xp.Common;
|
||||||
using NadekoBot.Modules.Xp.Services;
|
using NadekoBot.Modules.Xp.Services;
|
||||||
using NadekoBot.Services;
|
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -17,55 +15,23 @@ namespace NadekoBot.Modules.Xp
|
|||||||
public partial class Xp : NadekoTopLevelModule<XpService>
|
public partial class Xp : NadekoTopLevelModule<XpService>
|
||||||
{
|
{
|
||||||
private readonly DiscordSocketClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly DbService _db;
|
|
||||||
|
|
||||||
public Xp(DiscordSocketClient client,DbService db)
|
public Xp(DiscordSocketClient client)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
_db = db;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//[NadekoCommand, Usage, Description, Aliases]
|
|
||||||
//[RequireContext(ContextType.Guild)]
|
|
||||||
//[OwnerOnly]
|
|
||||||
//public async Task Populate()
|
|
||||||
//{
|
|
||||||
// var rng = new NadekoRandom();
|
|
||||||
// using (var uow = _db.UnitOfWork)
|
|
||||||
// {
|
|
||||||
// for (var i = 0ul; i < 1000000; i++)
|
|
||||||
// {
|
|
||||||
// uow.DiscordUsers.Add(new DiscordUser()
|
|
||||||
// {
|
|
||||||
// AvatarId = i.ToString(),
|
|
||||||
// Discriminator = "1234",
|
|
||||||
// UserId = i,
|
|
||||||
// Username = i.ToString(),
|
|
||||||
// Club = null,
|
|
||||||
// });
|
|
||||||
// var xp = uow.Xp.GetOrCreateUser(Context.Guild.Id, i);
|
|
||||||
// xp.Xp = rng.Next(100, 100000);
|
|
||||||
// }
|
|
||||||
// uow.Complete();
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
//[Ratelimit(30)]
|
|
||||||
public async Task Experience([Remainder]IUser user = null)
|
public async Task Experience([Remainder]IUser user = null)
|
||||||
{
|
{
|
||||||
user = user ?? Context.User;
|
user = user ?? Context.User;
|
||||||
var sw = Stopwatch.StartNew();
|
|
||||||
await Context.Channel.TriggerTypingAsync();
|
await Context.Channel.TriggerTypingAsync();
|
||||||
var img = await _service.GenerateImageAsync((IGuildUser)user);
|
var img = await _service.GenerateImageAsync((IGuildUser)user);
|
||||||
sw.Stop();
|
|
||||||
_log.Info("Generating finished in {0:F2}s", sw.Elapsed.TotalSeconds);
|
await Context.Channel.SendFileAsync(img.ToStream(), $"{user.Id}_xp.png")
|
||||||
sw.Restart();
|
|
||||||
await Context.Channel.SendFileAsync(img, $"{user.Id}_xp.png")
|
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
sw.Stop();
|
|
||||||
_log.Info("Sending finished in {0:F2}s", sw.Elapsed.TotalSeconds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -74,7 +40,7 @@ namespace NadekoBot.Modules.Xp
|
|||||||
{
|
{
|
||||||
page--;
|
page--;
|
||||||
|
|
||||||
if (page < 0 || page > 100)
|
if (page < 0)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
||||||
var roles = _service.GetRoleRewards(Context.Guild.Id)
|
var roles = _service.GetRoleRewards(Context.Guild.Id)
|
||||||
@ -203,7 +169,7 @@ namespace NadekoBot.Modules.Xp
|
|||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public Task XpLeaderboard(int page = 1)
|
public Task XpLeaderboard(int page = 1)
|
||||||
{
|
{
|
||||||
if (--page < 0 || page > 100)
|
if (--page < 0)
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|
||||||
return Context.Channel.SendPaginatedConfirmAsync(_client, page, async (curPage) =>
|
return Context.Channel.SendPaginatedConfirmAsync(_client, page, async (curPage) =>
|
||||||
@ -244,28 +210,32 @@ namespace NadekoBot.Modules.Xp
|
|||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task XpGlobalLeaderboard(int page = 1)
|
public async Task XpGlobalLeaderboard(int page = 1)
|
||||||
{
|
{
|
||||||
if (--page < 0 || page > 100)
|
if (--page < 0)
|
||||||
return;
|
return;
|
||||||
var users = _service.GetUserXps(page);
|
|
||||||
|
|
||||||
var embed = new EmbedBuilder()
|
await Context.Channel.SendPaginatedConfirmAsync(_client, page, async (curPage) =>
|
||||||
.WithTitle(GetText("global_leaderboard"))
|
|
||||||
.WithOkColor();
|
|
||||||
|
|
||||||
if (!users.Any())
|
|
||||||
embed.WithDescription("-");
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
for (int i = 0; i < users.Length; i++)
|
var users = _service.GetUserXps(curPage);
|
||||||
{
|
|
||||||
var user = users[i];
|
|
||||||
embed.AddField(
|
|
||||||
$"#{(i + 1 + page * 9)} {(user.ToString())}",
|
|
||||||
$"{GetText("level_x", LevelStats.FromXp(users[i].TotalXp).Level)} - {users[i].TotalXp}xp");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await Context.Channel.EmbedAsync(embed);
|
var embed = new EmbedBuilder()
|
||||||
|
.WithTitle(GetText("global_leaderboard"))
|
||||||
|
.WithOkColor();
|
||||||
|
|
||||||
|
if (!users.Any())
|
||||||
|
return embed.WithDescription("-");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < users.Length; i++)
|
||||||
|
{
|
||||||
|
var user = await Context.Guild.GetUserAsync(users[i].UserId).ConfigureAwait(false);
|
||||||
|
embed.AddField(
|
||||||
|
$"#{(i + 1 + curPage * 9)} {(user?.ToString() ?? users[i].UserId.ToString())}",
|
||||||
|
$"{GetText("level_x", LevelStats.FromXp(users[i].TotalXp).Level)} - {users[i].TotalXp}xp");
|
||||||
|
}
|
||||||
|
|
||||||
|
return embed;
|
||||||
|
}
|
||||||
|
}, addPaginatedFooter: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
@ -20,8 +20,6 @@ using NadekoBot.Common.ShardCom;
|
|||||||
using NadekoBot.Common.TypeReaders;
|
using NadekoBot.Common.TypeReaders;
|
||||||
using NadekoBot.Common.TypeReaders.Models;
|
using NadekoBot.Common.TypeReaders.Models;
|
||||||
using NadekoBot.Services.Database;
|
using NadekoBot.Services.Database;
|
||||||
using StackExchange.Redis;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace NadekoBot
|
namespace NadekoBot
|
||||||
{
|
{
|
||||||
@ -141,7 +139,6 @@ namespace NadekoBot
|
|||||||
.AddManual<IEnumerable<GuildConfig>>(AllGuildConfigs) //todo wrap this
|
.AddManual<IEnumerable<GuildConfig>>(AllGuildConfigs) //todo wrap this
|
||||||
.AddManual<NadekoBot>(this)
|
.AddManual<NadekoBot>(this)
|
||||||
.AddManual<IUnitOfWork>(uow)
|
.AddManual<IUnitOfWork>(uow)
|
||||||
.AddManual<IDataCache>(new RedisCache())
|
|
||||||
.LoadFrom(Assembly.GetEntryAssembly())
|
.LoadFrom(Assembly.GetEntryAssembly())
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
@ -242,6 +239,13 @@ namespace NadekoBot
|
|||||||
#if GLOBAL_NADEKO
|
#if GLOBAL_NADEKO
|
||||||
isPublicNadeko = true;
|
isPublicNadeko = true;
|
||||||
#endif
|
#endif
|
||||||
|
//_log.Info(string.Join(", ", CommandService.Commands
|
||||||
|
// .Distinct(x => x.Name + x.Module.Name)
|
||||||
|
// .SelectMany(x => x.Aliases)
|
||||||
|
// .GroupBy(x => x)
|
||||||
|
// .Where(x => x.Count() > 1)
|
||||||
|
// .Select(x => x.Key + $"({x.Count()})")));
|
||||||
|
|
||||||
//unload modules which are not available on the public bot
|
//unload modules which are not available on the public bot
|
||||||
|
|
||||||
if(isPublicNadeko)
|
if(isPublicNadeko)
|
||||||
@ -252,7 +256,6 @@ namespace NadekoBot
|
|||||||
.ForEach(x => CommandService.RemoveModuleAsync(x));
|
.ForEach(x => CommandService.RemoveModuleAsync(x));
|
||||||
|
|
||||||
Ready.TrySetResult(true);
|
Ready.TrySetResult(true);
|
||||||
HandleStatusChanges();
|
|
||||||
_log.Info($"Shard {Client.ShardId} ready.");
|
_log.Info($"Shard {Client.ShardId} ready.");
|
||||||
//_log.Info(await stats.Print().ConfigureAwait(false));
|
//_log.Info(await stats.Print().ConfigureAwait(false));
|
||||||
}
|
}
|
||||||
@ -315,51 +318,5 @@ namespace NadekoBot
|
|||||||
}
|
}
|
||||||
})).Start();
|
})).Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleStatusChanges()
|
|
||||||
{
|
|
||||||
var sub = Services.GetService<IDataCache>().Redis.GetSubscriber();
|
|
||||||
sub.Subscribe("status.game_set", async (ch, game) =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var obj = new { Name = default(string) };
|
|
||||||
obj = JsonConvert.DeserializeAnonymousType(game, obj);
|
|
||||||
await Client.SetGameAsync(obj.Name).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_log.Warn(ex);
|
|
||||||
}
|
|
||||||
}, CommandFlags.FireAndForget);
|
|
||||||
|
|
||||||
sub.Subscribe("status.stream_set", async (ch, streamData) =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var obj = new { Name = "", Url = "" };
|
|
||||||
obj = JsonConvert.DeserializeAnonymousType(streamData, obj);
|
|
||||||
await Client.SetGameAsync(obj.Name, obj.Url, StreamType.Twitch).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_log.Warn(ex);
|
|
||||||
}
|
|
||||||
}, CommandFlags.FireAndForget);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task SetGameAsync(string game)
|
|
||||||
{
|
|
||||||
var obj = new { Name = game };
|
|
||||||
var sub = Services.GetService<IDataCache>().Redis.GetSubscriber();
|
|
||||||
return sub.PublishAsync("status.game_set", JsonConvert.SerializeObject(obj));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task SetStreamAsync(string name, string url)
|
|
||||||
{
|
|
||||||
var obj = new { Name = name, Url = url };
|
|
||||||
var sub = Services.GetService<IDataCache>().Redis.GetSubscriber();
|
|
||||||
return sub.PublishAsync("status.game_set", JsonConvert.SerializeObject(obj));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,30 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
<Description>General purpose Discord bot written in C#.</Description>
|
||||||
<RuntimeFrameworkVersion>2.0.0</RuntimeFrameworkVersion>
|
<Copyright>Kwoth</Copyright>
|
||||||
<OutputType>exe</OutputType>
|
<Authors>Kwoth</Authors>
|
||||||
<AssetTargetFallback>$(AssetTargetFallback);dnxcore50;portable-net45+win8+wpa81</AssetTargetFallback>
|
<PublisherName>Kwoth</PublisherName>
|
||||||
|
<TargetFramework>netcoreapp1.1</TargetFramework>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
<AssemblyName>NadekoBot</AssemblyName>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<PackageId>NadekoBot</PackageId>
|
||||||
|
<RuntimeFrameworkVersion>1.1.1</RuntimeFrameworkVersion>
|
||||||
|
<PackageTargetFallback>$(PackageTargetFallback);dnxcore50;portable-net45+win8+wpa81</PackageTargetFallback>
|
||||||
|
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
|
||||||
|
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
|
||||||
|
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
|
||||||
|
<GenerateAssemblyInformationalVersionAttribute>false</GenerateAssemblyInformationalVersionAttribute>
|
||||||
|
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
|
||||||
|
<AssemblyVersion>1.0.0.0</AssemblyVersion>
|
||||||
|
<FileVersion>1.0.0.0</FileVersion>
|
||||||
<ApplicationIcon>nadeko_icon.ico</ApplicationIcon>
|
<ApplicationIcon>nadeko_icon.ico</ApplicationIcon>
|
||||||
<RuntimeIdentifiers>win7-x64<!--;ubuntu.14.04-x64;osx.10.10-x64 --></RuntimeIdentifiers>
|
<RuntimeIdentifiers>win7-x64<!--;ubuntu.14.04-x64;osx.10.10-x64 --></RuntimeIdentifiers>
|
||||||
<Configurations>Debug;Release;global_nadeko</Configurations>
|
|
||||||
<LangVersion>latest</LangVersion>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition=" '$(Version)' == '' ">
|
<PropertyGroup Condition=" '$(Version)' == '' ">
|
||||||
<VersionPrefix Condition=" '$(VersionPrefix)' == '' ">1.9.1</VersionPrefix>
|
<VersionPrefix Condition=" '$(VersionPrefix)' == '' ">1.4.1</VersionPrefix>
|
||||||
<Version Condition=" '$(VersionSuffix)' != '' ">$(VersionPrefix).$(VersionSuffix)</Version>
|
<Version Condition=" '$(VersionSuffix)' != '' ">$(VersionPrefix).$(VersionSuffix)</Version>
|
||||||
<Version Condition=" '$(Version)' == '' ">$(VersionPrefix)</Version>
|
<Version Condition=" '$(Version)' == '' ">$(VersionPrefix)</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@ -47,24 +59,27 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AngleSharp" Version="0.9.9" />
|
<PackageReference Include="AngleSharp" Version="0.9.9" />
|
||||||
<PackageReference Include="Discord.Net" Version="2.0.0-alpha-build-00828" />
|
<PackageReference Include="Discord.Net" Version="2.0.0-alpha-build-00828" />
|
||||||
<PackageReference Include="CoreCLR-NCalc" Version="2.1.3" />
|
<PackageReference Include="libvideo" Version="1.0.1" />
|
||||||
<PackageReference Include="Google.Apis.Urlshortener.v1" Version="1.29.1.138" />
|
<PackageReference Include="CoreCLR-NCalc" Version="2.1.2" />
|
||||||
<PackageReference Include="Google.Apis.YouTube.v3" Version="1.29.1.976" />
|
<PackageReference Include="Google.Apis.Urlshortener.v1" Version="1.19.0.138" />
|
||||||
<PackageReference Include="Google.Apis.Customsearch.v1" Version="1.29.1.896" />
|
<PackageReference Include="Google.Apis.YouTube.v3" Version="1.20.0.701" />
|
||||||
|
<PackageReference Include="Google.Apis.Customsearch.v1" Version="1.20.0.466" />
|
||||||
<PackageReference Include="ImageSharp" Version="1.0.0-alpha9-00194" />
|
<PackageReference Include="ImageSharp" Version="1.0.0-alpha9-00194" />
|
||||||
<PackageReference Include="ImageSharp.Drawing" Version="1.0.0-alpha9-00189" />
|
<PackageReference Include="ImageSharp.Drawing" Version="1.0.0-alpha9-00189" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.0.0" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.0.0" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.0.0" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="1.1.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="2.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="1.1.1" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
|
<PackageReference Include="Microsoft.Extensions.PlatformAbstractions" Version="1.1.0" />
|
||||||
<PackageReference Include="NLog" Version="5.0.0-beta10" />
|
<PackageReference Include="Newtonsoft.Json" Version="10.0.2" />
|
||||||
<PackageReference Include="StackExchange.Redis" Version="1.2.6" />
|
<PackageReference Include="NLog" Version="5.0.0-beta03" />
|
||||||
<PackageReference Include="System.ValueTuple" Version="4.4.0" />
|
<PackageReference Include="NYoutubeDL" Version="0.4.4" />
|
||||||
|
<PackageReference Include="System.ValueTuple" Version="4.4.0-preview1-25305-02" />
|
||||||
|
<PackageReference Include="System.Xml.XPath" Version="4.3.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)' == 'GlobalNadeko' ">
|
<PropertyGroup Condition=" '$(Configuration)' == 'GlobalNadeko' ">
|
||||||
@ -72,12 +87,22 @@
|
|||||||
<NoWarn>$(NoWarn);CS1573;CS1591</NoWarn>
|
<NoWarn>$(NoWarn);CS1573;CS1591</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<LangVersion>latest</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.0" />
|
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.0" />
|
||||||
<DotNetCliToolReference Include="Microsoft.DotNet.Watcher.Tools" Version="2.0.0" />
|
<DotNetCliToolReference Include="Microsoft.DotNet.Watcher.Tools" Version="1.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Update="Resources\CommandStrings.Designer.cs">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Compile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
15
src/NadekoBot/NadekoBot.nuspec
Normal file
15
src/NadekoBot/NadekoBot.nuspec
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||||
|
<metadata>
|
||||||
|
<id>NadekoBot</id>
|
||||||
|
<version>1.4.0-2$suffix$</version>
|
||||||
|
<title>NadekoBot</title>
|
||||||
|
<authors>Kwoth</authors>
|
||||||
|
<owners>Kwoth</owners>
|
||||||
|
<description>General purpose discord chat bot written in C#.</description>
|
||||||
|
<tags>nadeko;bot;nadekobot;discord bot</tags>
|
||||||
|
<projectUrl>https://github.com/Kwoth/NadekoBot</projectUrl>
|
||||||
|
<licenseUrl>https://choosealicense.com/licenses/unlicense/</licenseUrl>
|
||||||
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
|
</metadata>
|
||||||
|
</package>
|
7
src/NadekoBot/NadekoBot.xproj.DotSettings
Normal file
7
src/NadekoBot/NadekoBot.xproj.DotSettings
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=modules_005Cadministration_005Ccommands/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=modules_005Cgambling_005Ccommands/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=modules_005Cgames_005Ccommands/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=modules_005Cpermissions_005Ccommands/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=modules_005Csearches_005Ccommands/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=modules_005Cutility_005Ccommands/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
19
src/NadekoBot/Properties/AssemblyInfo.cs
Normal file
19
src/NadekoBot/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("NadekoBot")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyInformationalVersion("1.0")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("f8225ac4-3cbc-40b4-bcf3-1cacf276bf29")]
|
@ -3589,7 +3589,7 @@
|
|||||||
<value>`{0}xpex Role Excluded-Role` `{0}xpex Server`</value>
|
<value>`{0}xpex Role Excluded-Role` `{0}xpex Server`</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="xpexclude_desc" xml:space="preserve">
|
<data name="xpexclude_desc" xml:space="preserve">
|
||||||
<value>Exclude a channel, role or current server from the xp system.</value>
|
<value>Exclude a user or a role from the xp system, or whole current server.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="xpnotify_cmd" xml:space="preserve">
|
<data name="xpnotify_cmd" xml:space="preserve">
|
||||||
<value>xpnotify xpn</value>
|
<value>xpnotify xpn</value>
|
||||||
@ -3780,31 +3780,4 @@
|
|||||||
<data name="nsfwclearcache_desc" xml:space="preserve">
|
<data name="nsfwclearcache_desc" xml:space="preserve">
|
||||||
<value>Clears nsfw cache.</value>
|
<value>Clears nsfw cache.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="clubadmin_cmd" xml:space="preserve">
|
|
||||||
<value>clubadmin</value>
|
|
||||||
</data>
|
|
||||||
<data name="clubadmin_usage" xml:space="preserve">
|
|
||||||
<value>`{0}clubadmin`</value>
|
|
||||||
</data>
|
|
||||||
<data name="clubadmin_desc" xml:space="preserve">
|
|
||||||
<value>Assigns (or unassigns) staff role to the member of the club. Admins can ban, kick and accept applications.</value>
|
|
||||||
</data>
|
|
||||||
<data name="autoboobs_cmd" xml:space="preserve">
|
|
||||||
<value>autoboobs</value>
|
|
||||||
</data>
|
|
||||||
<data name="autoboobs_desc" xml:space="preserve">
|
|
||||||
<value>Posts a boobs every X seconds. 20 seconds minimum. Provide no arguments to disable.</value>
|
|
||||||
</data>
|
|
||||||
<data name="autoboobs_usage" xml:space="preserve">
|
|
||||||
<value>`{0}autoboobs 30` or `{0}autoboobs`</value>
|
|
||||||
</data>
|
|
||||||
<data name="autobutts_cmd" xml:space="preserve">
|
|
||||||
<value>autobutts</value>
|
|
||||||
</data>
|
|
||||||
<data name="autobutts_desc" xml:space="preserve">
|
|
||||||
<value>Posts a butts every X seconds. 20 seconds minimum. Provide no arguments to disable.</value>
|
|
||||||
</data>
|
|
||||||
<data name="autobutts_usage" xml:space="preserve">
|
|
||||||
<value>`{0}autobutts 30` or `{0}autobutts`</value>
|
|
||||||
</data>
|
|
||||||
</root>
|
</root>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using Newtonsoft.Json;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace NadekoBot.Services.Database.Models
|
namespace NadekoBot.Services.Database.Models
|
||||||
@ -7,9 +6,7 @@ namespace NadekoBot.Services.Database.Models
|
|||||||
public class CustomReaction : DbEntity
|
public class CustomReaction : DbEntity
|
||||||
{
|
{
|
||||||
public ulong? GuildId { get; set; }
|
public ulong? GuildId { get; set; }
|
||||||
|
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
[JsonIgnore]
|
|
||||||
public Regex Regex { get; set; }
|
public Regex Regex { get; set; }
|
||||||
public string Response { get; set; }
|
public string Response { get; set; }
|
||||||
public string Trigger { get; set; }
|
public string Trigger { get; set; }
|
||||||
@ -19,7 +16,6 @@ namespace NadekoBot.Services.Database.Models
|
|||||||
public bool AutoDeleteTrigger { get; set; }
|
public bool AutoDeleteTrigger { get; set; }
|
||||||
public bool DmResponse { get; set; }
|
public bool DmResponse { get; set; }
|
||||||
|
|
||||||
[JsonIgnore]
|
|
||||||
public bool IsGlobal => !GuildId.HasValue;
|
public bool IsGlobal => !GuildId.HasValue;
|
||||||
|
|
||||||
public bool ContainsAnywhere { get; set; }
|
public bool ContainsAnywhere { get; set; }
|
||||||
|
@ -10,9 +10,6 @@ namespace NadekoBot.Services.Database.Models
|
|||||||
public string AvatarId { get; set; }
|
public string AvatarId { get; set; }
|
||||||
|
|
||||||
public ClubInfo Club { get; set; }
|
public ClubInfo Club { get; set; }
|
||||||
public bool IsClubAdmin { get; set; }
|
|
||||||
|
|
||||||
public int TotalXp { get; set; }
|
|
||||||
public DateTime LastLevelUp { get; set; } = DateTime.UtcNow;
|
public DateTime LastLevelUp { get; set; } = DateTime.UtcNow;
|
||||||
public DateTime LastXpGain { get; set; } = DateTime.MinValue;
|
public DateTime LastXpGain { get; set; } = DateTime.MinValue;
|
||||||
public XpNotificationType NotifyOnLevelUp { get; set; }
|
public XpNotificationType NotifyOnLevelUp { get; set; }
|
||||||
|
@ -3,21 +3,23 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.EntityFrameworkCore.Design;
|
|
||||||
using Microsoft.Data.Sqlite;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace NadekoBot.Services.Database
|
namespace NadekoBot.Services.Database
|
||||||
{
|
{
|
||||||
public class NadekoContextFactory : IDesignTimeDbContextFactory<NadekoContext>
|
|
||||||
|
public class NadekoContextFactory : IDbContextFactory<NadekoContext>
|
||||||
{
|
{
|
||||||
public NadekoContext CreateDbContext(string[] args)
|
/// <summary>
|
||||||
|
/// :\ Used for migrations
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="options"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public NadekoContext Create(DbContextFactoryOptions options)
|
||||||
{
|
{
|
||||||
var optionsBuilder = new DbContextOptionsBuilder<NadekoContext>();
|
var optionsBuilder = new DbContextOptionsBuilder();
|
||||||
var builder = new SqliteConnectionStringBuilder("Data Source=data/NadekoBot.db");
|
optionsBuilder.UseSqlite("Filename=./data/NadekoBot.db");
|
||||||
builder.DataSource = Path.Combine(AppContext.BaseDirectory, builder.DataSource);
|
|
||||||
optionsBuilder.UseSqlite(builder.ToString());
|
|
||||||
var ctx = new NadekoContext(optionsBuilder.Options);
|
var ctx = new NadekoContext(optionsBuilder.Options);
|
||||||
ctx.Database.SetCommandTimeout(60);
|
ctx.Database.SetCommandTimeout(60);
|
||||||
return ctx;
|
return ctx;
|
||||||
@ -56,7 +58,12 @@ namespace NadekoBot.Services.Database
|
|||||||
public DbSet<ModulePrefix> ModulePrefixes { get; set; }
|
public DbSet<ModulePrefix> ModulePrefixes { get; set; }
|
||||||
public DbSet<RewardedUser> RewardedUsers { get; set; }
|
public DbSet<RewardedUser> RewardedUsers { get; set; }
|
||||||
|
|
||||||
public NadekoContext(DbContextOptions<NadekoContext> options) : base(options)
|
public NadekoContext() : base()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public NadekoContext(DbContextOptions options) : base(options)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,7 +231,7 @@ namespace NadekoBot.Services.Database
|
|||||||
musicPlaylistEntity
|
musicPlaylistEntity
|
||||||
.HasMany(p => p.Songs)
|
.HasMany(p => p.Songs)
|
||||||
.WithOne()
|
.WithOne()
|
||||||
.OnDelete(DeleteBehavior.Cascade);
|
.OnDelete(Microsoft.EntityFrameworkCore.Metadata.DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -322,7 +329,7 @@ namespace NadekoBot.Services.Database
|
|||||||
#region ClubManytoMany
|
#region ClubManytoMany
|
||||||
|
|
||||||
modelBuilder.Entity<ClubApplicants>()
|
modelBuilder.Entity<ClubApplicants>()
|
||||||
.HasKey(t => new { t.ClubId, t.UserId });
|
.HasKey(t => new { t.ClubId, t.UserId });
|
||||||
|
|
||||||
modelBuilder.Entity<ClubApplicants>()
|
modelBuilder.Entity<ClubApplicants>()
|
||||||
.HasOne(pt => pt.User)
|
.HasOne(pt => pt.User)
|
||||||
@ -333,7 +340,7 @@ namespace NadekoBot.Services.Database
|
|||||||
.WithMany(x => x.Applicants);
|
.WithMany(x => x.Applicants);
|
||||||
|
|
||||||
modelBuilder.Entity<ClubBans>()
|
modelBuilder.Entity<ClubBans>()
|
||||||
.HasKey(t => new { t.ClubId, t.UserId });
|
.HasKey(t => new { t.ClubId, t.UserId });
|
||||||
|
|
||||||
modelBuilder.Entity<ClubBans>()
|
modelBuilder.Entity<ClubBans>()
|
||||||
.HasOne(pt => pt.User)
|
.HasOne(pt => pt.User)
|
||||||
|
@ -10,7 +10,6 @@ namespace NadekoBot.Services.Database.Repositories
|
|||||||
int GetNextDiscrim(string clubName);
|
int GetNextDiscrim(string clubName);
|
||||||
ClubInfo GetByName(string v, int discrim, Func<DbSet<ClubInfo>, IQueryable<ClubInfo>> func = null);
|
ClubInfo GetByName(string v, int discrim, Func<DbSet<ClubInfo>, IQueryable<ClubInfo>> func = null);
|
||||||
ClubInfo GetByOwner(ulong userId, Func<DbSet<ClubInfo>, IQueryable<ClubInfo>> func = null);
|
ClubInfo GetByOwner(ulong userId, Func<DbSet<ClubInfo>, IQueryable<ClubInfo>> func = null);
|
||||||
ClubInfo GetByOwnerOrAdmin(ulong userId);
|
|
||||||
ClubInfo GetByMember(ulong userId, Func<DbSet<ClubInfo>, IQueryable<ClubInfo>> func = null);
|
ClubInfo GetByMember(ulong userId, Func<DbSet<ClubInfo>, IQueryable<ClubInfo>> func = null);
|
||||||
ClubInfo[] GetClubLeaderboardPage(int page);
|
ClubInfo[] GetClubLeaderboardPage(int page);
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,5 @@ namespace NadekoBot.Services.Database.Repositories
|
|||||||
public interface IDiscordUserRepository : IRepository<DiscordUser>
|
public interface IDiscordUserRepository : IRepository<DiscordUser>
|
||||||
{
|
{
|
||||||
DiscordUser GetOrCreate(IUser original);
|
DiscordUser GetOrCreate(IUser original);
|
||||||
int GetUserGlobalRanking(ulong id);
|
|
||||||
DiscordUser[] GetUsersXpLeaderboardFor(int page);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,10 @@ namespace NadekoBot.Services.Database.Repositories
|
|||||||
public interface IXpRepository : IRepository<UserXpStats>
|
public interface IXpRepository : IRepository<UserXpStats>
|
||||||
{
|
{
|
||||||
UserXpStats GetOrCreateUser(ulong guildId, ulong userId);
|
UserXpStats GetOrCreateUser(ulong guildId, ulong userId);
|
||||||
int GetUserGuildRanking(ulong userId, ulong guildId);
|
int GetTotalUserXp(ulong userId);
|
||||||
UserXpStats[] GetUsersFor(ulong guildId, int page);
|
UserXpStats[] GetUsersFor(ulong guildId, int page);
|
||||||
|
(ulong UserId, int TotalXp)[] GetUsersFor(int page);
|
||||||
|
int GetUserGlobalRanking(ulong userId);
|
||||||
|
int GetUserGuildRanking(ulong userId, ulong guildId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,30 +24,6 @@ namespace NadekoBot.Services.Database.Repositories.Impl
|
|||||||
return func(_set).FirstOrDefault(x => x.Owner.UserId == userId);
|
return func(_set).FirstOrDefault(x => x.Owner.UserId == userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClubInfo GetByOwnerOrAdmin(ulong userId)
|
|
||||||
{
|
|
||||||
return _set
|
|
||||||
.Include(x => x.Bans)
|
|
||||||
.ThenInclude(x => x.User)
|
|
||||||
.Include(x => x.Applicants)
|
|
||||||
.ThenInclude(x => x.User)
|
|
||||||
.Include(x => x.Owner)
|
|
||||||
.FirstOrDefault(x => x.Owner.UserId == userId) ??
|
|
||||||
_context.Set<DiscordUser>()
|
|
||||||
.Include(x => x.Club)
|
|
||||||
.ThenInclude(x => x.Users)
|
|
||||||
.Include(x => x.Club)
|
|
||||||
.ThenInclude(x => x.Bans)
|
|
||||||
.ThenInclude(x => x.User)
|
|
||||||
.Include(x => x.Club)
|
|
||||||
.ThenInclude(x => x.Applicants)
|
|
||||||
.ThenInclude(x => x.User)
|
|
||||||
.Include(x => x.Club)
|
|
||||||
.ThenInclude(x => x.Owner)
|
|
||||||
.FirstOrDefault(x => x.UserId == userId && x.IsClubAdmin)
|
|
||||||
?.Club;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ClubInfo GetByName(string name, int discrim, Func<DbSet<ClubInfo>, IQueryable<ClubInfo>> func = null)
|
public ClubInfo GetByName(string name, int discrim, Func<DbSet<ClubInfo>, IQueryable<ClubInfo>> func = null)
|
||||||
{
|
{
|
||||||
if (func == null)
|
if (func == null)
|
||||||
|
@ -37,23 +37,5 @@ namespace NadekoBot.Services.Database.Repositories.Impl
|
|||||||
|
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetUserGlobalRanking(ulong id)
|
|
||||||
{
|
|
||||||
return _set.Count(x => x.TotalXp >
|
|
||||||
_set.Where(y => y.UserId == id)
|
|
||||||
.DefaultIfEmpty()
|
|
||||||
.Sum(y => y.TotalXp));
|
|
||||||
}
|
|
||||||
|
|
||||||
public DiscordUser[] GetUsersXpLeaderboardFor(int page)
|
|
||||||
{
|
|
||||||
return _set
|
|
||||||
.OrderByDescending(x => x.TotalXp)
|
|
||||||
.Skip(page * 9)
|
|
||||||
.Take(9)
|
|
||||||
.AsEnumerable()
|
|
||||||
.ToArray();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,11 @@ namespace NadekoBot.Services.Database.Repositories.Impl
|
|||||||
return usr;
|
return usr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int GetTotalUserXp(ulong userId)
|
||||||
|
{
|
||||||
|
return _set.Where(x => x.UserId == userId).Sum(x => x.Xp);
|
||||||
|
}
|
||||||
|
|
||||||
public UserXpStats[] GetUsersFor(ulong guildId, int page)
|
public UserXpStats[] GetUsersFor(ulong guildId, int page)
|
||||||
{
|
{
|
||||||
return _set.Where(x => x.GuildId == guildId)
|
return _set.Where(x => x.GuildId == guildId)
|
||||||
@ -38,6 +43,15 @@ namespace NadekoBot.Services.Database.Repositories.Impl
|
|||||||
.ToArray();
|
.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int GetUserGlobalRanking(ulong userId)
|
||||||
|
{
|
||||||
|
return _set
|
||||||
|
.GroupBy(x => x.UserId)
|
||||||
|
.Count(x => x.Sum(y => y.Xp) > _set
|
||||||
|
.Where(y => y.UserId == userId)
|
||||||
|
.Sum(y => y.Xp)) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
public int GetUserGuildRanking(ulong userId, ulong guildId)
|
public int GetUserGuildRanking(ulong userId, ulong guildId)
|
||||||
{
|
{
|
||||||
return _set
|
return _set
|
||||||
@ -48,5 +62,16 @@ namespace NadekoBot.Services.Database.Repositories.Impl
|
|||||||
.DefaultIfEmpty()
|
.DefaultIfEmpty()
|
||||||
.Sum())) + 1;
|
.Sum())) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public (ulong UserId, int TotalXp)[] GetUsersFor(int page)
|
||||||
|
{
|
||||||
|
return _set.GroupBy(x => x.UserId)
|
||||||
|
.OrderByDescending(x => x.Sum(y => y.Xp))
|
||||||
|
.Skip(page * 9)
|
||||||
|
.Take(9)
|
||||||
|
.AsEnumerable()
|
||||||
|
.Select(x => (x.Key, x.Sum(y => y.Xp)))
|
||||||
|
.ToArray();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,28 +1,25 @@
|
|||||||
using Microsoft.Data.Sqlite;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using NadekoBot.Services.Database;
|
using NadekoBot.Services.Database;
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace NadekoBot.Services
|
namespace NadekoBot.Services
|
||||||
{
|
{
|
||||||
public class DbService
|
public class DbService
|
||||||
{
|
{
|
||||||
private readonly DbContextOptions<NadekoContext> options;
|
private readonly DbContextOptions options;
|
||||||
private readonly DbContextOptions<NadekoContext> migrateOptions;
|
private readonly DbContextOptions migrateOptions;
|
||||||
|
|
||||||
|
private readonly string _connectionString;
|
||||||
|
|
||||||
public DbService(IBotCredentials creds)
|
public DbService(IBotCredentials creds)
|
||||||
{
|
{
|
||||||
var builder = new SqliteConnectionStringBuilder(creds.Db.ConnectionString);
|
_connectionString = creds.Db.ConnectionString;
|
||||||
builder.DataSource = Path.Combine(AppContext.BaseDirectory, builder.DataSource);
|
var optionsBuilder = new DbContextOptionsBuilder();
|
||||||
|
optionsBuilder.UseSqlite(creds.Db.ConnectionString);
|
||||||
var optionsBuilder = new DbContextOptionsBuilder<NadekoContext>();
|
|
||||||
optionsBuilder.UseSqlite(builder.ToString());
|
|
||||||
options = optionsBuilder.Options;
|
options = optionsBuilder.Options;
|
||||||
|
|
||||||
optionsBuilder = new DbContextOptionsBuilder<NadekoContext>();
|
optionsBuilder = new DbContextOptionsBuilder();
|
||||||
optionsBuilder.UseSqlite(builder.ToString(), x => x.SuppressForeignKeyEnforcement());
|
optionsBuilder.UseSqlite(creds.Db.ConnectionString, x => x.SuppressForeignKeyEnforcement());
|
||||||
migrateOptions = optionsBuilder.Options;
|
migrateOptions = optionsBuilder.Options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
using StackExchange.Redis;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NadekoBot.Services
|
|
||||||
{
|
|
||||||
public interface IDataCache
|
|
||||||
{
|
|
||||||
ConnectionMultiplexer Redis { get; }
|
|
||||||
Task<(bool Success, byte[] Data)> TryGetImageDataAsync(string key);
|
|
||||||
Task<(bool Success, string Data)> TryGetAnimeDataAsync(string key);
|
|
||||||
Task SetImageDataAsync(string key, byte[] data);
|
|
||||||
Task SetAnimeDataAsync(string link, string data);
|
|
||||||
}
|
|
||||||
}
|
|
@ -90,13 +90,18 @@ namespace NadekoBot.Services.Impl
|
|||||||
ulong.TryParse(data[nameof(ClientId)], out ulong clId);
|
ulong.TryParse(data[nameof(ClientId)], out ulong clId);
|
||||||
ClientId = clId;
|
ClientId = clId;
|
||||||
|
|
||||||
|
//var scId = data[nameof(SoundCloudClientId)];
|
||||||
|
//SoundCloudClientId = scId;
|
||||||
|
//SoundCloudClientId = string.IsNullOrWhiteSpace(scId)
|
||||||
|
// ?
|
||||||
|
// : scId;
|
||||||
CarbonKey = data[nameof(CarbonKey)];
|
CarbonKey = data[nameof(CarbonKey)];
|
||||||
var dbSection = data.GetSection("db");
|
var dbSection = data.GetSection("db");
|
||||||
Db = new DBConfig(string.IsNullOrWhiteSpace(dbSection["Type"])
|
Db = new DBConfig(string.IsNullOrWhiteSpace(dbSection["Type"])
|
||||||
? "sqlite"
|
? "sqlite"
|
||||||
: dbSection["Type"],
|
: dbSection["Type"],
|
||||||
string.IsNullOrWhiteSpace(dbSection["ConnectionString"])
|
string.IsNullOrWhiteSpace(dbSection["ConnectionString"])
|
||||||
? "Data Source=data/NadekoBot.db"
|
? "Filename=./data/NadekoBot.db"
|
||||||
: dbSection["ConnectionString"]);
|
: dbSection["ConnectionString"]);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -120,7 +125,7 @@ namespace NadekoBot.Services.Impl
|
|||||||
public string SoundCloudClientId { get; set; } = "";
|
public string SoundCloudClientId { get; set; } = "";
|
||||||
public string CleverbotApiKey { get; } = "";
|
public string CleverbotApiKey { get; } = "";
|
||||||
public string CarbonKey { get; set; } = "";
|
public string CarbonKey { get; set; } = "";
|
||||||
public DBConfig Db { get; set; } = new DBConfig("sqlite", "Data Source=data/NadekoBot.db");
|
public DBConfig Db { get; set; } = new DBConfig("sqlite", "Filename=./data/NadekoBot.db");
|
||||||
public int TotalShards { get; set; } = 1;
|
public int TotalShards { get; set; } = 1;
|
||||||
public string PatreonAccessToken { get; set; } = "";
|
public string PatreonAccessToken { get; set; } = "";
|
||||||
public string PatreonCampaignId { get; set; } = "334038";
|
public string PatreonCampaignId { get; set; } = "334038";
|
||||||
|
@ -5,9 +5,6 @@ using System.Linq;
|
|||||||
using Discord;
|
using Discord;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using NadekoBot.Common;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
namespace NadekoBot.Services.Impl
|
namespace NadekoBot.Services.Impl
|
||||||
{
|
{
|
||||||
@ -19,14 +16,6 @@ namespace NadekoBot.Services.Impl
|
|||||||
public ConcurrentDictionary<ulong, CultureInfo> GuildCultureInfos { get; }
|
public ConcurrentDictionary<ulong, CultureInfo> GuildCultureInfos { get; }
|
||||||
public CultureInfo DefaultCultureInfo { get; private set; } = CultureInfo.CurrentCulture;
|
public CultureInfo DefaultCultureInfo { get; private set; } = CultureInfo.CurrentCulture;
|
||||||
|
|
||||||
private static readonly Dictionary<string, CommandData> _commandData;
|
|
||||||
|
|
||||||
static Localization()
|
|
||||||
{
|
|
||||||
_commandData = JsonConvert.DeserializeObject<Dictionary<string, CommandData>>(
|
|
||||||
File.ReadAllText("./data/command_strings.json"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Localization() { }
|
private Localization() { }
|
||||||
public Localization(IBotConfigProvider bcp, IEnumerable<GuildConfig> gcs, DbService db)
|
public Localization(IBotConfigProvider bcp, IEnumerable<GuildConfig> gcs, DbService db)
|
||||||
{
|
{
|
||||||
@ -128,19 +117,10 @@ namespace NadekoBot.Services.Impl
|
|||||||
return info ?? DefaultCultureInfo;
|
return info ?? DefaultCultureInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CommandData LoadCommand(string key)
|
public static string LoadCommandString(string key)
|
||||||
{
|
{
|
||||||
_commandData.TryGetValue(key, out var toReturn);
|
string toReturn = Resources.CommandStrings.ResourceManager.GetString(key);
|
||||||
|
return string.IsNullOrWhiteSpace(toReturn) ? key : toReturn;
|
||||||
if (toReturn == null)
|
|
||||||
return new CommandData
|
|
||||||
{
|
|
||||||
Cmd = key,
|
|
||||||
Desc = key,
|
|
||||||
Usage = key,
|
|
||||||
};
|
|
||||||
|
|
||||||
return toReturn;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,40 +0,0 @@
|
|||||||
using StackExchange.Redis;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NadekoBot.Services.Impl
|
|
||||||
{
|
|
||||||
public class RedisCache : IDataCache
|
|
||||||
{
|
|
||||||
public ConnectionMultiplexer Redis { get; }
|
|
||||||
private readonly IDatabase _db;
|
|
||||||
|
|
||||||
public RedisCache()
|
|
||||||
{
|
|
||||||
Redis = ConnectionMultiplexer.Connect("127.0.0.1");
|
|
||||||
Redis.PreserveAsyncOrder = false;
|
|
||||||
_db = Redis.GetDatabase();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<(bool Success, byte[] Data)> TryGetImageDataAsync(string key)
|
|
||||||
{
|
|
||||||
byte[] x = await _db.StringGetAsync("image_" + key);
|
|
||||||
return (x != null, x);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task SetImageDataAsync(string key, byte[] data)
|
|
||||||
{
|
|
||||||
return _db.StringSetAsync("image_" + key, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<(bool Success, string Data)> TryGetAnimeDataAsync(string key)
|
|
||||||
{
|
|
||||||
string x = await _db.StringGetAsync("anime_" + key);
|
|
||||||
return (x != null, x);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task SetAnimeDataAsync(string key, string data)
|
|
||||||
{
|
|
||||||
return _db.StringSetAsync("anime_" + key, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -20,7 +20,7 @@ namespace NadekoBot.Services.Impl
|
|||||||
private readonly IBotCredentials _creds;
|
private readonly IBotCredentials _creds;
|
||||||
private readonly DateTime _started;
|
private readonly DateTime _started;
|
||||||
|
|
||||||
public const string BotVersion = "1.9.0";
|
public const string BotVersion = "1.8.4";
|
||||||
|
|
||||||
public string Author => "Kwoth#2560";
|
public string Author => "Kwoth#2560";
|
||||||
public string Library => "Discord.Net";
|
public string Library => "Discord.Net";
|
||||||
|
@ -11,7 +11,7 @@ namespace NadekoBot.Services
|
|||||||
var logConfig = new LoggingConfiguration();
|
var logConfig = new LoggingConfiguration();
|
||||||
var consoleTarget = new ColoredConsoleTarget()
|
var consoleTarget = new ColoredConsoleTarget()
|
||||||
{
|
{
|
||||||
Layout = @"${date:format=HH\:mm\:ss} ${logger:shortName=True} | ${message}"
|
Layout = @"${date:format=HH\:mm\:ss} ${logger} | ${message}"
|
||||||
};
|
};
|
||||||
logConfig.AddTarget("Console", consoleTarget);
|
logConfig.AddTarget("Console", consoleTarget);
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
"customreactions_stats_not_found": "No stats for that trigger found, no action taken.",
|
"customreactions_stats_not_found": "No stats for that trigger found, no action taken.",
|
||||||
"customreactions_trigger": "Trigger",
|
"customreactions_trigger": "Trigger",
|
||||||
"customreactions_redacted_too_long": "Redecated because it's too long.",
|
"customreactions_redacted_too_long": "Redecated because it's too long.",
|
||||||
|
"nsfw_autohentai_stopped": "Autohentai stopped.",
|
||||||
"nsfw_not_found": "No results found.",
|
"nsfw_not_found": "No results found.",
|
||||||
"nsfw_blacklisted_tag_list": "List of blacklisted tags:",
|
"nsfw_blacklisted_tag_list": "List of blacklisted tags:",
|
||||||
"nsfw_blacklisted_tag": "One or more tags you've used are blacklisted",
|
"nsfw_blacklisted_tag": "One or more tags you've used are blacklisted",
|
||||||
@ -867,10 +868,5 @@
|
|||||||
"xp_club_icon_set": "New club icon set.",
|
"xp_club_icon_set": "New club icon set.",
|
||||||
"xp_club_bans_for": "Bans for {0} club",
|
"xp_club_bans_for": "Bans for {0} club",
|
||||||
"xp_club_apps_for": "Applicants for {0} club",
|
"xp_club_apps_for": "Applicants for {0} club",
|
||||||
"xp_club_leaderboard": "Club leaderboard - page {0}",
|
"xp_club_leaderboard": "Club leaderboard - page {0}"
|
||||||
"xp_club_admin_add": "{0} is now a club admin.",
|
|
||||||
"xp_club_admin_remove": "{0} is no longer club admin.",
|
|
||||||
"xp_club_admin_error": "Error. You are either not the owner of the club, or that user is not in your club.",
|
|
||||||
"nsfw_started": "Started. Reposting every {0}s.",
|
|
||||||
"nsfw_stopped": "Stopped reposting."
|
|
||||||
}
|
}
|
@ -13,7 +13,7 @@
|
|||||||
"CarbonKey": "",
|
"CarbonKey": "",
|
||||||
"Db": {
|
"Db": {
|
||||||
"Type": "sqlite",
|
"Type": "sqlite",
|
||||||
"ConnectionString": "Data Source=data/NadekoBot.db"
|
"ConnectionString": "Filename=./data/NadekoBot.db"
|
||||||
},
|
},
|
||||||
"TotalShards": 1,
|
"TotalShards": 1,
|
||||||
"PatreonAccessToken": "",
|
"PatreonAccessToken": "",
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user