Merge remote-tracking branch 'refs/remotes/Kwoth/master' into patch-4

# Conflicts:
#	NadekoBot/NadekoBot.cs
#	NadekoBot/NadekoBot.csproj
This commit is contained in:
appelemac 2016-05-02 14:23:17 +02:00
commit f3ee5042b7
19 changed files with 296 additions and 103 deletions

View File

@ -10,7 +10,7 @@ ________________________________________________________________________________
- Go to (https://discordapp.com/developers/applications/me). Log in if you have to with your Discord account. Press "New Application" and fill out an App Name and, optionally, an app description and icon. Afterwards, create the application. Once the application is created, click on "Create a Bot User" and confirm it. You will then see the bot's username, ID and token. Reveal and copy the token and the bot ID. - Go to (https://discordapp.com/developers/applications/me). Log in if you have to with your Discord account. Press "New Application" and fill out an App Name and, optionally, an app description and icon. Afterwards, create the application. Once the application is created, click on "Create a Bot User" and confirm it. You will then see the bot's username, ID and token. Reveal and copy the token and the bot ID.
- Open up credentials.json. Paste the token into the Token field, between the quotes. Paste the ID into the BotID field. Leave email and password fields empty. Save and close credentials.json. - Open up credentials.json. Paste the token into the Token field, between the quotes. Paste the ID into the BotID field. Leave email and password fields empty. Save and close credentials.json.
- Go into data folder and make sure you have config.json file. If there is no config.json, rename the config_example.json to config.json. - Go into data folder and make sure you have config.json file. If there is no config.json, rename the config_example.json to config.json.
- Copy your CLIENT ID (that's in the same Developer page where you brought your token) and replace `12345678` in the this link: - Copy your CLIENT ID (that's in the same Developer page where you brought your token) and replace `12345678` in this link:
https://discordapp.com/oauth2/authorize?client_id=12345678&scope=bot&permissions=66186303 with it. Go to that link and you will be able to add your bot to your server. https://discordapp.com/oauth2/authorize?client_id=12345678&scope=bot&permissions=66186303 with it. Go to that link and you will be able to add your bot to your server.
- Start NadekoBot.exe. In a text channel, **not a direct message**, type in [.uid @______] without the brackets, filling in the underlined portion with your name and send the message. Your bot will reply with a number; this is your ID. Copy this ID and close NadekoBot.exe. - Start NadekoBot.exe. In a text channel, **not a direct message**, type in [.uid @______] without the brackets, filling in the underlined portion with your name and send the message. Your bot will reply with a number; this is your ID. Copy this ID and close NadekoBot.exe.
- Reopen credentials.json. Paste your ID into the square brackets ("OwnerIds": [1231312313]). You can add multiple owners by separating IDs with a comma. Close and save credentials.json. - Reopen credentials.json. Paste your ID into the square brackets ("OwnerIds": [1231312313]). You can add multiple owners by separating IDs with a comma. Close and save credentials.json.

View File

@ -1,7 +1,7 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14 # Visual Studio 14
VisualStudioVersion = 14.0.25008.0 VisualStudioVersion = 14.0.25123.0
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NadekoBot", "NadekoBot\NadekoBot.csproj", "{27A886F5-CDDA-4F4A-81EE-6DAFCCE9DE46}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NadekoBot", "NadekoBot\NadekoBot.csproj", "{27A886F5-CDDA-4F4A-81EE-6DAFCCE9DE46}"
EndProject EndProject

View File

@ -158,8 +158,34 @@ namespace NadekoBot.Classes
return conn.Table<T>().Where(p).ToList().OrderBy(x => r.Next()).FirstOrDefault(); return conn.Table<T>().Where(p).ToList().OrderBy(x => r.Next()).FirstOrDefault();
} }
} }
/// <summary>
///
/// </summary>
/// <param name="num">Page number (0+)</param>
/// <returns></returns>
internal List<PlaylistData> GetPlaylistData(int num)
{
using (var conn = new SQLiteConnection(FilePath))
{
return conn.Query<PlaylistData>(
@"SELECT mp.Name as 'Name',mp.Id as 'Id', mp.CreatorName as 'Creator', Count(*) as 'SongCnt' FROM MusicPlaylist as mp
INNER JOIN PlaylistSongInfo as psi
ON mp.Id = psi.PlaylistId
Group BY mp.Name
Order By mp.DateAdded desc
Limit 20 OFFSET ?", num * 20);
} }
} }
}
}
public class PlaylistData
{
public string Name { get; set; }
public int Id { get; set; }
public string Creator { get; set; }
public int SongCnt { get; set; }
}
public static class Queries public static class Queries
{ {

View File

@ -138,14 +138,21 @@ namespace NadekoBot.Extensions
/// <param name="list"></param> /// <param name="list"></param>
public static void Shuffle<T>(this IList<T> list) public static void Shuffle<T>(this IList<T> list)
{ {
// Thanks to @Joe4Evr for finding a bug in the old version of the shuffle
var provider = new RNGCryptoServiceProvider(); var provider = new RNGCryptoServiceProvider();
var n = list.Count; var n = list.Count;
while (n > 1) while (n > 1)
{ {
var box = new byte[1]; var box = new byte[(n / Byte.MaxValue) + 1];
do provider.GetBytes(box); int boxSum;
while (!(box[0] < n * (byte.MaxValue / n))); do
var k = (box[0] % n); {
provider.GetBytes(box);
boxSum = box.Sum(b => b);
}
while (!(boxSum < n * ((Byte.MaxValue * box.Length) / n)));
var k = (boxSum % n);
n--; n--;
var value = list[k]; var value = list[k];
list[k] = list[n]; list[k] = list[n];

View File

@ -219,9 +219,10 @@ namespace NadekoBot
DateAdded = DateTime.Now DateAdded = DateTime.Now
}); });
} }
catch catch (Exception ex)
{ {
Console.WriteLine("Error in ran command DB write."); Console.WriteLine("Probably unimportant error in ran command DB write.");
Console.WriteLine(ex);
} }
}).ConfigureAwait(false); }).ConfigureAwait(false);
} }

