few more thingies, ready for prerelease

This commit is contained in:
Master Kwoth 2016-03-03 18:24:58 +01:00
parent 827b5bae0c
commit a6ebff0a17
31 changed files with 190 additions and 185 deletions

View File

@ -45,9 +45,9 @@ namespace NadekoBot.Classes {
}
}
internal List<T> GetAllRows<T>() where T : IDataModel, new() {
internal HashSet<T> GetAllRows<T>() where T : IDataModel, new() {
using (var conn = new SQLiteConnection(FilePath)) {
return conn.Table<T>().ToList();
return new HashSet<T>(conn.Table<T>());
}
}

View File

@ -24,10 +24,10 @@ namespace NadekoBot.Classes.Music {
public class MusicPlayer {
public static int MaximumPlaylistSize => 50;
private IAudioClient _client { get; set; }
private IAudioClient audioClient { get; set; }
private List<Song> _playlist = new List<Song>();
public IReadOnlyCollection<Song> Playlist => _playlist;
private readonly List<Song> playlist = new List<Song>();
public IReadOnlyCollection<Song> Playlist => playlist;
private readonly object playlistLock = new object();
public Song CurrentSong { get; set; } = default(Song);
@ -57,7 +57,7 @@ namespace NadekoBot.Classes.Music {
Task.Run(async () => {
while (true) {
try {
_client = await PlaybackVoiceChannel.JoinAudio();
audioClient = await PlaybackVoiceChannel.JoinAudio();
}
catch {
await Task.Delay(1000);
@ -67,7 +67,7 @@ namespace NadekoBot.Classes.Music {
if (CurrentSong != null) {
try {
OnStarted(CurrentSong);
await CurrentSong.Play(_client, cancelToken);
await CurrentSong.Play(audioClient, cancelToken);
}
catch (OperationCanceledException) {
Console.WriteLine("Song canceled");
@ -98,7 +98,7 @@ namespace NadekoBot.Classes.Music {
public void Stop() {
lock (playlistLock) {
_playlist.Clear();
playlist.Clear();
try {
if (!SongCancelSource.IsCancellationRequested)
SongCancelSource.Cancel();
@ -113,7 +113,7 @@ namespace NadekoBot.Classes.Music {
public void Shuffle() {
lock (playlistLock) {
_playlist.Shuffle();
playlist.Shuffle();
}
}
@ -129,10 +129,10 @@ namespace NadekoBot.Classes.Music {
private Song GetNextSong() {
lock (playlistLock) {
if (_playlist.Count == 0)
if (playlist.Count == 0)
return null;
var toReturn = _playlist[0];
_playlist.RemoveAt(0);
var toReturn = playlist[0];
playlist.RemoveAt(0);
return toReturn;
}
}
@ -141,7 +141,7 @@ namespace NadekoBot.Classes.Music {
if (s == null)
throw new ArgumentNullException(nameof(s));
lock (playlistLock) {
_playlist.Add(s);
playlist.Add(s);
}
}
@ -149,20 +149,20 @@ namespace NadekoBot.Classes.Music {
if (s == null)
throw new ArgumentNullException(nameof(s));
lock (playlistLock) {
_playlist.Remove(s);
playlist.Remove(s);
}
}
public void RemoveSongAt(int index) {
lock (playlistLock) {
if (index < 0 || index >= _playlist.Count)
if (index < 0 || index >= playlist.Count)
throw new ArgumentException("Invalid index");
_playlist.RemoveAt(index);
playlist.RemoveAt(index);
}
}
internal Task MoveToVoiceChannel(Channel voiceChannel) {
if (_client?.State != ConnectionState.Connected)
if (audioClient?.State != ConnectionState.Connected)
throw new InvalidOperationException("Can't move while bot is not connected to voice channel.");
PlaybackVoiceChannel = voiceChannel;
return PlaybackVoiceChannel.JoinAudio();
@ -170,7 +170,7 @@ namespace NadekoBot.Classes.Music {
internal void ClearQueue() {
lock (playlistLock) {
_playlist.Clear();
playlist.Clear();
}
}
}

View File

@ -124,7 +124,7 @@ namespace NadekoBot.Classes.Music {
$"**【 {SongInfo.Title.TrimTo(55)} 】**`{(SongInfo.Provider ?? "-")}`";
public SongInfo SongInfo { get; }
private PoopyBuffer songBuffer { get; } = new PoopyBuffer(10.MB());
private PoopyBuffer songBuffer { get; } = new PoopyBuffer(4.MiB());
private bool prebufferingComplete { get; set; } = false;
public MusicPlayer MusicPlayer { get; set; }
@ -145,7 +145,7 @@ namespace NadekoBot.Classes.Music {
RedirectStandardError = false,
CreateNoWindow = true,
});
var blockSize = 3840;
const int blockSize = 3840;
var buffer = new byte[blockSize];
var attempt = 0;
while (!cancelToken.IsCancellationRequested) {
@ -164,6 +164,7 @@ namespace NadekoBot.Classes.Music {
} catch {
Console.WriteLine("Buffering errored");
} finally {
Console.WriteLine($"Buffering done." + $" [{songBuffer.ContentLength}]");
if (p != null) {
p.CancelOutputRead();
p.StandardOutput.Dispose();
@ -172,11 +173,10 @@ namespace NadekoBot.Classes.Music {
p.Dispose();
}
}
Console.WriteLine($"Buffering done." + $" [{songBuffer.ContentLength}]");
});
internal async Task Play(IAudioClient voiceClient, CancellationToken cancelToken) {
var t = BufferSong(cancelToken).ConfigureAwait(false);
var bufferTask = BufferSong(cancelToken).ConfigureAwait(false);
var bufferAttempts = 0;
const int waitPerAttempt = 500;
var toAttemptTimes = SongInfo.ProviderType != MusicType.Normal ? 5 : 9;
@ -185,7 +185,7 @@ namespace NadekoBot.Classes.Music {
}
cancelToken.ThrowIfCancellationRequested();
Console.WriteLine($"Prebuffering done? in {waitPerAttempt * bufferAttempts}");
var blockSize = 3840;
const int blockSize = 3840;
var buffer = new byte[blockSize];
var attempt = 0;
while (!cancelToken.IsCancellationRequested) {
@ -206,6 +206,7 @@ namespace NadekoBot.Classes.Music {
buffer = AdjustVolume(buffer, MusicPlayer.Volume);
voiceClient.Send(buffer, 0, read);
}
await bufferTask;
cancelToken.ThrowIfCancellationRequested();
//try {
// voiceClient.Clear();
@ -366,14 +367,13 @@ namespace NadekoBot.Classes.Music {
return query;
}
private static bool IsRadioLink(string query) {
return (query.StartsWith("http") ||
query.StartsWith("ww"))
&&
(query.Contains(".pls") ||
query.Contains(".m3u") ||
query.Contains(".asx") ||
query.Contains(".xspf"));
}
private static bool IsRadioLink(string query) =>
(query.StartsWith("http") ||
query.StartsWith("ww"))
&&
(query.Contains(".pls") ||
query.Contains(".m3u") ||
query.Contains(".asx") ||
query.Contains(".xspf"));
}
}

View File

@ -6,6 +6,7 @@ using System.Linq;
using NadekoBot.Extensions;
using System.Threading.Tasks;
using System.Reflection;
using NadekoBot.Modules;
namespace NadekoBot {
public class NadekoStats {
@ -84,22 +85,27 @@ namespace NadekoBot {
public Task LoadStats() =>
Task.Run(() => {
var songs = Music.MusicPlayers.Count;
var sb = new System.Text.StringBuilder();
sb.AppendLine("`Author: Kwoth` `Library: Discord.Net`");
sb.AppendLine($"`Bot Version: {BotVersion}`");
sb.AppendLine($"`Bot id: {NadekoBot.Client.CurrentUser.Id}`");
sb.AppendLine($"`Owner id: {(NadekoBot.Creds.OwnerIds.FirstOrDefault())}`");
sb.Append("`Owners' Ids:` ");
sb.AppendLine("`" + String.Join(", ", NadekoBot.Creds.OwnerIds) + "`");
sb.AppendLine($"`Uptime: {GetUptimeString()}`");
sb.Append($"`Servers: {ServerCount}");
sb.Append($" | TextChannels: {TextChannelsCount}");
sb.AppendLine($" | VoiceChannels: {VoiceChannelsCount}`");
sb.AppendLine($"`Commands Ran this session: {commandsRan}`");
sb.AppendLine($"`Message queue size:{NadekoBot.Client.MessageQueue.Count}`");
sb.AppendLine($"`Greeted {Commands.ServerGreetCommand.Greeted} times.`");
sb.AppendLine($"`Message queue size: {NadekoBot.Client.MessageQueue.Count}`");
sb.Append($"`Greeted {Commands.ServerGreetCommand.Greeted} times.`");
sb.AppendLine($" `| Playing {songs} songs, ".SnPl(songs) +
$"{Music.MusicPlayers.Sum(kvp => kvp.Value.Playlist.Count)} queued.`");
sb.AppendLine($"`Heap: {Heap(false)}`");
statsCache = sb.ToString();
});
public string Heap() => Math.Round((double)GC.GetTotalMemory(true) / 1.MiB(), 2).ToString();
public string Heap(bool pass = true) => Math.Round((double)GC.GetTotalMemory(pass) / 1.MiB(), 2).ToString();
public async Task<string> GetStats() {
if (statsStopwatch.Elapsed.Seconds <= 5) return statsCache;

View File

@ -4,12 +4,14 @@ using System.Threading.Tasks;
using Discord;
using Discord.Commands;
using System.Collections.Concurrent;
using System.Collections.Generic;
namespace NadekoBot.Classes.Permissions {
internal class PermissionChecker : IPermissionChecker {
public static PermissionChecker Instance { get; } = new PermissionChecker();
private ConcurrentDictionary<User, DateTime> timeBlackList { get; } = new ConcurrentDictionary<User, DateTime>();
private HashSet<ulong> serverBlacklist { get; } = new HashSet<ulong>();
static PermissionChecker() { }
public PermissionChecker() {

View File

@ -21,7 +21,7 @@ namespace NadekoBot.Classes.Trivia {
private CancellationTokenSource triviaCancelSource { get; set; }
public TriviaQuestion CurrentQuestion { get; private set; }
public List<TriviaQuestion> oldQuestions { get; } = new List<TriviaQuestion>();
public HashSet<TriviaQuestion> oldQuestions { get; } = new HashSet<TriviaQuestion>();
public ConcurrentDictionary<User, int> Users { get; } = new ConcurrentDictionary<User, int>();

View File

@ -7,7 +7,7 @@ using System.Text.RegularExpressions;
namespace NadekoBot.Classes.Trivia {
public class TriviaQuestion {
//represents the min size to judge levDistance with
public static List<Tuple<int, int>> strictness = new List<Tuple<int, int>>() {
private static readonly HashSet<Tuple<int, int>> strictness = new HashSet<Tuple<int, int>> {
new Tuple<int, int>(6, 0),
new Tuple<int, int>(7, 1),
new Tuple<int, int>(12, 2),

View File

@ -6,12 +6,11 @@ using System.Linq;
namespace NadekoBot.Classes.Trivia {
public class TriviaQuestionPool {
private static readonly TriviaQuestionPool _instance = new TriviaQuestionPool();
public static TriviaQuestionPool Instance => _instance;
public static TriviaQuestionPool Instance { get; } = new TriviaQuestionPool();
public List<TriviaQuestion> pool = new List<TriviaQuestion>();
public HashSet<TriviaQuestion> pool = new HashSet<TriviaQuestion>();
private Random _r { get; } = new Random();
private Random rng { get; } = new Random();
static TriviaQuestionPool() { }
@ -19,22 +18,21 @@ namespace NadekoBot.Classes.Trivia {
Reload();
}
public TriviaQuestion GetRandomQuestion(List<TriviaQuestion> exclude) {
public TriviaQuestion GetRandomQuestion(IEnumerable<TriviaQuestion> exclude) {
var list = pool.Except(exclude).ToList();
var rand = _r.Next(0, list.Count);
var rand = rng.Next(0, list.Count);
return list[rand];
}
internal void Reload() {
JArray arr = JArray.Parse(File.ReadAllText("data/questions.txt"));
var arr = JArray.Parse(File.ReadAllText("data/questions.txt"));
foreach (var item in arr) {
TriviaQuestion tq;
tq = new TriviaQuestion(item["Question"].ToString(), item["Answer"].ToString(), item["Category"]?.ToString());
var tq = new TriviaQuestion(item["Question"].ToString(), item["Answer"].ToString(), item["Category"]?.ToString());
pool.Add(tq);
}
var r = new Random();
pool = pool.OrderBy(x => r.Next()).ToList();
pool = new HashSet<TriviaQuestion>(pool.OrderBy(x => r.Next()));
}
}
}

View File

@ -8,7 +8,7 @@ using System.Linq;
using System.Threading;
namespace NadekoBot.Commands {
internal class ClashOfClans : DiscordCommand {
internal class ClashOfClans : IDiscordCommand {
private const string prefix = ",";
public static ConcurrentDictionary<ulong, List<ClashWar>> ClashWars { get; } = new ConcurrentDictionary<ulong, List<ClashWar>>();
@ -19,7 +19,7 @@ namespace NadekoBot.Commands {
}
public override Func<CommandEventArgs, Task> DoFunc() => async e => {
public Func<CommandEventArgs, Task> DoFunc() => async e => {
if (!e.User.ServerPermissions.ManageChannels)
return;
List<ClashWar> wars;
@ -50,7 +50,7 @@ namespace NadekoBot.Commands {
//war with the index X started.
};
public override void Init(CommandGroupBuilder cgb) {
public void Init(CommandGroupBuilder cgb) {
cgb.CreateCommand(prefix + "createwar")
.Alias(prefix + "cw")
.Description($"Creates a new war by specifying a size (>10 and multiple of 5) and enemy clan name.\n**Usage**:{prefix}cw 15 The Enemy Clan")

View File

@ -5,14 +5,13 @@ using Discord.Commands;
namespace NadekoBot.Commands
{
internal class CopyCommand : DiscordCommand
internal class CopyCommand : IDiscordCommand
{
private List<ulong> CopiedUsers;
private readonly HashSet<ulong> CopiedUsers = new HashSet<ulong>();
public CopyCommand()
{
CopiedUsers = new List<ulong>();
client.MessageReceived += Client_MessageReceived;
NadekoBot.Client.MessageReceived += Client_MessageReceived;
}
private async void Client_MessageReceived(object sender, Discord.MessageEventArgs e)
@ -27,16 +26,15 @@ namespace NadekoBot.Commands
catch { }
}
public override Func<CommandEventArgs, Task> DoFunc() => async e =>
public Func<CommandEventArgs, Task> DoFunc() => async e =>
{
if (CopiedUsers.Contains(e.User.Id)) return;
CopiedUsers.Add(e.User.Id);
await e.Channel.SendMessage(" I'll start copying you now.");
return;
};
public override void Init(CommandGroupBuilder cgb)
public void Init(CommandGroupBuilder cgb)
{
cgb.CreateCommand("copyme")
.Alias("cm")
@ -55,7 +53,6 @@ namespace NadekoBot.Commands
CopiedUsers.Remove(e.User.Id);
await e.Channel.SendMessage(" I wont copy anymore.");
return;
};
}
}

View File

@ -8,15 +8,14 @@ using Discord.Commands;
using NadekoBot.Extensions;
namespace NadekoBot.Commands {
internal class DiceRollCommand : DiscordCommand {
public DiceRollCommand() { }
internal class DiceRollCommand : IDiscordCommand {
public override Func<CommandEventArgs, Task> DoFunc() {
Random r = new Random();
public Func<CommandEventArgs, Task> DoFunc() {
var r = new Random();
return async e => {
if (e.Args[0] == "") {
int num1 = r.Next(0, 10);
int num2 = r.Next(0, 10);
var num1 = r.Next(0, 10);
var num2 = r.Next(0, 10);
Image[] images;
@ -26,26 +25,25 @@ namespace NadekoBot.Commands {
images = new Image[2] { GetDice(num1), GetDice(num2) };
}
Bitmap bitmap = images.Merge();
var bitmap = images.Merge();
await e.Channel.SendFile("dice.png", bitmap.ToStream(ImageFormat.Png));
return;
} else {
try {
int num = int.Parse(e.Args[0]);
var num = int.Parse(e.Args[0]);
if (num < 1) num = 1;
if (num > 30) {
await e.Channel.SendMessage("You can roll up to 30 dies at a time.");
num = 30;
}
List<Image> dices = new List<Image>(num);
List<int> values = new List<int>(num);
for (int i = 0; i < num; i++) {
int randomNumber = r.Next(1, 7);
int toInsert = dices.Count;
var dices = new List<Image>(num);
var values = new List<int>(num);
for (var i = 0; i < num; i++) {
var randomNumber = r.Next(1, 7);
var toInsert = dices.Count;
if (randomNumber == 6 || dices.Count == 0)
toInsert = 0;
else if (randomNumber != 1)
for (int j = 0; j < dices.Count; j++) {
for (var j = 0; j < dices.Count; j++) {
if (values[j] < randomNumber) {
toInsert = j;
break;
@ -55,12 +53,11 @@ namespace NadekoBot.Commands {
values.Insert(toInsert, randomNumber);
}
Bitmap bitmap = dices.Merge();
var bitmap = dices.Merge();
await e.Channel.SendMessage(values.Count + " Dies rolled. Total: **" + values.Sum() + "** Average: **" + (values.Sum() / (1.0f * values.Count)).ToString("N2") + "**");
await e.Channel.SendFile("dices.png", bitmap.ToStream(ImageFormat.Png));
} catch {
await e.Channel.SendMessage("Please enter a number of dices to roll.");
return;
}
}
};
@ -68,7 +65,7 @@ namespace NadekoBot.Commands {
private Image GetDice(int num) => Properties.Resources.ResourceManager.GetObject("_" + num) as Image;
public override void Init(CommandGroupBuilder cgb) {
public void Init(CommandGroupBuilder cgb) {
cgb.CreateCommand("$roll")
.Description("Rolls 2 dice from 0-10. If you supply a number [x] it rolls up to 30 normal dice.\n**Usage**: $roll [x]")
.Parameter("num", ParameterType.Optional)
@ -86,7 +83,7 @@ namespace NadekoBot.Commands {
if (e.GetArg("range").Contains("-")) {
var arr = e.GetArg("range").Split('-')
.Take(2)
.Select(x => int.Parse(x))
.Select(int.Parse)
.ToArray();
if (arr[0] > arr[1])
throw new ArgumentException("First argument should be bigger than the second one.");

View File

@ -7,14 +7,14 @@ using Discord.Commands;
using NadekoBot.Extensions;
namespace NadekoBot.Commands {
internal class DrawCommand : DiscordCommand {
internal class DrawCommand : IDiscordCommand {
private static ConcurrentDictionary<Discord.Server, Cards> AllDecks = new ConcurrentDictionary<Discord.Server, Cards>();
public DrawCommand() {
}
public override Func<CommandEventArgs, Task> DoFunc() => async (e) => {
public Func<CommandEventArgs, Task> DoFunc() => async (e) => {
if (!AllDecks.ContainsKey(e.Server)) {
await e.Channel.SendMessage("Shuffling cards...");
AllDecks.TryAdd(e.Server, new Cards());
@ -53,7 +53,7 @@ namespace NadekoBot.Commands {
}
};
public override void Init(CommandGroupBuilder cgb) {
public void Init(CommandGroupBuilder cgb) {
cgb.CreateCommand("$draw")
.Description("Draws a card from the deck.If you supply number [x], she draws up to 5 cards from the deck.\n**Usage**: $draw [x]")
.Parameter("count", ParameterType.Optional)

View File

@ -5,17 +5,14 @@ using Discord.Commands;
using NadekoBot.Extensions;
namespace NadekoBot.Commands {
internal class FlipCoinCommand : DiscordCommand {
internal class FlipCoinCommand : IDiscordCommand {
private Random _r;
public FlipCoinCommand() {
_r = new Random();
}
private readonly Random rng = new Random();
public override Func<CommandEventArgs, Task> DoFunc() => async e => {
public Func<CommandEventArgs, Task> DoFunc() => async e => {
if (e.GetArg("count") == "") {
if (_r.Next(0, 2) == 1)
if (rng.Next(0, 2) == 1)
await e.Channel.SendFile("heads.png", Properties.Resources.heads.ToStream(System.Drawing.Imaging.ImageFormat.Png));
else
await e.Channel.SendFile("tails.png", Properties.Resources.tails.ToStream(System.Drawing.Imaging.ImageFormat.Png));
@ -24,22 +21,20 @@ namespace NadekoBot.Commands {
if (int.TryParse(e.GetArg("count"), out result)) {
if (result > 10)
result = 10;
Image[] imgs = new Image[result];
for (int i = 0; i < result; i++) {
imgs[i] = _r.Next(0, 2) == 0 ?
var imgs = new Image[result];
for (var i = 0; i < result; i++) {
imgs[i] = rng.Next(0, 2) == 0 ?
Properties.Resources.tails :
Properties.Resources.heads;
}
await e.Channel.SendFile($"{result} coins.png", imgs.Merge().ToStream(System.Drawing.Imaging.ImageFormat.Png));
return;
}
await e.Channel.SendMessage("Invalid number");
}
};
public override void Init(CommandGroupBuilder cgb) {
public void Init(CommandGroupBuilder cgb) {
cgb.CreateCommand("$flip")
.Description("Flips coin(s) - heads or tails, and shows an image.\n**Usage**: `$flip` or `$flip 3`")
.Parameter("count", ParameterType.Optional)

View File

@ -6,8 +6,8 @@ using Discord.Commands;
using NadekoBot.Extensions;
namespace NadekoBot.Commands {
internal class HelpCommand : DiscordCommand {
public override Func<CommandEventArgs, Task> DoFunc() => async e => {
internal class HelpCommand : IDiscordCommand {
public Func<CommandEventArgs, Task> DoFunc() => async e => {
#region OldHelp
/*
string helpstr = "**COMMANDS DO NOT WORK IN PERSONAL MESSAGES**\nOfficial repo: **github.com/Kwoth/NadekoBot/**";
@ -60,7 +60,7 @@ Version: `{NadekoStats.Instance.BotVersion}`";
string lastCategory = "";
foreach (var com in client.GetService<CommandService>().AllCommands) {
foreach (var com in NadekoBot.Client.GetService<CommandService>().AllCommands) {
if (com.Category != lastCategory) {
helpstr += "\n### " + com.Category + " \n";
helpstr += "Command and aliases | Description | Usage\n";
@ -76,10 +76,9 @@ Version: `{NadekoStats.Instance.BotVersion}`";
#else
File.WriteAllText("commandlist.md", helpstr);
#endif
return;
};
public override void Init(CommandGroupBuilder cgb) {
public void Init(CommandGroupBuilder cgb) {
cgb.CreateCommand("-h")
.Alias(new string[] { "-help", NadekoBot.BotMention + " help", NadekoBot.BotMention + " h", "~h" })
.Description("Either shows a help for a single command, or PMs you help link if no arguments are specified.\n**Usage**: '-h !m q' or just '-h' ")

View File

@ -0,0 +1,19 @@
using System;
using System.Threading.Tasks;
using Discord;
using Discord.Commands;
namespace NadekoBot.Commands
{
/// <summary>
/// Base DiscordCommand Class.
/// Inherit this class to create your own command.
/// </summary>
public interface IDiscordCommand
{
/// <summary>
/// Initializes the CommandBuilder with values using CommandGroupBuilder
/// </summary>
void Init(CommandGroupBuilder cgb);
}
}

View File

@ -10,7 +10,7 @@ using NadekoBot.Extensions;
using Newtonsoft.Json.Linq;
namespace NadekoBot.Commands {
internal class LoLCommands : DiscordCommand {
internal class LoLCommands : IDiscordCommand {
private class CachedChampion {
public System.IO.Stream ImageStream { get; set; }
@ -43,7 +43,7 @@ namespace NadekoBot.Commands {
"If you consider playing teemo, do it. If you consider teemo, you deserve him.",
"Doesn't matter what you ban really. Enemy will ban your main and you will lose." };
public override Func<CommandEventArgs, Task> DoFunc() {
public Func<CommandEventArgs, Task> DoFunc() {
throw new NotImplementedException();
}
@ -55,7 +55,7 @@ namespace NadekoBot.Commands {
public float StatScore { get; set; }
}
public override void Init(CommandGroupBuilder cgb) {
public void Init(CommandGroupBuilder cgb) {
cgb.CreateCommand("~lolchamp")
.Description("Shows League Of Legends champion statistics. If there are spaces/apostrophes or in the name - omit them. Optional second parameter is a role.\n**Usage**:~lolchamp Riven or ~lolchamp Annie sup")
.Parameter("champ", ParameterType.Required)

View File

@ -5,7 +5,7 @@ using Discord.Commands;
using Discord;
namespace NadekoBot.Commands {
internal class LogCommand : DiscordCommand {
internal class LogCommand : IDiscordCommand {
public LogCommand() {
NadekoBot.Client.MessageReceived += MsgRecivd;
@ -14,12 +14,12 @@ namespace NadekoBot.Commands {
NadekoBot.Client.UserUpdated += UsrUpdtd;
}
private ConcurrentDictionary<Server, Channel> logs = new ConcurrentDictionary<Server, Channel>();
private ConcurrentDictionary<Server, Channel> loggingPresences = new ConcurrentDictionary<Server, Channel>();
private readonly ConcurrentDictionary<Server, Channel> logs = new ConcurrentDictionary<Server, Channel>();
private readonly ConcurrentDictionary<Server, Channel> loggingPresences = new ConcurrentDictionary<Server, Channel>();
//
private ConcurrentDictionary<Channel, Channel> voiceChannelLog = new ConcurrentDictionary<Channel, Channel>();
private readonly ConcurrentDictionary<Channel, Channel> voiceChannelLog = new ConcurrentDictionary<Channel, Channel>();
public override Func<CommandEventArgs, Task> DoFunc() => async e => {
public Func<CommandEventArgs, Task> DoFunc() => async e => {
if (!NadekoBot.IsOwner(e.User.Id) ||
!e.User.ServerPermissions.ManageServer)
return;
@ -107,7 +107,7 @@ namespace NadekoBot.Commands {
}
catch { }
}
public override void Init(CommandGroupBuilder cgb) {
public void Init(CommandGroupBuilder cgb) {
cgb.CreateCommand(".logserver")
.Description("Toggles logging in this channel. Logs every message sent/deleted/edited on the server. BOT OWNER ONLY. SERVER OWNER ONLY.")
.Do(DoFunc());

View File

@ -8,9 +8,9 @@ using System.Timers;
using NadekoBot.Modules;
namespace NadekoBot.Commands {
internal class PlayingRotate : DiscordCommand {
internal class PlayingRotate : IDiscordCommand {
private static List<string> rotatingStatuses = new List<string>();
private static readonly List<string> rotatingStatuses = new List<string>();
private static readonly Timer timer = new Timer(12000);
public static Dictionary<string, Func<string>> PlayingPlaceholders { get; } =
@ -60,7 +60,7 @@ namespace NadekoBot.Commands {
};
}
public override Func<CommandEventArgs, Task> DoFunc() => async e => {
public Func<CommandEventArgs, Task> DoFunc() => async e => {
if (timer.Enabled)
timer.Stop();
else
@ -68,7 +68,7 @@ namespace NadekoBot.Commands {
await e.Channel.SendMessage($"❗`Rotating playing status has been {(timer.Enabled ? "enabled" : "disabled")}.`");
};
public override void Init(CommandGroupBuilder cgb) {
public void Init(CommandGroupBuilder cgb) {
cgb.CreateCommand(".rotateplaying")
.Alias(".ropl")
.Description("Toggles rotation of playing status of the dynamic strings you specified earlier.")

View File

@ -8,15 +8,15 @@ using Discord;
using Discord.Commands;
namespace NadekoBot.Commands {
internal class PollCommand : DiscordCommand {
internal class PollCommand : IDiscordCommand {
public static ConcurrentDictionary<Server, Poll> ActivePolls = new ConcurrentDictionary<Server, Poll>();
public override Func<CommandEventArgs, Task> DoFunc() {
public Func<CommandEventArgs, Task> DoFunc() {
throw new NotImplementedException();
}
public override void Init(CommandGroupBuilder cgb) {
public void Init(CommandGroupBuilder cgb) {
cgb.CreateCommand(">poll")
.Description("Creates a poll, only person who has manage server permission can do it.\n**Usage**: >poll Question?;Answer1;Answ 2;A_3")
.Parameter("allargs", ParameterType.Unparsed)

View File

@ -4,7 +4,7 @@ using Discord.Commands;
using NadekoBot.Extensions;
namespace NadekoBot.Commands {
internal class RequestsCommand : DiscordCommand {
internal class RequestsCommand : IDiscordCommand {
public void SaveRequest(CommandEventArgs e, string text) {
Classes.DbHandler.Instance.InsertData(new Classes._DataModels.Request {
RequestText = text,
@ -37,11 +37,7 @@ namespace NadekoBot.Commands {
public Classes._DataModels.Request ResolveRequest(int requestNumber) =>
Classes.DbHandler.Instance.Delete<Classes._DataModels.Request>(requestNumber);
public override Func<CommandEventArgs, Task> DoFunc() {
throw new NotImplementedException();
}
public override void Init(CommandGroupBuilder cgb) {
public void Init(CommandGroupBuilder cgb) {
cgb.CreateCommand("req")
.Alias("request")
@ -95,7 +91,7 @@ namespace NadekoBot.Commands {
var sc = ResolveRequest(int.Parse(e.Args[0]));
if (sc != null) {
await e.Channel.SendMessage(e.User.Mention + " Request resolved, notice sent.");
await client.GetServer((ulong)sc.ServerId).GetUser((ulong)sc.UserId).Send("**This request of yours has been resolved:**\n" + sc.RequestText);
await NadekoBot.Client.GetServer((ulong)sc.ServerId).GetUser((ulong)sc.UserId).Send("**This request of yours has been resolved:**\n" + sc.RequestText);
} else {
await e.Channel.SendMessage("No request on that number.");
}

View File

@ -21,7 +21,7 @@ public class AsyncLazy<T> : Lazy<Task<T>>
*/
namespace NadekoBot.Commands {
internal class ServerGreetCommand : DiscordCommand {
internal class ServerGreetCommand : IDiscordCommand {
public static ConcurrentDictionary<ulong, AnnounceControls> AnnouncementsDictionary;
@ -33,11 +33,11 @@ namespace NadekoBot.Commands {
NadekoBot.Client.UserJoined += UserJoined;
NadekoBot.Client.UserLeft += UserLeft;
List<Classes._DataModels.Announcement> data = Classes.DbHandler.Instance.GetAllRows<Classes._DataModels.Announcement>();
var data = Classes.DbHandler.Instance.GetAllRows<Classes._DataModels.Announcement>();
if (data.Any())
foreach (var obj in data)
AnnouncementsDictionary.TryAdd((ulong)obj.ServerId, new AnnounceControls(obj));
if (!data.Any()) return;
foreach (var obj in data)
AnnouncementsDictionary.TryAdd((ulong)obj.ServerId, new AnnounceControls(obj));
}
private async void UserLeft(object sender, UserEventArgs e) {
@ -172,11 +172,11 @@ namespace NadekoBot.Commands {
}
}
public override Func<CommandEventArgs, Task> DoFunc() {
public Func<CommandEventArgs, Task> DoFunc() {
throw new NotImplementedException();
}
public override void Init(CommandGroupBuilder cgb) {
public void Init(CommandGroupBuilder cgb) {
cgb.CreateCommand(".greet")
.Description("Enables or Disables anouncements on the current channel when someone joins the server.")

View File

@ -21,12 +21,12 @@ namespace NadekoBot.Commands {
}
public class TypingGame {
public static float WORD_VALUE { get; } = 4.5f;
private Channel channel;
public string currentSentence;
public const float WORD_VALUE = 4.5f;
private readonly Channel channel;
public string CurrentSentence;
public bool IsActive;
private Stopwatch sw;
private List<ulong> finishedUserIds;
private readonly Stopwatch sw;
private readonly List<ulong> finishedUserIds;
public TypingGame(Channel channel) {
this.channel = channel;
@ -49,32 +49,33 @@ namespace NadekoBot.Commands {
}
internal async Task Start() {
if (IsActive) return; // can't start running game
IsActive = true;
currentSentence = SentencesProvider.GetRandomSentence();
int i = (int)(currentSentence.Length / WORD_VALUE * 1.7f);
await channel.SendMessage($":clock2: Next contest will last for {i} seconds. Type the bolded text as fast as you can.");
while (true) {
if (IsActive) return; // can't start running game
IsActive = true;
CurrentSentence = SentencesProvider.GetRandomSentence();
var i = (int) (CurrentSentence.Length/WORD_VALUE*1.7f);
await channel.SendMessage($":clock2: Next contest will last for {i} seconds. Type the bolded text as fast as you can.");
var msg = await channel.SendMessage("Starting new typing contest in **3**...");
await Task.Delay(1000);
await msg.Edit("Starting new typing contest in **2**...");
await Task.Delay(1000);
await msg.Edit("Starting new typing contest in **1**...");
await Task.Delay(1000);
await msg.Edit($":book:**{currentSentence.Replace(" ", " \x200B")}**:book:");
sw.Start();
HandleAnswers();
while (i > 0) {
var msg = await channel.SendMessage("Starting new typing contest in **3**...");
await Task.Delay(1000);
i--;
if (!IsActive)
return;
}
await msg.Edit("Starting new typing contest in **2**...");
await Task.Delay(1000);
await msg.Edit("Starting new typing contest in **1**...");
await Task.Delay(1000);
await msg.Edit($":book:**{CurrentSentence.Replace(" ", " \x200B")}**:book:");
sw.Start();
HandleAnswers();
await Stop();
await Start();
while (i > 0) {
await Task.Delay(1000);
i--;
if (!IsActive)
return;
}
await Stop();
}
}
private void HandleAnswers() {
@ -87,13 +88,13 @@ namespace NadekoBot.Commands {
var guess = e.Message.RawText;
var distance = currentSentence.LevenshteinDistance(guess);
var distance = CurrentSentence.LevenshteinDistance(guess);
var decision = Judge(distance, guess.Length);
if (decision && !finishedUserIds.Contains(e.User.Id)) {
finishedUserIds.Add(e.User.Id);
await channel.Send($"{e.User.Mention} finished in **{sw.Elapsed.Seconds}** seconds with { distance } errors, **{ currentSentence.Length / TypingGame.WORD_VALUE / sw.Elapsed.Seconds * 60 }** WPM!");
await channel.Send($"{e.User.Mention} finished in **{sw.Elapsed.Seconds}** seconds with { distance } errors, **{ CurrentSentence.Length / TypingGame.WORD_VALUE / sw.Elapsed.Seconds * 60 }** WPM!");
if (finishedUserIds.Count % 2 == 0) {
await e.Channel.SendMessage($":exclamation: `A lot of people finished, here is the text for those still typing:`\n\n:book:**{currentSentence}**:book:");
await e.Channel.SendMessage($":exclamation: `A lot of people finished, here is the text for those still typing:`\n\n:book:**{CurrentSentence}**:book:");
}
}
@ -105,7 +106,7 @@ namespace NadekoBot.Commands {
}
internal class SpeedTyping : DiscordCommand {
internal class SpeedTyping : IDiscordCommand {
private static Dictionary<ulong, TypingGame> runningContests;
@ -113,7 +114,7 @@ namespace NadekoBot.Commands {
runningContests = new Dictionary<ulong, TypingGame>();
}
public override Func<CommandEventArgs, Task> DoFunc() =>
public Func<CommandEventArgs, Task> DoFunc() =>
async e => {
if (runningContests.ContainsKey(e.User.Server.Id) && runningContests[e.User.Server.Id].IsActive) {
await e.Channel.SendMessage($"Contest already running in { runningContests[e.User.Server.Id].Channell.Mention } channel.");
@ -138,7 +139,7 @@ namespace NadekoBot.Commands {
await e.Channel.SendMessage("No contest to stop on this channel.");
};
public override void Init(CommandGroupBuilder cgb) {
public void Init(CommandGroupBuilder cgb) {
cgb.CreateCommand("typestart")
.Description("Starts a typing contest.")
.Do(DoFunc());

View File

@ -6,10 +6,10 @@ using Discord;
using TriviaGame = NadekoBot.Classes.Trivia.TriviaGame;
namespace NadekoBot.Commands {
internal class Trivia : DiscordCommand {
internal class Trivia : IDiscordCommand {
public static ConcurrentDictionary<Server, TriviaGame> runningTrivias = new ConcurrentDictionary<Server, TriviaGame>();
public override Func<CommandEventArgs, Task> DoFunc() => async e => {
public Func<CommandEventArgs, Task> DoFunc() => async e => {
TriviaGame trivia;
if (!runningTrivias.TryGetValue(e.Server, out trivia)) {
var triviaGame = new TriviaGame(e);
@ -21,7 +21,7 @@ namespace NadekoBot.Commands {
await e.Channel.SendMessage("Trivia game is already running on this server.\n" + trivia.CurrentQuestion);
};
public override void Init(CommandGroupBuilder cgb) {
public void Init(CommandGroupBuilder cgb) {
cgb.CreateCommand("t")
.Description("Starts a game of trivia.")
.Alias("-t")

View File

@ -6,17 +6,12 @@ using System.Collections.Concurrent;
using Discord;
namespace NadekoBot.Commands {
internal class VoiceNotificationCommand : DiscordCommand {
public VoiceNotificationCommand() {
//NadekoBot.client.
}
internal class VoiceNotificationCommand : IDiscordCommand {
//voicechannel/text channel
private ConcurrentDictionary<Channel, Channel> subscribers = new ConcurrentDictionary<Channel, Channel>();
private readonly ConcurrentDictionary<Channel, Channel> subscribers = new ConcurrentDictionary<Channel, Channel>();
public override Func<CommandEventArgs, Task> DoFunc() => async e => {
public Func<CommandEventArgs, Task> DoFunc() => async e => {
var arg = e.GetArg("voice_name");
if (string.IsNullOrWhiteSpace("voice_name"))
return;
@ -32,7 +27,7 @@ namespace NadekoBot.Commands {
}
};
public override void Init(CommandGroupBuilder cgb) {
public void Init(CommandGroupBuilder cgb) {
/*
cgb.CreateCommand(".voicenotif")
.Description("Enables notifications on who joined/left the voice channel.\n**Usage**:.voicenotif Karaoke club")

View File

@ -4,10 +4,7 @@ using NadekoBot.Commands;
namespace NadekoBot.Modules {
internal abstract class DiscordModule : IModule {
protected List<DiscordCommand> commands = new List<DiscordCommand>();
protected DiscordModule() {
}
protected readonly HashSet<IDiscordCommand> commands = new HashSet<IDiscordCommand>();
public abstract void Install(ModuleManager manager);
}

View File

@ -4,6 +4,8 @@ using Discord.Modules;
using NadekoBot.Commands;
using Newtonsoft.Json.Linq;
using System.IO;
using NadekoBot.Extensions;
//🃏
//🏁
namespace NadekoBot.Modules {

View File

@ -2,6 +2,7 @@
using Discord.Modules;
using Discord.Commands;
using NadekoBot.Commands;
using NadekoBot.Extensions;
namespace NadekoBot.Modules {
internal class Help : DiscordModule {

View File

@ -4,6 +4,7 @@ using Discord.Commands;
using NadekoBot.Classes;
using PermsHandler = NadekoBot.Classes.Permissions.PermissionsHandler;
using System.Linq;
using NadekoBot.Extensions;
namespace NadekoBot.Modules {
internal class PermissionModule : DiscordModule {
@ -14,7 +15,6 @@ namespace NadekoBot.Modules {
}
//todo word filtering/invite bans (?:discord(?:\.gg|app\.com\/invite)\/(?<id>([\w]{16}|(?:[\w]+-?){3})))
public override void Install(ModuleManager manager) {
var client = NadekoBot.Client;
manager.CreateCommands("", cgb => {
cgb.AddCheck(Classes.Permissions.PermissionChecker.Instance);
@ -75,7 +75,7 @@ namespace NadekoBot.Modules {
var role = e.Server.EveryoneRole;
if (!string.IsNullOrWhiteSpace(arg))
try {
role = PermissionHelper.ValidateRole(e.Server, e.GetArg("role"));
role = PermissionHelper.ValidateRole(e.Server, arg);
}
catch (Exception ex) {
await e.Channel.SendMessage("💢 Error: " + ex.Message);
@ -98,7 +98,7 @@ namespace NadekoBot.Modules {
var channel = e.Channel;
if (!string.IsNullOrWhiteSpace(arg))
try {
channel = PermissionHelper.ValidateChannel(e.Server, e.GetArg("channel"));
channel = PermissionHelper.ValidateChannel(e.Server, arg);
}
catch (Exception ex) {
await e.Channel.SendMessage("💢 Error: " + ex.Message);
@ -116,7 +116,6 @@ namespace NadekoBot.Modules {
.Description("Shows banned permissions for a certain user. No argument means for yourself.\n**Usage**: ;up Kwoth")
.Parameter("user", ParameterType.Unparsed)
.Do(async e => {
var arg = e.GetArg("user");
var user = e.User;
if (!string.IsNullOrWhiteSpace(e.GetArg("user")))
try {

View File

@ -127,8 +127,8 @@ namespace NadekoBot.Modules {
var headers = new Dictionary<string, string> { { "X-Mashape-Key", NadekoBot.Creds.MashapeKey } };
var res = await SearchHelper.GetResponseStringAsync($"https://omgvamp-hearthstone-v1.p.mashape.com/cards/search/{Uri.EscapeUriString(arg)}", headers);
try {
var items = JArray.Parse(res) as JArray;
var images = new List<System.Drawing.Image>();
var items = JArray.Parse(res);
var images = new List<Image>();
if (items == null)
throw new KeyNotFoundException("Cannot find a card by that name");
var cnt = 0;

View File

@ -9,6 +9,7 @@ using Discord.Audio;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Discord.Commands.Permissions.Userlist;
using NadekoBot.Classes.JSONModels;
using NadekoBot.Commands;

View File

@ -155,7 +155,7 @@
<Compile Include="Classes\Extensions.cs" />
<Compile Include="Commands\CopyCommand.cs" />
<Compile Include="Commands\DiceRollCommand.cs" />
<Compile Include="Commands\DiscordCommand.cs" />
<Compile Include="Commands\IDiscordCommand.cs" />
<Compile Include="Commands\DrawCommand.cs" />
<Compile Include="Commands\FlipCoinCommand.cs" />
<Compile Include="Commands\HelpCommand.cs" />