commit
c75a625aa7
@ -1 +1 @@
|
|||||||
Subproject commit 7c0cce6d35b04d883cf5ec2d775b051e4bc8739f
|
Subproject commit 4506fc5a54fe31d826649dc413467c52a3cd7896
|
@ -45,7 +45,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
var channel = msg.Channel as SocketTextChannel;
|
var channel = msg.Channel as SocketTextChannel;
|
||||||
if (channel == null)
|
if (channel == null)
|
||||||
return;
|
return;
|
||||||
if (DeleteMessagesOnCommand.Contains(channel.Guild.Id))
|
if (DeleteMessagesOnCommand.Contains(channel.Guild.Id) && cmd.Name != "prune")
|
||||||
await msg.DeleteAsync().ConfigureAwait(false);
|
await msg.DeleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -25,7 +25,6 @@ namespace NadekoBot.Modules.Administration
|
|||||||
static AutoAssignRoleCommands()
|
static AutoAssignRoleCommands()
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
var sw = Stopwatch.StartNew();
|
|
||||||
|
|
||||||
AutoAssignedRoles = new ConcurrentDictionary<ulong, ulong>(NadekoBot.AllGuildConfigs.Where(x => x.AutoAssignRoleId != 0)
|
AutoAssignedRoles = new ConcurrentDictionary<ulong, ulong>(NadekoBot.AllGuildConfigs.Where(x => x.AutoAssignRoleId != 0)
|
||||||
.ToDictionary(k => k.GuildId, v => v.AutoAssignRoleId));
|
.ToDictionary(k => k.GuildId, v => v.AutoAssignRoleId));
|
||||||
@ -46,9 +45,6 @@ namespace NadekoBot.Modules.Administration
|
|||||||
}
|
}
|
||||||
catch (Exception ex) { _log.Warn(ex); }
|
catch (Exception ex) { _log.Warn(ex); }
|
||||||
};
|
};
|
||||||
|
|
||||||
sw.Stop();
|
|
||||||
_log.Debug($"Loaded in {sw.Elapsed.TotalSeconds:F2}s");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
@ -10,6 +10,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration
|
namespace NadekoBot.Modules.Administration
|
||||||
@ -22,8 +23,8 @@ namespace NadekoBot.Modules.Administration
|
|||||||
private static Logger _log { get; }
|
private static Logger _log { get; }
|
||||||
public static List<PlayingStatus> RotatingStatusMessages { get; }
|
public static List<PlayingStatus> RotatingStatusMessages { get; }
|
||||||
public static bool RotatingStatuses { get; private set; } = false;
|
public static bool RotatingStatuses { get; private set; } = false;
|
||||||
|
private static Timer _t { get; }
|
||||||
//todo wtf is with this while(true) in constructor
|
|
||||||
static PlayingRotateCommands()
|
static PlayingRotateCommands()
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
@ -31,48 +32,43 @@ namespace NadekoBot.Modules.Administration
|
|||||||
RotatingStatusMessages = NadekoBot.BotConfig.RotatingStatusMessages;
|
RotatingStatusMessages = NadekoBot.BotConfig.RotatingStatusMessages;
|
||||||
RotatingStatuses = NadekoBot.BotConfig.RotatingStatuses;
|
RotatingStatuses = NadekoBot.BotConfig.RotatingStatuses;
|
||||||
|
|
||||||
var t = Task.Run(async () =>
|
|
||||||
|
|
||||||
|
_t = new Timer(async (_) =>
|
||||||
{
|
{
|
||||||
var index = 0;
|
var index = 0;
|
||||||
do
|
try
|
||||||
{
|
{
|
||||||
try
|
if (!RotatingStatuses)
|
||||||
|
return;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if (!RotatingStatuses)
|
if (index >= RotatingStatusMessages.Count)
|
||||||
continue;
|
index = 0;
|
||||||
else
|
|
||||||
{
|
|
||||||
if (index >= RotatingStatusMessages.Count)
|
|
||||||
index = 0;
|
|
||||||
|
|
||||||
if (!RotatingStatusMessages.Any())
|
if (!RotatingStatusMessages.Any())
|
||||||
continue;
|
return;
|
||||||
var status = RotatingStatusMessages[index++].Status;
|
var status = RotatingStatusMessages[index++].Status;
|
||||||
if (string.IsNullOrWhiteSpace(status))
|
if (string.IsNullOrWhiteSpace(status))
|
||||||
continue;
|
return;
|
||||||
PlayingPlaceholders.ForEach(e => status = status.Replace(e.Key, e.Value()));
|
PlayingPlaceholders.ForEach(e => status = status.Replace(e.Key, e.Value()));
|
||||||
var shards = NadekoBot.Client.Shards;
|
var shards = NadekoBot.Client.Shards;
|
||||||
for (int i = 0; i < shards.Count; i++)
|
for (int i = 0; i < shards.Count; i++)
|
||||||
|
{
|
||||||
|
ShardSpecificPlaceholders.ForEach(e => status = status.Replace(e.Key, e.Value(shards.ElementAt(i))));
|
||||||
|
try { await shards.ElementAt(i).SetGameAsync(status).ConfigureAwait(false); }
|
||||||
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
ShardSpecificPlaceholders.ForEach(e => status = status.Replace(e.Key, e.Value(shards.ElementAt(i))));
|
_log.Warn(ex);
|
||||||
try { await shards.ElementAt(i).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("Rotating playing status errored.\n" + ex);
|
||||||
finally
|
}
|
||||||
{
|
}, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
|
||||||
await Task.Delay(TimeSpan.FromMinutes(1));
|
|
||||||
}
|
|
||||||
} while (true);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Dictionary<string, Func<string>> PlayingPlaceholders { get; } =
|
public static Dictionary<string, Func<string>> PlayingPlaceholders { get; } =
|
||||||
@ -92,7 +88,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ "%queued%", () => Music.Music.MusicPlayers.Sum(kvp => kvp.Value.Playlist.Count).ToString()},
|
{ "%queued%", () => Music.Music.MusicPlayers.Sum(kvp => kvp.Value.Playlist.Count).ToString()},
|
||||||
{ "%time%", () => DateTime.Now.ToString("hh:mm " + TimeZoneInfo.Local.StandardName.GetInitials()) },
|
{ "%time%", () => DateTime.Now.ToString("HH:mm " + TimeZoneInfo.Local.StandardName.GetInitials()) },
|
||||||
{ "%shardcount%", () => NadekoBot.Client.Shards.Count.ToString() },
|
{ "%shardcount%", () => NadekoBot.Client.Shards.Count.ToString() },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -132,7 +132,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
if (ids[1].ToUpperInvariant().StartsWith("C:"))
|
if (ids[1].ToUpperInvariant().StartsWith("C:"))
|
||||||
{
|
{
|
||||||
var cid = ulong.Parse(ids[1].Substring(2));
|
var cid = ulong.Parse(ids[1].Substring(2));
|
||||||
var ch = (await server.GetTextChannelsAsync()).Where(c => c.Id == cid).FirstOrDefault();
|
var ch = server.TextChannels.Where(c => c.Id == cid).FirstOrDefault();
|
||||||
if (ch == null)
|
if (ch == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@ -159,9 +159,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[OwnerOnly]
|
[OwnerOnly]
|
||||||
public async Task Announce([Remainder] string message)
|
public async Task Announce([Remainder] string message)
|
||||||
{
|
{
|
||||||
var channels = await Task.WhenAll(NadekoBot.Client.GetGuilds().Select(g =>
|
var channels = NadekoBot.Client.GetGuilds().Select(g => g.DefaultChannel).ToArray();
|
||||||
g.GetDefaultChannelAsync()
|
|
||||||
)).ConfigureAwait(false);
|
|
||||||
if (channels == null)
|
if (channels == null)
|
||||||
return;
|
return;
|
||||||
await Task.WhenAll(channels.Where(c => c != null).Select(c => c.SendConfirmAsync($"🆕 Message from {Context.User} `[Bot Owner]`:", message)))
|
await Task.WhenAll(channels.Where(c => c != null).Select(c => c.SendConfirmAsync($"🆕 Message from {Context.User} `[Bot Owner]`:", message)))
|
||||||
|
@ -4,9 +4,11 @@ using Discord.WebSocket;
|
|||||||
using NadekoBot.Attributes;
|
using NadekoBot.Attributes;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
|
using NadekoBot.Services.Database;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using NLog;
|
using NLog;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@ -17,24 +19,76 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[Group]
|
[Group]
|
||||||
public class ServerGreetCommands : ModuleBase
|
public class ServerGreetCommands : ModuleBase
|
||||||
{
|
{
|
||||||
|
//make this to a field in the guildconfig table
|
||||||
|
class GreetSettings
|
||||||
|
{
|
||||||
|
public int AutoDeleteGreetMessagesTimer { get; set; }
|
||||||
|
public int AutoDeleteByeMessagesTimer { get; set; }
|
||||||
|
|
||||||
|
public ulong GreetMessageChannelId { get; set; }
|
||||||
|
public ulong ByeMessageChannelId { get; set; }
|
||||||
|
|
||||||
|
public bool SendDmGreetMessage { get; set; }
|
||||||
|
public string DmGreetMessageText { get; set; }
|
||||||
|
|
||||||
|
public bool SendChannelGreetMessage { get; set; }
|
||||||
|
public string ChannelGreetMessageText { get; set; }
|
||||||
|
|
||||||
|
public bool SendChannelByeMessage { get; set; }
|
||||||
|
public string ChannelByeMessageText { get; set; }
|
||||||
|
|
||||||
|
public static GreetSettings Create(GuildConfig g) => new GreetSettings()
|
||||||
|
{
|
||||||
|
AutoDeleteByeMessagesTimer = g.AutoDeleteByeMessagesTimer,
|
||||||
|
AutoDeleteGreetMessagesTimer = g.AutoDeleteGreetMessagesTimer,
|
||||||
|
GreetMessageChannelId = g.GreetMessageChannelId,
|
||||||
|
ByeMessageChannelId = g.ByeMessageChannelId,
|
||||||
|
SendDmGreetMessage = g.SendDmGreetMessage,
|
||||||
|
DmGreetMessageText = g.DmGreetMessageText,
|
||||||
|
SendChannelGreetMessage = g.SendChannelGreetMessage,
|
||||||
|
ChannelGreetMessageText = g.ChannelGreetMessageText,
|
||||||
|
SendChannelByeMessage = g.SendChannelByeMessage,
|
||||||
|
ChannelByeMessageText = g.ChannelByeMessageText,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private static Logger _log { get; }
|
private static Logger _log { get; }
|
||||||
|
|
||||||
|
private static ConcurrentDictionary<ulong, GreetSettings> GuildConfigsCache { get; } = new ConcurrentDictionary<ulong, GreetSettings>();
|
||||||
|
|
||||||
static ServerGreetCommands()
|
static ServerGreetCommands()
|
||||||
{
|
{
|
||||||
NadekoBot.Client.UserJoined += UserJoined;
|
NadekoBot.Client.UserJoined += UserJoined;
|
||||||
NadekoBot.Client.UserLeft += UserLeft;
|
NadekoBot.Client.UserLeft += UserLeft;
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
|
GuildConfigsCache = new ConcurrentDictionary<ulong, GreetSettings>(NadekoBot.AllGuildConfigs.ToDictionary(g => g.GuildId, (g) => GreetSettings.Create(g)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static GreetSettings GetOrAddSettingsForGuild(ulong guildId)
|
||||||
|
{
|
||||||
|
GreetSettings settings;
|
||||||
|
GuildConfigsCache.TryGetValue(guildId, out settings);
|
||||||
|
|
||||||
|
if (settings != null)
|
||||||
|
return settings;
|
||||||
|
|
||||||
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
|
{
|
||||||
|
var gc = uow.GuildConfigs.For(guildId, set => set);
|
||||||
|
settings = GreetSettings.Create(gc);
|
||||||
|
}
|
||||||
|
|
||||||
|
GuildConfigsCache.TryAdd(guildId, settings);
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
//todo optimize ASAP
|
//todo optimize ASAP
|
||||||
private static async Task UserLeft(IGuildUser user)
|
private static async Task UserLeft(IGuildUser user)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
GuildConfig conf;
|
var conf = GetOrAddSettingsForGuild(user.GuildId);
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
|
||||||
{
|
|
||||||
conf = uow.GuildConfigs.For(user.Guild.Id, set => set);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!conf.SendChannelByeMessage) return;
|
if (!conf.SendChannelByeMessage) return;
|
||||||
var channel = (await user.Guild.GetTextChannelsAsync()).SingleOrDefault(c => c.Id == conf.ByeMessageChannelId);
|
var channel = (await user.Guild.GetTextChannelsAsync()).SingleOrDefault(c => c.Id == conf.ByeMessageChannelId);
|
||||||
@ -62,11 +116,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
GuildConfig conf;
|
var conf = GetOrAddSettingsForGuild(user.GuildId);
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
|
||||||
{
|
|
||||||
conf = uow.GuildConfigs.For(user.Guild.Id, set => set);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (conf.SendChannelGreetMessage)
|
if (conf.SendChannelGreetMessage)
|
||||||
{
|
{
|
||||||
@ -133,6 +183,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
var conf = uow.GuildConfigs.For(id, set => set);
|
var conf = uow.GuildConfigs.For(id, set => set);
|
||||||
conf.AutoDeleteGreetMessagesTimer = timer;
|
conf.AutoDeleteGreetMessagesTimer = timer;
|
||||||
|
|
||||||
|
var toAdd = GreetSettings.Create(conf);
|
||||||
|
GuildConfigsCache.AddOrUpdate(id, toAdd, (key, old) => toAdd);
|
||||||
|
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -159,6 +212,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
enabled = conf.SendChannelGreetMessage = value ?? !conf.SendChannelGreetMessage;
|
enabled = conf.SendChannelGreetMessage = value ?? !conf.SendChannelGreetMessage;
|
||||||
conf.GreetMessageChannelId = channelId;
|
conf.GreetMessageChannelId = channelId;
|
||||||
|
|
||||||
|
var toAdd = GreetSettings.Create(conf);
|
||||||
|
GuildConfigsCache.AddOrUpdate(guildId, toAdd, (key, old) => toAdd);
|
||||||
|
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
return enabled;
|
return enabled;
|
||||||
@ -201,6 +257,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
conf.ChannelGreetMessageText = message;
|
conf.ChannelGreetMessageText = message;
|
||||||
greetMsgEnabled = conf.SendChannelGreetMessage;
|
greetMsgEnabled = conf.SendChannelGreetMessage;
|
||||||
|
|
||||||
|
var toAdd = GreetSettings.Create(conf);
|
||||||
|
GuildConfigsCache.AddOrUpdate(guildId, toAdd, (key, old) => toAdd);
|
||||||
|
|
||||||
uow.Complete();
|
uow.Complete();
|
||||||
}
|
}
|
||||||
return greetMsgEnabled;
|
return greetMsgEnabled;
|
||||||
@ -227,6 +286,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
var conf = uow.GuildConfigs.For(guildId, set => set);
|
var conf = uow.GuildConfigs.For(guildId, set => set);
|
||||||
enabled = conf.SendDmGreetMessage = value ?? !conf.SendDmGreetMessage;
|
enabled = conf.SendDmGreetMessage = value ?? !conf.SendDmGreetMessage;
|
||||||
|
|
||||||
|
var toAdd = GreetSettings.Create(conf);
|
||||||
|
GuildConfigsCache.AddOrUpdate(guildId, toAdd, (key, old) => toAdd);
|
||||||
|
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
return enabled;
|
return enabled;
|
||||||
@ -269,6 +331,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
conf.DmGreetMessageText = message;
|
conf.DmGreetMessageText = message;
|
||||||
greetMsgEnabled = conf.SendDmGreetMessage;
|
greetMsgEnabled = conf.SendDmGreetMessage;
|
||||||
|
|
||||||
|
var toAdd = GreetSettings.Create(conf);
|
||||||
|
GuildConfigsCache.AddOrUpdate(guildId, toAdd, (key, old) => toAdd);
|
||||||
|
|
||||||
uow.Complete();
|
uow.Complete();
|
||||||
}
|
}
|
||||||
return greetMsgEnabled;
|
return greetMsgEnabled;
|
||||||
@ -296,6 +361,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
enabled = conf.SendChannelByeMessage = value ?? !conf.SendChannelByeMessage;
|
enabled = conf.SendChannelByeMessage = value ?? !conf.SendChannelByeMessage;
|
||||||
conf.ByeMessageChannelId = channelId;
|
conf.ByeMessageChannelId = channelId;
|
||||||
|
|
||||||
|
var toAdd = GreetSettings.Create(conf);
|
||||||
|
GuildConfigsCache.AddOrUpdate(guildId, toAdd, (key, old) => toAdd);
|
||||||
|
|
||||||
await uow.CompleteAsync();
|
await uow.CompleteAsync();
|
||||||
}
|
}
|
||||||
return enabled;
|
return enabled;
|
||||||
@ -338,6 +406,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
conf.ChannelByeMessageText = message;
|
conf.ChannelByeMessageText = message;
|
||||||
byeMsgEnabled = conf.SendChannelByeMessage;
|
byeMsgEnabled = conf.SendChannelByeMessage;
|
||||||
|
|
||||||
|
var toAdd = GreetSettings.Create(conf);
|
||||||
|
GuildConfigsCache.AddOrUpdate(guildId, toAdd, (key, old) => toAdd);
|
||||||
|
|
||||||
uow.Complete();
|
uow.Complete();
|
||||||
}
|
}
|
||||||
return byeMsgEnabled;
|
return byeMsgEnabled;
|
||||||
@ -356,16 +427,19 @@ namespace NadekoBot.Modules.Administration
|
|||||||
await Context.Channel.SendConfirmAsync("ℹ️ Automatic deletion of bye messages has been **disabled**.").ConfigureAwait(false);
|
await Context.Channel.SendConfirmAsync("ℹ️ Automatic deletion of bye messages has been **disabled**.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task SetByeDel(ulong id, int timer)
|
private static async Task SetByeDel(ulong guildId, int timer)
|
||||||
{
|
{
|
||||||
if (timer < 0 || timer > 600)
|
if (timer < 0 || timer > 600)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
var conf = uow.GuildConfigs.For(id, set => set);
|
var conf = uow.GuildConfigs.For(guildId, set => set);
|
||||||
conf.AutoDeleteByeMessagesTimer = timer;
|
conf.AutoDeleteByeMessagesTimer = timer;
|
||||||
|
|
||||||
|
var toAdd = GreetSettings.Create(conf);
|
||||||
|
GuildConfigsCache.AddOrUpdate(guildId, toAdd, (key, old) => toAdd);
|
||||||
|
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await (await guild.GetOwnerAsync()).SendErrorAsync(
|
await guild.Owner.SendErrorAsync(
|
||||||
"⚠️ I don't have **manage server** and/or **manage channels** permission," +
|
"⚠️ I don't have **manage server** and/or **manage channels** permission," +
|
||||||
$" so I cannot run `voice+text` on **{guild.Name}** server.").ConfigureAwait(false);
|
$" so I cannot run `voice+text` on **{guild.Name}** server.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@ -75,16 +75,16 @@ namespace NadekoBot.Modules.Administration
|
|||||||
var beforeVch = before.VoiceChannel;
|
var beforeVch = before.VoiceChannel;
|
||||||
if (beforeVch != null)
|
if (beforeVch != null)
|
||||||
{
|
{
|
||||||
var textChannel = (await guild.GetTextChannelsAsync()).Where(t => t.Name == GetChannelName(beforeVch.Name).ToLowerInvariant()).FirstOrDefault();
|
var textChannel = guild.TextChannels.Where(t => t.Name == GetChannelName(beforeVch.Name).ToLowerInvariant()).FirstOrDefault();
|
||||||
if (textChannel != null)
|
if (textChannel != null)
|
||||||
await textChannel.AddPermissionOverwriteAsync(user,
|
await textChannel.AddPermissionOverwriteAsync(user,
|
||||||
new OverwritePermissions(readMessages: PermValue.Deny,
|
new OverwritePermissions(readMessages: PermValue.Deny,
|
||||||
sendMessages: PermValue.Deny)).ConfigureAwait(false);
|
sendMessages: PermValue.Deny)).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
var afterVch = after.VoiceChannel;
|
var afterVch = after.VoiceChannel;
|
||||||
if (afterVch != null && guild.AFKChannelId != afterVch.Id)
|
if (afterVch != null && guild.AFKChannel?.Id != afterVch.Id)
|
||||||
{
|
{
|
||||||
var textChannel = (await guild.GetTextChannelsAsync())
|
ITextChannel textChannel = guild.TextChannels
|
||||||
.Where(t => t.Name == GetChannelName(afterVch.Name).ToLowerInvariant())
|
.Where(t => t.Name == GetChannelName(afterVch.Name).ToLowerInvariant())
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
if (textChannel == null)
|
if (textChannel == null)
|
||||||
|
@ -36,10 +36,8 @@ namespace NadekoBot.Modules.ClashOfClans
|
|||||||
.GetAllWars()
|
.GetAllWars()
|
||||||
.Select(cw =>
|
.Select(cw =>
|
||||||
{
|
{
|
||||||
cw.Channel = NadekoBot.Client.GetGuild(cw.GuildId)
|
cw.Channel = NadekoBot.Client.GetGuild(cw.GuildId)?
|
||||||
?.GetTextChannelAsync(cw.ChannelId)
|
.GetTextChannel(cw.ChannelId);
|
||||||
.GetAwaiter()
|
|
||||||
.GetResult();
|
|
||||||
return cw;
|
return cw;
|
||||||
})
|
})
|
||||||
.Where(cw => cw.Channel != null)
|
.Where(cw => cw.Channel != null)
|
||||||
@ -322,7 +320,7 @@ namespace NadekoBot.Modules.ClashOfClans
|
|||||||
|
|
||||||
public static async Task<ClashWar> CreateWar(string enemyClan, int size, ulong serverId, ulong channelId)
|
public static async Task<ClashWar> CreateWar(string enemyClan, int size, ulong serverId, ulong channelId)
|
||||||
{
|
{
|
||||||
var channel = await NadekoBot.Client.GetGuild(serverId)?.GetTextChannelAsync(channelId);
|
var channel = NadekoBot.Client.GetGuild(serverId)?.GetTextChannel(channelId);
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
var cw = new ClashWar
|
var cw = new ClashWar
|
||||||
|
@ -10,14 +10,16 @@ using NadekoBot.Extensions;
|
|||||||
using NLog;
|
using NLog;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.CustomReactions
|
namespace NadekoBot.Modules.CustomReactions
|
||||||
{
|
{
|
||||||
[NadekoModule("CustomReactions", ".")]
|
[NadekoModule("CustomReactions", ".")]
|
||||||
public class CustomReactions : DiscordModule
|
public class CustomReactions : DiscordModule
|
||||||
{
|
{
|
||||||
public static ConcurrentHashSet<CustomReaction> GlobalReactions { get; } = new ConcurrentHashSet<CustomReaction>();
|
private static CustomReaction[] _globalReactions = new CustomReaction[] { };
|
||||||
public static ConcurrentDictionary<ulong, ConcurrentHashSet<CustomReaction>> GuildReactions { get; } = new ConcurrentDictionary<ulong, ConcurrentHashSet<CustomReaction>>();
|
public static CustomReaction[] GlobalReactions => _globalReactions;
|
||||||
|
public static ConcurrentDictionary<ulong, CustomReaction[]> GuildReactions { get; } = new ConcurrentDictionary<ulong, CustomReaction[]>();
|
||||||
|
|
||||||
public static ConcurrentDictionary<string, uint> ReactionStats { get; } = new ConcurrentDictionary<string, uint>();
|
public static ConcurrentDictionary<string, uint> ReactionStats { get; } = new ConcurrentDictionary<string, uint>();
|
||||||
|
|
||||||
@ -30,8 +32,8 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
var items = uow.CustomReactions.GetAll();
|
var items = uow.CustomReactions.GetAll();
|
||||||
GuildReactions = new ConcurrentDictionary<ulong, ConcurrentHashSet<CustomReaction>>(items.Where(g => g.GuildId != null && g.GuildId != 0).GroupBy(k => k.GuildId.Value).ToDictionary(g => g.Key, g => new ConcurrentHashSet<CustomReaction>(g)));
|
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 = new ConcurrentHashSet<CustomReaction>(items.Where(g => g.GuildId == null || g.GuildId == 0));
|
_globalReactions = items.Where(g => g.GuildId == null || g.GuildId == 0).ToArray();
|
||||||
}
|
}
|
||||||
sw.Stop();
|
sw.Stop();
|
||||||
_log.Debug($"Loaded in {sw.Elapsed.TotalSeconds:F2}s");
|
_log.Debug($"Loaded in {sw.Elapsed.TotalSeconds:F2}s");
|
||||||
@ -46,32 +48,46 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
var content = umsg.Content.Trim().ToLowerInvariant();
|
var content = umsg.Content.Trim().ToLowerInvariant();
|
||||||
ConcurrentHashSet<CustomReaction> reactions;
|
CustomReaction[] reactions;
|
||||||
|
|
||||||
GuildReactions.TryGetValue(channel.Guild.Id, out reactions);
|
GuildReactions.TryGetValue(channel.Guild.Id, out reactions);
|
||||||
if (reactions != null && reactions.Any())
|
if (reactions != null && reactions.Any())
|
||||||
{
|
{
|
||||||
var reaction = reactions.Where(cr =>
|
var rs = reactions.Where(cr =>
|
||||||
{
|
{
|
||||||
|
if (cr == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
var hasTarget = cr.Response.ToLowerInvariant().Contains("%target%");
|
var hasTarget = cr.Response.ToLowerInvariant().Contains("%target%");
|
||||||
var trigger = cr.TriggerWithContext(umsg).Trim().ToLowerInvariant();
|
var trigger = cr.TriggerWithContext(umsg).Trim().ToLowerInvariant();
|
||||||
return ((hasTarget && content.StartsWith(trigger + " ")) || content == trigger);
|
return ((hasTarget && content.StartsWith(trigger + " ")) || content == trigger);
|
||||||
}).Shuffle().FirstOrDefault();
|
}).ToArray();
|
||||||
if (reaction != null)
|
|
||||||
{
|
|
||||||
if (reaction.Response != "-")
|
|
||||||
try { await channel.SendMessageAsync(reaction.ResponseWithContext(umsg)).ConfigureAwait(false); } catch { }
|
|
||||||
|
|
||||||
ReactionStats.AddOrUpdate(reaction.Trigger, 1, (k, old) => ++old);
|
if (rs.Length != 0)
|
||||||
return true;
|
{
|
||||||
|
var reaction = rs[new NadekoRandom().Next(0, rs.Length)];
|
||||||
|
if (reaction != null)
|
||||||
|
{
|
||||||
|
if (reaction.Response != "-")
|
||||||
|
try { await channel.SendMessageAsync(reaction.ResponseWithContext(umsg)).ConfigureAwait(false); } catch { }
|
||||||
|
|
||||||
|
ReactionStats.AddOrUpdate(reaction.Trigger, 1, (k, old) => ++old);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var greaction = GlobalReactions.Where(cr =>
|
|
||||||
|
var grs = GlobalReactions.Where(cr =>
|
||||||
{
|
{
|
||||||
|
if (cr == null)
|
||||||
|
return false;
|
||||||
var hasTarget = cr.Response.ToLowerInvariant().Contains("%target%");
|
var hasTarget = cr.Response.ToLowerInvariant().Contains("%target%");
|
||||||
var trigger = cr.TriggerWithContext(umsg).Trim().ToLowerInvariant();
|
var trigger = cr.TriggerWithContext(umsg).Trim().ToLowerInvariant();
|
||||||
return ((hasTarget && content.StartsWith(trigger + " ")) || content == trigger);
|
return ((hasTarget && content.StartsWith(trigger + " ")) || content == trigger);
|
||||||
}).Shuffle().FirstOrDefault();
|
}).ToArray();
|
||||||
|
if (grs.Length == 0)
|
||||||
|
return false;
|
||||||
|
var greaction = grs[new NadekoRandom().Next(0, grs.Length)];
|
||||||
|
|
||||||
if (greaction != null)
|
if (greaction != null)
|
||||||
{
|
{
|
||||||
@ -114,12 +130,19 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
|
|
||||||
if (channel == null)
|
if (channel == null)
|
||||||
{
|
{
|
||||||
GlobalReactions.Add(cr);
|
Array.Resize(ref _globalReactions, _globalReactions.Length + 1);
|
||||||
|
_globalReactions[_globalReactions.Length - 1] = cr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var reactions = GuildReactions.GetOrAdd(Context.Guild.Id, new ConcurrentHashSet<CustomReaction>());
|
var reactions = GuildReactions.AddOrUpdate(Context.Guild.Id,
|
||||||
reactions.Add(cr);
|
Array.Empty<CustomReaction>(),
|
||||||
|
(k, old) =>
|
||||||
|
{
|
||||||
|
Array.Resize(ref old, old.Length + 1);
|
||||||
|
old[old.Length - 1] = cr;
|
||||||
|
return old;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
|
await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
|
||||||
@ -136,17 +159,17 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
{
|
{
|
||||||
if (page < 1 || page > 1000)
|
if (page < 1 || page > 1000)
|
||||||
return;
|
return;
|
||||||
ConcurrentHashSet<CustomReaction> customReactions;
|
CustomReaction[] customReactions;
|
||||||
if (Context.Guild == null)
|
if (Context.Guild == null)
|
||||||
customReactions = GlobalReactions;
|
customReactions = GlobalReactions.Where(cr => cr != null).ToArray();
|
||||||
else
|
else
|
||||||
customReactions = GuildReactions.GetOrAdd(Context.Guild.Id, new ConcurrentHashSet<CustomReaction>());
|
customReactions = GuildReactions.GetOrAdd(Context.Guild.Id, Array.Empty<CustomReaction>()).Where(cr => cr != null).ToArray();
|
||||||
|
|
||||||
if (customReactions == null || !customReactions.Any())
|
if (customReactions == null || !customReactions.Any())
|
||||||
await Context.Channel.SendErrorAsync("No custom reactions found").ConfigureAwait(false);
|
await Context.Channel.SendErrorAsync("No custom reactions found").ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var lastPage = customReactions.Count / 20;
|
var lastPage = customReactions.Length / 20;
|
||||||
await Context.Channel.SendPaginatedConfirmAsync(page, curPage =>
|
await Context.Channel.SendPaginatedConfirmAsync(page, curPage =>
|
||||||
new EmbedBuilder().WithOkColor()
|
new EmbedBuilder().WithOkColor()
|
||||||
.WithTitle("Custom reactions")
|
.WithTitle("Custom reactions")
|
||||||
@ -167,11 +190,11 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
[Priority(1)]
|
[Priority(1)]
|
||||||
public async Task ListCustReact(All x)
|
public async Task ListCustReact(All x)
|
||||||
{
|
{
|
||||||
ConcurrentHashSet<CustomReaction> customReactions;
|
CustomReaction[] customReactions;
|
||||||
if (Context.Guild == null)
|
if (Context.Guild == null)
|
||||||
customReactions = GlobalReactions;
|
customReactions = GlobalReactions.Where(cr => cr != null).ToArray();
|
||||||
else
|
else
|
||||||
customReactions = GuildReactions.GetOrAdd(Context.Guild.Id, new ConcurrentHashSet<CustomReaction>());
|
customReactions = GuildReactions.GetOrAdd(Context.Guild.Id, new CustomReaction[]{ }).Where(cr => cr != null).ToArray();
|
||||||
|
|
||||||
if (customReactions == null || !customReactions.Any())
|
if (customReactions == null || !customReactions.Any())
|
||||||
await Context.Channel.SendErrorAsync("No custom reactions found").ConfigureAwait(false);
|
await Context.Channel.SendErrorAsync("No custom reactions found").ConfigureAwait(false);
|
||||||
@ -195,11 +218,11 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
{
|
{
|
||||||
if (page < 1 || page > 10000)
|
if (page < 1 || page > 10000)
|
||||||
return;
|
return;
|
||||||
ConcurrentHashSet<CustomReaction> customReactions;
|
CustomReaction[] customReactions;
|
||||||
if (Context.Guild == null)
|
if (Context.Guild == null)
|
||||||
customReactions = GlobalReactions;
|
customReactions = GlobalReactions.Where(cr => cr != null).ToArray();
|
||||||
else
|
else
|
||||||
customReactions = GuildReactions.GetOrAdd(Context.Guild.Id, new ConcurrentHashSet<CustomReaction>());
|
customReactions = GuildReactions.GetOrAdd(Context.Guild.Id, new CustomReaction[]{ }).Where(cr => cr != null).ToArray();
|
||||||
|
|
||||||
if (customReactions == null || !customReactions.Any())
|
if (customReactions == null || !customReactions.Any())
|
||||||
await Context.Channel.SendErrorAsync("No custom reactions found").ConfigureAwait(false);
|
await Context.Channel.SendErrorAsync("No custom reactions found").ConfigureAwait(false);
|
||||||
@ -225,13 +248,13 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
public async Task ShowCustReact(int id)
|
public async Task ShowCustReact(int id)
|
||||||
{
|
{
|
||||||
ConcurrentHashSet<CustomReaction> customReactions;
|
CustomReaction[] customReactions;
|
||||||
if (Context.Guild == null)
|
if (Context.Guild == null)
|
||||||
customReactions = GlobalReactions;
|
customReactions = GlobalReactions;
|
||||||
else
|
else
|
||||||
customReactions = GuildReactions.GetOrAdd(Context.Guild.Id, new ConcurrentHashSet<CustomReaction>());
|
customReactions = GuildReactions.GetOrAdd(Context.Guild.Id, new CustomReaction[]{ });
|
||||||
|
|
||||||
var found = customReactions.FirstOrDefault(cr => cr.Id == id);
|
var found = customReactions.FirstOrDefault(cr => cr?.Id == id);
|
||||||
|
|
||||||
if (found == null)
|
if (found == null)
|
||||||
await Context.Channel.SendErrorAsync("No custom reaction found with that id.").ConfigureAwait(false);
|
await Context.Channel.SendErrorAsync("No custom reaction found with that id.").ConfigureAwait(false);
|
||||||
@ -265,13 +288,17 @@ 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);
|
||||||
GlobalReactions.RemoveWhere(cr => cr.Id == toDelete.Id);
|
//todo i can dramatically improve performance of this, if Ids are ordered.
|
||||||
|
_globalReactions = 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)
|
||||||
{
|
{
|
||||||
uow.CustomReactions.Remove(toDelete);
|
uow.CustomReactions.Remove(toDelete);
|
||||||
GuildReactions.GetOrAdd(Context.Guild.Id, new ConcurrentHashSet<CustomReaction>()).RemoveWhere(cr => cr.Id == toDelete.Id);
|
GuildReactions.AddOrUpdate(Context.Guild.Id, new CustomReaction[] { }, (key, old) =>
|
||||||
|
{
|
||||||
|
return old.Where(cr => cr?.Id != toDelete.Id).ToArray();
|
||||||
|
});
|
||||||
success = true;
|
success = true;
|
||||||
}
|
}
|
||||||
if (success)
|
if (success)
|
||||||
@ -312,8 +339,10 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
{
|
{
|
||||||
if (page < 1)
|
if (page < 1)
|
||||||
return;
|
return;
|
||||||
var ordered = ReactionStats.OrderByDescending(x => x.Value).ToList();
|
var ordered = ReactionStats.OrderByDescending(x => x.Value).ToArray();
|
||||||
var lastPage = ordered.Count / 9;
|
if (!ordered.Any())
|
||||||
|
return;
|
||||||
|
var lastPage = ordered.Length / 9;
|
||||||
await Context.Channel.SendPaginatedConfirmAsync(page,
|
await Context.Channel.SendPaginatedConfirmAsync(page,
|
||||||
(curPage) => ordered.Skip((curPage - 1) * 9)
|
(curPage) => ordered.Skip((curPage - 1) * 9)
|
||||||
.Take(9)
|
.Take(9)
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
|
using Discord.WebSocket;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
@ -25,9 +27,13 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
if(ch == null)
|
if(ch == null)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
var usrs = (ch.Guild.GetUsersAsync().GetAwaiter().GetResult());
|
var g = ch.Guild as SocketGuild;
|
||||||
|
if(g == null)
|
||||||
|
return "";
|
||||||
|
|
||||||
return usrs.Skip(new NadekoRandom().Next(0,usrs.Count-1)).Shuffle().FirstOrDefault()?.Mention ?? "";
|
var users = g.Users.ToArray();
|
||||||
|
|
||||||
|
return users[new NadekoRandom().Next(0, users.Length-1)].Mention;
|
||||||
} }
|
} }
|
||||||
//{"%rng%", (ctx) => { return new NadekoRandom().Next(0,10).ToString(); } }
|
//{"%rng%", (ctx) => { return new NadekoRandom().Next(0,10).ToString(); } }
|
||||||
};
|
};
|
||||||
|
@ -59,14 +59,14 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
try { await msg.DeleteAsync().ConfigureAwait(false); }
|
try { await msg.DeleteAsync().ConfigureAwait(false); }
|
||||||
catch { }
|
catch { return; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
using (msg.OnReaction(async (r) =>
|
using (msg.OnReaction(async (r) =>
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (r.Emoji.Name == "🌸" && r.User.IsSpecified && _flowerReactionAwardedUsers.Add(r.User.Value.Id))
|
if (r.Emoji.Name == "🌸" && r.User.IsSpecified && ((DateTime.UtcNow - r.User.Value.CreatedAt).TotalDays > 5) && _flowerReactionAwardedUsers.Add(r.User.Value.Id))
|
||||||
{
|
{
|
||||||
try { await CurrencyHandler.AddCurrencyAsync(r.User.Value, "Flower Reaction Event", 100, false).ConfigureAwait(false); } catch { }
|
try { await CurrencyHandler.AddCurrencyAsync(r.User.Value, "Flower Reaction Event", 100, false).ConfigureAwait(false); } catch { }
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
var members = role.Members().Where(u => u.Status != UserStatus.Offline && u.Status != UserStatus.Unknown);
|
var members = role.Members().Where(u => u.Status != UserStatus.Offline && u.Status != UserStatus.Unknown);
|
||||||
var membersArray = members as IUser[] ?? members.ToArray();
|
var membersArray = members as IUser[] ?? members.ToArray();
|
||||||
var usr = membersArray[new NadekoRandom().Next(0, membersArray.Length)];
|
var usr = membersArray[new NadekoRandom().Next(0, membersArray.Length)];
|
||||||
await Context.Channel.SendConfirmAsync("🎟 Raffled user", $"**{usr.Username}#{usr.Discriminator}** ID: `{usr.Id}`").ConfigureAwait(false);
|
await Context.Channel.SendConfirmAsync("🎟 Raffled user", $"**{usr.Username}#{usr.Discriminator}**", footer: $"ID: {usr.Id}").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
@ -69,6 +69,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
private readonly ConcurrentDictionary<string, IGuildUser> submissions = new ConcurrentDictionary<string, IGuildUser>();
|
private readonly ConcurrentDictionary<string, IGuildUser> submissions = new ConcurrentDictionary<string, IGuildUser>();
|
||||||
public IReadOnlyDictionary<string, IGuildUser> Submissions => submissions;
|
public IReadOnlyDictionary<string, IGuildUser> Submissions => submissions;
|
||||||
|
|
||||||
|
private readonly ConcurrentHashSet<ulong> usersWhoSubmitted = new ConcurrentHashSet<ulong>();
|
||||||
private readonly ConcurrentHashSet<ulong> usersWhoVoted = new ConcurrentHashSet<ulong>();
|
private readonly ConcurrentHashSet<ulong> usersWhoVoted = new ConcurrentHashSet<ulong>();
|
||||||
|
|
||||||
private int spamCount = 0;
|
private int spamCount = 0;
|
||||||
@ -190,10 +191,6 @@ namespace NadekoBot.Modules.Games
|
|||||||
try { await channel.EmbedAsync(GetEmbed()).ConfigureAwait(false); }
|
try { await channel.EmbedAsync(GetEmbed()).ConfigureAwait(false); }
|
||||||
catch { }
|
catch { }
|
||||||
}
|
}
|
||||||
//user didn't input something already
|
|
||||||
IGuildUser throwaway;
|
|
||||||
if (submissions.TryGetValue(input, out throwaway))
|
|
||||||
return;
|
|
||||||
var inputWords = input.Split(' '); //get all words
|
var inputWords = input.Split(' '); //get all words
|
||||||
|
|
||||||
if (inputWords.Length != startingLetters.Length) // number of words must be the same as the number of the starting letters
|
if (inputWords.Length != startingLetters.Length) // number of words must be the same as the number of the starting letters
|
||||||
@ -207,9 +204,15 @@ namespace NadekoBot.Modules.Games
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!usersWhoSubmitted.Add(guildUser.Id))
|
||||||
|
return;
|
||||||
//try adding it to the list of answers
|
//try adding it to the list of answers
|
||||||
if (!submissions.TryAdd(input, guildUser))
|
if (!submissions.TryAdd(input, guildUser))
|
||||||
|
{
|
||||||
|
usersWhoSubmitted.TryRemove(guildUser.Id);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// all good. valid input. answer recorded
|
// all good. valid input. answer recorded
|
||||||
await channel.SendConfirmAsync("Acrophobia", $"{guildUser.Mention} submitted their sentence. ({submissions.Count} total)");
|
await channel.SendConfirmAsync("Acrophobia", $"{guildUser.Mention} submitted their sentence. ({submissions.Count} total)");
|
||||||
|
@ -189,13 +189,13 @@ namespace NadekoBot.Modules.Games.Commands.Hangman
|
|||||||
catch (Exception ex) { _log.Warn(ex); }
|
catch (Exception ex) { _log.Warn(ex); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetHangman() => $@"\_\_\_\_\_\_\_\_\_
|
public string GetHangman() => $@". ┌─────┐
|
||||||
| |
|
.┃...............┋
|
||||||
| |
|
.┃...............┋
|
||||||
{(Errors > 0 ? "😲" : " ")} |
|
.┃{(Errors > 0 ? ".............😲" : "")}
|
||||||
{(Errors > 1 ? "/" : " ")} {(Errors > 2 ? "|" : " ")} {(Errors > 3 ? "\\" : " ")} |
|
.┃{(Errors > 1 ? "............./" : "")} {(Errors > 2 ? "|" : "")} {(Errors > 3 ? "\\" : "")}
|
||||||
{(Errors > 4 ? "/" : " ")} {(Errors > 5 ? "\\" : " ")} |
|
.┃{(Errors > 4 ? "............../" : "")} {(Errors > 5 ? "\\" : "")}
|
||||||
/-\";
|
/-\";
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
@ -61,7 +61,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await Context.Channel.SendConfirmAsync("Hangman game started", hm.ScrambledWord + "\n" + hm.GetHangman() + "\n" + hm.ScrambledWord);
|
await Context.Channel.SendConfirmAsync("Hangman game started", hm.ScrambledWord + "\n" + hm.GetHangman());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,9 +76,9 @@ namespace NadekoBot.Modules.Games.Trivia
|
|||||||
|
|
||||||
questionMessage = await channel.EmbedAsync(questionEmbed).ConfigureAwait(false);
|
questionMessage = await channel.EmbedAsync(questionEmbed).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (HttpException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound ||
|
catch (HttpException ex) when (ex.HttpCode == System.Net.HttpStatusCode.NotFound ||
|
||||||
ex.StatusCode == System.Net.HttpStatusCode.Forbidden ||
|
ex.HttpCode == System.Net.HttpStatusCode.Forbidden ||
|
||||||
ex.StatusCode == System.Net.HttpStatusCode.BadRequest)
|
ex.HttpCode == System.Net.HttpStatusCode.BadRequest)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -106,7 +106,7 @@ namespace NadekoBot.Modules.Games.Trivia
|
|||||||
await questionMessage.ModifyAsync(m => m.Embed = questionEmbed.WithFooter(efb => efb.WithText(CurrentQuestion.GetHint())).Build())
|
await questionMessage.ModifyAsync(m => m.Embed = questionEmbed.WithFooter(efb => efb.WithText(CurrentQuestion.GetHint())).Build())
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (HttpException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound || ex.StatusCode == System.Net.HttpStatusCode.Forbidden)
|
catch (HttpException ex) when (ex.HttpCode == System.Net.HttpStatusCode.NotFound || ex.HttpCode == System.Net.HttpStatusCode.Forbidden)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -711,14 +711,11 @@ namespace NadekoBot.Modules.Music
|
|||||||
await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
|
await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//todo only author or owner
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task DeletePlaylist([Remainder] int id)
|
public async Task DeletePlaylist([Remainder] int id)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
bool success = false;
|
bool success = false;
|
||||||
MusicPlaylist pl = null;
|
MusicPlaylist pl = null;
|
||||||
try
|
try
|
||||||
@ -747,7 +744,7 @@ namespace NadekoBot.Modules.Music
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Console.WriteLine(ex);
|
_log.Warn(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
using Discord;
|
using AngleSharp;
|
||||||
|
using AngleSharp.Dom.Html;
|
||||||
|
using AngleSharp.Extensions;
|
||||||
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using NadekoBot.Attributes;
|
using NadekoBot.Attributes;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
@ -8,6 +11,7 @@ using Newtonsoft.Json.Linq;
|
|||||||
using NLog;
|
using NLog;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -52,6 +56,116 @@ namespace NadekoBot.Modules.Searches
|
|||||||
}, null, TimeSpan.FromSeconds(0), TimeSpan.FromMinutes(29));
|
}, null, TimeSpan.FromSeconds(0), TimeSpan.FromMinutes(29));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[Priority(1)]
|
||||||
|
public async Task Mal([Remainder] string name)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(name))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var fullQueryLink = "https://myanimelist.net/profile/" + name;
|
||||||
|
|
||||||
|
var config = Configuration.Default.WithDefaultLoader();
|
||||||
|
var document = await BrowsingContext.New(config).OpenAsync(fullQueryLink);
|
||||||
|
|
||||||
|
var imageElem = document.QuerySelector("body > div#myanimelist > div.wrapper > div#contentWrapper > div#content > div.content-container > div.container-left > div.user-profile > div.user-image > img");
|
||||||
|
var imageUrl = ((IHtmlImageElement)imageElem)?.Source ?? "http://icecream.me/uploads/870b03f36b59cc16ebfe314ef2dde781.png";
|
||||||
|
|
||||||
|
var stats = document.QuerySelectorAll("body > div#myanimelist > div.wrapper > div#contentWrapper > div#content > div.content-container > div.container-right > div#statistics > div.user-statistics-stats > div.stats > div.clearfix > ul.stats-status > li > span").Select(x => x.InnerHtml).ToList();
|
||||||
|
|
||||||
|
var favorites = document.QuerySelectorAll("div.user-favorites > div.di-tc");
|
||||||
|
|
||||||
|
var favAnime = "No favorite anime yet";
|
||||||
|
if (favorites[0].QuerySelector("p") == null)
|
||||||
|
favAnime = string.Join("\n", favorites[0].QuerySelectorAll("ul > li > div.di-tc.va-t > a")
|
||||||
|
.Shuffle()
|
||||||
|
.Take(3)
|
||||||
|
.Select(x =>
|
||||||
|
{
|
||||||
|
var elem = (IHtmlAnchorElement)x;
|
||||||
|
return $"[{elem.InnerHtml}]({elem.Href})";
|
||||||
|
}));
|
||||||
|
|
||||||
|
//var favManga = "No favorite manga yet.";
|
||||||
|
//if (favorites[1].QuerySelector("p") == null)
|
||||||
|
// favManga = string.Join("\n", favorites[1].QuerySelectorAll("ul > li > div.di-tc.va-t > a")
|
||||||
|
// .Take(3)
|
||||||
|
// .Select(x =>
|
||||||
|
// {
|
||||||
|
// var elem = (IHtmlAnchorElement)x;
|
||||||
|
// return $"[{elem.InnerHtml}]({elem.Href})";
|
||||||
|
// }));
|
||||||
|
|
||||||
|
var info = document.QuerySelectorAll("ul.user-status:nth-child(3) > li")
|
||||||
|
.Select(x => Tuple.Create(x.Children[0].InnerHtml, x.Children[1].InnerHtml))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var daysAndMean = document.QuerySelectorAll("div.anime:nth-child(1) > div:nth-child(2) > div")
|
||||||
|
.Select(x => x.TextContent.Split(':').Select(y => y.Trim()).ToArray())
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
var embed = new EmbedBuilder()
|
||||||
|
.WithOkColor()
|
||||||
|
.WithTitle($"{name}'s MAL profile")
|
||||||
|
.AddField(efb => efb.WithName("💚 Watching").WithValue(stats[0]).WithIsInline(true))
|
||||||
|
.AddField(efb => efb.WithName("💙 Completed").WithValue(stats[1]).WithIsInline(true));
|
||||||
|
if (info.Count < 3)
|
||||||
|
embed.AddField(efb => efb.WithName("💛 On-Hold").WithValue(stats[2]).WithIsInline(true));
|
||||||
|
embed
|
||||||
|
.AddField(efb => efb.WithName("💔 Dropped").WithValue(stats[3]).WithIsInline(true))
|
||||||
|
.AddField(efb => efb.WithName("⚪ Plan to watch").WithValue(stats[4]).WithIsInline(true))
|
||||||
|
.AddField(efb => efb.WithName("🕐 " + daysAndMean[0][0]).WithValue(daysAndMean[0][1]).WithIsInline(true))
|
||||||
|
.AddField(efb => efb.WithName("📊 " + daysAndMean[1][0]).WithValue(daysAndMean[1][1]).WithIsInline(true))
|
||||||
|
.AddField(efb => efb.WithName(MalInfoToEmoji(info[0].Item1) + " " + info[0].Item1).WithValue(info[0].Item2.TrimTo(20)).WithIsInline(true))
|
||||||
|
.AddField(efb => efb.WithName(MalInfoToEmoji(info[1].Item1) + " " + info[1].Item1).WithValue(info[1].Item2.TrimTo(20)).WithIsInline(true));
|
||||||
|
if (info.Count > 2)
|
||||||
|
embed.AddField(efb => efb.WithName(MalInfoToEmoji(info[2].Item1) + " " + info[2].Item1).WithValue(info[2].Item2.TrimTo(20)).WithIsInline(true));
|
||||||
|
//if(info.Count > 3)
|
||||||
|
// embed.AddField(efb => efb.WithName(MalInfoToEmoji(info[3].Item1) + " " + info[3].Item1).WithValue(info[3].Item2).WithIsInline(true))
|
||||||
|
embed
|
||||||
|
.WithDescription($@"
|
||||||
|
** https://myanimelist.net/animelist/{ name } **
|
||||||
|
|
||||||
|
**Top 3 Favorite Anime:**
|
||||||
|
{favAnime}"
|
||||||
|
|
||||||
|
//**[Manga List](https://myanimelist.net/mangalist/{name})**
|
||||||
|
//💚`Reading:` {stats[5]}
|
||||||
|
//💙`Completed:` {stats[6]}
|
||||||
|
//💔`Dropped:` {stats[8]}
|
||||||
|
//⚪`Plan to read:` {stats[9]}
|
||||||
|
|
||||||
|
//**Top 3 Favorite Manga:**
|
||||||
|
//{favManga}"
|
||||||
|
|
||||||
|
)
|
||||||
|
.WithUrl(fullQueryLink)
|
||||||
|
.WithImageUrl(imageUrl);
|
||||||
|
|
||||||
|
await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string MalInfoToEmoji(string info) {
|
||||||
|
info = info.Trim().ToLowerInvariant();
|
||||||
|
switch (info)
|
||||||
|
{
|
||||||
|
case "gender":
|
||||||
|
return "🚁";
|
||||||
|
case "location":
|
||||||
|
return "🗺";
|
||||||
|
case "last online":
|
||||||
|
return "👥";
|
||||||
|
case "birthday":
|
||||||
|
return "📆";
|
||||||
|
default:
|
||||||
|
return "❔";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[Priority(0)]
|
||||||
|
public Task Mal(IUser usr) => Mal(usr.Username);
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
public async Task Anime([Remainder] string query)
|
public async Task Anime([Remainder] string query)
|
||||||
{
|
{
|
||||||
|
@ -45,7 +45,7 @@ namespace NadekoBot.Modules.Searches
|
|||||||
MemoryStream ms = new MemoryStream();
|
MemoryStream ms = new MemoryStream();
|
||||||
res.CopyTo(ms);
|
res.CopyTo(ms);
|
||||||
ms.Position = 0;
|
ms.Position = 0;
|
||||||
await Context.Channel.SendFileAsync(ms, $"{usr}.png", $"🎧 **Profile Link: **https://osu.ppy.sh/u/{Uri.EscapeDataString(usr)}\n`Image provided by https://lemmmy.pw/osusig`").ConfigureAwait(false);
|
await Context.Channel.SendFileAsync(ms, $"{usr}.png", $"🎧 **Profile Link:** <https://new.ppy.sh/u/{Uri.EscapeDataString(usr)}>\n`Image provided by https://lemmmy.pw/osusig`").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -60,9 +60,9 @@ namespace NadekoBot.Modules.Searches
|
|||||||
.WithThumbnailUrl(rankimg)
|
.WithThumbnailUrl(rankimg)
|
||||||
.AddField(fb => fb.WithName("**Level**").WithValue($"{model.level}").WithIsInline(true))
|
.AddField(fb => fb.WithName("**Level**").WithValue($"{model.level}").WithIsInline(true))
|
||||||
.AddField(fb => fb.WithName("**Quick Wins**").WithValue($"{model.Games.Quick.wins}").WithIsInline(true))
|
.AddField(fb => fb.WithName("**Quick Wins**").WithValue($"{model.Games.Quick.wins}").WithIsInline(true))
|
||||||
.AddField(fb => fb.WithName("**Current Competitive Wins**").WithValue($"{model.Games.Competitive.wins}").WithIsInline(true))
|
.AddField(fb => fb.WithName("**Competitive Wins**").WithValue($"{model.Games.Competitive.wins}").WithIsInline(true))
|
||||||
.AddField(fb => fb.WithName("**Current Competitive Loses**").WithValue($"{model.Games.Competitive.lost}").WithIsInline(true))
|
.AddField(fb => fb.WithName("**Competitive Loses**").WithValue($"{model.Games.Competitive.lost}").WithIsInline(true))
|
||||||
.AddField(fb => fb.WithName("**Current Competitive Played**").WithValue($"{model.Games.Competitive.played}").WithIsInline(true))
|
.AddField(fb => fb.WithName("**Competitive Played**").WithValue($"{model.Games.Competitive.played}").WithIsInline(true))
|
||||||
.AddField(fb => fb.WithName("**Competitive Rank**").WithValue(rank).WithIsInline(true))
|
.AddField(fb => fb.WithName("**Competitive Rank**").WithValue(rank).WithIsInline(true))
|
||||||
.AddField(fb => fb.WithName("**Competitive Playtime**").WithValue($"{model.Playtime.competitive}").WithIsInline(true))
|
.AddField(fb => fb.WithName("**Competitive Playtime**").WithValue($"{model.Playtime.competitive}").WithIsInline(true))
|
||||||
.AddField(fb => fb.WithName("**Quick Playtime**").WithValue($"{model.Playtime.quick}").WithIsInline(true))
|
.AddField(fb => fb.WithName("**Quick Playtime**").WithValue($"{model.Playtime.quick}").WithIsInline(true))
|
||||||
|
@ -105,7 +105,7 @@ namespace NadekoBot.Modules.Searches
|
|||||||
var server = NadekoBot.Client.GetGuild(fs.GuildId);
|
var server = NadekoBot.Client.GetGuild(fs.GuildId);
|
||||||
if (server == null)
|
if (server == null)
|
||||||
return;
|
return;
|
||||||
var channel = await server.GetTextChannelAsync(fs.ChannelId);
|
var channel = server.GetTextChannel(fs.ChannelId);
|
||||||
if (channel == null)
|
if (channel == null)
|
||||||
return;
|
return;
|
||||||
try
|
try
|
||||||
|
@ -117,31 +117,49 @@ namespace NadekoBot.Modules.Searches
|
|||||||
|
|
||||||
terms = WebUtility.UrlEncode(terms).Replace(' ', '+');
|
terms = WebUtility.UrlEncode(terms).Replace(' ', '+');
|
||||||
|
|
||||||
var fullQueryLink = $"http://imgur.com/search?q={ terms }";
|
try
|
||||||
var config = Configuration.Default.WithDefaultLoader();
|
{
|
||||||
var document = await BrowsingContext.New(config).OpenAsync(fullQueryLink);
|
var res = await NadekoBot.Google.GetImageAsync(terms).ConfigureAwait(false);
|
||||||
|
var embed = new EmbedBuilder()
|
||||||
|
.WithOkColor()
|
||||||
|
.WithAuthor(eab => eab.WithName("Image Search For: " + terms.TrimTo(50))
|
||||||
|
.WithUrl("https://www.google.rs/search?q=" + terms + "&source=lnms&tbm=isch")
|
||||||
|
.WithIconUrl("http://i.imgur.com/G46fm8J.png"))
|
||||||
|
.WithDescription(res.Link)
|
||||||
|
.WithImageUrl(res.Link)
|
||||||
|
.WithTitle(Context.User.Mention);
|
||||||
|
await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
_log.Warn("Falling back to Imgur search.");
|
||||||
|
|
||||||
var elems = document.QuerySelectorAll("a.image-list-link");
|
var fullQueryLink = $"http://imgur.com/search?q={ terms }";
|
||||||
|
var config = Configuration.Default.WithDefaultLoader();
|
||||||
|
var document = await BrowsingContext.New(config).OpenAsync(fullQueryLink);
|
||||||
|
|
||||||
if (!elems.Any())
|
var elems = document.QuerySelectorAll("a.image-list-link");
|
||||||
return;
|
|
||||||
|
|
||||||
var img = (elems.FirstOrDefault()?.Children?.FirstOrDefault() as IHtmlImageElement);
|
if (!elems.Any())
|
||||||
|
return;
|
||||||
|
|
||||||
if (img?.Source == null)
|
var img = (elems.FirstOrDefault()?.Children?.FirstOrDefault() as IHtmlImageElement);
|
||||||
return;
|
|
||||||
|
|
||||||
var source = img.Source.Replace("b.", ".");
|
if (img?.Source == null)
|
||||||
|
return;
|
||||||
|
|
||||||
var embed = new EmbedBuilder()
|
var source = img.Source.Replace("b.", ".");
|
||||||
.WithOkColor()
|
|
||||||
.WithAuthor(eab => eab.WithName("Image Search For: " + terms.TrimTo(50))
|
var embed = new EmbedBuilder()
|
||||||
.WithUrl(fullQueryLink)
|
.WithOkColor()
|
||||||
.WithIconUrl("http://s.imgur.com/images/logo-1200-630.jpg?"))
|
.WithAuthor(eab => eab.WithName("Image Search For: " + terms.TrimTo(50))
|
||||||
.WithDescription(source)
|
.WithUrl(fullQueryLink)
|
||||||
.WithImageUrl(source)
|
.WithIconUrl("http://s.imgur.com/images/logo-1200-630.jpg?"))
|
||||||
.WithTitle(Context.User.Mention);
|
.WithDescription(source)
|
||||||
await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
|
.WithImageUrl(source)
|
||||||
|
.WithTitle(Context.User.Mention);
|
||||||
|
await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -150,34 +168,51 @@ namespace NadekoBot.Modules.Searches
|
|||||||
terms = terms?.Trim();
|
terms = terms?.Trim();
|
||||||
if (string.IsNullOrWhiteSpace(terms))
|
if (string.IsNullOrWhiteSpace(terms))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
terms = WebUtility.UrlEncode(terms).Replace(' ', '+');
|
terms = WebUtility.UrlEncode(terms).Replace(' ', '+');
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var res = await NadekoBot.Google.GetImageAsync(terms, new NadekoRandom().Next(0, 50)).ConfigureAwait(false);
|
||||||
|
var embed = new EmbedBuilder()
|
||||||
|
.WithOkColor()
|
||||||
|
.WithAuthor(eab => eab.WithName("Image Search For: " + terms.TrimTo(50))
|
||||||
|
.WithUrl("https://www.google.rs/search?q=" + terms + "&source=lnms&tbm=isch")
|
||||||
|
.WithIconUrl("http://i.imgur.com/G46fm8J.png"))
|
||||||
|
.WithDescription(res.Link)
|
||||||
|
.WithImageUrl(res.Link)
|
||||||
|
.WithTitle(Context.User.Mention);
|
||||||
|
await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
_log.Warn("Falling back to Imgur");
|
||||||
|
terms = WebUtility.UrlEncode(terms).Replace(' ', '+');
|
||||||
|
|
||||||
var fullQueryLink = $"http://imgur.com/search?q={ terms }";
|
var fullQueryLink = $"http://imgur.com/search?q={ terms }";
|
||||||
var config = Configuration.Default.WithDefaultLoader();
|
var config = Configuration.Default.WithDefaultLoader();
|
||||||
var document = await BrowsingContext.New(config).OpenAsync(fullQueryLink);
|
var document = await BrowsingContext.New(config).OpenAsync(fullQueryLink);
|
||||||
|
|
||||||
var elems = document.QuerySelectorAll("a.image-list-link").ToList();
|
var elems = document.QuerySelectorAll("a.image-list-link").ToList();
|
||||||
|
|
||||||
if (!elems.Any())
|
if (!elems.Any())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var img = (elems.ElementAtOrDefault(new NadekoRandom().Next(0, elems.Count))?.Children?.FirstOrDefault() as IHtmlImageElement);
|
var img = (elems.ElementAtOrDefault(new NadekoRandom().Next(0, elems.Count))?.Children?.FirstOrDefault() as IHtmlImageElement);
|
||||||
|
|
||||||
if (img?.Source == null)
|
if (img?.Source == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var source = img.Source.Replace("b.", ".");
|
var source = img.Source.Replace("b.", ".");
|
||||||
|
|
||||||
var embed = new EmbedBuilder()
|
var embed = new EmbedBuilder()
|
||||||
.WithOkColor()
|
.WithOkColor()
|
||||||
.WithAuthor(eab => eab.WithName("Image Search For: " + terms.TrimTo(50))
|
.WithAuthor(eab => eab.WithName("Image Search For: " + terms.TrimTo(50))
|
||||||
.WithUrl(fullQueryLink)
|
.WithUrl(fullQueryLink)
|
||||||
.WithIconUrl("http://s.imgur.com/images/logo-1200-630.jpg?"))
|
.WithIconUrl("http://s.imgur.com/images/logo-1200-630.jpg?"))
|
||||||
.WithDescription(source)
|
.WithDescription(source)
|
||||||
.WithImageUrl(source)
|
.WithImageUrl(source)
|
||||||
.WithTitle(Context.User.Mention);
|
.WithTitle(Context.User.Mention);
|
||||||
await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
|
await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -260,7 +295,7 @@ namespace NadekoBot.Modules.Searches
|
|||||||
.WithTitle(Context.User.Mention)
|
.WithTitle(Context.User.Mention)
|
||||||
.WithFooter(efb => efb.WithText(totalResults));
|
.WithFooter(efb => efb.WithText(totalResults));
|
||||||
|
|
||||||
var desc = await Task.WhenAll(results.Select(async res =>
|
var desc = await Task.WhenAll(results.Select(async res =>
|
||||||
$"[{Format.Bold(res?.Title)}]({(await NadekoBot.Google.ShortenUrl(res?.Link))})\n{res?.Text}\n\n"))
|
$"[{Format.Bold(res?.Title)}]({(await NadekoBot.Google.ShortenUrl(res?.Link))})\n{res?.Text}\n\n"))
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
await Context.Channel.EmbedAsync(embed.WithDescription(String.Concat(desc))).ConfigureAwait(false);
|
await Context.Channel.EmbedAsync(embed.WithDescription(String.Concat(desc))).ConfigureAwait(false);
|
||||||
|
@ -50,7 +50,7 @@ namespace NadekoBot.Modules.Utility
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static string GetText(IGuild server, ITextChannel channel, IGuildUser user, IUserMessage message) =>
|
private static string GetText(IGuild server, ITextChannel channel, IGuildUser user, IUserMessage message) =>
|
||||||
$"**{server.Name} | {channel.Name}** `{user.Username}`: " + message.Content;
|
$"**{server.Name} | {channel.Name}** `{user.Username}`: " + message.Content.SanitizeMentions();
|
||||||
|
|
||||||
public static readonly ConcurrentDictionary<int, ConcurrentHashSet<ITextChannel>> Subscribers = new ConcurrentDictionary<int, ConcurrentHashSet<ITextChannel>>();
|
public static readonly ConcurrentDictionary<int, ConcurrentHashSet<ITextChannel>> Subscribers = new ConcurrentDictionary<int, ConcurrentHashSet<ITextChannel>>();
|
||||||
private static Logger _log { get; }
|
private static Logger _log { get; }
|
||||||
|
@ -40,7 +40,7 @@ namespace NadekoBot.Modules.Utility
|
|||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
this.Repeater = repeater;
|
this.Repeater = repeater;
|
||||||
this.Channel = channel ?? NadekoBot.Client.GetGuild(repeater.GuildId)?.GetTextChannelAsync(repeater.ChannelId).GetAwaiter().GetResult();
|
this.Channel = channel ?? NadekoBot.Client.GetGuild(repeater.GuildId)?.GetTextChannel(repeater.ChannelId);
|
||||||
if (Channel == null)
|
if (Channel == null)
|
||||||
return;
|
return;
|
||||||
Task.Run(Run);
|
Task.Run(Run);
|
||||||
@ -69,12 +69,12 @@ namespace NadekoBot.Modules.Utility
|
|||||||
{
|
{
|
||||||
oldMsg = await Channel.SendMessageAsync(toSend).ConfigureAwait(false);
|
oldMsg = await Channel.SendMessageAsync(toSend).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (HttpException ex) when (ex.StatusCode == System.Net.HttpStatusCode.Forbidden)
|
catch (HttpException ex) when (ex.HttpCode == System.Net.HttpStatusCode.Forbidden)
|
||||||
{
|
{
|
||||||
_log.Warn("Missing permissions. Repeater stopped. ChannelId : {0}", Channel?.Id);
|
_log.Warn("Missing permissions. Repeater stopped. ChannelId : {0}", Channel?.Id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch (HttpException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
|
catch (HttpException ex) when (ex.HttpCode == System.Net.HttpStatusCode.NotFound)
|
||||||
{
|
{
|
||||||
_log.Warn("Channel not found. Repeater stopped. ChannelId : {0}", Channel?.Id);
|
_log.Warn("Channel not found. Repeater stopped. ChannelId : {0}", Channel?.Id);
|
||||||
return;
|
return;
|
||||||
|
@ -68,9 +68,7 @@ namespace NadekoBot.Modules.Utility
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var t = NadekoBot.Client.GetGuild(r.ServerId)?.GetTextChannelAsync(r.ChannelId).ConfigureAwait(false);
|
ch = NadekoBot.Client.GetGuild(r.ServerId)?.GetTextChannel(r.ChannelId);
|
||||||
if (t != null)
|
|
||||||
ch = await t.Value;
|
|
||||||
}
|
}
|
||||||
if (ch == null)
|
if (ch == null)
|
||||||
return;
|
return;
|
||||||
|
@ -116,15 +116,18 @@ namespace NadekoBot.Modules.Utility
|
|||||||
var arr = (await (Context.Channel as IGuildChannel).Guild.GetUsersAsync())
|
var arr = (await (Context.Channel as IGuildChannel).Guild.GetUsersAsync())
|
||||||
.Where(u => u.Game?.Name?.ToUpperInvariant() == game)
|
.Where(u => u.Game?.Name?.ToUpperInvariant() == game)
|
||||||
.Select(u => u.Username)
|
.Select(u => u.Username)
|
||||||
|
.Shuffle()
|
||||||
|
.Take(60)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
if (!arr.Any())
|
if (!arr.Any())
|
||||||
await Context.Channel.SendErrorAsync("Nobody is playing that game.").ConfigureAwait(false);
|
await Context.Channel.SendErrorAsync("Nobody is playing that game.").ConfigureAwait(false);
|
||||||
else
|
else {
|
||||||
await Context.Channel.SendConfirmAsync("```css\n" + string.Join("\n", arr.GroupBy(item => (i++) / 2)
|
await Context.Channel.SendConfirmAsync("```css\n" + string.Join("\n", arr.GroupBy(item => (i++) / 2)
|
||||||
.Select(ig => string.Concat(ig.Select(el => $"• {el,-27}")))) + "\n```")
|
.Select(ig => string.Concat(ig.Select(el => $"• {el,-27}")))) + "\n```")
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
@ -75,7 +75,8 @@ namespace NadekoBot
|
|||||||
|
|
||||||
//initialize Services
|
//initialize Services
|
||||||
CommandService = new CommandService(new CommandServiceConfig() {
|
CommandService = new CommandService(new CommandServiceConfig() {
|
||||||
CaseSensitiveCommands = false
|
CaseSensitiveCommands = false,
|
||||||
|
DefaultRunMode = RunMode.Sync
|
||||||
});
|
});
|
||||||
Google = new GoogleApiService();
|
Google = new GoogleApiService();
|
||||||
CommandHandler = new CommandHandler(Client, CommandService);
|
CommandHandler = new CommandHandler(Client, CommandService);
|
||||||
|
29
src/NadekoBot/Resources/CommandStrings.Designer.cs
generated
29
src/NadekoBot/Resources/CommandStrings.Designer.cs
generated
@ -177,7 +177,7 @@ namespace NadekoBot.Resources {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Adds a specified string to the list of playing strings to rotate. Supported placeholders: %servers%, %users%, %playing%, %queued%.
|
/// Looks up a localized string similar to Adds a specified string to the list of playing strings to rotate. Supported placeholders: %servers%, %users%, %playing%, %queued%, %time%,%shardid%,%shardcount%, %shardguilds%.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string addplaying_desc {
|
public static string addplaying_desc {
|
||||||
get {
|
get {
|
||||||
@ -4406,6 +4406,33 @@ namespace NadekoBot.Resources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to mal.
|
||||||
|
/// </summary>
|
||||||
|
public static string mal_cmd {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("mal_cmd", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Shows basic info from myanimelist profile..
|
||||||
|
/// </summary>
|
||||||
|
public static string mal_desc {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("mal_desc", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to `{0}mal straysocks`.
|
||||||
|
/// </summary>
|
||||||
|
public static string mal_usage {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("mal_usage", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to manga mang mq.
|
/// Looks up a localized string similar to manga mang mq.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -292,7 +292,7 @@
|
|||||||
<value>addplaying adpl</value>
|
<value>addplaying adpl</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="addplaying_desc" xml:space="preserve">
|
<data name="addplaying_desc" xml:space="preserve">
|
||||||
<value>Adds a specified string to the list of playing strings to rotate. Supported placeholders: %servers%, %users%, %playing%, %queued%</value>
|
<value>Adds a specified string to the list of playing strings to rotate. Supported placeholders: %servers%, %users%, %playing%, %queued%, %time%,%shardid%,%shardcount%, %shardguilds%</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="addplaying_usage" xml:space="preserve">
|
<data name="addplaying_usage" xml:space="preserve">
|
||||||
<value>`{0}adpl`</value>
|
<value>`{0}adpl`</value>
|
||||||
@ -1376,7 +1376,6 @@
|
|||||||
</data>
|
</data>
|
||||||
<data name="plant_usage" xml:space="preserve">
|
<data name="plant_usage" xml:space="preserve">
|
||||||
<value>`{0}plant` or `{0}plant 5`</value>
|
<value>`{0}plant` or `{0}plant 5`</value>
|
||||||
<comment> </comment>
|
|
||||||
</data>
|
</data>
|
||||||
<data name="gencurrency_cmd" xml:space="preserve">
|
<data name="gencurrency_cmd" xml:space="preserve">
|
||||||
<value>gencurrency gc</value>
|
<value>gencurrency gc</value>
|
||||||
@ -3025,4 +3024,13 @@
|
|||||||
<data name="waifuinfo_usage" xml:space="preserve">
|
<data name="waifuinfo_usage" xml:space="preserve">
|
||||||
<value>`{0}waifuinfo @MyCrush` or `{0}waifuinfo`</value>
|
<value>`{0}waifuinfo @MyCrush` or `{0}waifuinfo`</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="mal_cmd" xml:space="preserve">
|
||||||
|
<value>mal</value>
|
||||||
|
</data>
|
||||||
|
<data name="mal_desc" xml:space="preserve">
|
||||||
|
<value>Shows basic info from myanimelist profile.</value>
|
||||||
|
</data>
|
||||||
|
<data name="mal_usage" xml:space="preserve">
|
||||||
|
<value>`{0}mal straysocks`</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -159,8 +159,8 @@ namespace NadekoBot.Services
|
|||||||
|
|
||||||
private async Task<bool> WordFiltered(IGuild guild, SocketUserMessage usrMsg)
|
private async Task<bool> WordFiltered(IGuild guild, SocketUserMessage usrMsg)
|
||||||
{
|
{
|
||||||
var filteredChannelWords = Permissions.FilterCommands.FilteredWordsForChannel(usrMsg.Channel.Id, guild.Id);
|
var filteredChannelWords = Permissions.FilterCommands.FilteredWordsForChannel(usrMsg.Channel.Id, guild.Id) ?? new ConcurrentHashSet<string>();
|
||||||
var filteredServerWords = Permissions.FilterCommands.FilteredWordsForServer(guild.Id);
|
var filteredServerWords = Permissions.FilterCommands.FilteredWordsForServer(guild.Id) ?? new ConcurrentHashSet<string>();
|
||||||
var wordsInMessage = usrMsg.Content.ToLowerInvariant().Split(' ');
|
var wordsInMessage = usrMsg.Content.ToLowerInvariant().Split(' ');
|
||||||
if (filteredChannelWords.Count != 0 || filteredServerWords.Count != 0)
|
if (filteredChannelWords.Count != 0 || filteredServerWords.Count != 0)
|
||||||
{
|
{
|
||||||
@ -222,6 +222,7 @@ namespace NadekoBot.Services
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// maybe this message is a custom reaction
|
// maybe this message is a custom reaction
|
||||||
|
// todo log custom reaction executions. return struct with info
|
||||||
var crExecuted = await Task.Run(() => CustomReactions.TryExecuteCustomReaction(usrMsg)).ConfigureAwait(false);
|
var crExecuted = await Task.Run(() => CustomReactions.TryExecuteCustomReaction(usrMsg)).ConfigureAwait(false);
|
||||||
if (crExecuted) //if it was, don't execute the command
|
if (crExecuted) //if it was, don't execute the command
|
||||||
return;
|
return;
|
||||||
|
@ -8,13 +8,19 @@ using System.Text.RegularExpressions;
|
|||||||
using Google.Apis.Urlshortener.v1;
|
using Google.Apis.Urlshortener.v1;
|
||||||
using Google.Apis.Urlshortener.v1.Data;
|
using Google.Apis.Urlshortener.v1.Data;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
using Google.Apis.Customsearch.v1;
|
||||||
|
using Google.Apis.Customsearch.v1.Data;
|
||||||
|
|
||||||
namespace NadekoBot.Services.Impl
|
namespace NadekoBot.Services.Impl
|
||||||
{
|
{
|
||||||
public class GoogleApiService : IGoogleApiService
|
public class GoogleApiService : IGoogleApiService
|
||||||
{
|
{
|
||||||
|
const string search_engine_id = "018084019232060951019:hs5piey28-e";
|
||||||
|
|
||||||
private YouTubeService yt;
|
private YouTubeService yt;
|
||||||
private UrlshortenerService sh;
|
private UrlshortenerService sh;
|
||||||
|
private CustomsearchService cs;
|
||||||
|
|
||||||
private Logger _log { get; }
|
private Logger _log { get; }
|
||||||
|
|
||||||
public GoogleApiService()
|
public GoogleApiService()
|
||||||
@ -22,13 +28,14 @@ namespace NadekoBot.Services.Impl
|
|||||||
var bcs = new BaseClientService.Initializer
|
var bcs = new BaseClientService.Initializer
|
||||||
{
|
{
|
||||||
ApplicationName = "Nadeko Bot",
|
ApplicationName = "Nadeko Bot",
|
||||||
ApiKey = NadekoBot.Credentials.GoogleApiKey
|
ApiKey = NadekoBot.Credentials.GoogleApiKey,
|
||||||
};
|
};
|
||||||
|
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
yt = new YouTubeService(bcs);
|
yt = new YouTubeService(bcs);
|
||||||
sh = new UrlshortenerService(bcs);
|
sh = new UrlshortenerService(bcs);
|
||||||
|
cs = new CustomsearchService(bcs);
|
||||||
}
|
}
|
||||||
public async Task<IEnumerable<string>> GetPlaylistIdsByKeywordsAsync(string keywords, int count = 1)
|
public async Task<IEnumerable<string>> GetPlaylistIdsByKeywordsAsync(string keywords, int count = 1)
|
||||||
{
|
{
|
||||||
@ -150,7 +157,7 @@ namespace NadekoBot.Services.Impl
|
|||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
//todo AsyncEnumerable
|
//todo AsyncEnumerable
|
||||||
public async Task<IReadOnlyDictionary<string,TimeSpan>> GetVideoDurationsAsync(IEnumerable<string> videoIds)
|
public async Task<IReadOnlyDictionary<string, TimeSpan>> GetVideoDurationsAsync(IEnumerable<string> videoIds)
|
||||||
{
|
{
|
||||||
var videoIdsList = videoIds as List<string> ?? videoIds.ToList();
|
var videoIdsList = videoIds as List<string> ?? videoIds.ToList();
|
||||||
|
|
||||||
@ -179,5 +186,34 @@ namespace NadekoBot.Services.Impl
|
|||||||
|
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct ImageResult
|
||||||
|
{
|
||||||
|
public Result.ImageData Image { get; }
|
||||||
|
public string Link { get; }
|
||||||
|
|
||||||
|
public ImageResult(Result.ImageData image, string link)
|
||||||
|
{
|
||||||
|
this.Image = image;
|
||||||
|
this.Link = link;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<ImageResult> GetImageAsync(string query, int start = 1)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(query))
|
||||||
|
throw new ArgumentNullException(nameof(query));
|
||||||
|
|
||||||
|
var req = cs.Cse.List(query);
|
||||||
|
req.Cx = search_engine_id;
|
||||||
|
req.Num = 1;
|
||||||
|
req.Fields = "items(image(contextLink,thumbnailLink),link)";
|
||||||
|
req.SearchType = CseResource.ListRequest.SearchTypeEnum.Image;
|
||||||
|
req.Start = start;
|
||||||
|
|
||||||
|
var search = await req.ExecuteAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
return new ImageResult(search.Items[0].Image, search.Items[0].Link);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ namespace NadekoBot.Services.Impl
|
|||||||
private DiscordShardedClient client;
|
private DiscordShardedClient client;
|
||||||
private DateTime started;
|
private DateTime started;
|
||||||
|
|
||||||
public const string BotVersion = "1.1.4";
|
public const string BotVersion = "1.1.5";
|
||||||
|
|
||||||
public string Author => "Kwoth#2560";
|
public string Author => "Kwoth#2560";
|
||||||
public string Library => "Discord.Net";
|
public string Library => "Discord.Net";
|
||||||
|
@ -237,7 +237,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Title":"Careers in Psychology: Opportunities in a Changing World",
|
"Title":"Careers in Psychology: Opportunities in a Changing World",
|
||||||
"Text":"This text addresses the growing need among students and faculty for information about the careers available in psychology at the bachelorâs and graduate level."
|
"Text":"This text addresses the growing need among students and faculty for information about the careers available in psychology at the bachelors and graduate level."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Title":"Philosophy of Psychology",
|
"Title":"Philosophy of Psychology",
|
||||||
|
Loading…
Reference in New Issue
Block a user