View File

@ -263,12 +263,19 @@ namespace NadekoBot.Classes
{ {
try try
{ {
XDocument doc = await Task.Run(() => XDocument.Load(" http://e621.net/post/index.xml?tags=" + Uri.EscapeUriString(tags) + "%20order:random&limit=1")); var headers = new Dictionary<string, string>() {
int id = Convert.ToInt32(doc.Root.Element("post").Element("id").Value); {"User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.202 Safari/535.1"},
return (doc.Root.Element("post").Element("file_url").Value); {"Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" },
};
var data = await GetResponseStreamAsync(
"http://e621.net/post/index.xml?tags=" + Uri.EscapeUriString(tags) + "%20order:random&limit=1",
headers);
var doc = XDocument.Load(data);
return doc.Descendants("file_url").FirstOrDefault().Value;
} }
catch (Exception) catch (Exception ex)
{ {
Console.WriteLine("Error in e621 search: \n" + ex);
return "Error, do you have too many tags?"; return "Error, do you have too many tags?";
} }
} }

View File

@ -69,9 +69,9 @@ namespace NadekoBot.Modules.Administration.Commands
if (channel == null) return; if (channel == null) return;
Greeted++; Greeted++;
var toDelete = await channel.SendMessage(msg).ConfigureAwait(false); var toDelete = await channel.SendMessage(msg).ConfigureAwait(false);
if (e.Server.CurrentUser.GetPermissions(channel).ManageMessages) if (e.Server.CurrentUser.GetPermissions(channel).ManageMessages && controls.DeleteGreetMessages)
{ {
await Task.Delay(300000).ConfigureAwait(false); // 5 minutes await Task.Delay(30000).ConfigureAwait(false); // 5 minutes
await toDelete.Delete().ConfigureAwait(false); await toDelete.Delete().ConfigureAwait(false);
} }
} }
@ -102,9 +102,9 @@ namespace NadekoBot.Modules.Administration.Commands
if (channel == null) return; if (channel == null) return;
Greeted++; Greeted++;
var toDelete = await channel.SendMessage(msg).ConfigureAwait(false); var toDelete = await channel.SendMessage(msg).ConfigureAwait(false);
if (e.Server.CurrentUser.GetPermissions(channel).ManageMessages) if (e.Server.CurrentUser.GetPermissions(channel).ManageMessages && controls.DeleteGreetMessages)
{ {
await Task.Delay(300000).ConfigureAwait(false); // 5 minutes await Task.Delay(30000).ConfigureAwait(false); // 5 minutes
await toDelete.Delete().ConfigureAwait(false); await toDelete.Delete().ConfigureAwait(false);
} }
} }
@ -160,6 +160,15 @@ namespace NadekoBot.Modules.Administration.Commands
set { _model.ServerId = (long)value; } set { _model.ServerId = (long)value; }
} }
public bool DeleteGreetMessages {
get {
return _model.DeleteGreetMessages;
}
set {
_model.DeleteGreetMessages = value; Save();
}
}
public AnnounceControls(DataModels.Announcement model) public AnnounceControls(DataModels.Announcement model)
{ {
this._model = model; this._model = model;
@ -196,6 +205,8 @@ namespace NadekoBot.Modules.Administration.Commands
return Greet = true; return Greet = true;
} }
} }
internal bool ToggleDelete() => DeleteGreetMessages = !DeleteGreetMessages;
internal bool ToggleGreetPM() => GreetPM = !GreetPM; internal bool ToggleGreetPM() => GreetPM = !GreetPM;
internal bool ToggleByePM() => ByePM = !ByePM; internal bool ToggleByePM() => ByePM = !ByePM;
@ -207,18 +218,27 @@ namespace NadekoBot.Modules.Administration.Commands
internal override void Init(CommandGroupBuilder cgb) internal override void Init(CommandGroupBuilder cgb)
{ {
cgb.CreateCommand(Module.Prefix + "grdel")
.Description("Enables or Disables automatic deletion of greet and bye messages.")
.Do(async e =>
{
if (!e.User.ServerPermissions.ManageServer) return;
var ann = AnnouncementsDictionary.GetOrAdd(e.Server.Id, new AnnounceControls(e.Server.Id));
if (ann.ToggleDelete())
await e.Channel.SendMessage("`Automatic deletion of greet and bye messages has been enabled.`").ConfigureAwait(false);
else
await e.Channel.SendMessage("`Automatic deletion of greet and bye messages has been disabled.`").ConfigureAwait(false);
});
cgb.CreateCommand(Module.Prefix + "greet") cgb.CreateCommand(Module.Prefix + "greet")
.Description("Enables or Disables anouncements on the current channel when someone joins the server.") .Description("Enables or Disables anouncements on the current channel when someone joins the server.")
.Do(async e => .Do(async e =>
{ {
if (!e.User.ServerPermissions.ManageServer) return; if (!e.User.ServerPermissions.ManageServer) return;
if (!AnnouncementsDictionary.ContainsKey(e.Server.Id)) var ann = AnnouncementsDictionary.GetOrAdd(e.Server.Id, new AnnounceControls(e.Server.Id));
AnnouncementsDictionary.TryAdd(e.Server.Id, new AnnounceControls(e.Server.Id));
var controls = AnnouncementsDictionary[e.Server.Id]; if (ann.ToggleGreet(e.Channel.Id))
if (controls.ToggleGreet(e.Channel.Id))
await e.Channel.SendMessage("Greet announcements enabled on this channel.").ConfigureAwait(false); await e.Channel.SendMessage("Greet announcements enabled on this channel.").ConfigureAwait(false);
else else
await e.Channel.SendMessage("Greet announcements disabled.").ConfigureAwait(false); await e.Channel.SendMessage("Greet announcements disabled.").ConfigureAwait(false);
@ -231,12 +251,11 @@ namespace NadekoBot.Modules.Administration.Commands
{ {
if (!e.User.ServerPermissions.ManageServer) return; if (!e.User.ServerPermissions.ManageServer) return;
if (e.GetArg("msg") == null) return; if (e.GetArg("msg") == null) return;
if (!AnnouncementsDictionary.ContainsKey(e.Server.Id)) var ann = AnnouncementsDictionary.GetOrAdd(e.Server.Id, new AnnounceControls(e.Server.Id));
AnnouncementsDictionary.TryAdd(e.Server.Id, new AnnounceControls(e.Server.Id));
AnnouncementsDictionary[e.Server.Id].GreetText = e.GetArg("msg"); ann.GreetText = e.GetArg("msg");
await e.Channel.SendMessage("New greet message set.").ConfigureAwait(false); await e.Channel.SendMessage("New greet message set.").ConfigureAwait(false);
if (!AnnouncementsDictionary[e.Server.Id].Greet) if (!ann.Greet)
await e.Channel.SendMessage("Enable greet messsages by typing `.greet`").ConfigureAwait(false); await e.Channel.SendMessage("Enable greet messsages by typing `.greet`").ConfigureAwait(false);
}); });
@ -245,12 +264,9 @@ namespace NadekoBot.Modules.Administration.Commands
.Do(async e => .Do(async e =>
{ {
if (!e.User.ServerPermissions.ManageServer) return; if (!e.User.ServerPermissions.ManageServer) return;
if (!AnnouncementsDictionary.ContainsKey(e.Server.Id)) var ann = AnnouncementsDictionary.GetOrAdd(e.Server.Id, new AnnounceControls(e.Server.Id));
AnnouncementsDictionary.TryAdd(e.Server.Id, new AnnounceControls(e.Server.Id));
var controls = AnnouncementsDictionary[e.Server.Id]; if (ann.ToggleBye(e.Channel.Id))
if (controls.ToggleBye(e.Channel.Id))
await e.Channel.SendMessage("Bye announcements enabled on this channel.").ConfigureAwait(false); await e.Channel.SendMessage("Bye announcements enabled on this channel.").ConfigureAwait(false);
else else
await e.Channel.SendMessage("Bye announcements disabled.").ConfigureAwait(false); await e.Channel.SendMessage("Bye announcements disabled.").ConfigureAwait(false);
@ -263,12 +279,11 @@ namespace NadekoBot.Modules.Administration.Commands
{ {
if (!e.User.ServerPermissions.ManageServer) return; if (!e.User.ServerPermissions.ManageServer) return;
if (e.GetArg("msg") == null) return; if (e.GetArg("msg") == null) return;
if (!AnnouncementsDictionary.ContainsKey(e.Server.Id)) var ann = AnnouncementsDictionary.GetOrAdd(e.Server.Id, new AnnounceControls(e.Server.Id));
AnnouncementsDictionary.TryAdd(e.Server.Id, new AnnounceControls(e.Server.Id));
AnnouncementsDictionary[e.Server.Id].ByeText = e.GetArg("msg"); ann.ByeText = e.GetArg("msg");
await e.Channel.SendMessage("New bye message set.").ConfigureAwait(false); await e.Channel.SendMessage("New bye message set.").ConfigureAwait(false);
if (!AnnouncementsDictionary[e.Server.Id].Bye) if (!ann.Bye)
await e.Channel.SendMessage("Enable bye messsages by typing `.bye`.").ConfigureAwait(false); await e.Channel.SendMessage("Enable bye messsages by typing `.bye`.").ConfigureAwait(false);
}); });
@ -277,15 +292,14 @@ namespace NadekoBot.Modules.Administration.Commands
.Do(async e => .Do(async e =>
{ {
if (!e.User.ServerPermissions.ManageServer) return; if (!e.User.ServerPermissions.ManageServer) return;
if (!AnnouncementsDictionary.ContainsKey(e.Server.Id)) var ann = AnnouncementsDictionary.GetOrAdd(e.Server.Id, new AnnounceControls(e.Server.Id));
AnnouncementsDictionary.TryAdd(e.Server.Id, new AnnounceControls(e.Server.Id));
AnnouncementsDictionary[e.Server.Id].ToggleByePM();
if (AnnouncementsDictionary[e.Server.Id].ByePM) if (ann.ToggleByePM())
await e.Channel.SendMessage("Bye messages will be sent in a PM from now on.\n ⚠ Keep in mind this might fail if the user and the bot have no common servers after the user leaves.").ConfigureAwait(false); await e.Channel.SendMessage("Bye messages will be sent in a PM from now on.\n ⚠ Keep in mind this might fail if the user and the bot have no common servers after the user leaves.").ConfigureAwait(false);
else else
await e.Channel.SendMessage("Bye messages will be sent in a bound channel from now on.").ConfigureAwait(false); await e.Channel.SendMessage("Bye messages will be sent in a bound channel from now on.").ConfigureAwait(false);
if (!AnnouncementsDictionary[e.Server.Id].Bye) if (!ann.Bye)
await e.Channel.SendMessage("Enable bye messsages by typing `.bye`, and set the bye message using `.byemsg`").ConfigureAwait(false); await e.Channel.SendMessage("Enable bye messsages by typing `.bye`, and set the bye message using `.byemsg`").ConfigureAwait(false);
}); });
@ -294,15 +308,14 @@ namespace NadekoBot.Modules.Administration.Commands
.Do(async e => .Do(async e =>
{ {
if (!e.User.ServerPermissions.ManageServer) return; if (!e.User.ServerPermissions.ManageServer) return;
if (!AnnouncementsDictionary.ContainsKey(e.Server.Id))
AnnouncementsDictionary.TryAdd(e.Server.Id, new AnnounceControls(e.Server.Id));
AnnouncementsDictionary[e.Server.Id].ToggleGreetPM(); var ann = AnnouncementsDictionary.GetOrAdd(e.Server.Id, new AnnounceControls(e.Server.Id));
if (AnnouncementsDictionary[e.Server.Id].GreetPM)
if (ann.ToggleGreetPM())
await e.Channel.SendMessage("Greet messages will be sent in a PM from now on.").ConfigureAwait(false); await e.Channel.SendMessage("Greet messages will be sent in a PM from now on.").ConfigureAwait(false);
else else
await e.Channel.SendMessage("Greet messages will be sent in a bound channel from now on.").ConfigureAwait(false); await e.Channel.SendMessage("Greet messages will be sent in a bound channel from now on.").ConfigureAwait(false);
if (!AnnouncementsDictionary[e.Server.Id].Greet) if (!ann.Greet)
await e.Channel.SendMessage("Enable greet messsages by typing `.greet`, and set the greet message using `.greetmsg`").ConfigureAwait(false); await e.Channel.SendMessage("Enable greet messsages by typing `.greet`, and set the greet message using `.greetmsg`").ConfigureAwait(false);
}); });
} }

View File

@ -130,7 +130,7 @@ namespace NadekoBot.Modules.Games.Commands.Trivia
await channel.SendMessage($"☑️ {e.User.Mention} guessed it! The answer was: **{CurrentQuestion.Answer}**").ConfigureAwait(false); await channel.SendMessage($"☑️ {e.User.Mention} guessed it! The answer was: **{CurrentQuestion.Answer}**").ConfigureAwait(false);
if (Users[e.User] != WinRequirement) return; if (Users[e.User] != WinRequirement) return;
ShouldStopGame = true; ShouldStopGame = true;
await channel.Send($":exclamation: We have a winner! Its {e.User.Mention}.").ConfigureAwait(false); await channel.Send($":exclamation: We have a winner! It's {e.User.Mention}.").ConfigureAwait(false);
// add points to the winner // add points to the winner
await FlowersHandler.AddFlowersAsync(e.User, "Won Trivia", 2).ConfigureAwait(false); await FlowersHandler.AddFlowersAsync(e.User, "Won Trivia", 2).ConfigureAwait(false);
} }

View File

@ -11,47 +11,21 @@ namespace NadekoBot.Classes.Help.Commands
{ {
internal class HelpCommand : DiscordCommand internal class HelpCommand : DiscordCommand
{ {
public Func<CommandEventArgs, Task> DoFunc() => async e => public Func<CommandEventArgs, Task> HelpFunc() => async e =>
{ {
#region OldHelp var comToFind = e.GetArg("command")?.ToLowerInvariant();
/* if (string.IsNullOrWhiteSpace(comToFind))
string helpstr = "**COMMANDS DO NOT WORK IN PERSONAL MESSAGES**\nOfficial repo: **github.com/Kwoth/NadekoBot/**";
string lastCategory = "";
foreach (var com in client.GetService<CommandService>().AllCommands)
{
if (com.Category != lastCategory)
{
helpstr += "\n`----`**`" + com.Category + "`**`----`\n";
lastCategory = com.Category;
}
helpstr += PrintCommandHelp(com);
}
helpstr += "\nBot Creator's server: https://discord.gg/0ehQwTK2RBhxEi0X";
helpstr = helpstr.Replace(NadekoBot.botMention, "@BotName");
while (helpstr.Length > 2000)
{
var curstr = helpstr.Substring(0, 2000);
await e.User.Send(curstr.Substring(0, curstr.LastIndexOf("\n") + 1)).ConfigureAwait(false);
helpstr = curstr.Substring(curstr.LastIndexOf("\n") + 1) + helpstr.Substring(2000);
await Task.Delay(200).ConfigureAwait(false);
}
*/
#endregion OldHelp
if (string.IsNullOrWhiteSpace(e.GetArg("command")))
{ {
await e.User.Send(HelpString).ConfigureAwait(false); await e.User.Send(HelpString).ConfigureAwait(false);
return; return;
} }
await Task.Run(async () => await Task.Run(async () =>
{ {
var comToFind = e.GetArg("command");
var com = NadekoBot.Client.GetService<CommandService>().AllCommands var com = NadekoBot.Client.GetService<CommandService>().AllCommands
.FirstOrDefault(c => c.Text.ToLower().Equals(comToFind)); .FirstOrDefault(c => c.Text.ToLowerInvariant().Equals(comToFind) ||
c.Aliases.Select(a => a.ToLowerInvariant()).Contains(comToFind));
if (com != null) if (com != null)
await e.Channel.SendMessage($"`Help for '{com.Text}':` **{com.Description}**").ConfigureAwait(false); await e.Channel.SendMessage($"`Help for '{com.Text}':` {com.Description}").ConfigureAwait(false);
}).ConfigureAwait(false); }).ConfigureAwait(false);
}; };
public static string HelpString => (NadekoBot.IsBot public static string HelpString => (NadekoBot.IsBot
@ -102,7 +76,7 @@ Version: `{NadekoStats.Instance.BotVersion}`";
.Alias(Module.Prefix + "help", NadekoBot.BotMention + " help", NadekoBot.BotMention + " h", "~h") .Alias(Module.Prefix + "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' ") .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' ")
.Parameter("command", ParameterType.Unparsed) .Parameter("command", ParameterType.Unparsed)
.Do(DoFunc()); .Do(HelpFunc());
cgb.CreateCommand(Module.Prefix + "hgit") cgb.CreateCommand(Module.Prefix + "hgit")
.Description("Generates the commandlist.md file. **Owner Only!**") .Description("Generates the commandlist.md file. **Owner Only!**")
.AddCheck(SimpleCheckers.OwnerOnly()) .AddCheck(SimpleCheckers.OwnerOnly())

View File

@ -488,16 +488,6 @@ namespace NadekoBot.Modules.Music
}); });
//cgb.CreateCommand("info")
// .Description("Prints music info (queued/finished/playing) only to this channel")
// .Do(async e =>
// {
// MusicPlayer musicPlayer;
// if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer))
// return;
// musicPlayer
// });
cgb.CreateCommand("load") cgb.CreateCommand("load")
.Description("Loads a playlist under a certain name. \n**Usage**: `!m load classical-1`") .Description("Loads a playlist under a certain name. \n**Usage**: `!m load classical-1`")
.Parameter("name", ParameterType.Unparsed) .Parameter("name", ParameterType.Unparsed)
@ -553,6 +543,23 @@ namespace NadekoBot.Modules.Music
} }
}); });
cgb.CreateCommand("playlists")
.Alias("pls")
.Description("Lists all playlists. Paginated. 20 per page. Default page is 0.\n**Usage**:`!m pls 1`")
.Parameter("num", ParameterType.Optional)
.Do(e =>
{
int num = 0;
int.TryParse(e.GetArg("num"), out num);
if (num < 0)
return;
var result = DbHandler.Instance.GetPlaylistData(num);
if (result.Count == 0)
e.Channel.SendMessage($"`No saved playlists found on page {num}`");
else
e.Channel.SendMessage($"```js\n--- List of saved playlists ---\n\n" + string.Join("\n", result.Select(r => $"'{r.Name}-{r.Id}' by {r.Creator} ({r.SongCnt} songs)")) + $"\n\n --- Page {num} ---```");
});
cgb.CreateCommand("goto") cgb.CreateCommand("goto")
.Description("Goes to a specific time in seconds in a song.") .Description("Goes to a specific time in seconds in a song.")
.Parameter("time") .Parameter("time")
@ -589,6 +596,20 @@ namespace NadekoBot.Modules.Music
await e.Channel.SendMessage($"`Skipped to {minutes}:{seconds}`").ConfigureAwait(false); await e.Channel.SendMessage($"`Skipped to {minutes}:{seconds}`").ConfigureAwait(false);
}); });
cgb.CreateCommand("getlink")
.Alias("gl")
.Description("Shows a link to the currently playing song.")
.Do(async e =>
{
MusicPlayer musicPlayer;
if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer))
return;
var curSong = musicPlayer.CurrentSong;
if (curSong == null)
return;
await e.Channel.SendMessage($"🎶`Current song:` <{curSong.SongInfo.Query}>");
});
}); });
} }

