Fixed memory leak, trivia hints are after 6 sec, etc

This commit is contained in:
Master Kwoth 2016-01-30 05:24:32 +01:00
parent 1316c83bd4
commit 00f09b66bd
11 changed files with 178 additions and 209 deletions

View File

@ -5,27 +5,31 @@ using System.Threading.Tasks;
using System.Security.Cryptography; using System.Security.Cryptography;
using Discord.Commands; using Discord.Commands;
using Discord; using Discord;
using Discord.Legacy;
using NadekoBot.Modules; using NadekoBot.Modules;
using System.IO; using System.IO;
using System.Drawing; using System.Drawing;
namespace NadekoBot.Extensions namespace NadekoBot.Extensions {
{
public static class Extensions public static class Extensions
{ {
public static string Scramble(this string word) { public static string Scramble(this string word) {
var letters = word.ToArray(); var letters = word.ToArray();
for (int i = 0; i < letters.Length; i++) int count = 0;
{ for (int i = 0; i < letters.Length; i++) {
if (i % 3 == 0) if (letters[i] == ' ')
{ continue;
count++;
if (count <= letters.Length / 5)
continue;
if (count % 3 == 0)
continue; continue;
}
if (letters[i] != ' ') if (letters[i] != ' ')
letters[i] = '_'; letters[i] = '_';
} }
return "`"+string.Join(" ", letters)+"`"; return "`"+string.Join(" ", letters)+"`";
} }

View File

@ -15,13 +15,15 @@ namespace NadekoBot.Classes.Music {
public StreamRequest CurrentSong; public StreamRequest CurrentSong;
public bool IsPaused { get; internal set; } = false; public bool IsPaused { get; internal set; } = false;
public bool Stopped { get; private set; }
public IAudioClient VoiceClient; public IAudioClient VoiceClient;
private readonly object _voiceLock = new object(); private readonly object _voiceLock = new object();
public MusicControls() { public MusicControls() {
Task.Run(async () => { Task.Run(async () => {
while (true) { while (!Stopped) {
try { try {
lock (_voiceLock) { lock (_voiceLock) {
if (CurrentSong == null) { if (CurrentSong == null) {
@ -36,7 +38,7 @@ namespace NadekoBot.Classes.Music {
} catch (Exception e) { } catch (Exception e) {
Console.WriteLine("Bug in music task run. " + e); Console.WriteLine("Bug in music task run. " + e);
} }
await Task.Delay(200); await Task.Delay(500);
} }
}); });
} }
@ -52,7 +54,11 @@ namespace NadekoBot.Classes.Music {
if (SongQueue.Count != 0) { if (SongQueue.Count != 0) {
CurrentSong = SongQueue[0]; CurrentSong = SongQueue[0];
SongQueue.RemoveAt(0); SongQueue.RemoveAt(0);
} else return; } else {
VoiceClient?.Disconnect();
VoiceClient = null;
return;
}
} }
try { try {
@ -60,32 +66,35 @@ namespace NadekoBot.Classes.Music {
} catch (Exception ex) { } catch (Exception ex) {
Console.WriteLine($"Starting failed: {ex}"); Console.WriteLine($"Starting failed: {ex}");
CurrentSong?.Stop(); CurrentSong?.Stop();
CurrentSong = null;
} }
} }
internal void Stop() { internal void Stop() {
lock (_voiceLock) { lock (_voiceLock) {
Stopped = true;
foreach (var kvp in SongQueue) { foreach (var kvp in SongQueue) {
if(kvp != null) if(kvp != null)
kvp.Cancel(); kvp.Cancel();
} }
SongQueue?.Clear(); SongQueue.Clear();
LoadNextSong(); CurrentSong?.Stop();
CurrentSong = null;
VoiceClient?.Disconnect(); VoiceClient?.Disconnect();
VoiceClient = null; VoiceClient = null;
} }
} }
internal StreamRequest CreateStreamRequest(CommandEventArgs e, string query, Channel voiceChannel) { internal async Task<StreamRequest> CreateStreamRequest(CommandEventArgs e, string query, Channel voiceChannel) {
if (VoiceChannel == null) if (VoiceChannel == null)
throw new ArgumentNullException("Please join a voicechannel."); throw new ArgumentNullException("Please join a voicechannel.");
StreamRequest sr = null; StreamRequest sr = null;
if (VoiceClient == null) {
VoiceChannel = voiceChannel;
VoiceClient = await NadekoBot.client.Audio().Join(VoiceChannel);
}
sr = new StreamRequest(e, query, this);
lock (_voiceLock) { lock (_voiceLock) {
if (VoiceClient == null) {
VoiceClient = NadekoBot.client.Audio().Join(VoiceChannel).Result;
}
sr = new StreamRequest(e, query, this);
SongQueue.Add(sr); SongQueue.Add(sr);
} }
return sr; return sr;

View File

@ -6,13 +6,13 @@ using System.Threading.Tasks;
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using Discord.Audio; using Discord.Audio;
using YoutubeExtractor;
using NadekoBot.Modules; using NadekoBot.Modules;
using System.IO; using System.IO;
using System.Diagnostics; using System.Diagnostics;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using System.Threading; using System.Threading;
using Timer = System.Timers.Timer; using Timer = System.Timers.Timer;
using YoutubeExtractor;
namespace NadekoBot.Classes.Music { namespace NadekoBot.Classes.Music {
public enum StreamState { public enum StreamState {
@ -94,12 +94,12 @@ namespace NadekoBot.Classes.Music {
musicStreamer?.Stop(); musicStreamer?.Stop();
} }
internal Task Start() => internal async Task Start() {
Task.Run(async () => { Console.WriteLine("Start called.");
Console.WriteLine("Start called.");
int attemptsLeft = 4; int attemptsLeft = 4;
//wait for up to 4 seconds to resolve a link //wait for up to 4 seconds to resolve a link
try {
while (State == StreamState.Resolving) { while (State == StreamState.Resolving) {
await Task.Delay(1000); await Task.Delay(1000);
Console.WriteLine("Resolving..."); Console.WriteLine("Resolving...");
@ -107,13 +107,15 @@ namespace NadekoBot.Classes.Music {
throw new TimeoutException("Resolving timed out."); throw new TimeoutException("Resolving timed out.");
} }
} }
try { await musicStreamer.StartPlayback();
await musicStreamer.StartPlayback(); } catch (TimeoutException) {
} catch (Exception ex) { Console.WriteLine("Resolving timed out.");
Console.WriteLine("Error in start playback." + ex.Message); privateState = StreamState.Completed;
privateState = StreamState.Completed; } catch (Exception ex) {
} Console.WriteLine("Error in start playback." + ex.Message);
}); privateState = StreamState.Completed;
}
}
} }
public class MusicStreamer { public class MusicStreamer {
@ -127,7 +129,7 @@ namespace NadekoBot.Classes.Music {
StreamRequest parent; StreamRequest parent;
private readonly object _bufferLock = new object(); private readonly object _bufferLock = new object();
private CancellationTokenSource bufferCancelSource; private bool prebufferingComplete = false;
public MusicStreamer(StreamRequest parent, string directUrl, Channel channel) { public MusicStreamer(StreamRequest parent, string directUrl, Channel channel) {
this.parent = parent; this.parent = parent;
@ -136,7 +138,6 @@ namespace NadekoBot.Classes.Music {
this.Url = directUrl; this.Url = directUrl;
Console.WriteLine("Created new streamer"); Console.WriteLine("Created new streamer");
State = StreamState.Queued; State = StreamState.Queued;
bufferCancelSource = new CancellationTokenSource();
} }
public string Stats() => public string Stats() =>
@ -162,12 +163,9 @@ namespace NadekoBot.Classes.Music {
int attempt = 0; int attempt = 0;
while (true) { while (true) {
//wait for the read pos to catch up with write pos
while (buffer.writePos - buffer.readPos > 5.MB() && State != StreamState.Completed) { while (buffer.writePos - buffer.readPos > 5.MB() && State != StreamState.Completed) {
if (!bufferCancelSource.IsCancellationRequested) { prebufferingComplete = true;
Console.WriteLine("Canceling buffer token");
Task.Run(() => bufferCancelSource.Cancel());
}
await Task.Delay(500); await Task.Delay(500);
} }
@ -228,11 +226,18 @@ namespace NadekoBot.Classes.Music {
if (parent.OnBuffering != null) if (parent.OnBuffering != null)
parent.OnBuffering(); parent.OnBuffering();
BufferSong(); BufferSong();
try {
await Task.Delay(5000, bufferCancelSource.Token); // prebuffering wait stuff start
} catch (Exception) { int bufferAttempts = 0;
Console.WriteLine("Buffered enough in less than 5 seconds!"); int waitPerAttempt = 500;
while (!prebufferingComplete && bufferAttempts++ < 10) {
await Task.Delay(waitPerAttempt);
} }
if (prebufferingComplete) {
Console.WriteLine($"Prebuffering finished in {bufferAttempts*500}");
}
// prebuffering wait stuff end
//Task.Run(async () => { while (true) { Console.WriteLine($"Title: {parent.Title} State:{State}"); await Task.Delay(200); } }); //Task.Run(async () => { while (true) { Console.WriteLine($"Title: {parent.Title} State:{State}"); await Task.Delay(200); } });
if (parent.OnStarted != null) if (parent.OnStarted != null)
parent.OnStarted(); parent.OnStarted();
@ -265,8 +270,6 @@ namespace NadekoBot.Classes.Music {
} else } else
attempt = 0; attempt = 0;
if (State == StreamState.Completed) { if (State == StreamState.Completed) {
Console.WriteLine("Canceled"); Console.WriteLine("Canceled");
break; break;

View File

@ -12,10 +12,11 @@ using System.Timers;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using System.Collections; using System.Collections;
namespace NadekoBot //github.com/micmorris contributed quite a bit to making trivia better!
{ namespace NadekoBot {
public class Trivia : DiscordCommand public class Trivia : DiscordCommand {
{ public static float HINT_TIME_SECONDS = 6;
public static Dictionary<ulong, TriviaGame> runningTrivias; public static Dictionary<ulong, TriviaGame> runningTrivias;
public Trivia() : base() { public Trivia() : base() {
@ -28,47 +29,37 @@ namespace NadekoBot
var tg = new TriviaGame(e, NadekoBot.client); var tg = new TriviaGame(e, NadekoBot.client);
runningTrivias.Add(e.Server.Id, tg); runningTrivias.Add(e.Server.Id, tg);
return tg; return tg;
} }
public TriviaQuestion GetCurrentQuestion(ulong serverId) => runningTrivias[serverId].currentQuestion; public TriviaQuestion GetCurrentQuestion(ulong serverId) => runningTrivias[serverId].currentQuestion;
public override Func<CommandEventArgs, Task> DoFunc() => async e => public override Func<CommandEventArgs, Task> DoFunc() => async e => {
{
TriviaGame tg; TriviaGame tg;
if ((tg = StartNewGame(e)) != null) if ((tg = StartNewGame(e)) != null) {
{ await e.Send("**Trivia game started!**\nFirst player to get to 10 points wins! You have 30 seconds per question.\nUse command `tq` if game was started by accident.**");
await e.Send("**Trivia game started!**\nFirst player to get to 10 points wins! You have 30 seconds per question.\nUse command [tq] if game was started by accident.\nTyping [idfk] 15 seconds after the question has started will give you a hint."); } else
}
else
await e.Send("Trivia game is already running on this server. The question is:\n**" + GetCurrentQuestion(e.Server.Id).Question + "**"); await e.Send("Trivia game is already running on this server. The question is:\n**" + GetCurrentQuestion(e.Server.Id).Question + "**");
}; };
private Func<CommandEventArgs, Task> LbFunc() => async e => private Func<CommandEventArgs, Task> LbFunc() => async e => {
{ if (runningTrivias.ContainsKey(e.Server.Id)) {
if (runningTrivias.ContainsKey(e.Server.Id))
{
var lb = runningTrivias[e.User.Server.Id].GetLeaderboard(); var lb = runningTrivias[e.User.Server.Id].GetLeaderboard();
await e.Send(lb); await e.Send(lb);
} } else
else
await e.Send("Trivia game is not running on this server."); await e.Send("Trivia game is not running on this server.");
}; };
private Func<CommandEventArgs, Task> RepeatFunc() => async e => private Func<CommandEventArgs, Task> RepeatFunc() => async e => {
{ if (runningTrivias.ContainsKey(e.Server.Id)) {
if (runningTrivias.ContainsKey(e.Server.Id))
{
var lb = runningTrivias[e.User.Server.Id].GetLeaderboard(); var lb = runningTrivias[e.User.Server.Id].GetLeaderboard();
await e.Send(lb); await e.Send(lb);
} } else
else
await e.Send("Trivia game is not running on this server."); await e.Send("Trivia game is not running on this server.");
}; };
public override void Init(CommandGroupBuilder cgb) public override void Init(CommandGroupBuilder cgb) {
{
cgb.CreateCommand("t") cgb.CreateCommand("t")
.Description("Starts a game of trivia.") .Description("Starts a game of trivia.")
.Alias("-t") .Alias("-t")
@ -87,18 +78,14 @@ namespace NadekoBot
.Do(QuitFunc()); .Do(QuitFunc());
} }
private Func<CommandEventArgs, Task> QuitFunc() => async e => private Func<CommandEventArgs, Task> QuitFunc() => async e => {
{ if (runningTrivias.ContainsKey(e.Server.Id) && runningTrivias[e.Server.Id].ChannelId == e.Channel.Id) {
if (runningTrivias.ContainsKey(e.Server.Id) && runningTrivias[e.Server.Id].ChannelId == e.Channel.Id) await e.Send("Trivia will stop after this question.");
{
await e.Send("Trivia will stop after this question. Run [**@NadekoBot clr**] to remove this bot's messages from the channel.");
runningTrivias[e.Server.Id].StopGame(); runningTrivias[e.Server.Id].StopGame();
} } else await e.Send("No trivias are running on this channel.");
else await e.Send("No trivias are running on this channel.");
}; };
internal static void FinishGame(TriviaGame triviaGame) internal static void FinishGame(TriviaGame triviaGame) {
{
runningTrivias.Remove(runningTrivias.Where(kvp => kvp.Value == triviaGame).First().Key); runningTrivias.Remove(runningTrivias.Where(kvp => kvp.Value == triviaGame).First().Key);
} }
} }
@ -127,11 +114,13 @@ namespace NadekoBot
private Stopwatch stopwatch; private Stopwatch stopwatch;
private bool isQuit = false; private bool isQuit = false;
private System.Threading.CancellationTokenSource hintCancelSource;
public TriviaGame(CommandEventArgs starter, DiscordClient client) { public TriviaGame(CommandEventArgs starter, DiscordClient client) {
this.users = new Dictionary<ulong, int>(); this.users = new Dictionary<ulong, int>();
this.client = client; this.client = client;
this._serverId = starter.Server.Id; this._serverId = starter.Server.Id;
this._channellId= starter.Channel.Id; this._channellId = starter.Channel.Id;
oldQuestions = new List<string>(); oldQuestions = new List<string>();
client.MessageReceived += PotentialGuess; client.MessageReceived += PotentialGuess;
@ -149,12 +138,12 @@ namespace NadekoBot
stopwatch = new Stopwatch(); stopwatch = new Stopwatch();
timeout.Elapsed += (s, e) => { TimeUp(); }; timeout.Elapsed += (s, e) => { TimeUp(); };
hintCancelSource = new System.Threading.CancellationTokenSource();
TriviaQuestionsPool.Instance.Reload(); TriviaQuestionsPool.Instance.Reload();
LoadNextRound(); LoadNextRound();
} }
private async void PotentialGuess(object sender, MessageEventArgs e) private async void PotentialGuess(object sender, MessageEventArgs e) {
{
if (e.Server == null || e.Channel == null) return; if (e.Server == null || e.Channel == null) return;
if (e.Server.Id != _serverId || !active) if (e.Server.Id != _serverId || !active)
return; return;
@ -163,26 +152,24 @@ namespace NadekoBot
return; return;
if (e.Message.Text.ToLower().Equals("idfk")) { if (e.Message.Text.ToLower().Equals("idfk")) {
GetHint(e); GetHint(e.Channel);
return; return;
} }
if (IsAnswerCorrect(e.Message.Text.ToLower(), currentQuestion.Answer.ToLower())) if (IsAnswerCorrect(e.Message.Text.ToLower(), currentQuestion.Answer.ToLower())) {
{
active = false; //start pause between rounds active = false; //start pause between rounds
timeout.Enabled = false; timeout.Enabled = false;
stopwatch.Stop(); stopwatch.Stop();
if (!users.ContainsKey(e.User.Id)) if (!users.ContainsKey(e.User.Id))
users.Add(e.User.Id, 1); users.Add(e.User.Id, 1);
else else {
{
users[e.User.Id]++; users[e.User.Id]++;
} }
await e.Send( e.User.Mention + " Guessed it!\n The answer was: **" + currentQuestion.Answer + "**"); await e.Send(e.User.Mention + " Guessed it!\n The answer was: **" + currentQuestion.Answer + "**");
if (users[e.User.Id] >= 10) { if (users[e.User.Id] >= 10) {
await e.Send( " We have a winner! It's " + e.User.Mention+"\n"+GetLeaderboard()+"\n To start a new game type '@NadekoBot t'"); await e.Send(" We have a winner! It's " + e.User.Mention + "\n" + GetLeaderboard() + "\n To start a new game type '@NadekoBot t'");
FinishGame(); FinishGame();
return; return;
} }
@ -192,16 +179,13 @@ namespace NadekoBot
} }
} }
private bool IsAnswerCorrect(string guess, string answer) private bool IsAnswerCorrect(string guess, string answer) {
{ if (guess.Equals(answer)) {
if(guess.Equals(answer))
{
return true; return true;
} }
guess = CleanString(guess); guess = CleanString(guess);
answer = CleanString(answer); answer = CleanString(answer);
if (guess.Equals(answer)) if (guess.Equals(answer)) {
{
return true; return true;
} }
@ -209,12 +193,9 @@ namespace NadekoBot
return Judge(guess.Length, answer.Length, levDistance); return Judge(guess.Length, answer.Length, levDistance);
} }
private bool Judge(int guessLength, int answerLength, int levDistance) private bool Judge(int guessLength, int answerLength, int levDistance) {
{ foreach (Tuple<int, int> level in strictness) {
foreach(Tuple<int, int> level in strictness) if (guessLength <= level.Item1 || answerLength <= level.Item1) {
{
if(guessLength <= level.Item1 || answerLength <= level.Item1)
{
if (levDistance <= level.Item2) if (levDistance <= level.Item2)
return true; return true;
else else
@ -224,8 +205,7 @@ namespace NadekoBot
return false; return false;
} }
private string CleanString(string str) private string CleanString(string str) {
{
str = " " + str + " "; str = " " + str + " ";
str = Regex.Replace(str, "\\s+", " "); str = Regex.Replace(str, "\\s+", " ");
str = Regex.Replace(str, "[^\\w\\d\\s]", ""); str = Regex.Replace(str, "[^\\w\\d\\s]", "");
@ -239,30 +219,24 @@ namespace NadekoBot
return str; return str;
} }
public async void GetHint(MessageEventArgs e) { public async void GetHint(Channel ch) {
if (timeout != null && !isQuit && stopwatch.ElapsedMilliseconds > 10000) await ch.Send(currentQuestion.Answer.Scramble());
await e.Send( currentQuestion.Answer.Scramble());
else {
await e.Send( $"You have to wait {10-stopwatch.ElapsedMilliseconds/1000} more seconds in order to get a hint.");
}
} }
public void StopGame() { public void StopGame() {
isQuit = true; isQuit = true;
} }
private void LoadNextRound() private void LoadNextRound() {
{
Channel ch = client.GetChannel(_channellId); Channel ch = client.GetChannel(_channellId);
if(currentQuestion!=null)
if (currentQuestion != null)
oldQuestions.Add(currentQuestion.Question); oldQuestions.Add(currentQuestion.Question);
currentQuestion = TriviaQuestionsPool.Instance.GetRandomQuestion(oldQuestions); currentQuestion = TriviaQuestionsPool.Instance.GetRandomQuestion(oldQuestions);
if (currentQuestion == null || isQuit) if (currentQuestion == null || isQuit) {
{
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
ch.Send("Trivia bot stopping. :\\\n" + GetLeaderboard()); ch.Send("Trivia bot stopping. :\\\n" + GetLeaderboard());
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
@ -279,12 +253,16 @@ namespace NadekoBot
timeout.Enabled = true;//starting countdown of the next question timeout.Enabled = true;//starting countdown of the next question
stopwatch.Reset(); stopwatch.Reset();
stopwatch.Start(); stopwatch.Start();
try {
await Task.Delay((int)Trivia.HINT_TIME_SECONDS * 1000);
GetHint(ch);
} catch (Exception) { }
}; };
return; return;
} }
private async void TimeUp() { private async void TimeUp() {
await client.GetChannel(_channellId)?.Send("**Time's up.**\nCorrect answer was: **" + currentQuestion.Answer+"**\n\n*[tq quits trivia][tl shows leaderboard]["+NadekoBot.botMention+" clr clears my messages]*"); await client.GetChannel(_channellId)?.Send("**Time's up.**\nCorrect answer was: **" + currentQuestion.Answer + "**\n\n*[tq quits trivia][tl shows leaderboard][" + NadekoBot.botMention + " clr clears my messages]*");
LoadNextRound(); LoadNextRound();
} }
@ -302,29 +280,26 @@ namespace NadekoBot
public string GetLeaderboard() { public string GetLeaderboard() {
if (users.Count == 0) if (users.Count == 0)
return ""; return "";
string str = "**Leaderboard:**\n-----------\n"; string str = "**Leaderboard:**\n-----------\n";
if(users.Count>1) if (users.Count > 1)
users.OrderBy(kvp => kvp.Value); users.OrderBy(kvp => kvp.Value);
foreach (var KeyValuePair in users) foreach (var KeyValuePair in users) {
{ str += "**" + client.GetServer(_serverId).GetUser(KeyValuePair.Key).Name + "** has " + KeyValuePair.Value + (KeyValuePair.Value == 1 ? "point." : "points.") + Environment.NewLine;
str += "**" + client.GetServer(_serverId).GetUser(KeyValuePair.Key).Name + "** has " +KeyValuePair.Value + (KeyValuePair.Value == 1 ? "point." : "points.") + Environment.NewLine;
} }
return str; return str;
} }
} }
public class TriviaQuestion public class TriviaQuestion {
{
public string Category; public string Category;
public string Question; public string Question;
public string Answer; public string Answer;
public TriviaQuestion(string q, string a) public TriviaQuestion(string q, string a) {
{
this.Question = q; this.Question = q;
this.Answer = a; this.Answer = a;
} }
@ -338,8 +313,7 @@ namespace NadekoBot
public class TriviaQuestionsPool { public class TriviaQuestionsPool {
private static TriviaQuestionsPool instance = null; private static TriviaQuestionsPool instance = null;
public static TriviaQuestionsPool Instance public static TriviaQuestionsPool Instance {
{
get { get {
if (instance == null) if (instance == null)
instance = new TriviaQuestionsPool(); instance = new TriviaQuestionsPool();
@ -352,21 +326,18 @@ namespace NadekoBot
private Random _r; private Random _r;
public TriviaQuestionsPool() public TriviaQuestionsPool() {
{
Reload(); Reload();
} }
public TriviaQuestion GetRandomQuestion(List<string> exclude) { public TriviaQuestion GetRandomQuestion(List<string> exclude) {
if (pool.Count == 0) if (pool.Count == 0)
return null; return null;
TriviaQuestion tq = pool[_r.Next(0, pool.Count)]; TriviaQuestion tq = pool[_r.Next(0, pool.Count)];
if (exclude.Count > 0 && exclude.Count < pool.Count) if (exclude.Count > 0 && exclude.Count < pool.Count) {
{ while (exclude.Contains(tq.Question)) {
while (exclude.Contains(tq.Question))
{
tq = pool[_r.Next(0, pool.Count)]; tq = pool[_r.Next(0, pool.Count)];
} }
} }

View File

@ -10,7 +10,7 @@ namespace NadekoBot
{ {
public override Func<CommandEventArgs, Task> DoFunc() => async e => public override Func<CommandEventArgs, Task> DoFunc() => async e =>
{ {
string helpstr = "Official repo: **github.com/Kwoth/NadekoBot/**"; string helpstr = "**COMMANDS DO NOT WORK IN PERSONAL MESSAGES**\nOfficial repo: **github.com/Kwoth/NadekoBot/**";
string lastCategory = ""; string lastCategory = "";
foreach (var com in client.Commands().AllCommands) foreach (var com in client.Commands().AllCommands)

View File

@ -10,17 +10,14 @@ using System.Threading.Tasks;
using NadekoBot.Commands; using NadekoBot.Commands;
using System.IO; using System.IO;
namespace NadekoBot.Modules namespace NadekoBot.Modules {
{ class Administration : DiscordModule {
class Administration : DiscordModule
{
public Administration() : base() { public Administration() : base() {
commands.Add(new HelpCommand()); commands.Add(new HelpCommand());
commands.Add(new ServerGreetCommand()); commands.Add(new ServerGreetCommand());
} }
public override void Install(ModuleManager manager) public override void Install(ModuleManager manager) {
{
manager.CreateCommands("", cgb => { manager.CreateCommands("", cgb => {
var client = manager.Client; var client = manager.Client;
@ -133,22 +130,22 @@ namespace NadekoBot.Modules
try { try {
bool rgb = args.Count() == 4; bool rgb = args.Count() == 4;
byte red = Convert.ToByte(rgb ? int.Parse(e.Args[1]) : Convert.ToInt32(e.Args[1].Substring(0,2), 16)); byte red = Convert.ToByte(rgb ? int.Parse(e.Args[1]) : Convert.ToInt32(e.Args[1].Substring(0, 2), 16));
byte green = Convert.ToByte(rgb ? int.Parse(e.Args[2]) : Convert.ToInt32(e.Args[1].Substring(2, 2), 16)); byte green = Convert.ToByte(rgb ? int.Parse(e.Args[2]) : Convert.ToInt32(e.Args[1].Substring(2, 2), 16));
byte blue = Convert.ToByte(rgb ? int.Parse(e.Args[3]) : Convert.ToInt32(e.Args[1].Substring(4, 2), 16)); byte blue = Convert.ToByte(rgb ? int.Parse(e.Args[3]) : Convert.ToInt32(e.Args[1].Substring(4, 2), 16));
await role.Edit(color: new Color(red, green, blue)); await role.Edit(color: new Color(red, green, blue));
await e.Channel.SendMessage($"Role {role.Name}'s color has been changed."); await e.Channel.SendMessage($"Role {role.Name}'s color has been changed.");
} catch (Exception ex) { } catch (Exception ex) {
await e.Send(":warning: Unspecified error, please report this."); await e.Send(":warning: Unspecified error, please report this.");
Console.WriteLine($".rolecolor error: {ex}"); Console.WriteLine($".rolecolor error: {ex}");
} }
}); });
cgb.CreateCommand(".b").Alias(".ban") cgb.CreateCommand(".b").Alias(".ban")
.Parameter("everything",ParameterType.Unparsed) .Parameter("everything", ParameterType.Unparsed)
.Description("Bans a mentioned user") .Description("Bans a mentioned user")
.Do(async e => { .Do(async e => {
try { try {
@ -259,7 +256,7 @@ namespace NadekoBot.Modules
.Parameter("user", ParameterType.Optional) .Parameter("user", ParameterType.Optional)
.Do(async e => { .Do(async e => {
var usr = e.User; var usr = e.User;
if(e.GetArg("user") != null) usr = e.Channel.FindUsers(e.GetArg("user")).FirstOrDefault(); if (e.GetArg("user") != null) usr = e.Channel.FindUsers(e.GetArg("user")).FirstOrDefault();
await e.Send($"Id of the user { usr.Name } is { usr.Id }"); await e.Send($"Id of the user { usr.Name } is { usr.Id }");
}); });
@ -343,15 +340,15 @@ namespace NadekoBot.Modules
await client.CurrentUser.Edit(NadekoBot.password, e.GetArg("new_name")); await client.CurrentUser.Edit(NadekoBot.password, e.GetArg("new_name"));
}); });
cgb.CreateCommand(".setgame")
.Description("Sets the bots game.")
.Parameter("set_game", ParameterType.Unparsed)
.Do(e => {
if (e.User.Id != NadekoBot.OwnerID || e.GetArg("set_game") == null) return;
client.SetGame(e.GetArg("set_game")); cgb.CreateCommand(".setgame")
}); .Description("Sets the bots game.")
.Parameter("set_game", ParameterType.Unparsed)
.Do(e => {
if (e.User.Id != NadekoBot.OwnerID || e.GetArg("set_game") == null) return;
client.SetGame(e.GetArg("set_game"));
});
cgb.CreateCommand(".checkmyperms") cgb.CreateCommand(".checkmyperms")
.Description("Checks your userspecific permissions on this channel.") .Description("Checks your userspecific permissions on this channel.")
@ -363,7 +360,7 @@ namespace NadekoBot.Modules
output += "```"; output += "```";
await e.User.SendMessage(output); await e.User.SendMessage(output);
}); });
Server commsServer = null; Server commsServer = null;
User commsUser = null; User commsUser = null;
@ -393,7 +390,7 @@ namespace NadekoBot.Modules
cgb.CreateCommand(".send") cgb.CreateCommand(".send")
.Description("Send a message to someone on a different server through the bot.**Owner only.**\n **Usage**: .send Message text multi word!") .Description("Send a message to someone on a different server through the bot.**Owner only.**\n **Usage**: .send Message text multi word!")
.Parameter("msg",ParameterType.Unparsed) .Parameter("msg", ParameterType.Unparsed)
.Do(async e => { .Do(async e => {
if (e.User.Id != NadekoBot.OwnerID) return; if (e.User.Id != NadekoBot.OwnerID) return;
try { try {
@ -435,34 +432,5 @@ namespace NadekoBot.Modules
*/ */
}); });
} }
bool announcingGreet = false;
Channel announceChannel = null;
Server joinServer = null;
string announceMsg = "Welcome to the server %user%";
private void Client_UserJoined(object sender, UserEventArgs e) {
if (e.Server != joinServer) return;
try {
announceChannel?.Send(announceMsg.Replace("%user%", e.User.Mention));
} catch (Exception) {
Console.WriteLine("Failed sending greet message to the specified channel");
}
}
bool announcingLeave = false;
Channel announceLeaveChannel = null;
Server leaveServer = null;
string announceLeaveMsg = "%user% has left the server";
private void Client_UserLeft(object sender, UserEventArgs e) {
if (e.Server != leaveServer) return;
try {
announceLeaveChannel?.Send(announceLeaveMsg.Replace("%user%", e.User.Mention));
} catch (Exception) {
Console.WriteLine("Failed sending leave message to the specified channel.");
}
}
} }
} }

View File

@ -182,7 +182,13 @@ namespace NadekoBot.Modules
.Parameter("mention", ParameterType.Required) .Parameter("mention", ParameterType.Required)
.Do(async e => .Do(async e =>
{ {
List<string> praises = new List<string> { " You are cool.", " You are nice!", " You did a good job.", " You did something nice.", " is awesome!" }; List<string> praises = new List<string> { " You are cool.",
" You are nice!",
" You did a good job.",
" You did something nice.",
" is awesome!",
" Wow."};
Random r = new Random(); Random r = new Random();
var u = e.Channel.FindUsers(e.GetArg("mention")).FirstOrDefault(); var u = e.Channel.FindUsers(e.GetArg("mention")).FirstOrDefault();
@ -320,21 +326,26 @@ namespace NadekoBot.Modules
.Description("Shows the message where you were last mentioned in this channel (checks last 10k messages)") .Description("Shows the message where you were last mentioned in this channel (checks last 10k messages)")
.Do(async e => { .Do(async e => {
Message msg; Message msg = null;
var msgs = e.Channel.Messages var msgs = e.Channel.Messages
.Where(m => m.MentionedUsers.Contains(e.User)) .Where(m => m.MentionedUsers.Contains(e.User))
.OrderByDescending(m => m.Timestamp); .OrderByDescending(m => m.Timestamp);
if (msgs.Count() > 0) if (msgs.Count() > 0)
msg = msgs.FirstOrDefault(); msg = msgs.First();
else { else {
var msgsarr = await e.Channel.DownloadMessages(10000); int attempt = 0;
msg = msgsarr Message lastMessage = null;
.Where(m => m.MentionedUsers.Contains(e.User)) while (msg == null && attempt++ < 5) {
.OrderByDescending(m => m.Timestamp) var msgsarr = await e.Channel.DownloadMessages(100, lastMessage?.Id);
.FirstOrDefault(); msg = msgsarr
.Where(m => m.MentionedUsers.Contains(e.User))
.OrderByDescending(m => m.Timestamp)
.FirstOrDefault();
lastMessage = msgsarr.OrderBy(m => m.Timestamp).First();
}
} }
if (msg != null) if (msg != null)
await e.Send("Last message mentioning you was at " + msg.Timestamp + "\n**Message:** " + msg.RawText.Replace("@everyone","@everryone")); await e.Send($"Last message mentioning you was at {msg.Timestamp}\n**Message from {msg.User.Name}:** {msg.RawText.Replace("@everyone", "@everryone")}");
else else
await e.Send("I can't find a message mentioning you."); await e.Send("I can't find a message mentioning you.");
}); });

View File

@ -58,9 +58,9 @@ namespace NadekoBot.Modules {
.Do(e => { .Do(e => {
if (musicPlayers.ContainsKey(e.Server) == false) return; if (musicPlayers.ContainsKey(e.Server) == false) return;
var player = musicPlayers[e.Server]; var player = musicPlayers[e.Server];
player.Stop();
MusicControls throwAwayValue; MusicControls throwAwayValue;
musicPlayers.TryRemove(e.Server, out throwAwayValue); musicPlayers.TryRemove(e.Server, out throwAwayValue);
player.Stop();
}); });
cgb.CreateCommand("p") cgb.CreateCommand("p")
@ -92,7 +92,7 @@ namespace NadekoBot.Modules {
} }
try { try {
var sr = player.CreateStreamRequest(e, e.GetArg("query"), player.VoiceChannel); var sr = await player.CreateStreamRequest(e, e.GetArg("query"), player.VoiceChannel);
if (sr == null) if (sr == null)
throw new NullReferenceException("StreamRequest is null."); throw new NullReferenceException("StreamRequest is null.");
Message msg = null; Message msg = null;

View File

@ -150,7 +150,7 @@ namespace NadekoBot {
$"\nUptime: {GetUptimeString()}" + $"\nUptime: {GetUptimeString()}" +
$"\nServers: {client.Servers.Count()}" + $"\nServers: {client.Servers.Count()}" +
$"\nChannels: {client.Servers.Sum(s => s.AllChannels.Count())}" + $"\nChannels: {client.Servers.Sum(s => s.AllChannels.Count())}" +
$"\nUsers: {client.Servers.SelectMany(x => x.Users.Select(y => y.Id)).Count()} ({client.Servers.SelectMany(x => x.Users.Select(y => y.Id)).Distinct().Count()} unique) ({client.Servers.SelectMany(x => x.Users.Where(y => y.Status != UserStatus.Offline).Select(y => y.Id)).Distinct().Count()} online)" + $"\nUsers: {client.Servers.SelectMany(x => x.Users.Select(y => y.Id)).Count()} (non-unique)" +
$"\nHeap: {Math.Round(GC.GetTotalMemory(true) / (1024.0 * 1024.0), 2).ToString()}MB" + $"\nHeap: {Math.Round(GC.GetTotalMemory(true) / (1024.0 * 1024.0), 2).ToString()}MB" +
$"\nCommands Ran this session: {commandsRan}"; $"\nCommands Ran this session: {commandsRan}";
} }
@ -183,7 +183,7 @@ namespace NadekoBot {
await OwnerUser.SendMessage(e.User + ": ```\n" + e.Message.Text + "\n```"); await OwnerUser.SendMessage(e.User + ": ```\n" + e.Message.Text + "\n```");
if (repliedRecently = !repliedRecently) { if (repliedRecently = !repliedRecently) {
await e.Send("You can type `-h` or `-help` or `@MyName help` in any of the channels I am in and I will send you a message with my commands.\n Or you can find out what i do here: https://github.com/Kwoth/NadekoBot\nYou can also just send me an invite link to a server and I will join it.\nIf you don't want me on your server, you can simply ban me ;(\nBot Creator's server: https://discord.gg/0ehQwTK2RBhxEi0X"); await e.Send("**COMMANDS DO NOT WORK IN PERSONAL MESSAGES**\nYou can type `-h` or `-help` or `@MyName help` in any of the channels I am in and I will send you a message with my commands.\n Or you can find out what i do here: https://github.com/Kwoth/NadekoBot\nYou can also just send me an invite link to a server and I will join it.\nIf you don't want me on your server, you can simply ban me ;(\nBot Creator's server: https://discord.gg/0ehQwTK2RBhxEi0X");
Timer t = new Timer(); Timer t = new Timer();
t.Interval = 2000; t.Interval = 2000;
t.Start(); t.Start();

View File

@ -73,6 +73,14 @@
<Prefer32Bit>true</Prefer32Bit> <Prefer32Bit>true</Prefer32Bit>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="libvideo, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\VideoLibrary.1.3.3\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\libvideo.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="libvideo.compat, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\VideoLibrary.Compat.1.3.3\lib\portable-net45+win+wpa81+MonoAndroid10+xamarinios10+MonoTouch10\libvideo.compat.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Manatee.Json, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c267f67a39449c62, processorArchitecture=MSIL"> <Reference Include="Manatee.Json, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c267f67a39449c62, processorArchitecture=MSIL">
<HintPath>..\packages\Manatee.Json.3.2.1\lib\net45\Manatee.Json.dll</HintPath> <HintPath>..\packages\Manatee.Json.3.2.1\lib\net45\Manatee.Json.dll</HintPath>
<Private>True</Private> <Private>True</Private>
@ -134,10 +142,6 @@
<HintPath>..\packages\taglib.2.1.0.0\lib\taglib-sharp.dll</HintPath> <HintPath>..\packages\taglib.2.1.0.0\lib\taglib-sharp.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="YoutubeExtractor, Version=0.10.10.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\YoutubeExtractor.0.10.10\lib\net35\YoutubeExtractor.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Classes\Music\MusicControls.cs" /> <Compile Include="Classes\Music\MusicControls.cs" />

View File

@ -11,7 +11,6 @@
<package id="Parse" version="1.6.2" targetFramework="net452" /> <package id="Parse" version="1.6.2" targetFramework="net452" />
<package id="RestSharp" version="105.2.3" targetFramework="net452" /> <package id="RestSharp" version="105.2.3" targetFramework="net452" />
<package id="taglib" version="2.1.0.0" targetFramework="net452" /> <package id="taglib" version="2.1.0.0" targetFramework="net452" />
<package id="VideoLibrary" version="1.3.1" targetFramework="net452" /> <package id="VideoLibrary" version="1.3.3" targetFramework="net452" />
<package id="VideoLibrary.Compat" version="1.3.3" targetFramework="net452" /> <package id="VideoLibrary.Compat" version="1.3.3" targetFramework="net452" />
<package id="YoutubeExtractor" version="0.10.10" targetFramework="net452" />
</packages> </packages>