commit
024ecf521a
@ -1 +1 @@
|
|||||||
Subproject commit fa2568bc312ba35f1518e47601c62fccdb949731
|
Subproject commit b9f767337d2b7c07ed76eb83c3bc5030109d5238
|
24
src/NadekoBot/DataStructures/ExecuteCommandResult.cs
Normal file
24
src/NadekoBot/DataStructures/ExecuteCommandResult.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using Discord.Commands;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using static NadekoBot.Modules.Permissions.Permissions;
|
||||||
|
|
||||||
|
namespace NadekoBot.DataStructures
|
||||||
|
{
|
||||||
|
public struct ExecuteCommandResult
|
||||||
|
{
|
||||||
|
public readonly CommandInfo CommandInfo;
|
||||||
|
public readonly PermissionCache PermissionCache;
|
||||||
|
public readonly IResult Result;
|
||||||
|
|
||||||
|
public ExecuteCommandResult(CommandInfo commandInfo, PermissionCache cache, IResult result)
|
||||||
|
{
|
||||||
|
this.CommandInfo = commandInfo;
|
||||||
|
this.PermissionCache = cache;
|
||||||
|
this.Result = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -78,7 +78,10 @@ namespace NadekoBot.Modules.Administration
|
|||||||
_client.UserPresenceUpdated += _client_UserPresenceUpdated;
|
_client.UserPresenceUpdated += _client_UserPresenceUpdated;
|
||||||
_client.UserVoiceStateUpdated += _client_UserVoiceStateUpdated;
|
_client.UserVoiceStateUpdated += _client_UserVoiceStateUpdated;
|
||||||
_client.UserVoiceStateUpdated += _client_UserVoiceStateUpdated_TTS;
|
_client.UserVoiceStateUpdated += _client_UserVoiceStateUpdated_TTS;
|
||||||
|
_client.GuildUserUpdated += _client_GuildUserUpdated;
|
||||||
|
#if !GLOBAL_NADEKO
|
||||||
_client.UserUpdated += _client_UserUpdated;
|
_client.UserUpdated += _client_UserUpdated;
|
||||||
|
#endif
|
||||||
|
|
||||||
_client.ChannelCreated += _client_ChannelCreated;
|
_client.ChannelCreated += _client_ChannelCreated;
|
||||||
_client.ChannelDestroyed += _client_ChannelDestroyed;
|
_client.ChannelDestroyed += _client_ChannelDestroyed;
|
||||||
@ -88,6 +91,38 @@ namespace NadekoBot.Modules.Administration
|
|||||||
MuteCommands.UserUnmuted += MuteCommands_UserUnmuted;
|
MuteCommands.UserUnmuted += MuteCommands_UserUnmuted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static async void _client_UserUpdated(SocketUser before, SocketUser after)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var str = "";
|
||||||
|
if (before.Username != after.Username)
|
||||||
|
str = $"👤__**{before.Username}#{before.Discriminator}**__ **| Name Changed |** 🆔 `{before.Id}`\n\t\t`New:` **{after.ToString()}**";
|
||||||
|
else if (before.AvatarUrl != after.AvatarUrl)
|
||||||
|
str = $"👤__**{before.Username}#{before.Discriminator}**__ **| Avatar Changed |** 🆔 `{before.Id}`\n\t🖼 {await NadekoBot.Google.ShortenUrl(before.AvatarUrl)} `=>` {await NadekoBot.Google.ShortenUrl(after.AvatarUrl)}";
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(str))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var guildsMemberOf = NadekoBot.Client.GetGuilds().Where(g => g.Users.Select(u => u.Id).Contains(before.Id)).ToList();
|
||||||
|
foreach (var g in guildsMemberOf)
|
||||||
|
{
|
||||||
|
LogSetting logSetting;
|
||||||
|
if (!GuildLogSettings.TryGetValue(g.Id, out logSetting)
|
||||||
|
|| (logSetting.UserUpdatedId == null))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ITextChannel logChannel;
|
||||||
|
if ((logChannel = await TryGetLogChannel(g, logSetting, LogType.UserUpdated)) == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
try { await logChannel.SendMessageAsync(str).ConfigureAwait(false); } catch { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{ }
|
||||||
|
}
|
||||||
|
|
||||||
private static async void _client_UserVoiceStateUpdated_TTS(SocketUser iusr, SocketVoiceState before, SocketVoiceState after)
|
private static async void _client_UserVoiceStateUpdated_TTS(SocketUser iusr, SocketVoiceState before, SocketVoiceState after)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -228,17 +263,10 @@ namespace NadekoBot.Modules.Administration
|
|||||||
catch (Exception ex) { _log.Warn(ex); }
|
catch (Exception ex) { _log.Warn(ex); }
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async void _client_UserUpdated(SocketUser uBefore, SocketUser uAfter)
|
private static async void _client_GuildUserUpdated(SocketGuildUser before, SocketGuildUser after)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var before = uBefore as SocketGuildUser;
|
|
||||||
if (before == null)
|
|
||||||
return;
|
|
||||||
var after = uAfter as SocketGuildUser;
|
|
||||||
if (after == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
LogSetting logSetting;
|
LogSetting logSetting;
|
||||||
if (!GuildLogSettings.TryGetValue(before.Guild.Id, out logSetting)
|
if (!GuildLogSettings.TryGetValue(before.Guild.Id, out logSetting)
|
||||||
|| (logSetting.UserUpdatedId == null))
|
|| (logSetting.UserUpdatedId == null))
|
||||||
@ -247,30 +275,25 @@ namespace NadekoBot.Modules.Administration
|
|||||||
ITextChannel logChannel;
|
ITextChannel logChannel;
|
||||||
if ((logChannel = await TryGetLogChannel(before.Guild, logSetting, LogType.UserUpdated)) == null)
|
if ((logChannel = await TryGetLogChannel(before.Guild, logSetting, LogType.UserUpdated)) == null)
|
||||||
return;
|
return;
|
||||||
string str = $"🕔`{prettyCurrentTime}`";
|
var str = "";
|
||||||
|
if (before.Nickname != after.Nickname)
|
||||||
if (before.Username != after.Username)
|
str = $"👤__**{before.Username}#{before.Discriminator}**__ **| Nickname Changed |** 🆔 `{before.Id}`\n\t\t`Old:` **{before.Nickname}**\n\t\t`New:` **{after.Nickname}**";
|
||||||
str += $"👤__**{before.Username}#{before.Discriminator}**__ **| Name Changed |** 🆔 `{before.Id}`\n\t\t`New:` **{after.ToString()}**";
|
|
||||||
else if (before.Nickname != after.Nickname)
|
|
||||||
str += $"👤__**{before.Username}#{before.Discriminator}**__ **| Nickname Changed |** 🆔 `{before.Id}`\n\t\t`Old:` **{before.Nickname}#{before.Discriminator}**\n\t\t`New:` **{after.Nickname}#{after.Discriminator}**";
|
|
||||||
else if (before.AvatarUrl != after.AvatarUrl)
|
|
||||||
str += $"👤__**{before.Username}#{before.Discriminator}**__ **| Avatar Changed |** 🆔 `{before.Id}`\n\t🖼 {await NadekoBot.Google.ShortenUrl(before.AvatarUrl)} `=>` {await NadekoBot.Google.ShortenUrl(after.AvatarUrl)}";
|
|
||||||
else if (!before.RoleIds.SequenceEqual(after.RoleIds))
|
else if (!before.RoleIds.SequenceEqual(after.RoleIds))
|
||||||
{
|
{
|
||||||
if (before.RoleIds.Count < after.RoleIds.Count)
|
if (before.RoleIds.Count < after.RoleIds.Count)
|
||||||
{
|
{
|
||||||
var diffRoles = after.RoleIds.Where(r => !before.RoleIds.Contains(r)).Select(r => "**" + before.Guild.GetRole(r).Name + "**");
|
var diffRoles = after.RoleIds.Where(r => !before.RoleIds.Contains(r)).Select(r => "**" + before.Guild.GetRole(r).Name + "**");
|
||||||
str += $"👤__**{before.ToString()}**__ **| User's Role Added |** 🆔 `{before.Id}`\n\t✅ {string.Join(", ", diffRoles).SanitizeMentions()}\n\t\t⚔ **`{string.Join(", ", after.GetRoles().Select(r => r.Name)).SanitizeMentions()}`** ⚔";
|
str = $"👤__**{before.ToString()}**__ **| User's Role Added |** 🆔 `{before.Id}`\n\t✅ {string.Join(", ", diffRoles).SanitizeMentions()}\n\t\t⚔ **`{string.Join(", ", after.GetRoles().Select(r => r.Name)).SanitizeMentions()}`** ⚔";
|
||||||
}
|
}
|
||||||
else if (before.RoleIds.Count > after.RoleIds.Count)
|
else if (before.RoleIds.Count > after.RoleIds.Count)
|
||||||
{
|
{
|
||||||
var diffRoles = before.RoleIds.Where(r => !after.RoleIds.Contains(r)).Select(r => "**" + before.Guild.GetRole(r).Name + "**");
|
var diffRoles = before.RoleIds.Where(r => !after.RoleIds.Contains(r)).Select(r => "**" + before.Guild.GetRole(r).Name + "**");
|
||||||
str += $"👤__**{before.ToString()}**__ **| User's Role Removed |** 🆔 `{before.Id}`\n\t🚮 {string.Join(", ", diffRoles).SanitizeMentions()}\n\t\t⚔ **`{string.Join(", ", after.GetRoles().Select(r => r.Name)).SanitizeMentions()}`** ⚔";
|
str = $"👤__**{before.ToString()}**__ **| User's Role Removed |** 🆔 `{before.Id}`\n\t🚮 {string.Join(", ", diffRoles).SanitizeMentions()}\n\t\t⚔ **`{string.Join(", ", after.GetRoles().Select(r => r.Name)).SanitizeMentions()}`** ⚔";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
try { await logChannel.SendMessageAsync(str).ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
try { await logChannel.SendMessageAsync($"🕔`{prettyCurrentTime}` " + str).ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
|
||||||
}
|
}
|
||||||
catch (Exception ex) { _log.Warn(ex); }
|
catch (Exception ex) { _log.Warn(ex); }
|
||||||
}
|
}
|
||||||
@ -745,9 +768,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
if (action.Value)
|
if (action.Value)
|
||||||
await channel.SendMessageAsync("✅ Logging all events on this channel.").ConfigureAwait(false);
|
await channel.SendConfirmAsync("Logging all events in this channel.").ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await channel.SendMessageAsync("ℹ️ Logging disabled.").ConfigureAwait(false);
|
await channel.SendConfirmAsync("Logging disabled.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -774,9 +797,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (removed == 0)
|
if (removed == 0)
|
||||||
await channel.SendMessageAsync($"🆗 Logging will **now ignore** #⃣ `{channel.Name} ({channel.Id})`").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"Logging will IGNORE **{channel.Mention} ({channel.Id})**").ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await channel.SendMessageAsync($"ℹ️ Logging will **no longer ignore** #⃣ `{channel.Name} ({channel.Id})`").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"Logging will NOT IGNORE **{channel.Mention} ({channel.Id})**").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -853,9 +876,9 @@ namespace NadekoBot.Modules.Administration
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (channelId != null)
|
if (channelId != null)
|
||||||
await channel.SendMessageAsync($"✅ Logging `{type}` event in #⃣ `{channel.Name} ({channel.Id})`").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"Logging **{type}** event in this channel.").ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await channel.SendMessageAsync($"ℹ️ Stopped logging `{type}` event.").ConfigureAwait(false);
|
await channel.SendConfirmAsync($"Stopped logging **{type}** event.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,8 +71,8 @@ namespace NadekoBot.Modules.Administration
|
|||||||
|
|
||||||
public static Dictionary<string, Func<string>> PlayingPlaceholders { get; } =
|
public static Dictionary<string, Func<string>> PlayingPlaceholders { get; } =
|
||||||
new Dictionary<string, Func<string>> {
|
new Dictionary<string, Func<string>> {
|
||||||
{"%servers%", () => NadekoBot.Client.GetGuilds().Count().ToString()},
|
{"%servers%", () => NadekoBot.Client.GetGuildsCount().ToString()},
|
||||||
{"%users%", () => NadekoBot.Client.GetGuilds().Select(s => s.Users.Count).Sum().ToString()},
|
{"%users%", () => NadekoBot.Client.GetGuilds().Sum(s => s.Users.Count).ToString()},
|
||||||
{"%playing%", () => {
|
{"%playing%", () => {
|
||||||
var cnt = Music.Music.MusicPlayers.Count(kvp => kvp.Value.CurrentSong != null);
|
var cnt = Music.Music.MusicPlayers.Count(kvp => kvp.Value.CurrentSong != null);
|
||||||
if (cnt != 1) return cnt.ToString();
|
if (cnt != 1) return cnt.ToString();
|
||||||
|
@ -20,7 +20,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
public async Task Leave([Remainder] string guildStr)
|
public async Task Leave([Remainder] string guildStr)
|
||||||
{
|
{
|
||||||
guildStr = guildStr.Trim().ToUpperInvariant();
|
guildStr = guildStr.Trim().ToUpperInvariant();
|
||||||
var server = NadekoBot.Client.GetGuilds().FirstOrDefault(g => g.Id.ToString().Trim().ToUpperInvariant() == guildStr) ??
|
var server = NadekoBot.Client.GetGuilds().FirstOrDefault(g => g.Id.ToString() == guildStr) ??
|
||||||
NadekoBot.Client.GetGuilds().FirstOrDefault(g => g.Name.Trim().ToUpperInvariant() == guildStr);
|
NadekoBot.Client.GetGuilds().FirstOrDefault(g => g.Name.Trim().ToUpperInvariant() == guildStr);
|
||||||
|
|
||||||
if (server == null)
|
if (server == null)
|
||||||
|
@ -26,9 +26,9 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
if (count == 1)
|
if (count == 1)
|
||||||
{
|
{
|
||||||
if (rng.Next(0, 2) == 1)
|
if (rng.Next(0, 2) == 1)
|
||||||
await Context.Channel.SendFileAsync(headsPath, $"{Context.User.Mention} flipped " + Format.Code("Heads") + ".").ConfigureAwait(false);
|
await Context.Channel.SendFileAsync(File.Open(headsPath, FileMode.OpenOrCreate), "heads.jpg", $"{Context.User.Mention} flipped " + Format.Code("Heads") + ".").ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await Context.Channel.SendFileAsync(tailsPath, $"{Context.User.Mention} flipped " + Format.Code("Tails") + ".").ConfigureAwait(false);
|
await Context.Channel.SendFileAsync(File.Open(tailsPath, FileMode.OpenOrCreate), "tails.jpg", $"{Context.User.Mention} flipped " + Format.Code("Tails") + ".").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (count > 10 || count < 1)
|
if (count > 10 || count < 1)
|
||||||
@ -93,7 +93,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
str = $"{Context.User.Mention}`Better luck next time.`";
|
str = $"{Context.User.Mention}`Better luck next time.`";
|
||||||
}
|
}
|
||||||
|
|
||||||
await Context.Channel.SendFileAsync(imgPathToSend, str).ConfigureAwait(false);
|
await Context.Channel.SendFileAsync(File.Open(imgPathToSend, FileMode.OpenOrCreate), "coin.jpg", str).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,10 +88,10 @@ namespace NadekoBot.Modules.Games
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#if !GLOBAL_NADEKO
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[RequireUserPermission(ChannelPermission.ManageMessages)]
|
[RequireUserPermission(GuildPermission.ManageMessages)]
|
||||||
public async Task Cleverbot()
|
public async Task Cleverbot()
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)Context.Channel;
|
var channel = (ITextChannel)Context.Channel;
|
||||||
@ -120,7 +120,6 @@ namespace NadekoBot.Modules.Games
|
|||||||
|
|
||||||
await Context.Channel.SendConfirmAsync($"{Context.User.Mention} Enabled cleverbot on this server.").ConfigureAwait(false);
|
await Context.Channel.SendConfirmAsync($"{Context.User.Mention} Enabled cleverbot on this server.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -12,37 +12,15 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace NadekoBot.Modules.Games.Commands.Hangman
|
namespace NadekoBot.Modules.Games.Commands.Hangman
|
||||||
{
|
{
|
||||||
public class HangmanModel
|
|
||||||
{
|
|
||||||
public List<HangmanObject> All { get; set; }
|
|
||||||
public List<HangmanObject> Animals { get; set; }
|
|
||||||
public List<HangmanObject> Countries { get; set; }
|
|
||||||
public List<HangmanObject> Movies { get; set; }
|
|
||||||
public List<HangmanObject> Things { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class HangmanTermPool
|
public class HangmanTermPool
|
||||||
{
|
{
|
||||||
public enum HangmanTermType
|
|
||||||
{
|
|
||||||
All,
|
|
||||||
Animals,
|
|
||||||
Countries,
|
|
||||||
Movies,
|
|
||||||
Things
|
|
||||||
}
|
|
||||||
|
|
||||||
const string termsPath = "data/hangman.json";
|
const string termsPath = "data/hangman.json";
|
||||||
public static HangmanModel data { get; }
|
public static IReadOnlyDictionary<string, HangmanObject[]> data { get; }
|
||||||
static HangmanTermPool()
|
static HangmanTermPool()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
data = JsonConvert.DeserializeObject<HangmanModel>(File.ReadAllText(termsPath));
|
data = JsonConvert.DeserializeObject<Dictionary<string, HangmanObject[]>>(File.ReadAllText(termsPath));
|
||||||
data.All = data.Animals.Concat(data.Countries)
|
|
||||||
.Concat(data.Movies)
|
|
||||||
.Concat(data.Things)
|
|
||||||
.ToList();
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -50,23 +28,27 @@ namespace NadekoBot.Modules.Games.Commands.Hangman
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static HangmanObject GetTerm(HangmanTermType type)
|
public static HangmanObject GetTerm(string type)
|
||||||
{
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(type))
|
||||||
|
throw new ArgumentNullException(nameof(type));
|
||||||
|
|
||||||
|
type = type.Trim();
|
||||||
|
|
||||||
var rng = new NadekoRandom();
|
var rng = new NadekoRandom();
|
||||||
switch (type)
|
|
||||||
{
|
if (type == "All") {
|
||||||
case HangmanTermType.Animals:
|
var keys = data.Keys.ToArray();
|
||||||
return data.Animals[rng.Next(0, data.Animals.Count)];
|
type = keys[rng.Next(0, keys.Length)];
|
||||||
case HangmanTermType.Countries:
|
|
||||||
return data.Countries[rng.Next(0, data.Countries.Count)];
|
|
||||||
case HangmanTermType.Movies:
|
|
||||||
return data.Movies[rng.Next(0, data.Movies.Count)];
|
|
||||||
case HangmanTermType.Things:
|
|
||||||
return data.Things[rng.Next(0, data.Things.Count)];
|
|
||||||
default:
|
|
||||||
return data.All[rng.Next(0, data.All.Count)];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HangmanObject[] termTypes;
|
||||||
|
data.TryGetValue(type, out termTypes);
|
||||||
|
|
||||||
|
if (termTypes.Length == 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return termTypes[rng.Next(0, termTypes.Length)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,20 +77,23 @@ namespace NadekoBot.Modules.Games.Commands.Hangman
|
|||||||
public bool GuessedAll => Guesses.IsSupersetOf(Term.Word.ToUpperInvariant()
|
public bool GuessedAll => Guesses.IsSupersetOf(Term.Word.ToUpperInvariant()
|
||||||
.Where(c => char.IsLetter(c) || char.IsDigit(c)));
|
.Where(c => char.IsLetter(c) || char.IsDigit(c)));
|
||||||
|
|
||||||
public HangmanTermPool.HangmanTermType TermType { get; }
|
public string TermType { get; }
|
||||||
|
|
||||||
public event Action<HangmanGame> OnEnded;
|
public event Action<HangmanGame> OnEnded;
|
||||||
|
|
||||||
public HangmanGame(IMessageChannel channel, HangmanTermPool.HangmanTermType type)
|
public HangmanGame(IMessageChannel channel, string type)
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
this.GameChannel = channel;
|
this.GameChannel = channel;
|
||||||
this.TermType = type;
|
this.TermType = type.ToTitleCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start()
|
public void Start()
|
||||||
{
|
{
|
||||||
this.Term = HangmanTermPool.GetTerm(TermType);
|
this.Term = HangmanTermPool.GetTerm(TermType);
|
||||||
|
|
||||||
|
if (this.Term == null)
|
||||||
|
throw new KeyNotFoundException("Can't find a term with that type. Use hangmanlist command.");
|
||||||
// start listening for answers when game starts
|
// start listening for answers when game starts
|
||||||
NadekoBot.Client.MessageReceived += PotentialGuess;
|
NadekoBot.Client.MessageReceived += PotentialGuess;
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
static HangmanCommands()
|
static HangmanCommands()
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
typesStr = $"`List of \"{NadekoBot.ModulePrefixes[typeof(Games).Name]}hangman\" term types:`\n" + String.Join(", ", Enum.GetNames(typeof(HangmanTermPool.HangmanTermType)));
|
typesStr = $"`List of \"{NadekoBot.ModulePrefixes[typeof(Games).Name]}hangman\" term types:`\n" + String.Join(", ", HangmanTermPool.data.Keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -33,7 +33,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
public async Task Hangman(HangmanTermPool.HangmanTermType type = HangmanTermPool.HangmanTermType.All)
|
public async Task Hangman([Remainder]string type = "All")
|
||||||
{
|
{
|
||||||
var hm = new HangmanGame(Context.Channel, type);
|
var hm = new HangmanGame(Context.Channel, type);
|
||||||
|
|
||||||
@ -48,7 +48,14 @@ namespace NadekoBot.Modules.Games
|
|||||||
HangmanGame throwaway;
|
HangmanGame throwaway;
|
||||||
HangmanGames.TryRemove(g.GameChannel.Id, out throwaway);
|
HangmanGames.TryRemove(g.GameChannel.Id, out throwaway);
|
||||||
};
|
};
|
||||||
|
try
|
||||||
|
{
|
||||||
hm.Start();
|
hm.Start();
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
try { await Context.Channel.SendErrorAsync($"Starting errored: {ex.Message}").ConfigureAwait(false); } catch { }
|
||||||
|
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() + "\n" + hm.ScrambledWord);
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,8 @@ namespace NadekoBot.Modules.Games
|
|||||||
lastGenerations.AddOrUpdate(channel.Id, DateTime.Now, (id, old) => DateTime.Now);
|
lastGenerations.AddOrUpdate(channel.Id, DateTime.Now, (id, old) => DateTime.Now);
|
||||||
|
|
||||||
var sent = await channel.SendFileAsync(
|
var sent = await channel.SendFileAsync(
|
||||||
GetRandomCurrencyImagePath(),
|
File.Open(GetRandomCurrencyImagePath(), FileMode.OpenOrCreate),
|
||||||
|
"RandomFlower.jpg",
|
||||||
$"❗ A random { Gambling.Gambling.CurrencyName } appeared! Pick it up by typing `{NadekoBot.ModulePrefixes[typeof(Games).Name]}pick`")
|
$"❗ A random { Gambling.Gambling.CurrencyName } appeared! Pick it up by typing `{NadekoBot.ModulePrefixes[typeof(Games).Name]}pick`")
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
plantedFlowers.AddOrUpdate(channel.Id, new List<IUserMessage>() { sent }, (id, old) => { old.Add(sent); return old; });
|
plantedFlowers.AddOrUpdate(channel.Id, new List<IUserMessage>() { sent }, (id, old) => { old.Add(sent); return old; });
|
||||||
@ -104,7 +105,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
}
|
}
|
||||||
#if !GLOBAL_NADEKO
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task Pick()
|
public async Task Pick()
|
||||||
@ -163,11 +164,10 @@ namespace NadekoBot.Modules.Games
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
msg = await Context.Channel.SendFileAsync(file, msgToSend).ConfigureAwait(false);
|
msg = await Context.Channel.SendFileAsync(File.Open(file, FileMode.OpenOrCreate), "plant.jpg", msgToSend).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
plantedFlowers.AddOrUpdate(Context.Channel.Id, new List<IUserMessage>() { msg }, (id, old) => { old.Add(msg); return old; });
|
plantedFlowers.AddOrUpdate(Context.Channel.Id, new List<IUserMessage>() { msg }, (id, old) => { old.Add(msg); return old; });
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
|
@ -7,6 +7,7 @@ using System;
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@ -17,7 +18,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
[Group]
|
[Group]
|
||||||
public class PollCommands : ModuleBase
|
public class PollCommands : ModuleBase
|
||||||
{
|
{
|
||||||
public static ConcurrentDictionary<IGuild, Poll> ActivePolls = new ConcurrentDictionary<IGuild, Poll>();
|
public static ConcurrentDictionary<ulong, Poll> ActivePolls = new ConcurrentDictionary<ulong, Poll>();
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireUserPermission(GuildPermission.ManageMessages)]
|
[RequireUserPermission(GuildPermission.ManageMessages)]
|
||||||
@ -31,6 +32,18 @@ namespace NadekoBot.Modules.Games
|
|||||||
public Task PublicPoll([Remainder] string arg = null)
|
public Task PublicPoll([Remainder] string arg = null)
|
||||||
=> InternalStartPoll(arg, isPublic: true);
|
=> InternalStartPoll(arg, isPublic: true);
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireUserPermission(GuildPermission.ManageMessages)]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task PollStats()
|
||||||
|
{
|
||||||
|
Games.Poll poll;
|
||||||
|
if (!ActivePolls.TryGetValue(Context.Guild.Id, out poll))
|
||||||
|
return;
|
||||||
|
|
||||||
|
await Context.Channel.EmbedAsync(poll.GetStats("Current Poll Results"));
|
||||||
|
}
|
||||||
|
|
||||||
private async Task InternalStartPoll(string arg, bool isPublic = false)
|
private async Task InternalStartPoll(string arg, bool isPublic = false)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)Context.Channel;
|
var channel = (ITextChannel)Context.Channel;
|
||||||
@ -44,7 +57,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
var poll = new Poll(Context.Message, data[0], data.Skip(1), isPublic: isPublic);
|
var poll = new Poll(Context.Message, data[0], data.Skip(1), isPublic: isPublic);
|
||||||
if (ActivePolls.TryAdd(channel.Guild, poll))
|
if (ActivePolls.TryAdd(channel.Guild.Id, poll))
|
||||||
{
|
{
|
||||||
await poll.StartPoll().ConfigureAwait(false);
|
await poll.StartPoll().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@ -60,7 +73,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
var channel = (ITextChannel)Context.Channel;
|
var channel = (ITextChannel)Context.Channel;
|
||||||
|
|
||||||
Poll poll;
|
Poll poll;
|
||||||
ActivePolls.TryRemove(channel.Guild, out poll);
|
ActivePolls.TryRemove(channel.Guild.Id, out poll);
|
||||||
await poll.StopPoll().ConfigureAwait(false);
|
await poll.StopPoll().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,20 +82,55 @@ namespace NadekoBot.Modules.Games
|
|||||||
{
|
{
|
||||||
private readonly IUserMessage originalMessage;
|
private readonly IUserMessage originalMessage;
|
||||||
private readonly IGuild guild;
|
private readonly IGuild guild;
|
||||||
private readonly string[] answers;
|
private string[] Answers { get; }
|
||||||
private ConcurrentDictionary<ulong, int> participants = new ConcurrentDictionary<ulong, int>();
|
private ConcurrentDictionary<ulong, int> participants = new ConcurrentDictionary<ulong, int>();
|
||||||
private readonly string question;
|
private readonly string question;
|
||||||
private DateTime started;
|
private DateTime started;
|
||||||
private CancellationTokenSource pollCancellationSource = new CancellationTokenSource();
|
private CancellationTokenSource pollCancellationSource = new CancellationTokenSource();
|
||||||
private readonly bool isPublic;
|
public bool IsPublic { get; }
|
||||||
|
|
||||||
public Poll(IUserMessage umsg, string question, IEnumerable<string> enumerable, bool isPublic = false)
|
public Poll(IUserMessage umsg, string question, IEnumerable<string> enumerable, bool isPublic = false)
|
||||||
{
|
{
|
||||||
this.originalMessage = umsg;
|
this.originalMessage = umsg;
|
||||||
this.guild = ((ITextChannel)umsg.Channel).Guild;
|
this.guild = ((ITextChannel)umsg.Channel).Guild;
|
||||||
this.question = question;
|
this.question = question;
|
||||||
this.answers = enumerable as string[] ?? enumerable.ToArray();
|
this.Answers = enumerable as string[] ?? enumerable.ToArray();
|
||||||
this.isPublic = isPublic;
|
this.IsPublic = isPublic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EmbedBuilder GetStats(string title)
|
||||||
|
{
|
||||||
|
var results = participants.GroupBy(kvp => kvp.Value)
|
||||||
|
.ToDictionary(x => x.Key, x => x.Sum(kvp => 1))
|
||||||
|
.OrderByDescending(kvp => kvp.Value)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
var eb = new EmbedBuilder().WithTitle(title);
|
||||||
|
|
||||||
|
var sb = new StringBuilder()
|
||||||
|
.AppendLine(Format.Bold(question))
|
||||||
|
.AppendLine();
|
||||||
|
|
||||||
|
var totalVotesCast = 0;
|
||||||
|
if (results.Length == 0)
|
||||||
|
{
|
||||||
|
sb.AppendLine("No votes cast.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < results.Length; i++)
|
||||||
|
{
|
||||||
|
var result = results[i];
|
||||||
|
sb.AppendLine($"`{i + 1}.` {Format.Bold(Answers[result.Key - 1])} with {Format.Bold(result.Value.ToString())} votes.");
|
||||||
|
totalVotesCast += result.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
eb.WithDescription(sb.ToString())
|
||||||
|
.WithFooter(efb => efb.WithText(totalVotesCast + " total votes cast."));
|
||||||
|
|
||||||
|
return eb;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task StartPoll()
|
public async Task StartPoll()
|
||||||
@ -91,8 +139,8 @@ namespace NadekoBot.Modules.Games
|
|||||||
NadekoBot.Client.MessageReceived += Vote;
|
NadekoBot.Client.MessageReceived += Vote;
|
||||||
var msgToSend = $"📃**{originalMessage.Author.Username}** has created a poll which requires your attention:\n\n**{question}**\n";
|
var msgToSend = $"📃**{originalMessage.Author.Username}** has created a poll which requires your attention:\n\n**{question}**\n";
|
||||||
var num = 1;
|
var num = 1;
|
||||||
msgToSend = answers.Aggregate(msgToSend, (current, answ) => current + $"`{num++}.` **{answ}**\n");
|
msgToSend = Answers.Aggregate(msgToSend, (current, answ) => current + $"`{num++}.` **{answ}**\n");
|
||||||
if (!isPublic)
|
if (!IsPublic)
|
||||||
msgToSend += "\n**Private Message me with the corresponding number of the answer.**";
|
msgToSend += "\n**Private Message me with the corresponding number of the answer.**";
|
||||||
else
|
else
|
||||||
msgToSend += "\n**Send a Message here with the corresponding number of the answer.**";
|
msgToSend += "\n**Send a Message here with the corresponding number of the answer.**";
|
||||||
@ -102,30 +150,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
public async Task StopPoll()
|
public async Task StopPoll()
|
||||||
{
|
{
|
||||||
NadekoBot.Client.MessageReceived -= Vote;
|
NadekoBot.Client.MessageReceived -= Vote;
|
||||||
try
|
await originalMessage.Channel.EmbedAsync(GetStats("POLL CLOSED")).ConfigureAwait(false);
|
||||||
{
|
|
||||||
var results = participants.GroupBy(kvp => kvp.Value)
|
|
||||||
.ToDictionary(x => x.Key, x => x.Sum(kvp => 1))
|
|
||||||
.OrderByDescending(kvp => kvp.Value);
|
|
||||||
|
|
||||||
var totalVotesCast = results.Sum(kvp => kvp.Value);
|
|
||||||
if (totalVotesCast == 0)
|
|
||||||
{
|
|
||||||
await originalMessage.Channel.SendMessageAsync("📄 **No votes have been cast.**").ConfigureAwait(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var closeMessage = $"--------------**POLL CLOSED**--------------\n" +
|
|
||||||
$"📄 , here are the results:\n";
|
|
||||||
closeMessage = results.Aggregate(closeMessage, (current, kvp) => current + $"`{kvp.Key}.` **[{answers[kvp.Key - 1]}]**" +
|
|
||||||
$" has {kvp.Value} votes." +
|
|
||||||
$"({kvp.Value * 1.0f / totalVotesCast * 100}%)\n");
|
|
||||||
|
|
||||||
await originalMessage.Channel.SendConfirmAsync($"📄 **Total votes cast**: {totalVotesCast}\n{closeMessage}").ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Error in poll game {ex}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void Vote(SocketMessage imsg)
|
private async void Vote(SocketMessage imsg)
|
||||||
@ -141,11 +166,11 @@ namespace NadekoBot.Modules.Games
|
|||||||
int vote;
|
int vote;
|
||||||
if (!int.TryParse(imsg.Content, out vote))
|
if (!int.TryParse(imsg.Content, out vote))
|
||||||
return;
|
return;
|
||||||
if (vote < 1 || vote > answers.Length)
|
if (vote < 1 || vote > Answers.Length)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
IMessageChannel ch;
|
IMessageChannel ch;
|
||||||
if (isPublic)
|
if (IsPublic)
|
||||||
{
|
{
|
||||||
//if public, channel must be the same the poll started in
|
//if public, channel must be the same the poll started in
|
||||||
if (originalMessage.Channel.Id != imsg.Channel.Id)
|
if (originalMessage.Channel.Id != imsg.Channel.Id)
|
||||||
@ -167,7 +192,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
//user can vote only once
|
//user can vote only once
|
||||||
if (participants.TryAdd(msg.Author.Id, vote))
|
if (participants.TryAdd(msg.Author.Id, vote))
|
||||||
{
|
{
|
||||||
if (!isPublic)
|
if (!IsPublic)
|
||||||
{
|
{
|
||||||
await ch.SendConfirmAsync($"Thanks for voting **{msg.Author.Username}**.").ConfigureAwait(false);
|
await ch.SendConfirmAsync($"Thanks for voting **{msg.Author.Username}**.").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ namespace NadekoBot.Modules.NSFW
|
|||||||
var link = await provider.ConfigureAwait(false);
|
var link = await provider.ConfigureAwait(false);
|
||||||
if (string.IsNullOrWhiteSpace(link))
|
if (string.IsNullOrWhiteSpace(link))
|
||||||
{
|
{
|
||||||
if (noError)
|
if (!noError)
|
||||||
await channel.SendErrorAsync("No results found.").ConfigureAwait(false);
|
await channel.SendErrorAsync("No results found.").ConfigureAwait(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -23,13 +23,18 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
[Group]
|
[Group]
|
||||||
public class BlacklistCommands : ModuleBase
|
public class BlacklistCommands : ModuleBase
|
||||||
{
|
{
|
||||||
public static ConcurrentHashSet<BlacklistItem> BlacklistedItems { get; set; } = new ConcurrentHashSet<BlacklistItem>();
|
public static ConcurrentHashSet<ulong> BlacklistedUsers { get; set; } = new ConcurrentHashSet<ulong>();
|
||||||
|
public static ConcurrentHashSet<ulong> BlacklistedGuilds { get; set; } = new ConcurrentHashSet<ulong>();
|
||||||
|
public static ConcurrentHashSet<ulong> BlacklistedChannels { get; set; } = new ConcurrentHashSet<ulong>();
|
||||||
|
|
||||||
static BlacklistCommands()
|
static BlacklistCommands()
|
||||||
{
|
{
|
||||||
using (var uow = DbHandler.UnitOfWork())
|
using (var uow = DbHandler.UnitOfWork())
|
||||||
{
|
{
|
||||||
BlacklistedItems = new ConcurrentHashSet<BlacklistItem>(uow.BotConfig.GetOrCreate().Blacklist);
|
var blacklist = uow.BotConfig.GetOrCreate().Blacklist;
|
||||||
|
BlacklistedUsers = new ConcurrentHashSet<ulong>(blacklist.Where(bi => bi.Type == BlacklistType.User).Select(c => c.ItemId));
|
||||||
|
BlacklistedGuilds = new ConcurrentHashSet<ulong>(blacklist.Where(bi => bi.Type == BlacklistType.Server).Select(c => c.ItemId));
|
||||||
|
BlacklistedChannels = new ConcurrentHashSet<ulong>(blacklist.Where(bi => bi.Type == BlacklistType.Channel).Select(c => c.ItemId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,12 +71,34 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
{
|
{
|
||||||
var item = new BlacklistItem { ItemId = id, Type = type };
|
var item = new BlacklistItem { ItemId = id, Type = type };
|
||||||
uow.BotConfig.GetOrCreate().Blacklist.Add(item);
|
uow.BotConfig.GetOrCreate().Blacklist.Add(item);
|
||||||
BlacklistedItems.Add(item);
|
if (type == BlacklistType.Server)
|
||||||
|
{
|
||||||
|
BlacklistedGuilds.Add(id);
|
||||||
|
}
|
||||||
|
else if (type == BlacklistType.Channel)
|
||||||
|
{
|
||||||
|
BlacklistedChannels.Add(id);
|
||||||
|
}
|
||||||
|
else if (type == BlacklistType.User)
|
||||||
|
{
|
||||||
|
BlacklistedUsers.Add(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uow.BotConfig.GetOrCreate().Blacklist.RemoveWhere(bi => bi.ItemId == id && bi.Type == type);
|
uow.BotConfig.GetOrCreate().Blacklist.RemoveWhere(bi => bi.ItemId == id && bi.Type == type);
|
||||||
BlacklistedItems.RemoveWhere(bi => bi.ItemId == id && bi.Type == type);
|
if (type == BlacklistType.Server)
|
||||||
|
{
|
||||||
|
BlacklistedGuilds.TryRemove(id);
|
||||||
|
}
|
||||||
|
else if (type == BlacklistType.Channel)
|
||||||
|
{
|
||||||
|
BlacklistedChannels.TryRemove(id);
|
||||||
|
}
|
||||||
|
else if (type == BlacklistType.User)
|
||||||
|
{
|
||||||
|
BlacklistedUsers.TryRemove(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
@ -23,8 +23,8 @@ namespace NadekoBot.Modules.Searches.Commands.Models
|
|||||||
public class Main
|
public class Main
|
||||||
{
|
{
|
||||||
public double temp { get; set; }
|
public double temp { get; set; }
|
||||||
public int pressure { get; set; }
|
public float pressure { get; set; }
|
||||||
public int humidity { get; set; }
|
public float humidity { get; set; }
|
||||||
public double temp_min { get; set; }
|
public double temp_min { get; set; }
|
||||||
public double temp_max { get; set; }
|
public double temp_max { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ namespace NadekoBot.Modules.Utility
|
|||||||
.AddField(fb => fb.WithName("**Voice Channels**").WithValue(voicechn.ToString()).WithIsInline(true))
|
.AddField(fb => fb.WithName("**Voice Channels**").WithValue(voicechn.ToString()).WithIsInline(true))
|
||||||
.AddField(fb => fb.WithName("**Created At**").WithValue($"{createdAt.ToString("dd.MM.yyyy HH:mm")}").WithIsInline(true))
|
.AddField(fb => fb.WithName("**Created At**").WithValue($"{createdAt.ToString("dd.MM.yyyy HH:mm")}").WithIsInline(true))
|
||||||
.AddField(fb => fb.WithName("**Region**").WithValue(guild.VoiceRegionId.ToString()).WithIsInline(true))
|
.AddField(fb => fb.WithName("**Region**").WithValue(guild.VoiceRegionId.ToString()).WithIsInline(true))
|
||||||
.AddField(fb => fb.WithName("**Roles**").WithValue(guild.Roles.Count().ToString()).WithIsInline(true))
|
.AddField(fb => fb.WithName("**Roles**").WithValue((guild.Roles.Count - 1).ToString()).WithIsInline(true))
|
||||||
.WithImageUrl(guild.IconUrl)
|
.WithImageUrl(guild.IconUrl)
|
||||||
.WithColor(NadekoBot.OkColor);
|
.WithColor(NadekoBot.OkColor);
|
||||||
if (guild.Emojis.Count() > 0)
|
if (guild.Emojis.Count() > 0)
|
||||||
@ -92,8 +92,7 @@ namespace NadekoBot.Modules.Utility
|
|||||||
embed.AddField(fb => fb.WithName("**ID**").WithValue(user.Id.ToString()).WithIsInline(true))
|
embed.AddField(fb => fb.WithName("**ID**").WithValue(user.Id.ToString()).WithIsInline(true))
|
||||||
.AddField(fb => fb.WithName("**Joined Server**").WithValue($"{user.JoinedAt?.ToString("dd.MM.yyyy HH:mm")}").WithIsInline(true))
|
.AddField(fb => fb.WithName("**Joined Server**").WithValue($"{user.JoinedAt?.ToString("dd.MM.yyyy HH:mm")}").WithIsInline(true))
|
||||||
.AddField(fb => fb.WithName("**Joined Discord**").WithValue($"{user.CreatedAt.ToString("dd.MM.yyyy HH:mm")}").WithIsInline(true))
|
.AddField(fb => fb.WithName("**Joined Discord**").WithValue($"{user.CreatedAt.ToString("dd.MM.yyyy HH:mm")}").WithIsInline(true))
|
||||||
.AddField(fb => fb.WithName("**Current Game**").WithValue($"{(user.Game?.Name == null ? "-" : user.Game.Value.Name)}").WithIsInline(true))
|
.AddField(fb => fb.WithName("**Roles**").WithValue($"**({user.RoleIds.Count})** - {string.Join(", ", user.GetRoles().Where(r => r.Id != r.Guild.EveryoneRole.Id).Select(r => r.Name)).SanitizeMentions()}").WithIsInline(true))
|
||||||
.AddField(fb => fb.WithName("**Roles**").WithValue($"**({user.RoleIds.Count})** - {string.Join(", ", user.GetRoles().Select(r => r.Name)).SanitizeMentions()}").WithIsInline(true))
|
|
||||||
.WithThumbnailUrl(user.AvatarUrl)
|
.WithThumbnailUrl(user.AvatarUrl)
|
||||||
.WithColor(NadekoBot.OkColor);
|
.WithColor(NadekoBot.OkColor);
|
||||||
await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
|
await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
|
||||||
|
@ -240,15 +240,27 @@ namespace NadekoBot.Modules.Utility
|
|||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task ChannelTopic()
|
public async Task ChannelTopic([Remainder]ITextChannel channel = null)
|
||||||
{
|
{
|
||||||
var channel = (ITextChannel)Context.Channel;
|
if (channel == null)
|
||||||
|
channel = (ITextChannel)Context.Channel;
|
||||||
|
|
||||||
var topic = channel.Topic;
|
var topic = channel.Topic;
|
||||||
if (string.IsNullOrWhiteSpace(topic))
|
if (string.IsNullOrWhiteSpace(topic))
|
||||||
await channel.SendErrorAsync("No topic set.");
|
await channel.SendErrorAsync("No topic set.").ConfigureAwait(false);
|
||||||
else
|
else
|
||||||
await channel.SendConfirmAsync("Channel topic", topic);
|
await channel.SendConfirmAsync("Channel topic", topic).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
[RequireBotPermission(ChannelPermission.CreateInstantInvite)]
|
||||||
|
[RequireUserPermission(ChannelPermission.CreateInstantInvite)]
|
||||||
|
public async Task CreateInvite()
|
||||||
|
{
|
||||||
|
var invite = await ((ITextChannel)Context.Channel).CreateInviteAsync(0, null, isUnique: true);
|
||||||
|
|
||||||
|
await Context.Channel.SendConfirmAsync($"{Context.User.Mention} https://discord.gg/{invite.Code}");
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
@ -269,8 +281,10 @@ namespace NadekoBot.Modules.Utility
|
|||||||
.AddField(efb => efb.WithName(Format.Bold("Memory")).WithValue($"{stats.Heap} MB").WithIsInline(true))
|
.AddField(efb => efb.WithName(Format.Bold("Memory")).WithValue($"{stats.Heap} MB").WithIsInline(true))
|
||||||
.AddField(efb => efb.WithName(Format.Bold("Owner ID(s)")).WithValue(stats.OwnerIds).WithIsInline(true))
|
.AddField(efb => efb.WithName(Format.Bold("Owner ID(s)")).WithValue(stats.OwnerIds).WithIsInline(true))
|
||||||
.AddField(efb => efb.WithName(Format.Bold("Uptime")).WithValue(stats.GetUptimeString("\n")).WithIsInline(true))
|
.AddField(efb => efb.WithName(Format.Bold("Uptime")).WithValue(stats.GetUptimeString("\n")).WithIsInline(true))
|
||||||
.AddField(efb => efb.WithName(Format.Bold("Presence")).WithValue($"{NadekoBot.Client.GetGuilds().Count} Servers\n{stats.TextChannels} Text Channels\n{stats.VoiceChannels} Voice Channels").WithIsInline(true))
|
.AddField(efb => efb.WithName(Format.Bold("Presence")).WithValue($"{NadekoBot.Client.GetGuildsCount()} Servers\n{stats.TextChannels} Text Channels\n{stats.VoiceChannels} Voice Channels").WithIsInline(true))
|
||||||
|
#if !GLOBAL_NADEKO
|
||||||
.WithFooter(efb => efb.WithText($"Playing {Music.Music.MusicPlayers.Where(mp => mp.Value.CurrentSong != null).Count()} songs, {Music.Music.MusicPlayers.Sum(mp => mp.Value.Playlist.Count)} queued."))
|
.WithFooter(efb => efb.WithText($"Playing {Music.Music.MusicPlayers.Where(mp => mp.Value.CurrentSong != null).Count()} songs, {Music.Music.MusicPlayers.Sum(mp => mp.Value.Playlist.Count)} queued."))
|
||||||
|
#endif
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,7 +312,7 @@ namespace NadekoBot.Modules.Utility
|
|||||||
if (page < 0)
|
if (page < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var guilds = NadekoBot.Client.GetGuilds().OrderBy(g => g.Name).Skip((page - 1) * 15).Take(15);
|
var guilds = await Task.Run(() => NadekoBot.Client.GetGuilds().OrderBy(g => g.Name).Skip((page - 1) * 15).Take(15)).ConfigureAwait(false);
|
||||||
|
|
||||||
if (!guilds.Any())
|
if (!guilds.Any())
|
||||||
{
|
{
|
||||||
|
@ -91,7 +91,9 @@ namespace NadekoBot
|
|||||||
//connect
|
//connect
|
||||||
await Client.LoginAsync(TokenType.Bot, Credentials.Token).ConfigureAwait(false);
|
await Client.LoginAsync(TokenType.Bot, Credentials.Token).ConfigureAwait(false);
|
||||||
await Client.ConnectAsync().ConfigureAwait(false);
|
await Client.ConnectAsync().ConfigureAwait(false);
|
||||||
//await Client.DownloadAllUsersAsync().ConfigureAwait(false);
|
#if !GLOBAL_NADEKO
|
||||||
|
await Client.DownloadAllUsersAsync().ConfigureAwait(false);
|
||||||
|
#endif
|
||||||
|
|
||||||
_log.Info("Connected");
|
_log.Info("Connected");
|
||||||
|
|
||||||
|
54
src/NadekoBot/Resources/CommandStrings.Designer.cs
generated
54
src/NadekoBot/Resources/CommandStrings.Designer.cs
generated
@ -1841,6 +1841,33 @@ namespace NadekoBot.Resources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to createinvite crinv.
|
||||||
|
/// </summary>
|
||||||
|
public static string createinvite_cmd {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("createinvite_cmd", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Creates a new invite which has infinite max uses and never expires..
|
||||||
|
/// </summary>
|
||||||
|
public static string createinvite_desc {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("createinvite_desc", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to `{0}crinv`.
|
||||||
|
/// </summary>
|
||||||
|
public static string createinvite_usage {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("createinvite_usage", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to createrole cr.
|
/// Looks up a localized string similar to createrole cr.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -5135,6 +5162,33 @@ namespace NadekoBot.Resources {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to pollstats.
|
||||||
|
/// </summary>
|
||||||
|
public static string pollstats_cmd {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("pollstats_cmd", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Shows the poll results without stopping the poll on this server..
|
||||||
|
/// </summary>
|
||||||
|
public static string pollstats_desc {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("pollstats_desc", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to `{0}pollstats`.
|
||||||
|
/// </summary>
|
||||||
|
public static string pollstats_usage {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("pollstats_usage", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to prune clr.
|
/// Looks up a localized string similar to prune clr.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -2871,4 +2871,22 @@
|
|||||||
<data name="rotaterolecolor_usage" xml:space="preserve">
|
<data name="rotaterolecolor_usage" xml:space="preserve">
|
||||||
<value>`{0}rrc 60 MyLsdRole #ff0000 #00ff00 #0000ff` or `{0}rrc 0 MyLsdRole`</value>
|
<value>`{0}rrc 60 MyLsdRole #ff0000 #00ff00 #0000ff` or `{0}rrc 0 MyLsdRole`</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="createinvite_cmd" xml:space="preserve">
|
||||||
|
<value>createinvite crinv</value>
|
||||||
|
</data>
|
||||||
|
<data name="createinvite_desc" xml:space="preserve">
|
||||||
|
<value>Creates a new invite which has infinite max uses and never expires.</value>
|
||||||
|
</data>
|
||||||
|
<data name="createinvite_usage" xml:space="preserve">
|
||||||
|
<value>`{0}crinv`</value>
|
||||||
|
</data>
|
||||||
|
<data name="pollstats_cmd" xml:space="preserve">
|
||||||
|
<value>pollstats</value>
|
||||||
|
</data>
|
||||||
|
<data name="pollstats_desc" xml:space="preserve">
|
||||||
|
<value>Shows the poll results without stopping the poll on this server.</value>
|
||||||
|
</data>
|
||||||
|
<data name="pollstats_usage" xml:space="preserve">
|
||||||
|
<value>`{0}pollstats`</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -29,10 +29,16 @@ namespace Services.CleverBotApi
|
|||||||
|
|
||||||
public static ChatterBot Create(ChatterBotType type, object arg)
|
public static ChatterBot Create(ChatterBotType type, object arg)
|
||||||
{
|
{
|
||||||
|
#if GLOBAL_NADEKO
|
||||||
|
var url = "http://www.cleverbot.com/webservicemin?uc=321&botapi=nadekobot";
|
||||||
|
#else
|
||||||
|
var url = "http://www.cleverbot.com/webservicemin?uc=321";
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case ChatterBotType.CLEVERBOT:
|
case ChatterBotType.CLEVERBOT:
|
||||||
return new Cleverbot("http://www.cleverbot.com/", "http://www.cleverbot.com/webservicemin?uc=321", 26);
|
return new Cleverbot("http://www.cleverbot.com/", url, 26);
|
||||||
case ChatterBotType.JABBERWACKY:
|
case ChatterBotType.JABBERWACKY:
|
||||||
return new Cleverbot("http://jabberwacky.com", "http://jabberwacky.com/webservicemin", 20);
|
return new Cleverbot("http://jabberwacky.com", "http://jabberwacky.com/webservicemin", 20);
|
||||||
case ChatterBotType.PANDORABOTS:
|
case ChatterBotType.PANDORABOTS:
|
||||||
|
@ -17,6 +17,8 @@ using static NadekoBot.Modules.Administration.Administration;
|
|||||||
using NadekoBot.Modules.CustomReactions;
|
using NadekoBot.Modules.CustomReactions;
|
||||||
using NadekoBot.Modules.Games;
|
using NadekoBot.Modules.Games;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
using System.Threading;
|
||||||
|
using NadekoBot.DataStructures;
|
||||||
|
|
||||||
namespace NadekoBot.Services
|
namespace NadekoBot.Services
|
||||||
{
|
{
|
||||||
@ -28,6 +30,8 @@ namespace NadekoBot.Services
|
|||||||
}
|
}
|
||||||
public class CommandHandler
|
public class CommandHandler
|
||||||
{
|
{
|
||||||
|
public const int GlobalCommandsCooldown = 1500;
|
||||||
|
|
||||||
private ShardedDiscordClient _client;
|
private ShardedDiscordClient _client;
|
||||||
private CommandService _commandService;
|
private CommandService _commandService;
|
||||||
private Logger _log;
|
private Logger _log;
|
||||||
@ -39,11 +43,19 @@ namespace NadekoBot.Services
|
|||||||
//userid/msg count
|
//userid/msg count
|
||||||
public ConcurrentDictionary<ulong, uint> UserMessagesSent { get; } = new ConcurrentDictionary<ulong, uint>();
|
public ConcurrentDictionary<ulong, uint> UserMessagesSent { get; } = new ConcurrentDictionary<ulong, uint>();
|
||||||
|
|
||||||
|
public ConcurrentHashSet<ulong> UsersOnShortCooldown { get; } = new ConcurrentHashSet<ulong>();
|
||||||
|
private Timer clearUsersOnShortCooldown { get; }
|
||||||
|
|
||||||
public CommandHandler(ShardedDiscordClient client, CommandService commandService)
|
public CommandHandler(ShardedDiscordClient client, CommandService commandService)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
_commandService = commandService;
|
_commandService = commandService;
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
|
clearUsersOnShortCooldown = new Timer((_) =>
|
||||||
|
{
|
||||||
|
UsersOnShortCooldown.Clear();
|
||||||
|
}, null, GlobalCommandsCooldown, GlobalCommandsCooldown);
|
||||||
}
|
}
|
||||||
public async Task StartHandling()
|
public async Task StartHandling()
|
||||||
{
|
{
|
||||||
@ -62,70 +74,13 @@ namespace NadekoBot.Services
|
|||||||
_client.MessageReceived += MessageReceivedHandler;
|
_client.MessageReceived += MessageReceivedHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void MessageReceivedHandler(SocketMessage msg)
|
private async Task<bool> TryRunCleverbot(SocketUserMessage usrMsg, IGuild guild)
|
||||||
{
|
{
|
||||||
|
if (guild == null)
|
||||||
|
return false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var usrMsg = msg as SocketUserMessage;
|
var cleverbotExecuted = await Games.CleverBotCommands.TryAsk(usrMsg).ConfigureAwait(false);
|
||||||
if (usrMsg == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
//if (!usrMsg.IsAuthor())
|
|
||||||
// UserMessagesSent.AddOrUpdate(usrMsg.Author.Id, 1, (key, old) => ++old);
|
|
||||||
|
|
||||||
if (msg.Author.IsBot || !NadekoBot.Ready) //no bots
|
|
||||||
return;
|
|
||||||
|
|
||||||
var guild = (msg.Channel as SocketTextChannel)?.Guild;
|
|
||||||
|
|
||||||
if (guild != null && guild.OwnerId != msg.Author.Id)
|
|
||||||
{
|
|
||||||
//todo split checks into their own modules
|
|
||||||
if (Permissions.FilterCommands.InviteFilteringChannels.Contains(msg.Channel.Id) ||
|
|
||||||
Permissions.FilterCommands.InviteFilteringServers.Contains(guild.Id))
|
|
||||||
{
|
|
||||||
if (usrMsg.Content.IsDiscordInvite())
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await usrMsg.DeleteAsync().ConfigureAwait(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
catch (HttpException ex)
|
|
||||||
{
|
|
||||||
_log.Warn("I do not have permission to filter invites in channel with id " + msg.Channel.Id, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var filteredWords = Permissions.FilterCommands.FilteredWordsForChannel(msg.Channel.Id, guild.Id).Concat(Permissions.FilterCommands.FilteredWordsForServer(guild.Id));
|
|
||||||
var wordsInMessage = usrMsg.Content.ToLowerInvariant().Split(' ');
|
|
||||||
if (filteredWords.Any(w => wordsInMessage.Contains(w)))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await usrMsg.DeleteAsync().ConfigureAwait(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
catch (HttpException ex)
|
|
||||||
{
|
|
||||||
_log.Warn("I do not have permission to filter words in channel with id " + msg.Channel.Id, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BlacklistItem blacklistedItem;
|
|
||||||
if ((blacklistedItem = Permissions.BlacklistCommands.BlacklistedItems.FirstOrDefault(bi =>
|
|
||||||
(bi.Type == BlacklistItem.BlacklistType.Server && bi.ItemId == guild?.Id) ||
|
|
||||||
(bi.Type == BlacklistItem.BlacklistType.Channel && bi.ItemId == msg.Channel.Id) ||
|
|
||||||
(bi.Type == BlacklistItem.BlacklistType.User && bi.ItemId == msg.Author.Id))) != null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var cleverbotExecuted = await Games.CleverBotCommands.TryAsk(usrMsg);
|
|
||||||
if (cleverbotExecuted)
|
if (cleverbotExecuted)
|
||||||
{
|
{
|
||||||
_log.Info($@"CleverBot Executed
|
_log.Info($@"CleverBot Executed
|
||||||
@ -133,48 +88,35 @@ namespace NadekoBot.Services
|
|||||||
Channel: {usrMsg.Channel?.Name} [{usrMsg.Channel?.Id}]
|
Channel: {usrMsg.Channel?.Name} [{usrMsg.Channel?.Id}]
|
||||||
UserId: {usrMsg.Author} [{usrMsg.Author.Id}]
|
UserId: {usrMsg.Author} [{usrMsg.Author.Id}]
|
||||||
Message: {usrMsg.Content}");
|
Message: {usrMsg.Content}");
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex) { _log.Warn(ex, "Error in cleverbot"); }
|
catch (Exception ex) { _log.Warn(ex, "Error in cleverbot"); }
|
||||||
|
return false;
|
||||||
try
|
|
||||||
{
|
|
||||||
// maybe this message is a custom reaction
|
|
||||||
var crExecuted = await CustomReactions.TryExecuteCustomReaction(usrMsg).ConfigureAwait(false);
|
|
||||||
|
|
||||||
//if it was, don't execute the command
|
|
||||||
if (crExecuted)
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
catch { }
|
|
||||||
|
|
||||||
string messageContent = usrMsg.Content;
|
private bool IsBlacklisted(IGuild guild, SocketUserMessage usrMsg) =>
|
||||||
|
(guild != null && BlacklistCommands.BlacklistedGuilds.Contains(guild.Id)) ||
|
||||||
|
BlacklistCommands.BlacklistedChannels.Contains(usrMsg.Channel.Id) ||
|
||||||
|
BlacklistCommands.BlacklistedUsers.Contains(usrMsg.Author.Id);
|
||||||
|
|
||||||
var sw = new Stopwatch();
|
|
||||||
sw.Start();
|
private async Task LogSuccessfulExecution(SocketUserMessage usrMsg, ExecuteCommandResult exec, SocketTextChannel channel, Stopwatch sw)
|
||||||
var exec = await ExecuteCommand(new CommandContext(_client.MainClient, usrMsg), messageContent, DependencyMap.Empty, MultiMatchHandling.Best);
|
|
||||||
var command = exec.CommandInfo;
|
|
||||||
var permCache = exec.PermissionCache;
|
|
||||||
var result = exec.Result;
|
|
||||||
sw.Stop();
|
|
||||||
var channel = (msg.Channel as ITextChannel);
|
|
||||||
if (result.IsSuccess)
|
|
||||||
{
|
{
|
||||||
await CommandExecuted(usrMsg, command);
|
await CommandExecuted(usrMsg, exec.CommandInfo).ConfigureAwait(false);
|
||||||
_log.Info("Command Executed after {4}s\n\t" +
|
_log.Info("Command Executed after {4}s\n\t" +
|
||||||
"User: {0}\n\t" +
|
"User: {0}\n\t" +
|
||||||
"Server: {1}\n\t" +
|
"Server: {1}\n\t" +
|
||||||
"Channel: {2}\n\t" +
|
"Channel: {2}\n\t" +
|
||||||
"Message: {3}",
|
"Message: {3}",
|
||||||
msg.Author + " [" + msg.Author.Id + "]", // {0}
|
usrMsg.Author + " [" + usrMsg.Author.Id + "]", // {0}
|
||||||
(channel == null ? "PRIVATE" : channel.Guild.Name + " [" + channel.Guild.Id + "]"), // {1}
|
(channel == null ? "PRIVATE" : channel.Guild.Name + " [" + channel.Guild.Id + "]"), // {1}
|
||||||
(channel == null ? "PRIVATE" : channel.Name + " [" + channel.Id + "]"), // {2}
|
(channel == null ? "PRIVATE" : channel.Name + " [" + channel.Id + "]"), // {2}
|
||||||
usrMsg.Content, // {3}
|
usrMsg.Content, // {3}
|
||||||
sw.Elapsed.TotalSeconds // {4}
|
sw.Elapsed.TotalSeconds);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
else if (!result.IsSuccess && result.Error != CommandError.UnknownCommand)
|
|
||||||
|
private void LogErroredExecution(SocketUserMessage usrMsg, ExecuteCommandResult exec, SocketTextChannel channel, Stopwatch sw)
|
||||||
{
|
{
|
||||||
_log.Warn("Command Errored after {5}s\n\t" +
|
_log.Warn("Command Errored after {5}s\n\t" +
|
||||||
"User: {0}\n\t" +
|
"User: {0}\n\t" +
|
||||||
@ -182,42 +124,152 @@ namespace NadekoBot.Services
|
|||||||
"Channel: {2}\n\t" +
|
"Channel: {2}\n\t" +
|
||||||
"Message: {3}\n\t" +
|
"Message: {3}\n\t" +
|
||||||
"Error: {4}",
|
"Error: {4}",
|
||||||
msg.Author + " [" + msg.Author.Id + "]", // {0}
|
usrMsg.Author + " [" + usrMsg.Author.Id + "]", // {0}
|
||||||
(channel == null ? "PRIVATE" : channel.Guild.Name + " [" + channel.Guild.Id + "]"), // {1}
|
(channel == null ? "PRIVATE" : channel.Guild.Name + " [" + channel.Guild.Id + "]"), // {1}
|
||||||
(channel == null ? "PRIVATE" : channel.Name + " [" + channel.Id + "]"), // {2}
|
(channel == null ? "PRIVATE" : channel.Name + " [" + channel.Id + "]"), // {2}
|
||||||
usrMsg.Content,// {3}
|
usrMsg.Content,// {3}
|
||||||
result.ErrorReason, // {4}
|
exec.Result.ErrorReason, // {4}
|
||||||
sw.Elapsed.TotalSeconds // {5}
|
sw.Elapsed.TotalSeconds // {5}
|
||||||
);
|
);
|
||||||
if (guild != null && command != null && result.Error == CommandError.Exception)
|
}
|
||||||
|
|
||||||
|
private async Task<bool> InviteFiltered(IGuild guild, SocketUserMessage usrMsg)
|
||||||
{
|
{
|
||||||
if (permCache != null && permCache.Verbose)
|
if ((Permissions.FilterCommands.InviteFilteringChannels.Contains(usrMsg.Channel.Id) ||
|
||||||
try { await msg.Channel.SendMessageAsync("⚠️ " + result.ErrorReason).ConfigureAwait(false); } catch { }
|
Permissions.FilterCommands.InviteFilteringServers.Contains(guild.Id)) &&
|
||||||
|
usrMsg.Content.IsDiscordInvite())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await usrMsg.DeleteAsync().ConfigureAwait(false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (HttpException ex)
|
||||||
|
{
|
||||||
|
_log.Warn("I do not have permission to filter invites in channel with id " + usrMsg.Channel.Id, ex);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<bool> WordFiltered(IGuild guild, SocketUserMessage usrMsg)
|
||||||
|
{
|
||||||
|
var filteredChannelWords = Permissions.FilterCommands.FilteredWordsForChannel(usrMsg.Channel.Id, guild.Id);
|
||||||
|
var filteredServerWords = Permissions.FilterCommands.FilteredWordsForServer(guild.Id);
|
||||||
|
var wordsInMessage = usrMsg.Content.ToLowerInvariant().Split(' ');
|
||||||
|
if (filteredChannelWords.Count != 0 || filteredServerWords.Count != 0)
|
||||||
|
{
|
||||||
|
foreach (var word in wordsInMessage)
|
||||||
|
{
|
||||||
|
if (filteredChannelWords.Contains(word) ||
|
||||||
|
filteredServerWords.Contains(word))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await usrMsg.DeleteAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (HttpException ex)
|
||||||
|
{
|
||||||
|
_log.Warn("I do not have permission to filter words in channel with id " + usrMsg.Channel.Id, ex);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void MessageReceivedHandler(SocketMessage msg)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (msg.Author.IsBot || !NadekoBot.Ready) //no bots, wait until bot connected and initialized
|
||||||
|
return;
|
||||||
|
|
||||||
|
var usrMsg = msg as SocketUserMessage;
|
||||||
|
if (usrMsg == null) //has to be an user message, not system/other messages.
|
||||||
|
return;
|
||||||
|
|
||||||
|
// track how many messagges each user is sending
|
||||||
|
UserMessagesSent.AddOrUpdate(usrMsg.Author.Id, 1, (key, old) => ++old);
|
||||||
|
|
||||||
|
// Bot will ignore commands which are ran more often than what specified by
|
||||||
|
// GlobalCommandsCooldown constant (miliseconds)
|
||||||
|
if (!UsersOnShortCooldown.Add(usrMsg.Author.Id))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var channel = msg.Channel as SocketTextChannel;
|
||||||
|
var guild = channel?.Guild;
|
||||||
|
|
||||||
|
if (guild != null && guild.OwnerId != msg.Author.Id)
|
||||||
|
{
|
||||||
|
if (await InviteFiltered(guild, usrMsg).ConfigureAwait(false))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (await WordFiltered(guild, usrMsg).ConfigureAwait(false))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsBlacklisted(guild, usrMsg))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var cleverBotRan = await TryRunCleverbot(usrMsg, guild).ConfigureAwait(false);
|
||||||
|
if (cleverBotRan)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// maybe this message is a custom reaction
|
||||||
|
var crExecuted = await CustomReactions.TryExecuteCustomReaction(usrMsg).ConfigureAwait(false);
|
||||||
|
if (crExecuted) //if it was, don't execute the command
|
||||||
|
return;
|
||||||
|
|
||||||
|
string messageContent = usrMsg.Content;
|
||||||
|
|
||||||
|
// execute the command and measure the time it took
|
||||||
|
var sw = Stopwatch.StartNew();
|
||||||
|
var exec = await ExecuteCommand(new CommandContext(_client.MainClient, usrMsg), messageContent, DependencyMap.Empty, MultiMatchHandling.Best);
|
||||||
|
sw.Stop();
|
||||||
|
|
||||||
|
if (exec.Result.IsSuccess)
|
||||||
|
{
|
||||||
|
await LogSuccessfulExecution(usrMsg, exec, channel, sw).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
else if (!exec.Result.IsSuccess && exec.Result.Error != CommandError.UnknownCommand)
|
||||||
|
{
|
||||||
|
LogErroredExecution(usrMsg, exec, channel, sw);
|
||||||
|
if (guild != null && exec.CommandInfo != null && exec.Result.Error == CommandError.Exception)
|
||||||
|
{
|
||||||
|
if (exec.PermissionCache != null && exec.PermissionCache.Verbose)
|
||||||
|
try { await msg.Channel.SendMessageAsync("⚠️ " + exec.Result.ErrorReason).ConfigureAwait(false); } catch { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (msg.Channel is IPrivateChannel)
|
if (msg.Channel is IPrivateChannel)
|
||||||
{
|
{
|
||||||
//rofl, gotta do this to prevent this message from occuring on polls
|
// rofl, gotta do this to prevent dm help message being sent to
|
||||||
|
// users who are voting on private polls (sending a number in a DM)
|
||||||
int vote;
|
int vote;
|
||||||
if (int.TryParse(msg.Content, out vote)) return;
|
if (int.TryParse(msg.Content, out vote)) return;
|
||||||
|
|
||||||
await msg.Channel.SendMessageAsync(Help.DMHelpString).ConfigureAwait(false);
|
await msg.Channel.SendMessageAsync(Help.DMHelpString).ConfigureAwait(false);
|
||||||
|
|
||||||
await DMForwardCommands.HandleDMForwarding(msg, ownerChannels);
|
await DMForwardCommands.HandleDMForwarding(msg, ownerChannels).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_log.Warn(ex, "Error in CommandHandler");
|
_log.Warn("Error in CommandHandler");
|
||||||
|
_log.Warn(ex);
|
||||||
if (ex.InnerException != null)
|
if (ex.InnerException != null)
|
||||||
_log.Warn(ex.InnerException, "Inner Exception of the error in CommandHandler");
|
{
|
||||||
|
_log.Warn("Inner Exception of the error in CommandHandler");
|
||||||
|
_log.Warn(ex.InnerException);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
public Task<ExecuteCommandResult> ExecuteCommandAsync(CommandContext context, int argPos, IDependencyMap dependencyMap = null, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception)
|
public Task<ExecuteCommandResult> ExecuteCommandAsync(CommandContext context, int argPos, IDependencyMap dependencyMap = null, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception)
|
||||||
=> ExecuteCommand(context, context.Message.Content.Substring(argPos), dependencyMap, multiMatchHandling);
|
=> ExecuteCommand(context, context.Message.Content.Substring(argPos), dependencyMap, multiMatchHandling);
|
||||||
|
|
||||||
@ -312,19 +364,5 @@ namespace NadekoBot.Services
|
|||||||
|
|
||||||
return new ExecuteCommandResult(null, null, SearchResult.FromError(CommandError.UnknownCommand, "This input does not match any overload."));
|
return new ExecuteCommandResult(null, null, SearchResult.FromError(CommandError.UnknownCommand, "This input does not match any overload."));
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct ExecuteCommandResult
|
|
||||||
{
|
|
||||||
public readonly CommandInfo CommandInfo;
|
|
||||||
public readonly PermissionCache PermissionCache;
|
|
||||||
public readonly IResult Result;
|
|
||||||
|
|
||||||
public ExecuteCommandResult(CommandInfo commandInfo, PermissionCache cache, IResult result)
|
|
||||||
{
|
|
||||||
this.CommandInfo = commandInfo;
|
|
||||||
this.PermissionCache = cache;
|
|
||||||
this.Result = result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
66
src/NadekoBot/Services/Discord/SocketMessageEventWrapper.cs
Normal file
66
src/NadekoBot/Services/Discord/SocketMessageEventWrapper.cs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
using Discord;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NadekoBot.Services.Discord
|
||||||
|
{
|
||||||
|
public class ReactionEventWrapper : IDisposable
|
||||||
|
{
|
||||||
|
public SocketMessage Message { get; }
|
||||||
|
public event Action<SocketReaction> OnReactionAdded = delegate { };
|
||||||
|
public event Action<SocketReaction> OnReactionRemoved = delegate { };
|
||||||
|
public event Action OnReactionsCleared = delegate { };
|
||||||
|
|
||||||
|
public ReactionEventWrapper(SocketMessage msg)
|
||||||
|
{
|
||||||
|
if (msg == null)
|
||||||
|
throw new ArgumentNullException(nameof(msg));
|
||||||
|
Message = msg;
|
||||||
|
|
||||||
|
msg.Discord.ReactionAdded += Discord_ReactionAdded;
|
||||||
|
msg.Discord.ReactionRemoved += Discord_ReactionRemoved;
|
||||||
|
msg.Discord.ReactionsCleared += Discord_ReactionsCleared;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task Discord_ReactionsCleared(ulong messageId, Optional<SocketUserMessage> reaction)
|
||||||
|
{
|
||||||
|
if (messageId == Message.Id)
|
||||||
|
OnReactionsCleared?.Invoke();
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task Discord_ReactionRemoved(ulong messageId, Optional<SocketUserMessage> arg2, SocketReaction reaction)
|
||||||
|
{
|
||||||
|
if (messageId == Message.Id)
|
||||||
|
OnReactionRemoved?.Invoke(reaction);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task Discord_ReactionAdded(ulong messageId, Optional<SocketUserMessage> message, SocketReaction reaction)
|
||||||
|
{
|
||||||
|
if(messageId == Message.Id)
|
||||||
|
OnReactionAdded?.Invoke(reaction);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnsubAll()
|
||||||
|
{
|
||||||
|
Message.Discord.ReactionAdded -= Discord_ReactionAdded;
|
||||||
|
Message.Discord.ReactionRemoved -= Discord_ReactionRemoved;
|
||||||
|
Message.Discord.ReactionsCleared -= Discord_ReactionsCleared;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool disposing = false;
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
return;
|
||||||
|
disposing = true;
|
||||||
|
UnsubAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -20,10 +20,13 @@ namespace NadekoBot.Services.Impl
|
|||||||
public string Library => "Discord.Net";
|
public string Library => "Discord.Net";
|
||||||
public int MessageCounter { get; private set; } = 0;
|
public int MessageCounter { get; private set; } = 0;
|
||||||
public int CommandsRan { get; private set; } = 0;
|
public int CommandsRan { get; private set; } = 0;
|
||||||
public string Heap => Math.Round((double)GC.GetTotalMemory(false) / 1.MiB(), 2).ToString();
|
public string Heap =>
|
||||||
public double MessagesPerSecond => MessageCounter / (double)GetUptime().TotalSeconds;
|
Math.Round((double)GC.GetTotalMemory(false) / 1.MiB(), 2).ToString();
|
||||||
public int TextChannels => client.GetGuilds().SelectMany(g => g.Channels.Where(c => c is ITextChannel)).Count();
|
public double MessagesPerSecond => MessageCounter / GetUptime().TotalSeconds;
|
||||||
public int VoiceChannels => client.GetGuilds().SelectMany(g => g.Channels.Where(c => c is IVoiceChannel)).Count();
|
private int _textChannels = 0;
|
||||||
|
public int TextChannels => _textChannels;
|
||||||
|
private int _voiceChannels = 0;
|
||||||
|
public int VoiceChannels => _voiceChannels;
|
||||||
public string OwnerIds => string.Join(", ", NadekoBot.Credentials.OwnerIds);
|
public string OwnerIds => string.Join(", ", NadekoBot.Credentials.OwnerIds);
|
||||||
|
|
||||||
Timer carbonitexTimer { get; }
|
Timer carbonitexTimer { get; }
|
||||||
@ -39,6 +42,45 @@ namespace NadekoBot.Services.Impl
|
|||||||
|
|
||||||
this.client.Disconnected += _ => Reset();
|
this.client.Disconnected += _ => Reset();
|
||||||
|
|
||||||
|
this.client.Connected += () =>
|
||||||
|
{
|
||||||
|
var guilds = this.client.GetGuilds();
|
||||||
|
_textChannels = guilds.Sum(g => g.Channels.Where(cx => cx is ITextChannel).Count());
|
||||||
|
_voiceChannels = guilds.Sum(g => g.Channels.Count) - _textChannels;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.client.ChannelCreated += (c) =>
|
||||||
|
{
|
||||||
|
if (c is ITextChannel)
|
||||||
|
++_textChannels;
|
||||||
|
else if (c is IVoiceChannel)
|
||||||
|
++_voiceChannels;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.client.ChannelDestroyed += (c) =>
|
||||||
|
{
|
||||||
|
if (c is ITextChannel)
|
||||||
|
--_textChannels;
|
||||||
|
else if (c is IVoiceChannel)
|
||||||
|
--_voiceChannels;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.client.JoinedGuild += (g) =>
|
||||||
|
{
|
||||||
|
var tc = g.Channels.Where(cx => cx is ITextChannel).Count();
|
||||||
|
var vc = g.Channels.Count - tc;
|
||||||
|
_textChannels += tc;
|
||||||
|
_voiceChannels += vc;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.client.LeftGuild += (g) =>
|
||||||
|
{
|
||||||
|
var tc = g.Channels.Where(cx => cx is ITextChannel).Count();
|
||||||
|
var vc = g.Channels.Count - tc;
|
||||||
|
_textChannels -= tc;
|
||||||
|
_voiceChannels -= vc;
|
||||||
|
};
|
||||||
|
|
||||||
this.carbonitexTimer = new Timer(async (state) =>
|
this.carbonitexTimer = new Timer(async (state) =>
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.CarbonKey))
|
if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.CarbonKey))
|
||||||
@ -49,7 +91,7 @@ namespace NadekoBot.Services.Impl
|
|||||||
{
|
{
|
||||||
using (var content = new FormUrlEncodedContent(
|
using (var content = new FormUrlEncodedContent(
|
||||||
new Dictionary<string, string> {
|
new Dictionary<string, string> {
|
||||||
{ "servercount", this.client.GetGuilds().Count.ToString() },
|
{ "servercount", this.client.GetGuildsCount().ToString() },
|
||||||
{ "key", NadekoBot.Credentials.CarbonKey }}))
|
{ "key", NadekoBot.Credentials.CarbonKey }}))
|
||||||
{
|
{
|
||||||
content.Headers.Clear();
|
content.Headers.Clear();
|
||||||
@ -71,7 +113,7 @@ Bot Version: [{BotVersion}]
|
|||||||
Bot ID: {curUser.Id}
|
Bot ID: {curUser.Id}
|
||||||
Owner ID(s): {OwnerIds}
|
Owner ID(s): {OwnerIds}
|
||||||
Uptime: {GetUptimeString()}
|
Uptime: {GetUptimeString()}
|
||||||
Servers: {client.GetGuilds().Count} | TextChannels: {TextChannels} | VoiceChannels: {VoiceChannels}
|
Servers: {client.GetGuildsCount()} | TextChannels: {TextChannels} | VoiceChannels: {VoiceChannels}
|
||||||
Commands Ran this session: {CommandsRan}
|
Commands Ran this session: {CommandsRan}
|
||||||
Messages: {MessageCounter} [{MessagesPerSecond:F2}/sec] Heap: [{Heap} MB]");
|
Messages: {MessageCounter} [{MessagesPerSecond:F2}/sec] Heap: [{Heap} MB]");
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ namespace NadekoBot
|
|||||||
public event Action<SocketMessage> MessageReceived = delegate { };
|
public event Action<SocketMessage> MessageReceived = delegate { };
|
||||||
public event Action<SocketGuildUser> UserLeft = delegate { };
|
public event Action<SocketGuildUser> UserLeft = delegate { };
|
||||||
public event Action<SocketUser, SocketUser> UserUpdated = delegate { };
|
public event Action<SocketUser, SocketUser> UserUpdated = delegate { };
|
||||||
|
public event Action<SocketGuildUser, SocketGuildUser> GuildUserUpdated = delegate { };
|
||||||
public event Action<Optional<SocketMessage>, SocketMessage> MessageUpdated = delegate { };
|
public event Action<Optional<SocketMessage>, SocketMessage> MessageUpdated = delegate { };
|
||||||
public event Action<ulong, Optional<SocketMessage>> MessageDeleted = delegate { };
|
public event Action<ulong, Optional<SocketMessage>> MessageDeleted = delegate { };
|
||||||
public event Action<SocketUser, SocketGuild> UserBanned = delegate { };
|
public event Action<SocketUser, SocketGuild> UserBanned = delegate { };
|
||||||
@ -27,11 +28,18 @@ namespace NadekoBot
|
|||||||
public event Action<SocketChannel> ChannelCreated = delegate { };
|
public event Action<SocketChannel> ChannelCreated = delegate { };
|
||||||
public event Action<SocketChannel> ChannelDestroyed = delegate { };
|
public event Action<SocketChannel> ChannelDestroyed = delegate { };
|
||||||
public event Action<SocketChannel, SocketChannel> ChannelUpdated = delegate { };
|
public event Action<SocketChannel, SocketChannel> ChannelUpdated = delegate { };
|
||||||
|
|
||||||
|
public event Action<SocketGuild> JoinedGuild = delegate { };
|
||||||
|
public event Action<SocketGuild> LeftGuild = delegate { };
|
||||||
|
|
||||||
public event Action<Exception> Disconnected = delegate { };
|
public event Action<Exception> Disconnected = delegate { };
|
||||||
|
public event Action Connected = delegate { };
|
||||||
|
|
||||||
private uint _connectedCount = 0;
|
private uint _connectedCount = 0;
|
||||||
private uint _downloadedCount = 0;
|
private uint _downloadedCount = 0;
|
||||||
|
|
||||||
|
private int _guildCount = 0;
|
||||||
|
|
||||||
private IReadOnlyList<DiscordSocketClient> Clients { get; }
|
private IReadOnlyList<DiscordSocketClient> Clients { get; }
|
||||||
|
|
||||||
public ShardedDiscordClient(DiscordSocketConfig discordSocketConfig)
|
public ShardedDiscordClient(DiscordSocketConfig discordSocketConfig)
|
||||||
@ -54,6 +62,7 @@ namespace NadekoBot
|
|||||||
};
|
};
|
||||||
client.UserLeft += arg1 => { UserLeft(arg1); return Task.CompletedTask; };
|
client.UserLeft += arg1 => { UserLeft(arg1); return Task.CompletedTask; };
|
||||||
client.UserUpdated += (arg1, gu2) => { UserUpdated(arg1, gu2); return Task.CompletedTask; };
|
client.UserUpdated += (arg1, gu2) => { UserUpdated(arg1, gu2); return Task.CompletedTask; };
|
||||||
|
client.GuildMemberUpdated += (arg1, arg2) => { GuildUserUpdated(arg1, arg2); return Task.CompletedTask; };
|
||||||
client.MessageUpdated += (arg1, m2) => { MessageUpdated(arg1, m2); return Task.CompletedTask; };
|
client.MessageUpdated += (arg1, m2) => { MessageUpdated(arg1, m2); return Task.CompletedTask; };
|
||||||
client.MessageDeleted += (arg1, arg2) => { MessageDeleted(arg1, arg2); return Task.CompletedTask; };
|
client.MessageDeleted += (arg1, arg2) => { MessageDeleted(arg1, arg2); return Task.CompletedTask; };
|
||||||
client.UserBanned += (arg1, arg2) => { UserBanned(arg1, arg2); return Task.CompletedTask; };
|
client.UserBanned += (arg1, arg2) => { UserBanned(arg1, arg2); return Task.CompletedTask; };
|
||||||
@ -63,9 +72,13 @@ namespace NadekoBot
|
|||||||
client.ChannelCreated += arg => { ChannelCreated(arg); return Task.CompletedTask; };
|
client.ChannelCreated += arg => { ChannelCreated(arg); return Task.CompletedTask; };
|
||||||
client.ChannelDestroyed += arg => { ChannelDestroyed(arg); return Task.CompletedTask; };
|
client.ChannelDestroyed += arg => { ChannelDestroyed(arg); return Task.CompletedTask; };
|
||||||
client.ChannelUpdated += (arg1, arg2) => { ChannelUpdated(arg1, arg2); return Task.CompletedTask; };
|
client.ChannelUpdated += (arg1, arg2) => { ChannelUpdated(arg1, arg2); return Task.CompletedTask; };
|
||||||
|
client.JoinedGuild += (arg1) => { JoinedGuild(arg1); ++_guildCount; return Task.CompletedTask; };
|
||||||
|
client.LeftGuild += (arg1) => { LeftGuild(arg1); --_guildCount; return Task.CompletedTask; };
|
||||||
|
|
||||||
_log.Info($"Shard #{i} initialized.");
|
_log.Info($"Shard #{i} initialized.");
|
||||||
|
#if GLOBAL_NADEKO
|
||||||
client.Log += Client_Log;
|
client.Log += Client_Log;
|
||||||
|
#endif
|
||||||
var j = i;
|
var j = i;
|
||||||
client.Disconnected += (ex) =>
|
client.Disconnected += (ex) =>
|
||||||
{
|
{
|
||||||
@ -91,11 +104,22 @@ namespace NadekoBot
|
|||||||
public SocketSelfUser CurrentUser() =>
|
public SocketSelfUser CurrentUser() =>
|
||||||
Clients[0].CurrentUser;
|
Clients[0].CurrentUser;
|
||||||
|
|
||||||
public IReadOnlyCollection<SocketGuild> GetGuilds() =>
|
public IEnumerable<SocketGuild> GetGuilds() =>
|
||||||
Clients.SelectMany(c => c.Guilds).ToList();
|
Clients.SelectMany(c => c.Guilds);
|
||||||
|
|
||||||
public SocketGuild GetGuild(ulong id) =>
|
public int GetGuildsCount() =>
|
||||||
Clients.Select(c => c.GetGuild(id)).FirstOrDefault(g => g != null);
|
_guildCount;
|
||||||
|
|
||||||
|
public SocketGuild GetGuild(ulong id)
|
||||||
|
{
|
||||||
|
foreach (var c in Clients)
|
||||||
|
{
|
||||||
|
var g = c.GetGuild(id);
|
||||||
|
if (g != null)
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public Task<IDMChannel> GetDMChannelAsync(ulong channelId) =>
|
public Task<IDMChannel> GetDMChannelAsync(ulong channelId) =>
|
||||||
Clients[0].GetDMChannelAsync(channelId);
|
Clients[0].GetDMChannelAsync(channelId);
|
||||||
@ -120,6 +144,7 @@ namespace NadekoBot
|
|||||||
await c.ConnectAsync().ConfigureAwait(false);
|
await c.ConnectAsync().ConfigureAwait(false);
|
||||||
sw.Stop();
|
sw.Stop();
|
||||||
_log.Info($"Shard #{c.ShardId} connected after {sw.Elapsed.TotalSeconds:F2}s ({++_connectedCount}/{Clients.Count})");
|
_log.Info($"Shard #{c.ShardId} connected after {sw.Elapsed.TotalSeconds:F2}s ({++_connectedCount}/{Clients.Count})");
|
||||||
|
_guildCount += c.Guilds.Count;
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@ -132,6 +157,7 @@ namespace NadekoBot
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Connected();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Task DownloadAllUsersAsync() =>
|
internal Task DownloadAllUsersAsync() =>
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
|
using Discord.WebSocket;
|
||||||
using ImageSharp;
|
using ImageSharp;
|
||||||
|
using NadekoBot.Services.Discord;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
@ -16,6 +18,13 @@ namespace NadekoBot.Extensions
|
|||||||
{
|
{
|
||||||
public static class Extensions
|
public static class Extensions
|
||||||
{
|
{
|
||||||
|
public static ReactionEventWrapper OnReactionAdded(this SocketMessage msg, Action<SocketReaction> reactionAdded)
|
||||||
|
{
|
||||||
|
var wrap = new ReactionEventWrapper(msg);
|
||||||
|
wrap.OnReactionAdded += reactionAdded;
|
||||||
|
return wrap;
|
||||||
|
}
|
||||||
|
|
||||||
public static void AddFakeHeaders(this HttpClient http)
|
public static void AddFakeHeaders(this HttpClient http)
|
||||||
{
|
{
|
||||||
http.DefaultRequestHeaders.Clear();
|
http.DefaultRequestHeaders.Clear();
|
||||||
|
Loading…
Reference in New Issue
Block a user