View File

@ -48,14 +48,7 @@ namespace NadekoBot.Modules.NSFW
var tag = e.GetArg("tag")?.Trim() ?? ""; var tag = e.GetArg("tag")?.Trim() ?? "";
await e.Channel.SendMessage(await SearchHelper.GetGelbooruImageLink(tag).ConfigureAwait(false)).ConfigureAwait(false); await e.Channel.SendMessage(await SearchHelper.GetGelbooruImageLink(tag).ConfigureAwait(false)).ConfigureAwait(false);
}); });
cgb.CreateCommand(Prefix + "safebooru")
.Description("Shows a random image from safebooru with a given tag. Tag is optional but preffered. (multiple tags are appended with +)\n**Usage**: ~safebooru yuri+kissing")
.Parameter("tag", ParameterType.Unparsed)
.Do(async e =>
{
var tag = e.GetArg("tag")?.Trim() ?? "";
await e.Channel.SendMessage(await SearchHelper.GetSafebooruImageLink(tag).ConfigureAwait(false)).ConfigureAwait(false);
});
cgb.CreateCommand(Prefix + "rule34") cgb.CreateCommand(Prefix + "rule34")
.Description("Shows a random image from rule34.xx with a given tag. Tag is optional but preffered. (multiple tags are appended with +)\n**Usage**: ~gelbooru yuri+kissing") .Description("Shows a random image from rule34.xx with a given tag. Tag is optional but preffered. (multiple tags are appended with +)\n**Usage**: ~gelbooru yuri+kissing")
.Parameter("tag", ParameterType.Unparsed) .Parameter("tag", ParameterType.Unparsed)

View File

@ -0,0 +1,92 @@
using Discord;
using Discord.Commands;
using NadekoBot.Classes;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
/// <summary>
/// I have no idea what am i doing
/// </summary>
namespace NadekoBot.Modules.Programming.Commands
{
class HaskellRepl : DiscordCommand
{
ConcurrentQueue<KeyValuePair<string, Channel>> commandQueue = new ConcurrentQueue<KeyValuePair<string, Channel>>();
Thread haskellThread;
public HaskellRepl(DiscordModule module) : base(module)
{
//start haskell interpreter
haskellThread = new Thread(new ThreadStart(() =>
{
var p = Process.Start(new ProcessStartInfo
{
FileName = "stack", //shouldn't use repl, but a Language.Haskell.Interpreter somehow
Arguments = "repl",
UseShellExecute = false,
RedirectStandardInput = true,
RedirectStandardOutput = true,
CreateNoWindow = true,
});
Task.Run(async () =>
{
while (true)
{
while (commandQueue.Count == 0)
await Task.Delay(100);
//read from queue
KeyValuePair<string, Channel> com;
if (!commandQueue.TryDequeue(out com))
{
await Task.Delay(100);
continue;
}
//var bytes = Encoding.ASCII.GetBytes(com.Key);
//send the command to the process
p.StandardInput.WriteLine(com.Key);
//wait 50 ms for execution
await Task.Delay(50);
//read everything from the output
var outBuffer = new byte[1500];
p.StandardOutput.BaseStream.Read(outBuffer, 0, 1500);
var outStr = Encoding.ASCII.GetString(outBuffer);
//send to channel
await com.Value.SendMessage($"```hs\nPrelude> {com.Key}\n" + outStr + "\n```");
}
});
}));
haskellThread.Start();
}
internal override void Init(CommandGroupBuilder cgb)
{
cgb.CreateCommand(Module.Prefix + "hs")
.Description("Executes a haskell express with LAMBDABOT")
.Parameter("command", ParameterType.Unparsed)
.Do(e =>
{
var com = e.GetArg("command")?.Trim();
if (string.IsNullOrWhiteSpace(com))
return;
//send a command and a channel to the queue
commandQueue.Enqueue(new KeyValuePair<string, Channel>(com, e.Channel));
});
}
}
}

View File

@ -0,0 +1,26 @@
using Discord.Modules;
using NadekoBot.Extensions;
using NadekoBot.Modules.Permissions.Classes;
using NadekoBot.Modules.Programming.Commands;
namespace NadekoBot.Modules.Programming
{
class ProgrammingModule : DiscordModule
{
public override string Prefix => NadekoBot.Config.CommandPrefixes.Programming;
public ProgrammingModule()
{
commands.Add(new HaskellRepl(this));
}
public override void Install(ModuleManager manager)
{
manager.CreateCommands("", cgb =>
{
cgb.AddCheck(PermissionChecker.Instance);
commands.ForEach(c => c.Init(cgb));
});
}
}
}

View File

@ -92,6 +92,8 @@ namespace NadekoBot.Modules.Searches.Commands
} }
else else
{ {
CultureInfo ci = new CultureInfo("en-US");
Thread.CurrentThread.CurrentCulture = ci;
reInitCurrencyConverterTable(); reInitCurrencyConverterTable();
Unit inUnit = currTable.CreateUnit(quantity, from.ToUpperInvariant()); Unit inUnit = currTable.CreateUnit(quantity, from.ToUpperInvariant());
Unit outUnit = inUnit.Convert(currTable.CurrencyCode(to.ToUpperInvariant())); Unit outUnit = inUnit.Convert(currTable.CurrencyCode(to.ToUpperInvariant()));
@ -108,11 +110,18 @@ namespace NadekoBot.Modules.Searches.Commands
private void reInitCurrencyConverterTable() private void reInitCurrencyConverterTable()
{ {
if (lastChanged == null || lastChanged.DayOfYear != DateTime.Now.DayOfYear) if (lastChanged == null || lastChanged.DayOfYear != DateTime.Now.DayOfYear)
{
try
{ {
exchangeRateProvider = new WebExchangeRatesProvider(); exchangeRateProvider = new WebExchangeRatesProvider();
currTable = new CurrencyExchangeTable(exchangeRateProvider); currTable = new CurrencyExchangeTable(exchangeRateProvider);
lastChanged = DateTime.Now; lastChanged = DateTime.Now;
} }
catch
{
Console.WriteLine("Error with the currency download.");
}
}
} }
private void ResolveUnitCodes(string from, string to, out UnitTable table, out int fromCode, out int toCode) private void ResolveUnitCodes(string from, string to, out UnitTable table, out int fromCode, out int toCode)

View File

@ -409,6 +409,27 @@ $@"🌍 **Weather for** 【{obj["target"]}】
return; return;
await e.Channel.SendMessage($"https://images.google.com/searchbyimage?image_url={usr.AvatarUrl}").ConfigureAwait(false); await e.Channel.SendMessage($"https://images.google.com/searchbyimage?image_url={usr.AvatarUrl}").ConfigureAwait(false);
}); });
cgb.CreateCommand(Prefix + "revimg")
.Description("Returns a google reverse image search for an image from a link.")
.Parameter("image", ParameterType.Unparsed)
.Do(async e =>
{
var imgLink = e.GetArg("image")?.Trim();
if (string.IsNullOrWhiteSpace(imgLink))
return;
await e.Channel.SendMessage($"https://images.google.com/searchbyimage?image_url={imgLink}").ConfigureAwait(false);
});
cgb.CreateCommand(Prefix + "safebooru")
.Description("Shows a random image from safebooru with a given tag. Tag is optional but preffered. (multiple tags are appended with +)\n**Usage**: ~safebooru yuri+kissing")
.Parameter("tag", ParameterType.Unparsed)
.Do(async e =>
{
var tag = e.GetArg("tag")?.Trim() ?? "";
await e.Channel.SendMessage(await SearchHelper.GetSafebooruImageLink(tag).ConfigureAwait(false)).ConfigureAwait(false);
});
}); });
} }
} }

View File

@ -200,7 +200,6 @@ namespace NadekoBot
await Client.Connect(Creds.Token).ConfigureAwait(false); await Client.Connect(Creds.Token).ConfigureAwait(false);
IsBot = true; IsBot = true;
} }
Console.WriteLine(NadekoBot.Client.CurrentUser.Id);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -213,7 +212,7 @@ namespace NadekoBot
return; return;
} }
//await Task.Delay(90000).ConfigureAwait(false); await Task.Delay(2000).ConfigureAwait(false);
Console.WriteLine("-----------------"); Console.WriteLine("-----------------");
Console.WriteLine(await NadekoStats.Instance.GetStats().ConfigureAwait(false)); Console.WriteLine(await NadekoStats.Instance.GetStats().ConfigureAwait(false));
Console.WriteLine("-----------------"); Console.WriteLine("-----------------");

View File

@ -124,6 +124,9 @@
<Compile Include="Classes\DBHandler.cs" /> <Compile Include="Classes\DBHandler.cs" />
<Compile Include="Classes\FlowersHandler.cs" /> <Compile Include="Classes\FlowersHandler.cs" />
<Compile Include="Modules\CustomReactions\CustomReactions.cs" /> <Compile Include="Modules\CustomReactions\CustomReactions.cs" />
<Compile Include="Modules\Programming\Commands\HaskellRepl.cs" />
<Compile Include="Modules\Programming\ProgrammingModule.cs" />
<Compile Include="Modules\Searches\Commands\IMDB\ImdbMovie.cs" /> <Compile Include="Modules\Searches\Commands\IMDB\ImdbMovie.cs" />
<Compile Include="Modules\Searches\Commands\IMDB\ImdbScraper.cs" /> <Compile Include="Modules\Searches\Commands\IMDB\ImdbScraper.cs" />
<Compile Include="Classes\IncidentsHandler.cs" /> <Compile Include="Classes\IncidentsHandler.cs" />

View File

@ -15,5 +15,6 @@ namespace NadekoBot.DataModels
[JsonProperty("byeChannel")] [JsonProperty("byeChannel")]
public long ByeChannelId { get; set; } = 0; public long ByeChannelId { get; set; } = 0;
public string ByeText { get; set; } = "%user% has left the server."; public string ByeText { get; set; } = "%user% has left the server.";
public bool DeleteGreetMessages { get; set; } = true;
} }
} }

View File

@ -16,9 +16,8 @@ When you clone the project, make sure to run `git submodule init` and `git submo
**This is how the credentials.json should look like:** **This is how the credentials.json should look like:**
```json ```json
{ {
"Username":"bot_email",
"BotId": 123123123123, "BotId": 123123123123,
"Password":"bot_password", "Token":"Bot.Token",
"GoogleAPIKey":"google_api_key", "GoogleAPIKey":"google_api_key",
"OwnerIds":[123123123123, 123123123123], "OwnerIds":[123123123123, 123123123123],
"TrelloAppKey": "your_trello_app_key (optional)", "TrelloAppKey": "your_trello_app_key (optional)",
@ -52,6 +51,7 @@ Next to your exe you must also have a data folder in which there is config.json
"UserBlacklist": [] "UserBlacklist": []
} }
``` ```
- http://discord.kongslien.net/guide.html <- to make a bot account and get the `Token`
- BotId and OwnerIds are **NOT** names of the owner and the bot. If you do not know the id of your bot, put 2 random numbers in those fields, run the bot and do `.uid @MyBotName` - that will give you your bot\_id, do the same for yourself `.uid @MyName` and copy the numbers in their respective fields. - BotId and OwnerIds are **NOT** names of the owner and the bot. If you do not know the id of your bot, put 2 random numbers in those fields, run the bot and do `.uid @MyBotName` - that will give you your bot\_id, do the same for yourself `.uid @MyName` and copy the numbers in their respective fields.
- For google api key, you need to enable URL shortner, Youtube video search **and custom search** in the [dev console](https://console.developers.google.com/). - For google api key, you need to enable URL shortner, Youtube video search **and custom search** in the [dev console](https://console.developers.google.com/).
- For the Soundcloud Api key you need a Soundcloud account. You need to create a new app on http://soundcloud.com/you/apps/new and after that go here http://soundcloud.com/you/apps click on the name of your created your app and copy the Client ID. Paste it into credentials.json. - For the Soundcloud Api key you need a Soundcloud account. You need to create a new app on http://soundcloud.com/you/apps/new and after that go here http://soundcloud.com/you/apps click on the name of your created your app and copy the Client ID. Paste it into credentials.json.