diff --git a/.gitignore b/.gitignore index 1dd55335..67d693a9 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ obj/ NadekoBot/bin/debug/*.* NadekoBot/bin/debug/data/permissions NadekoBot/bin/debug/data/incidents +NadekoBot/bin/debug/data/musicdata NadekoBot/bin/NadekoRelease/*.* !NadekoBot/bin/Debug/data/currency_images/* Tests/bin diff --git a/ComprehensiveGuide.md b/ComprehensiveGuide.md index 1b2c3ea4..1666d345 100644 --- a/ComprehensiveGuide.md +++ b/ComprehensiveGuide.md @@ -1,65 +1,112 @@ ________________________________________________________________________________ -*Thanks to @Flatbread for making this guide* +*Thanks to @Flatbread and Mirai for making this guide* ________________________________________________________________________________ -#### Setting Up NadekoBot v0.98 -###### Prerequisites: -1) NET Framework 4.5.2 (or 4.6) -- Start with making a folder, lets name it `Nadeko` -- Make sure you have **7zip** installed, if not then head to http://www.7-zip.org/download.html and download/install it. -- Now head to https://github.com/Kwoth/NadekoUpdater/releases/tag/v1.0 and download `WINDOWS.-.nadeupdater.7z - - *Alternatively, you can download nadekobot from [releases](https://github.com/Kwoth/NadekoBot/releases) and extract the zip yourself. That is what updater does, except it makes it easier for you to update because it doesn't overwrite important files. If you are downloading releases you will have to be careful about your config, credentials, and other files you edited in order to preserve your data every time you update.* +### Setting Up NadekoBot on Windows +#### Prerequisites +- 1) [NET Framework][NET Framework] 4.5.2 (or 4.6) +- 2) [FFMPEG][FFMPEG] +- 3) Google Account +- 4) Soundcloud Account (if you want soundcloud support) +- 5) [7zip][7zip] (or whatever you are using, WinRar) +- 6) [Notepad++][Notepad++] + +####Guide: + +- Create a folder, name it `Nadeko`. +- Head to [Releases][Releases]* and download `WINDOWS.-.nadeupdater.7z`. - Copy `WINDOWS.-.nadeupdater.7z` to the `Nadeko` (folder we created before) and extract everything. - You will see a file `NadekoUpdater.bat ` and a folder `publish ` after extraction. - Run/Launch/Open the file `NadekoUpdater.bat ` and you will see it running in cmd.exe asking you with **3 options** *1-3*. -- You can try the stable release, but its better to get the newest release if you want all features/upgrades. So for that press `2 ` and hit `Enter ` (read everything shows up on screen) -- It should ask you `Are you sure you want to update?` and for that type `y ` and hit `Enter ` -- It should complete downloading (might take a while) and you can type `3 ` and hit `Enter ` and close it. -- You should now see a new folder `NadekoBot ` inside our `Nadeko ` folder. -- Open it and head over to https://github.com/Kwoth/NadekoBot/blob/master/README.md to setup credentials or just check it out for your knowledge. -- **For Basic Credentials Setup:** -- Rename `credentials_example.json ` into `credentials.json ` (Note: If you do not see a **.json** after `credentials_example.json `, do not add the **.json**. `You are most likely to have "Hide file extensions" as enabled. `) -- **Go to:** http://discord.kongslien.net/guide.html **for detailed guidance with screenshots.** or :arrow_down: -- **Follow for textual guidelines:** Go here https://discordapp.com/developers/applications/me -- Log in 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** *(one by one xD)*. -- Open up `credentials.json` with **NotePad++** Paste the **token** into the **Token** field, between the `"quotes"`. Paste the **Bot ID** into the **BotID** field, when done, *Save* and *close* `credentials.json` -- **To Invite your bot to your server:** -- 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. -- 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]). **Just paste/replace your ID with existing and keep the default format intact, you don't need to add extra space or anything else.** You can add multiple owners by separating IDs with a comma. Close and save credentials.json. + - 1) Stable release - current stable release, but might not contain all the newest Nadeko updates. + - 2) Newest release - release with all features/upgrades. + - 3) Exit +- Press `2` on your keyboard and hit `Enter`. Type `y` and hit `Enter` again. Downloading might take a while, so just be patient and wait. When download is done, press `3` on your keyboard and close the updater. +- You should have a new folder named `NadekoBot` inside the `Nadeko` folder we previously created. +####Creating DiscordBot application +- Go to [DiscordApp][DiscordApp]. +- Log in with your Discord account. +- On the left side, press `New Application`. +- Fill out the `App Name` (your bot's name, in this case), put the image you want, and add an app description(optional). +- Create the application. +- Once the application is created, click on `Create a Bot User` and confirm it. +- Keep this window open for now. + +####Setting up Credentials.json file +- In our `NadekoBot` folder you should have `.json` file named `credentials_example.json`. (Note: If you do not see a **.json** after `credentials_example.json `, do not add the `**.json**`. You most likely have `"Hide file extensions"` enabled.) +- Rename `credentials_example.json` to `credentials.json`. +- Open the file with your [Notepad++][Notepad++]. +- In there you will see fields like `Token`, `ClientId`, `BotId`, `OwnerIDs`. +- In your [DiscordApp][DiscordApp], under `Bot User` part, you will see the `Token:click to reveal` part, click to reveal it. +- Copy your bot's token, and put it between `" "` in your `credentials.json` file. +- Copy `Client ID` and replace it with the example one in your `credentials.json`. +- Copy `Bot ID` and replace it with the example one in your `credentials.json`. +- Save your `credentials.json` but keep it open. We need to put your `User ID` and owner. + +####Inviting your bot to your server [Invite Guide][Invite Guide] +- Create a new server in Discord. +- Copy your `Client ID` from your [DiscordApp][DiscordApp]. +- Replace `12345678` in this link `https://discordapp.com/oauth2/authorize?client_id=12345678&scope=bot&permissions=66186303` with your `Client ID`. +- Link should look like this: `https://discordapp.com/oauth2/authorize?client_id=**YOUR_CLENT_ID**&scope=bot&permissions=66186303`. +- Go to newly created link and pick the server we created, and click `Authorize`. +- Bot should be added to your server. + +####Starting the bot +- Enter your `NadekoBot` folder that should be (hopefully) in your `Nadeko` folder. +- Run `NadekoBot.exe` (Note: There is `NadekoBot.exe` and `NadekoBot.exe.config`, dont run the second one) +- Your bot should now be online in the server we added him to. +- Note: Your bot will be offline in case you close `NadekoBot.exe`. + +####Setting up OwnerIds: +- In the server where your bot is, in a text channel, type `.uid` +- Your `User ID` should show, copy it. +- Close `NadekoBot.exe` +- Replace your `User ID` in the `credentials.json` between `[ ]` and save the changes. +- Run `NadekoBot.exe` again. +- Now you are the bot owner. +- You can add `User IDs` from the other users by separating IDs with a comma if you want to have more owners. + +`*Alternatively, you can download nadekobot from [Releases][Releases] and extract the zip yourself. That is what updater does, except it makes it easier for you to update because it doesn't overwrite important files. If you are downloading releases you will have to be careful about your config, credentials, and other files you edited in order to preserve your data every time you update.` ________________________________________________________________________________ #### Setting Up NadekoBot For Music -###### Setting up `ffmpeg` with installer: -1) Google Account -2) Soundcloud Account (if you want soundcloud support) -3) Download installer here: https://goo.gl/lQZnsH (pick the one for your system, either 32 or 64bit and then click 'download') -4) Run the installer +##### Prerequisites +- 1) [FFMPEG][FFMPEG] installed. +- 2) Setting up API keys. -5) Follow these steps on how to setup API keys: -- Go to https://console.developers.google.com and log in. -- Create a new project (name does not matter). Once the project is created, go into "Enable and manage APIs." -- Under the "Other Popular APIs" section, enable "URL Shortener API". Under the "YouTube APIs" section, enable "YouTube Data API". Also enable Custom Search Api. -- On the left tab, access Credentials. There will be a line saying "If you wish to skip this step and create an API key, client ID or service account." Click on API Key, and then Server Key in the new window that appears. Enter in a name for the server key. A new window will appear with your Google API key. Copy the key. -- Open up credentials.json. For "GoogleAPIKey", fill in with the new key. -- Go to (https://soundcloud.com/you/apps/new). Enter a name for the app and create it. You will see a page with the title of your app, and a field labeled Client ID. Copy the ID. In credentials.json, fill in "SoundcloudClientID" with the copied ID. +- Follow these steps on how to setup Google API keys: + - Go to [Google Console][Google Console] and log in. + - Create a new project (name does not matter). Once the project is created, go into "Enable and manage APIs." + - Under the "Other Popular APIs" section, enable `URL Shortener API` and `Custom Search Api`. Under the `YouTube APIs` section, enable `YouTube Data API`. + - On the left tab, access `Credentials`. Click `Create Credentials` button. Click on `API Key`, and then `Server Key` in the new window that appears. Enter in a name for the `Server Key`. A new window will appear with your `Google API key`. + - Copy the key. + - Open up `credentials.json`. + - For `"GoogleAPIKey"`, fill in with the new key we copied. +- Follow these steps on how to setup Soundcloud API key: + - Go to [Soundcloud][Soundcloud]. + - Enter a name for the app and create it. + - You will see a page with the title of your app, and a field labeled `Client ID`. Copy the ID. + - In `credentials.json`, fill in `"SoundcloudClientID"` with the copied ID. - Restart your computer. -###### Prerequisites for manual `ffmpeg` setup: -1) Google Account -2) Soundcloud Account (if you want soundcloud support) +##### Prerequisites for manual `ffmpeg` setup: +**Do this step in case you were not able to install `ffmpeg` with the installer.** - Create a folder named `ffmpeg` in your main Windows directory. We will use **C:\ffmpeg** (for our guide) - Download FFMPEG through the link https://ffmpeg.zeranoe.com/builds/ (download static build) - Extract it using `7zip` and place the folder `ffmpeg-xxxxx-git-xxxxx-xxxx-static` inside **C:\ffmpeg** - Before proceeding, check out this gif to set up `ffmpeg` PATH correctly http://i.imgur.com/aR5l1Hn.gif *(thanks to PooPeePants#7135)* - Go to My Computer, right click and select Properties. On the left tab, select Advanced System Settings. Under the Advanced tab, select Environmental Variables near the bottom. One of the variables should be called "Path". Add a semi-colon (;) to the end followed by your FFMPEG's **bin** install location (**for example C:\ffmpeg\ffmpeg-xxxxx-git-xxxxx-xxxx-static\bin**). Save and close. -- Go to https://console.developers.google.com and log in. -- Create a new project (name does not matter). Once the project is created, go into "Enable and manage APIs." -- Under the "Other Popular APIs" section, enable "URL Shortener API". Under the "YouTube APIs" section, enable "YouTube Data API". Also enable Custom Search Api. -- On the left tab, access Credentials. There will be a line saying "If you wish to skip this step and create an API key, client ID or service account." Click on API Key, and then Server Key in the new window that appears. Enter in a name for the server key. A new window will appear with your Google API key. Copy the key. -- Open up credentials.json. For "GoogleAPIKey", fill in with the new key. -- Go to (https://soundcloud.com/you/apps/new). Enter a name for the app and create it. You will see a page with the title of your app, and a field labeled Client ID. Copy the ID. In credentials.json, fill in "SoundcloudClientID" with the copied ID. +- Setup your API keys as explained above. - Restart your computer. + +[NET Framework]: https://www.microsoft.com/en-us/download/details.aspx?id=48130 +[FFMPEG]: https://github.com/Soundofdarkness/FFMPEG-Installer +[7zip]: http://www.7-zip.org/download.html +[Releases]: //github.com/Kwoth/NadekoUpdater/releases/tag/v1.0 +[DiscordApp]: https://discordapp.com/developers/applications/me +[Notepad++]: https://notepad-plus-plus.org/ +[Invite Guide]: http://discord.kongslien.net/guide.html +[Google Console]: https://console.developers.google.com +[Soundcloud]: https://soundcloud.com/you/apps/new diff --git a/DockerGuide.md b/DockerGuide.md new file mode 100644 index 00000000..5a87bc22 --- /dev/null +++ b/DockerGuide.md @@ -0,0 +1,54 @@ +## Docker guide with digitalocean + +#####Prerequisites: +- Digital ocean account (you can use my [reflink][reflink] to support the project and get 10$ after you register) +- [PuTTY][PuTTY] +- A bot account - follow this [guide][guide] +- $5 +- Common sense + +#####Guide +- Click on the create droplet button +![img](http://i.imgur.com/g2ayOcC.png) + +- Pick one click apps and select docker on 14.04 + +![img](http://imgur.com/065Xkme.png) + +- Pick any droplet size you want (5$ will work ok-ish on a few servers) +- Pick location closest to your discord server's location +- Pick a hostname +![img](http://imgur.com/ifPKB6p.png) + +- Click create + +You will get an email from DigitalOcean with your credentials now. + +Open putty and type ip adress **you got in your email** with port 22 + +![img](http://imgur.com/Mh5ehsh.png) + +- Console will open and you will be prompted for a username, type `root`. +- Type in the password you got in the email. +- Confirm the password you just typed in. +- Type in the new password. +- Confirm new password. + +- When you are successfully logged in, type +`docker run --name nadeko -v /nadeko:/config uirel/nadeko` + +- Wait for it to download and at one point it is going to start throwing errors due to `credentials.json` being empty +- CTRL+C to exit that +- Type `docker stop nadeko` +- Type `nano /nadeko/credentials.json` and type in your `credentials` +- CTRL+X then CTRL+Y to save +- Type `docker start nadeko` +- Type `docker logs -f nadeko` to see the console output + +**Your bot is running, enjoy! o/** + +*When you want to update the bot, just type `docker restart nadeko` as it always downloads latest prerelease* + +[reflink]: http://m.do.co/c/46b4d3d44795/ +[PuTTY]: http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html +[guide]: http://discord.kongslien.net/guide.html diff --git a/LinuxSetup.md b/LinuxSetup.md index 1295edc5..784e1253 100644 --- a/LinuxSetup.md +++ b/LinuxSetup.md @@ -26,10 +26,12 @@ If you entered your Droplets IP address correctly, it should show **login as:** ######MONO (Source: [Mono Source][Mono Source]) -**1)** +**1) Installing Mono** `sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF` + `echo "deb http://download.mono-project.com/repo/debian wheezy main" | sudo tee /etc/apt/sources.list.d/mono-xamarin.list` + `sudo apt-get update` Note if the command is not being initiated, hit **Enter** @@ -47,7 +49,9 @@ Note if the command is not being initiated, hit **Enter** *ONLY CentOS 7, Fedora 19 (and later)* `yum install yum-util` + `rpm --import "http://keyserver.ubuntu.com/pks/lookup?op=get&search=0x3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF"` + `yum-config-manager --add-repo http://download.mono-project.com/repo/centos/` **3)** @@ -71,8 +75,11 @@ Opus Voice Codec **In case you are having issues with Mono where you get a random string and the bot won't run, do this:** `sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF` + `echo "deb http://download.mono-project.com/repo/debian wheezy main" | sudo tee /etc/apt/sources.list.d/mono-xamarin.list` + `apt-get install ca-certificates-mono` + `mozroots --import --sync` @@ -222,6 +229,8 @@ Type/ Copy and hit **Enter**. Now time to **move bot to background** and to do that, press **CTRL+B+D** (this will ditach the nadeko session using TMUX), and you can finally close PuTTY now. +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. + **NOW YOU HAVE YOUR OWN NADEKO BOT** `Thanks to Kwoth <3` ######SOME MORE INFO (JUST TO KNOW): diff --git a/NadekoBot/Classes/DBHandler.cs b/NadekoBot/Classes/DBHandler.cs index 3f2963cc..db8dee81 100644 --- a/NadekoBot/Classes/DBHandler.cs +++ b/NadekoBot/Classes/DBHandler.cs @@ -13,129 +13,74 @@ namespace NadekoBot.Classes private string FilePath { get; } = "data/nadekobot.sqlite"; + public SQLiteConnection Connection { get; set; } + static DbHandler() { } public DbHandler() { - using (var conn = new SQLiteConnection(FilePath)) + Connection = new SQLiteConnection(FilePath); + Connection.CreateTable(); + Connection.CreateTable(); + Connection.CreateTable(); + Connection.CreateTable(); + Connection.CreateTable(); + Connection.CreateTable(); + Connection.CreateTable(); + Connection.CreateTable(); + Connection.CreateTable(); + Connection.CreateTable(); + Connection.CreateTable(); + Connection.CreateTable(); + Connection.CreateTable(); + Connection.CreateTable(); + Connection.CreateTable(); + Connection.Execute(Queries.TransactionTriggerQuery); + try { - conn.CreateTable(); - conn.CreateTable(); - conn.CreateTable(); - conn.CreateTable(); - conn.CreateTable(); - conn.CreateTable(); - conn.CreateTable(); - conn.CreateTable(); - conn.CreateTable(); - conn.CreateTable(); - conn.CreateTable(); - conn.CreateTable(); - conn.CreateTable(); - conn.CreateTable(); - conn.CreateTable(); - conn.Execute(Queries.TransactionTriggerQuery); - try - { - conn.Execute(Queries.DeletePlaylistTriggerQuery); - } - catch (Exception ex) - { - Console.WriteLine(ex); - } + Connection.Execute(Queries.DeletePlaylistTriggerQuery); + } + catch (Exception ex) + { + Console.WriteLine(ex); } } internal T FindOne(Expression> p) where T : IDataModel, new() { - using (var conn = new SQLiteConnection(FilePath)) - { - return conn.Table().Where(p).FirstOrDefault(); - } + return Connection.Table().Where(p).FirstOrDefault(); + } internal IList FindAll(Expression> p) where T : IDataModel, new() { - using (var conn = new SQLiteConnection(FilePath)) - { - return conn.Table().Where(p).ToList(); - } - } - internal void DeleteAll() where T : IDataModel - { - using (var conn = new SQLiteConnection(FilePath)) - { - conn.DeleteAll(); - } + return Connection.Table().Where(p).ToList(); + } internal void DeleteWhere(Expression> p) where T : IDataModel, new() { - using (var conn = new SQLiteConnection(FilePath)) - { - var id = conn.Table().Where(p).FirstOrDefault()?.Id; - if (id.HasValue) - conn.Delete(id); - } - } - - internal void InsertData(T o) where T : IDataModel - { - using (var conn = new SQLiteConnection(FilePath)) - { - conn.Insert(o, typeof(T)); - } - } - - internal void InsertMany(T objects) where T : IEnumerable - { - using (var conn = new SQLiteConnection(FilePath)) - { - conn.InsertAll(objects); - } - } - - internal void UpdateData(T o) where T : IDataModel - { - using (var conn = new SQLiteConnection(FilePath)) - { - conn.Update(o, typeof(T)); - } - } - - internal void UpdateAll(IEnumerable objs) where T : IDataModel - { - using (var conn = new SQLiteConnection(FilePath)) - { - conn.UpdateAll(objs); - } + var id = Connection.Table().Where(p).FirstOrDefault()?.Id; + if (id.HasValue) + Connection.Delete(id); } internal HashSet GetAllRows() where T : IDataModel, new() { - using (var conn = new SQLiteConnection(FilePath)) - { - return new HashSet(conn.Table()); - } + return new HashSet(Connection.Table()); } internal CurrencyState GetStateByUserId(long id) { - using (var conn = new SQLiteConnection(FilePath)) - { - return conn.Table().Where(x => x.UserId == id).FirstOrDefault(); - } + return Connection.Table().Where(x => x.UserId == id).FirstOrDefault(); } internal T Delete(int id) where T : IDataModel, new() { - using (var conn = new SQLiteConnection(FilePath)) - { - var found = conn.Find(id); - if (found != null) - conn.Delete(found.Id); - return found; - } + var found = Connection.Find(id); + if (found != null) + Connection.Delete(found.Id); + return found; } /// @@ -143,14 +88,11 @@ namespace NadekoBot.Classes /// internal void Save(T o) where T : IDataModel, new() { - using (var conn = new SQLiteConnection(FilePath)) - { - var found = conn.Find(o.Id); - if (found == null) - conn.Insert(o, typeof(T)); - else - conn.Update(o, typeof(T)); - } + var found = Connection.Find(o.Id); + if (found == null) + Connection.Insert(o, typeof(T)); + else + Connection.Update(o, typeof(T)); } /// @@ -158,20 +100,14 @@ namespace NadekoBot.Classes /// internal void SaveAll(IEnumerable ocol) where T : IDataModel, new() { - using (var conn = new SQLiteConnection(FilePath)) - { - foreach (var o in ocol) - conn.InsertOrReplace(o); - } + foreach (var o in ocol) + Connection.InsertOrReplace(o); } internal T GetRandom(Expression> p) where T : IDataModel, new() { - using (var conn = new SQLiteConnection(FilePath)) - { - var r = new Random(); - return conn.Table().Where(p).ToList().OrderBy(x => r.Next()).FirstOrDefault(); - } + var r = new Random(); + return Connection.Table().Where(p).ToList().OrderBy(x => r.Next()).FirstOrDefault(); } /// /// @@ -180,24 +116,19 @@ namespace NadekoBot.Classes /// internal List GetPlaylistData(int num) { - using (var conn = new SQLiteConnection(FilePath)) - { - return conn.Query( + return Connection.Query( @"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); - } + } internal IEnumerable GetTopRichest(int n = 10) { - using (var conn = new SQLiteConnection(FilePath)) - { - return conn.Table().OrderByDescending(cs => cs.Value).Take(n).ToList(); - } + return Connection.Table().OrderByDescending(cs => cs.Value).Take(n).ToList(); } } } diff --git a/NadekoBot/Classes/FlowersHandler.cs b/NadekoBot/Classes/FlowersHandler.cs index 6fa042ea..57191c63 100644 --- a/NadekoBot/Classes/FlowersHandler.cs +++ b/NadekoBot/Classes/FlowersHandler.cs @@ -10,7 +10,7 @@ namespace NadekoBot.Classes return; await Task.Run(() => { - DbHandler.Instance.InsertData(new DataModels.CurrencyTransaction + DbHandler.Instance.Connection.Insert(new DataModels.CurrencyTransaction { Reason = reason, UserId = (long)u.Id, @@ -36,7 +36,7 @@ namespace NadekoBot.Classes if (state.Value < amount) return false; - DbHandler.Instance.InsertData(new DataModels.CurrencyTransaction + DbHandler.Instance.Connection.Insert(new DataModels.CurrencyTransaction { Reason = reason, UserId = (long)u.Id, diff --git a/NadekoBot/Classes/IncidentsHandler.cs b/NadekoBot/Classes/IncidentsHandler.cs index 5d8190fe..3042f824 100644 --- a/NadekoBot/Classes/IncidentsHandler.cs +++ b/NadekoBot/Classes/IncidentsHandler.cs @@ -19,7 +19,7 @@ namespace NadekoBot.Classes Read = false }; - DbHandler.Instance.InsertData(incident); + DbHandler.Instance.Connection.Insert(incident, typeof(Incident)); } } } diff --git a/NadekoBot/Classes/NadekoStats.cs b/NadekoBot/Classes/NadekoStats.cs index 3ccbc272..8161348a 100644 --- a/NadekoBot/Classes/NadekoStats.cs +++ b/NadekoBot/Classes/NadekoStats.cs @@ -46,20 +46,7 @@ namespace NadekoBot commandService.CommandExecuted += StatsCollector_RanCommand; commandService.CommandFinished += CommandService_CommandFinished; - commandService.CommandErrored += (s, e) => - { - try - { - if (e.ErrorType == CommandErrorType.Exception) - File.AppendAllText("errors.txt", $@"Command: {e.Command} -{e.Exception} -------------------------------------- -"); - } - catch { - Console.WriteLine("Command errored errorring"); - } - }; + commandService.CommandErrored += CommandService_CommandFinished; Task.Run(StartCollecting); @@ -208,7 +195,7 @@ namespace NadekoBot .ConfigureAwait(false); var connectedServers = NadekoBot.Client.Servers.Count(); - Classes.DbHandler.Instance.InsertData(new DataModels.Stats + Classes.DbHandler.Instance.Connection.Insert(new DataModels.Stats { OnlineUsers = onlineUsers, RealOnlineUsers = realOnlineUsers, @@ -236,10 +223,31 @@ namespace NadekoBot private void CommandService_CommandFinished(object sender, CommandEventArgs e) { + DateTime dt; if (!commandTracker.TryGetValue(e.Message.Id, out dt)) return; - Console.WriteLine($">>COMMAND ENDED after *{(DateTime.UtcNow - dt).TotalSeconds}s*\nCmd: {e.Command.Text}\nMsg: {e.Message.Text}\nUsr: {e.User.Name} [{e.User.Id}]\nSrvr: {e.Server?.Name ?? "PRIVATE"} [{e.Server?.Id}]\n-----"); + try + { + if (e is CommandErrorEventArgs) + { + var er = e as CommandErrorEventArgs; + if (er.ErrorType == CommandErrorType.Exception) + { + File.AppendAllText("errors.txt", $@"Command: {er.Command} +{er.Exception} +------------------------------------- +"); + Console.WriteLine($">>COMMAND ERRORED after *{(DateTime.UtcNow - dt).TotalSeconds}s*\nCmd: {e.Command.Text}\nMsg: {e.Message.Text}\nUsr: {e.User.Name} [{e.User.Id}]\nSrvr: {e.Server?.Name ?? "PRIVATE"} [{e.Server?.Id}]\n-----"); + } + + } + else + { + Console.WriteLine($">>COMMAND ENDED after *{(DateTime.UtcNow - dt).TotalSeconds}s*\nCmd: {e.Command.Text}\nMsg: {e.Message.Text}\nUsr: {e.User.Name} [{e.User.Id}]\nSrvr: {e.Server?.Name ?? "PRIVATE"} [{e.Server?.Id}]\n-----"); + } + } + catch { } } private async void StatsCollector_RanCommand(object sender, CommandEventArgs e) @@ -252,7 +260,7 @@ namespace NadekoBot try { commandsRan++; - Classes.DbHandler.Instance.InsertData(new DataModels.Command + Classes.DbHandler.Instance.Connection.Insert(new DataModels.Command { ServerId = (long)(e.Server?.Id ?? 0), ServerName = e.Server?.Name ?? "--Direct Message--", diff --git a/NadekoBot/Classes/SearchHelper.cs b/NadekoBot/Classes/SearchHelper.cs index 7f26e1da..a0a59e9b 100644 --- a/NadekoBot/Classes/SearchHelper.cs +++ b/NadekoBot/Classes/SearchHelper.cs @@ -25,16 +25,13 @@ namespace NadekoBot.Classes { private static DateTime lastRefreshed = DateTime.MinValue; private static string token { get; set; } = ""; - private static readonly HttpClient httpClient = new HttpClient(); public static async Task GetResponseStreamAsync(string url, IEnumerable> headers = null, RequestHttpMethod method = RequestHttpMethod.Get) { if (string.IsNullOrWhiteSpace(url)) throw new ArgumentNullException(nameof(url)); - //if its a post or there are no headers, use static httpclient - // if there are headers and it's get, it's not threadsafe - var cl = headers == null || method == RequestHttpMethod.Post ? httpClient : new HttpClient(); + var cl = new HttpClient(); cl.DefaultRequestHeaders.Clear(); switch (method) { @@ -178,7 +175,7 @@ namespace NadekoBot.Classes return null; } - public static async Task GetRelatedVideoId(string id) + public static async Task> GetRelatedVideoIds(string id, int count = 1) { if (string.IsNullOrWhiteSpace(id)) throw new ArgumentNullException(nameof(id)); @@ -189,20 +186,14 @@ namespace NadekoBot.Classes } var response = await GetResponseStringAsync( $"https://www.googleapis.com/youtube/v3/search?" + - $"part=snippet&maxResults=1&type=video" + + $"part=snippet&maxResults={count}&type=video" + $"&relatedToVideoId={id}" + $"&key={NadekoBot.Creds.GoogleAPIKey}").ConfigureAwait(false); JObject obj = JObject.Parse(response); var data = JsonConvert.DeserializeObject(response); - if (data.items.Length > 0) - { - var toReturn = "http://www.youtube.com/watch?v=" + data.items[0].id.videoId.ToString(); - return toReturn; - } - else - return null; + return data.items.Select(v => "http://www.youtube.com/watch?v=" + v.id.videoId); } public static async Task GetPlaylistIdByKeyword(string query) diff --git a/NadekoBot/Modules/Administration/AdministrationModule.cs b/NadekoBot/Modules/Administration/AdministrationModule.cs index 036687aa..23402c81 100644 --- a/NadekoBot/Modules/Administration/AdministrationModule.cs +++ b/NadekoBot/Modules/Administration/AdministrationModule.cs @@ -64,7 +64,7 @@ namespace NadekoBot.Modules.Administration commands.ForEach(cmd => cmd.Init(cgb)); cgb.CreateCommand(Prefix + "delmsgoncmd") - .Description("Toggles the automatic deletion of user's successful command message to prevent chat flood. Server Manager Only.") + .Description($"Toggles the automatic deletion of user's successful command message to prevent chat flood. **Server Manager Only.** | `{Prefix}delmsgoncmd`") .AddCheck(SimpleCheckers.ManageServer()) .Do(async e => { @@ -79,7 +79,7 @@ namespace NadekoBot.Modules.Administration }); cgb.CreateCommand(Prefix + "restart") - .Description("Restarts the bot. Might not work. **Bot Owner Only**") + .Description($"Restarts the bot. Might not work. **Bot Owner Only** | `{Prefix}restart`") .AddCheck(SimpleCheckers.OwnerOnly()) .Do(async e => { @@ -90,7 +90,7 @@ namespace NadekoBot.Modules.Administration }); cgb.CreateCommand(Prefix + "setrole").Alias(Prefix + "sr") - .Description($"Sets a role for a given user. | `{Prefix}sr @User Guest`") + .Description($"Sets a role for a given user. **Needs Manage Roles Permissions.**| `{Prefix}sr @User Guest`") .Parameter("user_name", ParameterType.Required) .Parameter("role_name", ParameterType.Unparsed) .AddCheck(SimpleCheckers.CanManageRoles) @@ -133,7 +133,7 @@ namespace NadekoBot.Modules.Administration }); cgb.CreateCommand(Prefix + "removerole").Alias(Prefix + "rr") - .Description($"Removes a role from a given user. | `{Prefix}rr @User Admin`") + .Description($"Removes a role from a given user. **Needs Manage Roles Permissions.**| `{Prefix}rr @User Admin`") .Parameter("user_name", ParameterType.Required) .Parameter("role_name", ParameterType.Unparsed) .AddCheck(SimpleCheckers.CanManageRoles) @@ -171,7 +171,7 @@ namespace NadekoBot.Modules.Administration cgb.CreateCommand(Prefix + "renamerole") .Alias(Prefix + "renr") - .Description($"Renames a role. Role you are renaming must be lower than bot's highest role. | `{Prefix}renr \"First role\" SecondRole`") + .Description($"Renames a role. Roles you are renaming must be lower than bot's highest role. **Manage Roles Permissions.** | `{Prefix}renr \"First role\" SecondRole`") .Parameter("r1", ParameterType.Required) .Parameter("r2", ParameterType.Required) .AddCheck(new SimpleCheckers.ManageRoles()) @@ -204,7 +204,7 @@ namespace NadekoBot.Modules.Administration }); cgb.CreateCommand(Prefix + "removeallroles").Alias(Prefix + "rar") - .Description($"Removes all roles from a mentioned user. | `{Prefix}rar @User`") + .Description($"Removes all roles from a mentioned user. **Needs Manage Roles Permissions.**| `{Prefix}rar @User`") .Parameter("user_name", ParameterType.Unparsed) .AddCheck(SimpleCheckers.CanManageRoles) .Do(async e => @@ -230,7 +230,7 @@ namespace NadekoBot.Modules.Administration }); cgb.CreateCommand(Prefix + "createrole").Alias(Prefix + "cr") - .Description($"Creates a role with a given name. | `{Prefix}cr Awesome Role`") + .Description($"Creates a role with a given name. **Needs Manage Roles Permissions.**| `{Prefix}cr Awesome Role`") .Parameter("role_name", ParameterType.Unparsed) .AddCheck(SimpleCheckers.CanManageRoles) .Do(async e => @@ -253,7 +253,7 @@ namespace NadekoBot.Modules.Administration .Parameter("r", ParameterType.Optional) .Parameter("g", ParameterType.Optional) .Parameter("b", ParameterType.Optional) - .Description($"Set a role's color to the hex or 0-255 rgb color value provided. | `{Prefix}rc Admin 255 200 100` or `{Prefix}rc Admin ffba55`") + .Description($"Set a role's color to the hex or 0-255 rgb color value provided. **Needs Manage Roles Permissions.** | `{Prefix}rc Admin 255 200 100` or `{Prefix}rc Admin ffba55`") .Do(async e => { if (!e.User.ServerPermissions.ManageRoles) @@ -298,7 +298,7 @@ namespace NadekoBot.Modules.Administration cgb.CreateCommand(Prefix + "ban").Alias(Prefix + "b") .Parameter("user", ParameterType.Required) .Parameter("msg", ParameterType.Unparsed) - .Description($"Bans a user by id or name with an optional message. | `{Prefix}b \"@some Guy\" Your behaviour is toxic.`") + .Description($"Bans a user by id or name with an optional message. **Needs Ban Permissions.**| `{Prefix}b \"@some Guy\" Your behaviour is toxic.`") .Do(async e => { var msg = e.GetArg("msg"); @@ -333,7 +333,7 @@ namespace NadekoBot.Modules.Administration cgb.CreateCommand(Prefix + "softban").Alias(Prefix + "sb") .Parameter("user", ParameterType.Required) .Parameter("msg", ParameterType.Unparsed) - .Description($"Bans and then unbans a user by id or name with an optional message. | `{Prefix}sb \"@some Guy\" Your behaviour is toxic.`") + .Description($"Bans and then unbans a user by id or name with an optional message. **Needs Ban Permissions.**| `{Prefix}sb \"@some Guy\" Your behaviour is toxic.`") .Do(async e => { var msg = e.GetArg("msg"); @@ -369,7 +369,7 @@ namespace NadekoBot.Modules.Administration cgb.CreateCommand(Prefix + "kick").Alias(Prefix + "k") .Parameter("user") .Parameter("msg", ParameterType.Unparsed) - .Description($"Kicks a mentioned user. | `{Prefix}k \"@some Guy\" Your behaviour is toxic.`") + .Description($"Kicks a mentioned user. **Needs Kick Permissions.**| `{Prefix}k \"@some Guy\" Your behaviour is toxic.`") .Do(async e => { var msg = e.GetArg("msg"); @@ -400,13 +400,13 @@ namespace NadekoBot.Modules.Administration } }); cgb.CreateCommand(Prefix + "mute") - .Description($"Mutes mentioned user or users. | `{Prefix}mute \"@Someguy\"` or `{Prefix}mute \"@Someguy\" \"@Someguy\"`") + .Description($"Mutes mentioned user or users. **Needs Mute Permissions.**| `{Prefix}mute \"@Someguy\"` or `{Prefix}mute \"@Someguy\" \"@Someguy\"`") .Parameter("throwaway", ParameterType.Unparsed) .Do(async e => { if (!e.User.ServerPermissions.MuteMembers) { - await e.Channel.SendMessage("You do not have permission to do that.").ConfigureAwait(false); + await e.Channel.SendMessage("I most likely don't have the permission necessary for that.").ConfigureAwait(false); return; } if (!e.Message.MentionedUsers.Any()) @@ -421,12 +421,12 @@ namespace NadekoBot.Modules.Administration } catch { - await e.Channel.SendMessage("I do not have permission to do that most likely.").ConfigureAwait(false); + await e.Channel.SendMessage("I most likely don't have the permission necessary for that.").ConfigureAwait(false); } }); cgb.CreateCommand(Prefix + "unmute") - .Description($"Unmutes mentioned user or users. | `{Prefix}unmute \"@Someguy\"` or `{Prefix}unmute \"@Someguy\" \"@Someguy\"`") + .Description($"Unmutes mentioned user or users. **Needs Mute Permissions.**| `{Prefix}unmute \"@Someguy\"` or `{Prefix}unmute \"@Someguy\" \"@Someguy\"`") .Parameter("throwaway", ParameterType.Unparsed) .Do(async e => { @@ -447,13 +447,13 @@ namespace NadekoBot.Modules.Administration } catch { - await e.Channel.SendMessage("I do not have permission to do that most likely.").ConfigureAwait(false); + await e.Channel.SendMessage("I most likely don't have the permission necessary for that.").ConfigureAwait(false); } }); cgb.CreateCommand(Prefix + "deafen") .Alias(Prefix + "deaf") - .Description($"Deafens mentioned user or users | `{Prefix}deaf \"@Someguy\"` or `{Prefix}deaf \"@Someguy\" \"@Someguy\"`") + .Description($"Deafens mentioned user or users. **Needs Deafen Permissions.**| `{Prefix}deaf \"@Someguy\"` or `{Prefix}deaf \"@Someguy\" \"@Someguy\"`") .Parameter("throwaway", ParameterType.Unparsed) .Do(async e => { @@ -474,13 +474,13 @@ namespace NadekoBot.Modules.Administration } catch { - await e.Channel.SendMessage("I do not have permission to do that most likely.").ConfigureAwait(false); + await e.Channel.SendMessage("I most likely don't have the permission necessary for that.").ConfigureAwait(false); } }); cgb.CreateCommand(Prefix + "undeafen") .Alias(Prefix + "undef") - .Description($"Undeafens mentioned user or users | `{Prefix}undef \"@Someguy\"` or `{Prefix}undef \"@Someguy\" \"@Someguy\"`") + .Description($"Undeafens mentioned user or users. **Needs Deafen Permissions.** | `{Prefix}undef \"@Someguy\"` or `{Prefix}undef \"@Someguy\" \"@Someguy\"`") .Parameter("throwaway", ParameterType.Unparsed) .Do(async e => { @@ -501,13 +501,13 @@ namespace NadekoBot.Modules.Administration } catch { - await e.Channel.SendMessage("I do not have permission to do that most likely.").ConfigureAwait(false); + await e.Channel.SendMessage("I most likely don't have the permission necessary for that.").ConfigureAwait(false); } }); cgb.CreateCommand(Prefix + "delvoichanl") .Alias(Prefix + "dvch") - .Description($"Deletes a voice channel with a given name. | `{Prefix}dvch VoiceChannelName`") + .Description($"Deletes a voice channel with a given name. **Needs Manage Channel Permissions.**| `{Prefix}dvch VoiceChannelName`") .Parameter("channel_name", ParameterType.Required) .Do(async e => { @@ -530,7 +530,7 @@ namespace NadekoBot.Modules.Administration cgb.CreateCommand(Prefix + "creatvoichanl") .Alias(Prefix + "cvch") - .Description($"Creates a new voice channel with a given name. | `{Prefix}cvch VoiceChannelName`") + .Description($"Creates a new voice channel with a given name. **Needs Manage Channel Permissions.** | `{Prefix}cvch VoiceChannelName`") .Parameter("channel_name", ParameterType.Required) .Do(async e => { @@ -550,7 +550,7 @@ namespace NadekoBot.Modules.Administration cgb.CreateCommand(Prefix + "deltxtchanl") .Alias(Prefix + "dtch") - .Description($"Deletes a text channel with a given name. | `{Prefix}dtch TextChannelName`") + .Description($"Deletes a text channel with a given name. **Needs Manage Channel Permissions.** | `{Prefix}dtch TextChannelName`") .Parameter("channel_name", ParameterType.Required) .Do(async e => { @@ -572,7 +572,7 @@ namespace NadekoBot.Modules.Administration cgb.CreateCommand(Prefix + "creatxtchanl") .Alias(Prefix + "ctch") - .Description($"Creates a new text channel with a given name. | `{Prefix}ctch TextChannelName`") + .Description($"Creates a new text channel with a given name. **Needs Manage Channel Permissions.** | `{Prefix}ctch TextChannelName`") .Parameter("channel_name", ParameterType.Required) .Do(async e => { @@ -592,7 +592,7 @@ namespace NadekoBot.Modules.Administration cgb.CreateCommand(Prefix + "settopic") .Alias(Prefix + "st") - .Description($"Sets a topic on the current channel. | `{Prefix}st My new topic`") + .Description($"Sets a topic on the current channel. **Needs Manage Channel Permissions.** | `{Prefix}st My new topic`") .AddCheck(SimpleCheckers.ManageChannels()) .Parameter("topic", ParameterType.Unparsed) .Do(async e => @@ -604,7 +604,7 @@ namespace NadekoBot.Modules.Administration cgb.CreateCommand(Prefix + "setchanlname") .Alias(Prefix + "schn") - .Description($"Changed the name of the current channel.| `{Prefix}schn NewName`") + .Description($"Changed the name of the current channel. **Needs Manage Channel Permissions.**| `{Prefix}schn NewName`") .AddCheck(SimpleCheckers.ManageChannels()) .Parameter("name", ParameterType.Unparsed) .Do(async e => @@ -617,7 +617,7 @@ namespace NadekoBot.Modules.Administration }); cgb.CreateCommand(Prefix + "heap") - .Description("Shows allocated memory - **Bot Owner Only!**") + .Description($"Shows allocated memory - **Bot Owner Only!** | `{Prefix}heap`") .AddCheck(SimpleCheckers.OwnerOnly()) .Do(async e => { @@ -628,19 +628,19 @@ namespace NadekoBot.Modules.Administration cgb.CreateCommand(Prefix + "prune") .Alias(Prefix + "clr") .Description( - "`.prune` removes all nadeko's messages in the last 100 messages.`.prune X` removes last X messages from the channel (up to 100)`.prune @Someone` removes all Someone's messages in the last 100 messages.`.prune @Someone X` removes last X 'Someone's' messages in the channel. | `.prune` or `.prune 5` or `.prune @Someone` or `.prune @Someone X`") + "`.prune` removes all nadeko's messages in the last 100 messages.`.prune X` removes last X messages from the channel (up to 100)`.prune @Someone` removes all Someone's messages in the last 100 messages.`.prune @Someone X` removes last X 'Someone's' messages in the channel. " + + $"| `{Prefix}prune` or `{Prefix}prune 5` or `{Prefix}prune @Someone` or `{Prefix}prune @Someone X`") .Parameter("user_or_num", ParameterType.Optional) .Parameter("num", ParameterType.Optional) .Do(async e => { - Message[] msgs; if (string.IsNullOrWhiteSpace(e.GetArg("user_or_num"))) // if nothing is set, clear nadeko's messages, no permissions required { - msgs = (await e.Channel.DownloadMessages(100).ConfigureAwait(false));//.Where(m => m.User.Id == e.Server.CurrentUser.Id).ToArray(); - msgs = msgs.Where(m => m.User.Id == e.Server.CurrentUser.Id).ToArray(); - if (!msgs.Any()) + var msgs = (await e.Channel.DownloadMessages(100).ConfigureAwait(false)).Where(m => m.User?.Id == e.Server.CurrentUser.Id)?.ToArray(); + if (msgs == null || !msgs.Any()) return; - await e.Channel.DeleteMessages(msgs).ConfigureAwait(false); + var toDelete = msgs as Message[] ?? msgs.ToArray(); + await e.Channel.DeleteMessages(toDelete).ConfigureAwait(false); return; } if (!e.User.GetPermissions(e.Channel).ManageMessages) @@ -667,14 +667,14 @@ namespace NadekoBot.Modules.Administration val = 100; if (!int.TryParse(e.GetArg("num"), out val)) val = 100; - msgs = (await e.Channel.DownloadMessages(100).ConfigureAwait(false)).Where(m => m.User.Id == usr.Id).Take(val).ToArray(); - if (!msgs.Any()) + var mesgs = (await e.Channel.DownloadMessages(100).ConfigureAwait(false)).Where(m => m.User?.Id == usr.Id).Take(val); + if (mesgs == null || !mesgs.Any()) return; - await e.Channel.DeleteMessages(msgs).ConfigureAwait(false); + await e.Channel.DeleteMessages(mesgs as Message[] ?? mesgs.ToArray()).ConfigureAwait(false); }); cgb.CreateCommand(Prefix + "die") - .Description("Shuts the bot down and notifies users about the restart. **Bot Owner Only!**") + .Description($"Shuts the bot down and notifies users about the restart. **Bot Owner Only!** | `{Prefix}die`") .AddCheck(SimpleCheckers.OwnerOnly()) .Do(async e => { @@ -807,7 +807,7 @@ namespace NadekoBot.Modules.Administration }); cgb.CreateCommand(Prefix + "unstuck") - .Description("Clears the message queue. **Bot Owner Only!**") + .Description($"Clears the message queue. **Bot Owner Only!** | `{Prefix}unstuck`") .AddCheck(SimpleCheckers.OwnerOnly()) .Do(e => { @@ -815,7 +815,7 @@ namespace NadekoBot.Modules.Administration }); cgb.CreateCommand(Prefix + "donators") - .Description("List of lovely people who donated to keep this project alive.") + .Description($"List of lovely people who donated to keep this project alive. | `{Prefix}donators`") .Do(async e => { await Task.Run(async () => @@ -829,7 +829,7 @@ namespace NadekoBot.Modules.Administration }); cgb.CreateCommand(Prefix + "donadd") - .Description($"Add a donator to the database. | `.donadd Donate Amount`") + .Description($"Add a donator to the database. **Kwoth Only** | `{Prefix}donadd Donate Amount`") .Parameter("donator") .Parameter("amount") .AddCheck(SimpleCheckers.OwnerOnly()) @@ -842,7 +842,7 @@ namespace NadekoBot.Modules.Administration if (donator == null) return; try { - DbHandler.Instance.InsertData(new Donator + DbHandler.Instance.Connection.Insert(new Donator { Amount = amount, UserName = donator.Name, diff --git a/NadekoBot/Modules/Administration/Commands/AutoAssignRole.cs b/NadekoBot/Modules/Administration/Commands/AutoAssignRole.cs index c368aa0b..38084dfa 100644 --- a/NadekoBot/Modules/Administration/Commands/AutoAssignRole.cs +++ b/NadekoBot/Modules/Administration/Commands/AutoAssignRole.cs @@ -34,7 +34,7 @@ namespace NadekoBot.Modules.Administration.Commands { cgb.CreateCommand(Module.Prefix + "autoassignrole") .Alias(Module.Prefix + "aar") - .Description($"Automaticaly assigns a specified role to every user who joins the server. Type `.aar` to disable, `.aar Role Name` to enable") + .Description($"Automaticaly assigns a specified role to every user who joins the server. **Needs Manage Roles Permissions.** |`{Prefix}aar` to disable, `{Prefix}aar Role Name` to enable") .Parameter("role", ParameterType.Unparsed) .AddCheck(new SimpleCheckers.ManageRoles()) .Do(async e => diff --git a/NadekoBot/Modules/Administration/Commands/CrossServerTextChannel.cs b/NadekoBot/Modules/Administration/Commands/CrossServerTextChannel.cs index 0d2a3fe7..c08c34ef 100644 --- a/NadekoBot/Modules/Administration/Commands/CrossServerTextChannel.cs +++ b/NadekoBot/Modules/Administration/Commands/CrossServerTextChannel.cs @@ -64,8 +64,8 @@ namespace NadekoBot.Modules.Administration.Commands internal override void Init(CommandGroupBuilder cgb) { cgb.CreateCommand(Module.Prefix + "scsc") - .Description("Starts an instance of cross server channel. You will get a token as a DM" + - "that other people will use to tune in to the same instance") + .Description("Starts an instance of cross server channel. You will get a token as a DM " + + $"that other people will use to tune in to the same instance. **Bot Owner Only.** | `{Prefix}scsc`") .AddCheck(SimpleCheckers.OwnerOnly()) .Do(async e => { @@ -79,7 +79,7 @@ namespace NadekoBot.Modules.Administration.Commands }); cgb.CreateCommand(Module.Prefix + "jcsc") - .Description("Joins current channel to an instance of cross server channel using the token.") + .Description($"Joins current channel to an instance of cross server channel using the token. **Needs Manage Server Permissions.**| `{Prefix}jcsc`") .Parameter("token") .AddCheck(SimpleCheckers.ManageServer()) .Do(async e => @@ -95,7 +95,7 @@ namespace NadekoBot.Modules.Administration.Commands }); cgb.CreateCommand(Module.Prefix + "lcsc") - .Description("Leaves Cross server channel instance from this channel") + .Description($"Leaves Cross server channel instance from this channel. **Needs Manage Server Permissions.**| `{Prefix}lcsc`") .AddCheck(SimpleCheckers.ManageServer()) .Do(async e => { diff --git a/NadekoBot/Modules/Administration/Commands/CustomReactionsCommands.cs b/NadekoBot/Modules/Administration/Commands/CustomReactionsCommands.cs index a01f9a8d..2725e196 100644 --- a/NadekoBot/Modules/Administration/Commands/CustomReactionsCommands.cs +++ b/NadekoBot/Modules/Administration/Commands/CustomReactionsCommands.cs @@ -23,7 +23,7 @@ namespace NadekoBot.Modules.Administration.Commands cgb.CreateCommand(Prefix + "addcustreact") .Alias(Prefix + "acr") - .Description($"Add a custom reaction. Guide here: **Bot Owner Only!** | {Prefix}acr \"hello\" I love saying hello to %user%") + .Description($"Add a custom reaction. Guide here: **Bot Owner Only!** | `{Prefix}acr \"hello\" I love saying hello to %user%`") .AddCheck(SimpleCheckers.OwnerOnly()) .Parameter("name", ParameterType.Required) .Parameter("message", ParameterType.Unparsed) @@ -47,7 +47,7 @@ namespace NadekoBot.Modules.Administration.Commands cgb.CreateCommand(Prefix + "listcustreact") .Alias(Prefix + "lcr") - .Description($"Lists custom reactions (paginated with 30 commands per page). Use 'all' instead of page number to get all custom reactions DM-ed to you. |{Prefix}lcr 1") + .Description($"Lists custom reactions (paginated with 30 commands per page). Use 'all' instead of page number to get all custom reactions DM-ed to you. |`{Prefix}lcr 1`") .Parameter("num", ParameterType.Required) .Do(async e => { @@ -80,7 +80,7 @@ namespace NadekoBot.Modules.Administration.Commands cgb.CreateCommand(Prefix + "showcustreact") .Alias(Prefix + "scr") - .Description($"Shows all possible responses from a single custom reaction. |{Prefix}scr %mention% bb") + .Description($"Shows all possible responses from a single custom reaction. |`{Prefix}scr %mention% bb`") .Parameter("name", ParameterType.Unparsed) .Do(async e => { @@ -106,7 +106,7 @@ namespace NadekoBot.Modules.Administration.Commands cgb.CreateCommand(Prefix + "editcustreact") .Alias(Prefix + "ecr") - .Description("Edits a custom reaction, arguments are custom reactions name, index to change, and a (multiword) message **Bot Owner Only** | `.ecr \"%mention% disguise\" 2 Test 123`") + .Description($"Edits a custom reaction, arguments are custom reactions name, index to change, and a (multiword) message **Bot Owner Only** | `{Prefix}ecr \"%mention% disguise\" 2 Test 123`") .Parameter("name", ParameterType.Required) .Parameter("index", ParameterType.Required) .Parameter("message", ParameterType.Unparsed) @@ -146,7 +146,7 @@ namespace NadekoBot.Modules.Administration.Commands cgb.CreateCommand(Prefix + "delcustreact") .Alias(Prefix + "dcr") - .Description("Deletes a custom reaction with given name (and index)") + .Description($"Deletes a custom reaction with given name (and index). **Bot Owner Only.**| `{Prefix}dcr index`") .Parameter("name", ParameterType.Required) .Parameter("index", ParameterType.Optional) .AddCheck(SimpleCheckers.OwnerOnly()) diff --git a/NadekoBot/Modules/Administration/Commands/IncidentsCommands.cs b/NadekoBot/Modules/Administration/Commands/IncidentsCommands.cs index a5854708..ab93693a 100644 --- a/NadekoBot/Modules/Administration/Commands/IncidentsCommands.cs +++ b/NadekoBot/Modules/Administration/Commands/IncidentsCommands.cs @@ -14,26 +14,26 @@ namespace NadekoBot.Modules.Administration.Commands { cgb.CreateCommand(Module.Prefix + "listincidents") .Alias(Prefix + "lin") - .Description("List all UNREAD incidents and flags them as read.") + .Description($"List all UNREAD incidents and flags them as read. **Needs Manage Server Permissions.**| `{Prefix}lin`") .AddCheck(SimpleCheckers.ManageServer()) .Do(async e => { var sid = (long)e.Server.Id; var incs = DbHandler.Instance.FindAll(i => i.ServerId == sid && i.Read == false); - DbHandler.Instance.UpdateAll(incs.Select(i => { i.Read = true; return i; })); + DbHandler.Instance.Connection.UpdateAll(incs.Select(i => { i.Read = true; return i; })); await e.User.SendMessage(string.Join("\n----------------------", incs.Select(i => i.Text))); }); cgb.CreateCommand(Module.Prefix + "listallincidents") .Alias(Prefix + "lain") - .Description("Sends you a file containing all incidents and flags them as read.") + .Description($"Sends you a file containing all incidents and flags them as read. **Needs Manage Server Permissions.**| `{Prefix}lain`") .AddCheck(SimpleCheckers.ManageServer()) .Do(async e => { var sid = (long)e.Server.Id; var incs = DbHandler.Instance.FindAll(i => i.ServerId == sid); - DbHandler.Instance.UpdateAll(incs.Select(i => { i.Read = true; return i; })); + DbHandler.Instance.Connection.UpdateAll(incs.Select(i => { i.Read = true; return i; })); var data = string.Join("\n----------------------\n", incs.Select(i => i.Text)); MemoryStream ms = new MemoryStream(); var sw = new StreamWriter(ms); diff --git a/NadekoBot/Modules/Administration/Commands/LogCommand.cs b/NadekoBot/Modules/Administration/Commands/LogCommand.cs index 3bbce6d2..b5f19eb1 100644 --- a/NadekoBot/Modules/Administration/Commands/LogCommand.cs +++ b/NadekoBot/Modules/Administration/Commands/LogCommand.cs @@ -4,7 +4,10 @@ using NadekoBot.Classes; using NadekoBot.Extensions; using NadekoBot.Modules.Permissions.Classes; using System; +using System.Collections.Concurrent; +using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; namespace NadekoBot.Modules.Administration.Commands { @@ -12,6 +15,8 @@ namespace NadekoBot.Modules.Administration.Commands { private string prettyCurrentTime => $"【{DateTime.Now:HH:mm:ss}】"; + private ConcurrentBag> voicePresenceUpdates = new ConcurrentBag>(); + public LogCommand(DiscordModule module) : base(module) { NadekoBot.Client.MessageReceived += MsgRecivd; @@ -45,6 +50,36 @@ namespace NadekoBot.Modules.Administration.Commands } catch { } }; + + // start the userpresence queue + + NadekoBot.OnReady += () => Task.Run(async () => + { + while (true) + { + var toSend = new Dictionary(); + //take everything from the queue and merge the messages which are going to the same channel + KeyValuePair item; + while (voicePresenceUpdates.TryTake(out item)) + { + if (toSend.ContainsKey(item.Key)) + { + toSend[item.Key] = toSend[item.Key] + Environment.NewLine + item.Value; + } + else + { + toSend.Add(item.Key, item.Value); + } + } + //send merged messages to each channel + foreach (var k in toSend) + { + try { await k.Key.SendMessage(Environment.NewLine + k.Value).ConfigureAwait(false); } catch { } + } + + await Task.Delay(5000); + } + }); } private async void ChannelUpdated(object sender, ChannelUpdatedEventArgs e) @@ -177,13 +212,13 @@ namespace NadekoBot.Modules.Administration.Commands if (!string.IsNullOrWhiteSpace(e.Message.Text)) { await ch.SendMessage( - $@"🕔`{prettyCurrentTime}` **New Message** `#{e.Channel.Name}` + $@"🕔`{prettyCurrentTime}` **New Message** `#{e.Channel.Name}` 👤`{e.User?.ToString() ?? ("NULL")}` {e.Message.Text.Unmention()}").ConfigureAwait(false); } else { await ch.SendMessage( - $@"🕔`{prettyCurrentTime}` **File Uploaded** `#{e.Channel.Name}` + $@"🕔`{prettyCurrentTime}` **File Uploaded** `#{e.Channel.Name}` 👤`{e.User?.ToString() ?? ("NULL")}` {e.Message.Attachments.FirstOrDefault()?.ProxyUrl}").ConfigureAwait(false); } @@ -206,13 +241,13 @@ namespace NadekoBot.Modules.Administration.Commands if (!string.IsNullOrWhiteSpace(e.Message.Text)) { await ch.SendMessage( - $@"🕔`{prettyCurrentTime}` **Message** 🚮 `#{e.Channel.Name}` + $@"🕔`{prettyCurrentTime}` **Message** 🚮 `#{e.Channel.Name}` 👤`{e.User?.ToString() ?? ("NULL")}` {e.Message.Text.Unmention()}").ConfigureAwait(false); } else { await ch.SendMessage( - $@"🕔`{prettyCurrentTime}` **File Deleted** `#{e.Channel.Name}` + $@"🕔`{prettyCurrentTime}` **File Deleted** `#{e.Channel.Name}` 👤`{e.User?.ToString() ?? ("NULL")}` {e.Message.Attachments.FirstOrDefault()?.ProxyUrl}").ConfigureAwait(false); } } @@ -232,7 +267,7 @@ namespace NadekoBot.Modules.Administration.Commands if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null) return; await ch.SendMessage( -$@"🕔`{prettyCurrentTime}` **Message** 📝 `#{e.Channel.Name}` + $@"🕔`{prettyCurrentTime}` **Message** 📝 `#{e.Channel.Name}` 👤`{e.User?.ToString() ?? ("NULL")}` `Old:` {e.Before.Text.Unmention()} `New:` {e.After.Text.Unmention()}").ConfigureAwait(false); @@ -252,7 +287,7 @@ $@"🕔`{prettyCurrentTime}` **Message** 📝 `#{e.Channel.Name}` { if (e.Before.Status != e.After.Status) { - await ch.SendMessage($"`{prettyCurrentTime}`**{e.Before.Name}** is now **{e.After.Status}**.").ConfigureAwait(false); + voicePresenceUpdates.Add(new KeyValuePair(ch, $"`{prettyCurrentTime}`**{e.Before.Name}** is now **{e.After.Status}**.")); } } } @@ -340,7 +375,7 @@ $@"🕔`{prettyCurrentTime}` **Message** 📝 `#{e.Channel.Name}` { cgb.CreateCommand(Module.Prefix + "spmom") - .Description("Toggles whether mentions of other offline users on your server will send a pm to them.") + .Description($"Toggles whether mentions of other offline users on your server will send a pm to them. **Needs Manage Server Permissions.**| `{Prefix}spmom`") .AddCheck(SimpleCheckers.ManageServer()) .Do(async e => { @@ -356,7 +391,7 @@ $@"🕔`{prettyCurrentTime}` **Message** 📝 `#{e.Channel.Name}` }); cgb.CreateCommand(Module.Prefix + "logserver") - .Description("Toggles logging in this channel. Logs every message sent/deleted/edited on the server. **Bot Owner Only!**") + .Description($"Toggles logging in this channel. Logs every message sent/deleted/edited on the server. **Bot Owner Only!** | `{Prefix}logserver`") .AddCheck(SimpleCheckers.OwnerOnly()) .AddCheck(SimpleCheckers.ManageServer()) .Do(async e => @@ -371,14 +406,14 @@ $@"🕔`{prettyCurrentTime}` **Message** 📝 `#{e.Channel.Name}` Channel ch; if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null) return; - - SpecificConfigurations.Default.Of (e.Server.Id).LogServerChannel = null; + + SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel = null; await e.Channel.SendMessage($"❗**NO LONGER LOGGING IN {ch.Mention} CHANNEL**❗").ConfigureAwait(false); }); cgb.CreateCommand(Prefix + "logignore") - .Description($"Toggles whether the {Prefix}logserver command ignores this channel. Useful if you have hidden admin channel and public log channel.") + .Description($"Toggles whether the {Prefix}logserver command ignores this channel. Useful if you have hidden admin channel and public log channel. **Bot Owner Only!**| `{Prefix}logignore`") .AddCheck(SimpleCheckers.OwnerOnly()) .AddCheck(SimpleCheckers.ManageServer()) .Do(async e => @@ -396,7 +431,7 @@ $@"🕔`{prettyCurrentTime}` **Message** 📝 `#{e.Channel.Name}` }); cgb.CreateCommand(Module.Prefix + "userpresence") - .Description("Starts logging to this channel when someone from the server goes online/offline/idle.") + .Description($"Starts logging to this channel when someone from the server goes online/offline/idle. **Needs Manage Server Permissions.**| `{Prefix}userpresence`") .AddCheck(SimpleCheckers.ManageServer()) .Do(async e => { @@ -412,7 +447,7 @@ $@"🕔`{prettyCurrentTime}` **Message** 📝 `#{e.Channel.Name}` }); cgb.CreateCommand(Module.Prefix + "voicepresence") - .Description("Toggles logging to this channel whenever someone joins or leaves a voice channel you are in right now.") + .Description($"Toggles logging to this channel whenever someone joins or leaves a voice channel you are in right now. **Needs Manage Server Permissions.**| `{Prefix}voicerpresence`") .Parameter("all", ParameterType.Optional) .AddCheck(SimpleCheckers.ManageServer()) .Do(async e => diff --git a/NadekoBot/Modules/Administration/Commands/MessageRepeater.cs b/NadekoBot/Modules/Administration/Commands/MessageRepeater.cs index 4aa521a1..e87f5555 100644 --- a/NadekoBot/Modules/Administration/Commands/MessageRepeater.cs +++ b/NadekoBot/Modules/Administration/Commands/MessageRepeater.cs @@ -57,7 +57,7 @@ namespace NadekoBot.Modules.Administration.Commands cgb.CreateCommand(Module.Prefix + "repeatinvoke") .Alias(Module.Prefix + "repinv") - .Description("Immediately shows the repeat message and restarts the timer.") + .Description($"Immediately shows the repeat message and restarts the timer. **Needs Manage Messages Permissions.**| `{Prefix}repinv`") .AddCheck(SimpleCheckers.ManageMessages()) .Do(async e => { @@ -73,7 +73,7 @@ namespace NadekoBot.Modules.Administration.Commands cgb.CreateCommand(Module.Prefix + "repeat") .Description("Repeat a message every X minutes. If no parameters are specified, " + - "repeat is disabled. Requires manage messages. |`.repeat 5 Hello there`") + $"repeat is disabled. **Needs Manage Messages Permissions.** |`{Prefix}repeat 5 Hello there`") .Parameter("minutes", ParameterType.Optional) .Parameter("msg", ParameterType.Unparsed) .AddCheck(SimpleCheckers.ManageMessages()) diff --git a/NadekoBot/Modules/Administration/Commands/PlayingRotate.cs b/NadekoBot/Modules/Administration/Commands/PlayingRotate.cs index 2d22d870..c1caa0bc 100644 --- a/NadekoBot/Modules/Administration/Commands/PlayingRotate.cs +++ b/NadekoBot/Modules/Administration/Commands/PlayingRotate.cs @@ -96,14 +96,14 @@ namespace NadekoBot.Modules.Administration.Commands { cgb.CreateCommand(Module.Prefix + "rotateplaying") .Alias(Module.Prefix + "ropl") - .Description("Toggles rotation of playing status of the dynamic strings you specified earlier.") + .Description($"Toggles rotation of playing status of the dynamic strings you specified earlier. **Bot Owner Only!** | `{Prefix}ropl`") .AddCheck(SimpleCheckers.OwnerOnly()) .Do(DoFunc()); cgb.CreateCommand(Module.Prefix + "addplaying") .Alias(Module.Prefix + "adpl") .Description("Adds a specified string to the list of playing strings to rotate. " + - "Supported placeholders: " + string.Join(", ", PlayingPlaceholders.Keys)) + "Supported placeholders: " + string.Join(", ", PlayingPlaceholders.Keys)+ $" **Bot Owner Only!**| `{Prefix}adpl`") .Parameter("text", ParameterType.Unparsed) .AddCheck(SimpleCheckers.OwnerOnly()) .Do(async e => @@ -126,7 +126,7 @@ namespace NadekoBot.Modules.Administration.Commands cgb.CreateCommand(Module.Prefix + "listplaying") .Alias(Module.Prefix + "lipl") - .Description("Lists all playing statuses with their corresponding number.") + .Description($"Lists all playing statuses with their corresponding number. **Bot Owner Only!**| `{Prefix}lipl`") .AddCheck(SimpleCheckers.OwnerOnly()) .Do(async e => { @@ -143,7 +143,7 @@ namespace NadekoBot.Modules.Administration.Commands cgb.CreateCommand(Module.Prefix + "removeplaying") .Alias(Module.Prefix + "repl", Module.Prefix + "rmpl") - .Description("Removes a playing string on a given number.") + .Description($"Removes a playing string on a given number. **Bot Owner Only!**| `{Prefix}rmpl`") .Parameter("number", ParameterType.Required) .AddCheck(SimpleCheckers.OwnerOnly()) .Do(async e => diff --git a/NadekoBot/Modules/Administration/Commands/RatelimitCommand.cs b/NadekoBot/Modules/Administration/Commands/RatelimitCommand.cs index 22e0d695..d1f62bd9 100644 --- a/NadekoBot/Modules/Administration/Commands/RatelimitCommand.cs +++ b/NadekoBot/Modules/Administration/Commands/RatelimitCommand.cs @@ -41,7 +41,7 @@ namespace NadekoBot.Modules.Administration.Commands internal override void Init(CommandGroupBuilder cgb) { cgb.CreateCommand(Module.Prefix + "slowmode") - .Description("Toggles slow mode. When ON, users will be able to send only 1 message every 5 seconds.") + .Description($"Toggles slow mode. When ON, users will be able to send only 1 message every 5 seconds. **Needs Manage Messages Permissions.**| `{Prefix}slowmode`") .AddCheck(SimpleCheckers.ManageMessages()) .Do(async e => { diff --git a/NadekoBot/Modules/Administration/Commands/SelfAssignedRolesCommand.cs b/NadekoBot/Modules/Administration/Commands/SelfAssignedRolesCommand.cs index 2ef54772..8e5e54fb 100644 --- a/NadekoBot/Modules/Administration/Commands/SelfAssignedRolesCommand.cs +++ b/NadekoBot/Modules/Administration/Commands/SelfAssignedRolesCommand.cs @@ -17,7 +17,7 @@ namespace NadekoBot.Modules.Administration.Commands { cgb.CreateCommand(Module.Prefix + "asar") .Description("Adds a role, or list of roles separated by whitespace" + - "(use quotations for multiword roles) to the list of self-assignable roles. | .asar Gamer") + $"(use quotations for multiword roles) to the list of self-assignable roles. **Needs Manage Roles Permissions.**| `{Prefix}asar Gamer`") .Parameter("roles", ParameterType.Multiple) .AddCheck(SimpleCheckers.CanManageRoles) .Do(async e => @@ -44,7 +44,7 @@ namespace NadekoBot.Modules.Administration.Commands }); cgb.CreateCommand(Module.Prefix + "rsar") - .Description("Removes a specified role from the list of self-assignable roles.") + .Description($"Removes a specified role from the list of self-assignable roles. | `{Prefix}rsar`") .Parameter("role", ParameterType.Unparsed) .AddCheck(SimpleCheckers.CanManageRoles) .Do(async e => @@ -69,14 +69,14 @@ namespace NadekoBot.Modules.Administration.Commands }); cgb.CreateCommand(Module.Prefix + "lsar") - .Description("Lists all self-assignable roles.") + .Description($"Lists all self-assignable roles. | `{Prefix}lsar`") .Parameter("roles", ParameterType.Multiple) .Do(async e => { var config = SpecificConfigurations.Default.Of(e.Server.Id); var msg = new StringBuilder($"There are `{config.ListOfSelfAssignableRoles.Count}` self assignable roles:\n"); var toRemove = new HashSet(); - foreach (var roleId in config.ListOfSelfAssignableRoles.OrderBy(r=>r.ToString())) + foreach (var roleId in config.ListOfSelfAssignableRoles.OrderBy(r => r.ToString())) { var role = e.Server.GetRole(roleId); if (role == null) @@ -98,8 +98,8 @@ namespace NadekoBot.Modules.Administration.Commands - cgb.CreateCommand(Module.Prefix + "togglexclsar").Alias(Module.Prefix +"tesar") - .Description("toggle whether the self-assigned roles should be exclusive") + cgb.CreateCommand(Module.Prefix + "togglexclsar").Alias(Module.Prefix + "tesar") + .Description($"toggle whether the self-assigned roles should be exclusive | `{Prefix}tesar`") .AddCheck(SimpleCheckers.CanManageRoles) .Do(async e => { @@ -112,7 +112,7 @@ namespace NadekoBot.Modules.Administration.Commands cgb.CreateCommand(Module.Prefix + "iam") .Description("Adds a role to you that you choose. " + "Role must be on a list of self-assignable roles." + - " | .iam Gamer") + $" | `{Prefix}iam Gamer`") .Parameter("role", ParameterType.Unparsed) .Do(async e => { @@ -146,12 +146,13 @@ namespace NadekoBot.Modules.Administration.Commands { await e.User.AddRoles(role).ConfigureAwait(false); } - catch(HttpException ex) when (ex.StatusCode == System.Net.HttpStatusCode.InternalServerError) + catch (HttpException ex) when (ex.StatusCode == System.Net.HttpStatusCode.InternalServerError) { } - catch (Exception) + catch (Exception ex) { await e.Channel.SendMessage($":anger:`I am unable to add that role to you. I can't add roles to owners or other roles higher than my role in the role hierarchy.`").ConfigureAwait(false); + return; } var msg = await e.Channel.SendMessage($":ok:You now have {role.Name} role.").ConfigureAwait(false); await Task.Delay(3000).ConfigureAwait(false); @@ -167,7 +168,7 @@ namespace NadekoBot.Modules.Administration.Commands .Alias(Module.Prefix + "iamn") .Description("Removes a role to you that you choose. " + "Role must be on a list of self-assignable roles." + - " | .iamn Gamer") + $" | `{Prefix}iamn Gamer`") .Parameter("role", ParameterType.Unparsed) .Do(async e => { diff --git a/NadekoBot/Modules/Administration/Commands/SelfCommands.cs b/NadekoBot/Modules/Administration/Commands/SelfCommands.cs index c3b5fad2..f8019ac9 100644 --- a/NadekoBot/Modules/Administration/Commands/SelfCommands.cs +++ b/NadekoBot/Modules/Administration/Commands/SelfCommands.cs @@ -14,7 +14,7 @@ namespace NadekoBot.Modules.Administration.Commands internal override void Init(CommandGroupBuilder cgb) { cgb.CreateCommand(Module.Prefix + "leave") - .Description("Makes Nadeko leave the server. Either name or id required. | `.leave 123123123331`") + .Description($"Makes Nadeko leave the server. Either name or id required. **Bot Owner Only!**| `{Prefix}leave 123123123331`") .Parameter("arg", ParameterType.Required) .AddCheck(SimpleCheckers.OwnerOnly()) .Do(async e => diff --git a/NadekoBot/Modules/Administration/Commands/ServerGreetCommand.cs b/NadekoBot/Modules/Administration/Commands/ServerGreetCommand.cs index 54db0305..b2cdf3b4 100644 --- a/NadekoBot/Modules/Administration/Commands/ServerGreetCommand.cs +++ b/NadekoBot/Modules/Administration/Commands/ServerGreetCommand.cs @@ -219,7 +219,7 @@ namespace NadekoBot.Modules.Administration.Commands internal override void Init(CommandGroupBuilder cgb) { cgb.CreateCommand(Module.Prefix + "grdel") - .Description("Toggles automatic deletion of greet and bye messages.") + .Description($"Toggles automatic deletion of greet and bye messages. **Needs Manage Server Permissions.**| `{Prefix}grdel`") .Do(async e => { if (!e.User.ServerPermissions.ManageServer) return; @@ -232,7 +232,7 @@ namespace NadekoBot.Modules.Administration.Commands }); cgb.CreateCommand(Module.Prefix + "greet") - .Description("Toggles anouncements on the current channel when someone joins the server.") + .Description($"Toggles anouncements on the current channel when someone joins the server. **Needs Manage Server Permissions.**| `{Prefix}greet`") .Do(async e => { if (!e.User.ServerPermissions.ManageServer) return; @@ -245,7 +245,7 @@ namespace NadekoBot.Modules.Administration.Commands }); cgb.CreateCommand(Module.Prefix + "greetmsg") - .Description("Sets a new join announcement message. Type %user% if you want to mention the new member. Using it with no message will show the current greet message. | .greetmsg Welcome to the server, %user%.") + .Description($"Sets a new join announcement message. Type %user% if you want to mention the new member. Using it with no message will show the current greet message. **Needs Manage Server Permissions.**| `{Prefix}greetmsg Welcome to the server, %user%.`") .Parameter("msg", ParameterType.Unparsed) .Do(async e => { @@ -265,7 +265,7 @@ namespace NadekoBot.Modules.Administration.Commands }); cgb.CreateCommand(Module.Prefix + "bye") - .Description("Toggles anouncements on the current channel when someone leaves the server.") + .Description($"Toggles anouncements on the current channel when someone leaves the server. | `{Prefix}bye`") .Do(async e => { if (!e.User.ServerPermissions.ManageServer) return; @@ -278,7 +278,7 @@ namespace NadekoBot.Modules.Administration.Commands }); cgb.CreateCommand(Module.Prefix + "byemsg") - .Description("Sets a new leave announcement message. Type %user% if you want to mention the new member. Using it with no message will show the current bye message. | .byemsg %user% has left the server.") + .Description($"Sets a new leave announcement message. Type %user% if you want to mention the new member. Using it with no message will show the current bye message. **Needs Manage Server Permissions.**| `{Prefix}byemsg %user% has left the server.`") .Parameter("msg", ParameterType.Unparsed) .Do(async e => { @@ -297,7 +297,7 @@ namespace NadekoBot.Modules.Administration.Commands }); cgb.CreateCommand(Module.Prefix + "byepm") - .Description("Toggles whether the good bye messages will be sent in a PM or in the text channel.") + .Description($"Toggles whether the good bye messages will be sent in a PM or in the text channel. **Needs Manage Server Permissions.**| `{Prefix}byepm`") .Do(async e => { if (!e.User.ServerPermissions.ManageServer) return; @@ -313,7 +313,7 @@ namespace NadekoBot.Modules.Administration.Commands }); cgb.CreateCommand(Module.Prefix + "greetpm") - .Description("Toggles whether the greet messages will be sent in a PM or in the text channel.") + .Description($"Toggles whether the greet messages will be sent in a PM or in the text channel. **Needs Manage Server Permissions.**| `{Prefix}greetpm`") .Do(async e => { if (!e.User.ServerPermissions.ManageServer) return; diff --git a/NadekoBot/Modules/Administration/Commands/VoiceNotificationCommand.cs b/NadekoBot/Modules/Administration/Commands/VoiceNotificationCommand.cs deleted file mode 100644 index ae63a7db..00000000 --- a/NadekoBot/Modules/Administration/Commands/VoiceNotificationCommand.cs +++ /dev/null @@ -1,46 +0,0 @@ -using Discord; -using Discord.Commands; -using NadekoBot.Classes; -using System; -using System.Collections.Concurrent; -using System.Linq; -using System.Threading.Tasks; - -namespace NadekoBot.Modules.Administration.Commands -{ - internal class VoiceNotificationCommand : DiscordCommand - { - - //voicechannel/text channel - private readonly ConcurrentDictionary subscribers = new ConcurrentDictionary(); - - public Func DoFunc() => async e => - { - var arg = e.GetArg("voice_name"); - if (string.IsNullOrWhiteSpace("voice_name")) - return; - var voiceChannel = e.Server.FindChannels(arg, ChannelType.Voice).FirstOrDefault(); - if (voiceChannel == null) - return; - if (subscribers.ContainsKey(voiceChannel)) - { - await e.Channel.SendMessage("`Voice channel notifications disabled.`").ConfigureAwait(false); - return; - } - if (subscribers.TryAdd(voiceChannel, e.Channel)) - { - await e.Channel.SendMessage("`Voice channel notifications enabled.`").ConfigureAwait(false); - } - }; - - internal override void Init(CommandGroupBuilder cgb) - { - cgb.CreateCommand(Module.Prefix + "voicenotif") - .Description("Enables notifications on who joined/left the voice channel. |.voicenotif Karaoke club") - .Parameter("voice_name", ParameterType.Unparsed) - .Do(DoFunc()); - } - - public VoiceNotificationCommand(DiscordModule module) : base(module) { } - } -} diff --git a/NadekoBot/Modules/Administration/Commands/VoicePlusTextCommand.cs b/NadekoBot/Modules/Administration/Commands/VoicePlusTextCommand.cs index be6bae12..4c6a948c 100644 --- a/NadekoBot/Modules/Administration/Commands/VoicePlusTextCommand.cs +++ b/NadekoBot/Modules/Administration/Commands/VoicePlusTextCommand.cs @@ -88,7 +88,7 @@ namespace NadekoBot.Modules.Administration.Commands { cgb.CreateCommand(Module.Prefix + "cleanv+t") .Alias(Module.Prefix + "cv+t") - .Description("Deletes all text channels ending in `-voice` for which voicechannels are not found. **Use at your own risk.**") + .Description($"Deletes all text channels ending in `-voice` for which voicechannels are not found. **Use at your own risk.\nNeeds Manage Roles and Manage Channels Permissions.** | `{Prefix}cleanv+t`") .AddCheck(SimpleCheckers.CanManageRoles) .AddCheck(SimpleCheckers.ManageChannels()) .Do(async e => @@ -120,7 +120,7 @@ namespace NadekoBot.Modules.Administration.Commands cgb.CreateCommand(Module.Prefix + "voice+text") .Alias(Module.Prefix + "v+t") .Description("Creates a text channel for each voice channel only users in that voice channel can see." + - "If you are server owner, keep in mind you will see them all the time regardless.") + $"If you are server owner, keep in mind you will see them all the time regardless. **Needs Manage Roles and Manage Channels Permissions.**| `{Prefix}voice+text`") .AddCheck(SimpleCheckers.ManageChannels()) .AddCheck(SimpleCheckers.CanManageRoles) .Do(async e => diff --git a/NadekoBot/Modules/ClashOfClans/ClashOfClansModule.cs b/NadekoBot/Modules/ClashOfClans/ClashOfClansModule.cs index 37443900..449c4da6 100644 --- a/NadekoBot/Modules/ClashOfClans/ClashOfClansModule.cs +++ b/NadekoBot/Modules/ClashOfClans/ClashOfClansModule.cs @@ -148,7 +148,7 @@ namespace NadekoBot.Modules.ClashOfClans 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. |{Prefix}cw 15 The Enemy Clan") + .Description($"Creates a new war by specifying a size (>10 and multiple of 5) and enemy clan name. | `{Prefix}cw 15 The Enemy Clan`") .Parameter("size") .Parameter("enemy_clan", ParameterType.Unparsed) .Do(async e => @@ -186,7 +186,7 @@ namespace NadekoBot.Modules.ClashOfClans cgb.CreateCommand(Prefix + "startwar") .Alias(Prefix + "sw") - .Description("Starts a war with a given number.") + .Description("Starts a war with a given number. | `{Prefix}sw 15`") .Parameter("number", ParameterType.Required) .Do(async e => { @@ -211,7 +211,7 @@ namespace NadekoBot.Modules.ClashOfClans cgb.CreateCommand(Prefix + "listwar") .Alias(Prefix + "lw") - .Description($"Shows the active war claims by a number. Shows all wars in a short way if no number is specified. | {Prefix}lw [war_number] or {Prefix}lw") + .Description($"Shows the active war claims by a number. Shows all wars in a short way if no number is specified. | `{Prefix}lw [war_number] or {Prefix}lw`") .Parameter("number", ParameterType.Optional) .Do(async e => { @@ -253,7 +253,7 @@ namespace NadekoBot.Modules.ClashOfClans cgb.CreateCommand(Prefix + "claim") .Alias(Prefix + "call") .Alias(Prefix + "c") - .Description($"Claims a certain base from a certain war. You can supply a name in the third optional argument to claim in someone else's place. | {Prefix}call [war_number] [base_number] [optional_other_name]") + .Description($"Claims a certain base from a certain war. You can supply a name in the third optional argument to claim in someone else's place. | `{Prefix}call [war_number] [base_number] [optional_other_name]`") .Parameter("number") .Parameter("baseNumber") .Parameter("other_name", ParameterType.Unparsed) @@ -292,21 +292,21 @@ namespace NadekoBot.Modules.ClashOfClans .Alias(Prefix + "cf") .Alias(Prefix + "cf3") .Alias(Prefix + "claimfinish3") - .Description($"Finish your claim with 3 stars if you destroyed a base. Optional second argument finishes for someone else. | {Prefix}cf [war_number] [optional_other_name]") + .Description($"Finish your claim with 3 stars if you destroyed a base. Optional second argument finishes for someone else. | `{Prefix}cf [war_number] [optional_other_name]`") .Parameter("number", ParameterType.Required) .Parameter("other_name", ParameterType.Unparsed) .Do(e => FinishClaim(e)); cgb.CreateCommand(Prefix + "claimfinish2") .Alias(Prefix + "cf2") - .Description($"Finish your claim with 2 stars if you destroyed a base. Optional second argument finishes for someone else. | {Prefix}cf [war_number] [optional_other_name]") + .Description($"Finish your claim with 2 stars if you destroyed a base. Optional second argument finishes for someone else. | `{Prefix}cf [war_number] [optional_other_name]`") .Parameter("number", ParameterType.Required) .Parameter("other_name", ParameterType.Unparsed) .Do(e => FinishClaim(e, 2)); cgb.CreateCommand(Prefix + "claimfinish1") .Alias(Prefix + "cf1") - .Description($"Finish your claim with 1 stars if you destroyed a base. Optional second argument finishes for someone else. | {Prefix}cf [war_number] [optional_other_name]") + .Description($"Finish your claim with 1 stars if you destroyed a base. Optional second argument finishes for someone else. | `{Prefix}cf [war_number] [optional_other_name]`") .Parameter("number", ParameterType.Required) .Parameter("other_name", ParameterType.Unparsed) .Do(e => FinishClaim(e, 1)); @@ -314,7 +314,7 @@ namespace NadekoBot.Modules.ClashOfClans cgb.CreateCommand(Prefix + "unclaim") .Alias(Prefix + "uncall") .Alias(Prefix + "uc") - .Description($"Removes your claim from a certain war. Optional second argument denotes a person in whose place to unclaim | {Prefix}uc [war_number] [optional_other_name]") + .Description($"Removes your claim from a certain war. Optional second argument denotes a person in whose place to unclaim | `{Prefix}uc [war_number] [optional_other_name]`") .Parameter("number", ParameterType.Required) .Parameter("other_name", ParameterType.Unparsed) .Do(async e => @@ -344,7 +344,7 @@ namespace NadekoBot.Modules.ClashOfClans cgb.CreateCommand(Prefix + "endwar") .Alias(Prefix + "ew") - .Description($"Ends the war with a given index. |{Prefix}ew [war_number]") + .Description($"Ends the war with a given index. | `{Prefix}ew [war_number]`") .Parameter("number") .Do(async e => { diff --git a/NadekoBot/Modules/Conversations/Commands/RipCommand.cs b/NadekoBot/Modules/Conversations/Commands/RipCommand.cs index f6960e5f..9c4842bf 100644 --- a/NadekoBot/Modules/Conversations/Commands/RipCommand.cs +++ b/NadekoBot/Modules/Conversations/Commands/RipCommand.cs @@ -23,7 +23,7 @@ namespace NadekoBot.Modules.Conversations.Commands internal override void Init(CommandGroupBuilder cgb) { cgb.CreateCommand("rip") - .Description("Shows a grave image of someone with a start year | @NadekoBot rip @Someone 2000") + .Description("Shows a grave image of someone with a start year | `@NadekoBot rip @Someone 2000`") .Parameter("user", ParameterType.Required) .Parameter("year", ParameterType.Optional) .Do(async e => diff --git a/NadekoBot/Modules/Conversations/Conversations.cs b/NadekoBot/Modules/Conversations/Conversations.cs index 7432803f..a3611d0e 100644 --- a/NadekoBot/Modules/Conversations/Conversations.cs +++ b/NadekoBot/Modules/Conversations/Conversations.cs @@ -8,7 +8,6 @@ using NadekoBot.Modules.Permissions.Classes; using System; using System.Diagnostics; using System.IO; -using System.Linq; using System.Text; using System.Threading.Tasks; @@ -42,7 +41,7 @@ namespace NadekoBot.Modules.Conversations if (string.IsNullOrWhiteSpace(text)) return; await Task.Run(() => - Classes.DbHandler.Instance.InsertData(new DataModels.UserQuote() + Classes.DbHandler.Instance.Connection.Insert(new DataModels.UserQuote() { DateAdded = DateTime.Now, Keyword = e.GetArg("keyword").ToLowerInvariant(), @@ -102,7 +101,7 @@ namespace NadekoBot.Modules.Conversations commands.ForEach(cmd => cmd.Init(cgb)); cgb.CreateCommand("die") - .Description("Works only for the owner. Shuts the bot down.") + .Description("Works only for the owner. Shuts the bot down. | `@NadekoBot die`") .Do(async e => { if (NadekoBot.IsOwner(e.User.Id)) @@ -119,7 +118,7 @@ namespace NadekoBot.Modules.Conversations randServerSw.Start(); cgb.CreateCommand("do you love me") - .Description("Replies with positive answer only to the bot owner.") + .Description("Replies with positive answer only to the bot owner. | `@NadekoBot do you love me`") .Do(async e => { if (NadekoBot.IsOwner(e.User.Id)) @@ -130,7 +129,7 @@ namespace NadekoBot.Modules.Conversations cgb.CreateCommand("how are you") .Alias("how are you?") - .Description("Replies positive only if bot owner is online.") + .Description("Replies positive only if bot owner is online. | `@NadekoBot how are you`") .Do(async e => { if (NadekoBot.IsOwner(e.User.Id)) @@ -150,7 +149,7 @@ namespace NadekoBot.Modules.Conversations }); cgb.CreateCommand("fire") - .Description("Shows a unicode fire message. Optional parameter [x] tells her how many times to repeat the fire. | @NadekoBot fire [x]") + .Description("Shows a unicode fire message. Optional parameter [x] tells her how many times to repeat the fire. | `@NadekoBot fire [x]`") .Parameter("times", ParameterType.Optional) .Do(async e => { @@ -174,7 +173,7 @@ namespace NadekoBot.Modules.Conversations }); cgb.CreateCommand("dump") - .Description("Dumps all of the invites it can to dump.txt.** Owner Only.**") + .Description("Dumps all of the invites it can to dump.txt.** Owner Only.** | `@NadekoBot dump`") .Do(async e => { if (!NadekoBot.IsOwner(e.User.Id)) return; @@ -201,7 +200,7 @@ namespace NadekoBot.Modules.Conversations }); cgb.CreateCommand("ab") - .Description("Try to get 'abalabahaha'") + .Description("Try to get 'abalabahaha'| `@NadekoBot ab`") .Do(async e => { string[] strings = { "ba", "la", "ha" }; diff --git a/NadekoBot/Modules/CustomReactions/CustomReactions.cs b/NadekoBot/Modules/CustomReactions/CustomReactions.cs index a613b6c5..b62b2dd7 100644 --- a/NadekoBot/Modules/CustomReactions/CustomReactions.cs +++ b/NadekoBot/Modules/CustomReactions/CustomReactions.cs @@ -50,7 +50,7 @@ namespace NadekoBot.Modules.CustomReactions var c = cgb.CreateCommand(commandName); if (commandName.Contains(NadekoBot.BotMention)) c.Alias(commandName.Replace("<@", "<@!")); - c.Description($"Custom reaction. |{command.Key}") + c.Description($"Custom reaction. | `{command.Key}`") .Parameter("args", ParameterType.Unparsed) .Do(async e => { @@ -64,4 +64,4 @@ namespace NadekoBot.Modules.CustomReactions }); } } -} \ No newline at end of file +} diff --git a/NadekoBot/Modules/Gambling/Commands/AnimalRacing.cs b/NadekoBot/Modules/Gambling/Commands/AnimalRacing.cs index ae6c6819..a908128c 100644 --- a/NadekoBot/Modules/Gambling/Commands/AnimalRacing.cs +++ b/NadekoBot/Modules/Gambling/Commands/AnimalRacing.cs @@ -1,14 +1,13 @@ -using NadekoBot.Classes; +using Discord; +using Discord.Commands; +using NadekoBot.Classes; +using NadekoBot.Extensions; using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Discord.Commands; -using System.Collections.Concurrent; -using Discord; -using NadekoBot.Extensions; using System.Threading; +using System.Threading.Tasks; namespace NadekoBot.Modules.Gambling.Commands { @@ -23,8 +22,9 @@ namespace NadekoBot.Modules.Gambling.Commands internal override void Init(CommandGroupBuilder cgb) { cgb.CreateCommand(Prefix + "race") - .Description("Starts a new animal race.") - .Do(e => { + .Description($"Starts a new animal race. | `{Prefix}race`") + .Do(e => + { var ar = new AnimalRace(e.Server.Id, e.Channel); if (ar.Fail) { @@ -35,9 +35,10 @@ namespace NadekoBot.Modules.Gambling.Commands cgb.CreateCommand(Prefix + "joinrace") .Alias(Prefix + "jr") - .Description("Joins a new race. You can specify an amount of flowers for betting (optional). You will get YourBet*(participants-1) back if you win. | `$jr` or `$jr 5`") + .Description($"Joins a new race. You can specify an amount of flowers for betting (optional). You will get YourBet*(participants-1) back if you win. | `{Prefix}jr` or `{Prefix}jr 5`") .Parameter("amount", ParameterType.Optional) - .Do(async e => { + .Do(async e => + { int amount; if (!int.TryParse(e.GetArg("amount"), out amount) || amount < 0) @@ -55,11 +56,13 @@ namespace NadekoBot.Modules.Gambling.Commands await FlowersHandler.RemoveFlowers(e.User, "BetRace", (int)amount, true).ConfigureAwait(false); AnimalRace ar; - if (!AnimalRaces.TryGetValue(e.Server.Id, out ar)) { + if (!AnimalRaces.TryGetValue(e.Server.Id, out ar)) + { await e.Channel.SendMessage("No race exists on this server"); + return; } await ar.JoinRace(e.User, amount); - + }); } @@ -93,7 +96,7 @@ namespace NadekoBot.Modules.Gambling.Commands { try { - await raceChannel.SendMessage($"🏁`Race is starting in 20 seconds or when the room is full. Type $jr to join the race.`"); + await raceChannel.SendMessage($"🏁`Race is starting in 20 seconds or when the room is full. Type {NadekoBot.Config.CommandPrefixes.Gambling}jr to join the race.`"); var t = await Task.WhenAny(Task.Delay(20000, token), fullgame); Started = true; cancelSource.Cancel(); @@ -103,7 +106,7 @@ namespace NadekoBot.Modules.Gambling.Commands } else if (participants.Count > 1) { - await raceChannel.SendMessage("🏁`Game starting with " + participants.Count + " praticipants.`"); + await raceChannel.SendMessage("🏁`Game starting with " + participants.Count + " participants.`"); } else { @@ -127,7 +130,8 @@ namespace NadekoBot.Modules.Gambling.Commands AnimalRaces.TryRemove(serverId, out throwaway); } - private async Task StartRace() { + private async Task StartRace() + { var rng = new Random(); Participant winner = null; Message msg = null; @@ -163,14 +167,14 @@ namespace NadekoBot.Modules.Gambling.Commands |🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🔚|"; if (msg == null || messagesSinceGameStarted >= 10) // also resend the message if channel was spammed { - if(msg != null) + if (msg != null) try { await msg.Delete(); } catch { } msg = await raceChannel.SendMessage(text); messagesSinceGameStarted = 0; } else await msg.Edit(text); - + await Task.Delay(2500); } } @@ -199,10 +203,11 @@ namespace NadekoBot.Modules.Gambling.Commands messagesSinceGameStarted++; } - private async Task CheckForFullGameAsync(CancellationToken cancelToken) { + private async Task CheckForFullGameAsync(CancellationToken cancelToken) + { while (animals.Count > 0) { - await Task.Delay(100,cancelToken); + await Task.Delay(100, cancelToken); } } @@ -257,8 +262,8 @@ namespace NadekoBot.Modules.Gambling.Commands public override bool Equals(object obj) { var p = obj as Participant; - return p == null? - false: + return p == null ? + false : p.User == User; } @@ -279,7 +284,8 @@ namespace NadekoBot.Modules.Gambling.Commands { return str + "`3rd`"; } - else { + else + { return str + $"`{Place}th`"; } diff --git a/NadekoBot/Modules/Gambling/DiceRollCommand.cs b/NadekoBot/Modules/Gambling/DiceRollCommand.cs index 68a665fe..55bb5ee1 100644 --- a/NadekoBot/Modules/Gambling/DiceRollCommand.cs +++ b/NadekoBot/Modules/Gambling/DiceRollCommand.cs @@ -21,18 +21,18 @@ namespace NadekoBot.Modules.Gambling { cgb.CreateCommand(Module.Prefix + "roll") .Description("Rolls 0-100. If you supply a number [x] it rolls up to 30 normal dice." + - " If you split 2 numbers with letter d (xdy) it will roll x dice from 1 to y. | $roll or $roll 7 or $roll 3d5") + $" If you split 2 numbers with letter d (xdy) it will roll x dice from 1 to y. | `{Prefix}roll` or `{Prefix}roll 7` or `{Prefix}roll 3d5`") .Parameter("num", ParameterType.Optional) .Do(RollFunc()); cgb.CreateCommand(Module.Prefix + "rolluo") .Description("Rolls 0-100. If you supply a number [x] it rolls up to 30 normal dice (unordered)." + - " If you split 2 numbers with letter d (xdy) it will roll x dice from 1 to y. | $roll or $roll 7 or $roll 3d5") + $" If you split 2 numbers with letter d (xdy) it will roll x dice from 1 to y. | `{Prefix}roll` or `{Prefix}roll` 7 or `{Prefix}roll 3d5`") .Parameter("num", ParameterType.Optional) .Do(RollFunc(false)); cgb.CreateCommand(Module.Prefix + "nroll") - .Description("Rolls in a given range. | `$nroll 5` (rolls 0-5) or `$nroll 5-15`") + .Description($"Rolls in a given range. | `{Prefix}nroll 5` (rolls 0-5) or `{Prefix}nroll 5-15`") .Parameter("range", ParameterType.Required) .Do(NRollFunc()); } diff --git a/NadekoBot/Modules/Gambling/DrawCommand.cs b/NadekoBot/Modules/Gambling/DrawCommand.cs index 35d789bf..dbd023e1 100644 --- a/NadekoBot/Modules/Gambling/DrawCommand.cs +++ b/NadekoBot/Modules/Gambling/DrawCommand.cs @@ -17,13 +17,13 @@ namespace NadekoBot.Modules.Gambling internal override void Init(CommandGroupBuilder cgb) { cgb.CreateCommand(Module.Prefix + "draw") - .Description("Draws a card from the deck.If you supply number [x], she draws up to 5 cards from the deck. | $draw [x]") + .Description($"Draws a card from the deck.If you supply number [x], she draws up to 5 cards from the deck. | `{Prefix}draw [x]`") .Parameter("count", ParameterType.Optional) .Do(DrawCardFunc()); cgb.CreateCommand(Module.Prefix + "shuffle") .Alias(Module.Prefix + "sh") - .Description("Reshuffles all cards back into the deck.") + .Description($"Reshuffles all cards back into the deck.|`{Prefix}shuffle`") .Do(ReshuffleTask()); } diff --git a/NadekoBot/Modules/Gambling/FlipCoinCommand.cs b/NadekoBot/Modules/Gambling/FlipCoinCommand.cs index 6d8edf3c..d0b79919 100644 --- a/NadekoBot/Modules/Gambling/FlipCoinCommand.cs +++ b/NadekoBot/Modules/Gambling/FlipCoinCommand.cs @@ -15,7 +15,7 @@ namespace NadekoBot.Modules.Gambling internal override void Init(CommandGroupBuilder cgb) { cgb.CreateCommand(Module.Prefix + "flip") - .Description("Flips coin(s) - heads or tails, and shows an image. | `$flip` or `$flip 3`") + .Description($"Flips coin(s) - heads or tails, and shows an image. | `{Prefix}flip` or `{Prefix}flip 3`") .Parameter("count", ParameterType.Optional) .Do(FlipCoinFunc()); diff --git a/NadekoBot/Modules/Gambling/GamblingModule.cs b/NadekoBot/Modules/Gambling/GamblingModule.cs index 2b1ddc15..d7ced224 100644 --- a/NadekoBot/Modules/Gambling/GamblingModule.cs +++ b/NadekoBot/Modules/Gambling/GamblingModule.cs @@ -33,7 +33,7 @@ namespace NadekoBot.Modules.Gambling commands.ForEach(com => com.Init(cgb)); cgb.CreateCommand(Prefix + "raffle") - .Description($"Prints a name and ID of a random user from the online list from the (optional) role. | `{Prefix}raffle` or `{Prefix}raffle RoleName") + .Description($"Prints a name and ID of a random user from the online list from the (optional) role. | `{Prefix}raffle` or `{Prefix}raffle RoleName`") .Parameter("role", ParameterType.Optional) .Do(async e => { @@ -63,7 +63,7 @@ namespace NadekoBot.Modules.Gambling }); cgb.CreateCommand(Prefix + "give") - .Description(string.Format("Give someone a certain amount of {0}s", NadekoBot.Config.CurrencyName)) + .Description(string.Format("Give someone a certain amount of {0}s", NadekoBot.Config.CurrencyName)+ $"|`{Prefix}give 1 \"@SomeGuy\"`") .Parameter("amount", ParameterType.Required) .Parameter("receiver", ParameterType.Unparsed) .Do(async e => @@ -140,7 +140,7 @@ namespace NadekoBot.Modules.Gambling cgb.CreateCommand(Prefix + "betroll") .Alias(Prefix + "br") - .Description($"Bets a certain amount of {NadekoBot.Config.CurrencyName}s and rolls a dice. Rolling over 66 yields x2 flowers, over 90 - x3 and 100 x10. | {Prefix}br 5") + .Description($"Bets a certain amount of {NadekoBot.Config.CurrencyName}s and rolls a dice. Rolling over 66 yields x2 flowers, over 90 - x3 and 100 x10. | `{Prefix}br 5`") .Parameter("amount",ParameterType.Required) .Do(async e => { @@ -187,6 +187,7 @@ namespace NadekoBot.Modules.Gambling cgb.CreateCommand(Prefix + "leaderboard") .Alias(Prefix + "lb") + .Description($"Displays bot currency leaderboard | `{Prefix}lb`") .Do(async e => { var richestTemp = DbHandler.Instance.GetTopRichest(); diff --git a/NadekoBot/Modules/Games/Commands/BetrayGame.cs b/NadekoBot/Modules/Games/Commands/BetrayGame.cs index 0bf410b5..74b98bf6 100644 --- a/NadekoBot/Modules/Games/Commands/BetrayGame.cs +++ b/NadekoBot/Modules/Games/Commands/BetrayGame.cs @@ -20,7 +20,7 @@ namespace NadekoBot.Modules.Games.Commands cgb.CreateCommand(Module.Prefix + "betray") .Description("BETRAY GAME. Betray nadeko next turn." + "If Nadeko cooperates - you get extra points, nadeko loses a LOT." + - "If Nadeko betrays - you both lose some points.") + $"If Nadeko betrays - you both lose some points. | `{Prefix}betray`") .Do(async e => { await ReceiveAnswer(e, Answers.Betray).ConfigureAwait(false); @@ -29,7 +29,7 @@ namespace NadekoBot.Modules.Games.Commands cgb.CreateCommand(Module.Prefix + "cooperate") .Description("BETRAY GAME. Cooperate with nadeko next turn." + "If Nadeko cooperates - you both get bonus points." + - "If Nadeko betrays - you lose A LOT, nadeko gets extra.") + $"If Nadeko betrays - you lose A LOT, nadeko gets extra. | `{Prefix}cooperater`") .Do(async e => { diff --git a/NadekoBot/Modules/Games/Commands/Leet.cs b/NadekoBot/Modules/Games/Commands/Leet.cs index 22cdedbf..e71a80d0 100644 --- a/NadekoBot/Modules/Games/Commands/Leet.cs +++ b/NadekoBot/Modules/Games/Commands/Leet.cs @@ -1,5 +1,6 @@ using Discord.Commands; using NadekoBot.Classes; +using NadekoBot.Extensions; using System.Text; //taken from @@ -291,13 +292,13 @@ namespace NadekoBot.Modules.Games.Commands } #endregion } - return sb.ToString(); // Return result. + return sb.ToString().TrimTo(1995); // Return result. } internal override void Init(CommandGroupBuilder cgb) { cgb.CreateCommand(Module.Prefix + "leet") - .Description($"Converts a text to leetspeak with 6 (1-6) severity levels | {Module.Prefix}leet 3 Hello") + .Description($"Converts a text to leetspeak with 6 (1-6) severity levels | `{Module.Prefix}leet 3 Hello`") .Parameter("level", ParameterType.Required) .Parameter("text", ParameterType.Unparsed) .Do(async e => diff --git a/NadekoBot/Modules/Games/Commands/PlantPick.cs b/NadekoBot/Modules/Games/Commands/PlantPick.cs index d2882eb2..2752ad1f 100644 --- a/NadekoBot/Modules/Games/Commands/PlantPick.cs +++ b/NadekoBot/Modules/Games/Commands/PlantPick.cs @@ -65,7 +65,7 @@ namespace NadekoBot.Modules.Games.Commands internal override void Init(CommandGroupBuilder cgb) { cgb.CreateCommand(Module.Prefix + "pick") - .Description("Picks a flower planted in this channel.") + .Description($"Picks a flower planted in this channel. | `{Prefix}pick`") .Do(async e => { IEnumerable msgs; @@ -91,7 +91,7 @@ namespace NadekoBot.Modules.Games.Commands }); cgb.CreateCommand(Module.Prefix + "plant") - .Description("Spend a flower to plant it in this channel. (If bot is restarted or crashes, flower will be lost)") + .Description($"Spend a flower to plant it in this channel. (If bot is restarted or crashes, flower will be lost) | `{Prefix}plant`") .Do(async e => { await locker.WaitAsync().ConfigureAwait(false); @@ -124,7 +124,7 @@ namespace NadekoBot.Modules.Games.Commands cgb.CreateCommand(Prefix + "gencurrency") .Alias(Prefix + "gc") - .Description($"Toggles currency generation on this channel. Every posted message will have 2% chance to spawn a {NadekoBot.Config.CurrencyName}. Optional parameter cooldown time in minutes, 5 minutes by default. Requires Manage Messages permission. | `>gc` or `>gc 60`") + .Description($"Toggles currency generation on this channel. Every posted message will have 2% chance to spawn a {NadekoBot.Config.CurrencyName}. Optional parameter cooldown time in minutes, 5 minutes by default. Requires Manage Messages permission. | `{Prefix}gc` or `{Prefix}gc 60`") .AddCheck(SimpleCheckers.ManageMessages()) .Parameter("cd", ParameterType.Unparsed) .Do(async e => diff --git a/NadekoBot/Modules/Games/Commands/PollCommand.cs b/NadekoBot/Modules/Games/Commands/PollCommand.cs index 0e1bb81c..785d5c5f 100644 --- a/NadekoBot/Modules/Games/Commands/PollCommand.cs +++ b/NadekoBot/Modules/Games/Commands/PollCommand.cs @@ -18,7 +18,7 @@ namespace NadekoBot.Modules.Games.Commands internal override void Init(CommandGroupBuilder cgb) { cgb.CreateCommand(Module.Prefix + "poll") - .Description("Creates a poll, only person who has manage server permission can do it. | >poll Question?;Answer1;Answ 2;A_3") + .Description($"Creates a poll, only person who has manage server permission can do it. | `{Prefix}poll Question?;Answer1;Answ 2;A_3`") .Parameter("allargs", ParameterType.Unparsed) .Do(async e => { @@ -43,7 +43,7 @@ namespace NadekoBot.Modules.Games.Commands }).ConfigureAwait(false); }); cgb.CreateCommand(Module.Prefix + "pollend") - .Description("Stops active poll on this server and prints the results in this channel.") + .Description($"Stops active poll on this server and prints the results in this channel. | `{Prefix}pollend`") .Do(async e => { if (!e.User.ServerPermissions.ManageChannels) diff --git a/NadekoBot/Modules/Games/Commands/SpeedTyping.cs b/NadekoBot/Modules/Games/Commands/SpeedTyping.cs index c224de1d..07100820 100644 --- a/NadekoBot/Modules/Games/Commands/SpeedTyping.cs +++ b/NadekoBot/Modules/Games/Commands/SpeedTyping.cs @@ -168,21 +168,21 @@ namespace NadekoBot.Modules.Games.Commands internal override void Init(CommandGroupBuilder cgb) { cgb.CreateCommand(Module.Prefix + "typestart") - .Description("Starts a typing contest.") + .Description($"Starts a typing contest. | `{Prefix}typestart`") .Do(DoFunc()); cgb.CreateCommand(Module.Prefix + "typestop") - .Description("Stops a typing contest on the current channel.") + .Description($"Stops a typing contest on the current channel. | `{Prefix}typestop`") .Do(QuitFunc()); cgb.CreateCommand(Module.Prefix + "typeadd") - .Description("Adds a new article to the typing contest. Owner only.") + .Description($"Adds a new article to the typing contest. Owner only. | `{Prefix}typeadd wordswords`") .Parameter("text", ParameterType.Unparsed) .Do(async e => { if (!NadekoBot.IsOwner(e.User.Id) || string.IsNullOrWhiteSpace(e.GetArg("text"))) return; - DbHandler.Instance.InsertData(new TypingArticle + DbHandler.Instance.Connection.Insert(new TypingArticle { Text = e.GetArg("text"), DateAdded = DateTime.Now diff --git a/NadekoBot/Modules/Games/Commands/TriviaCommand.cs b/NadekoBot/Modules/Games/Commands/TriviaCommand.cs index 1873c254..75481309 100644 --- a/NadekoBot/Modules/Games/Commands/TriviaCommand.cs +++ b/NadekoBot/Modules/Games/Commands/TriviaCommand.cs @@ -46,7 +46,7 @@ namespace NadekoBot.Modules.Games.Commands }); cgb.CreateCommand(Module.Prefix + "tl") - .Description("Shows a current trivia leaderboard.") + .Description($"Shows a current trivia leaderboard. | `{Prefix}tl`") .Do(async e => { TriviaGame trivia; @@ -57,7 +57,7 @@ namespace NadekoBot.Modules.Games.Commands }); cgb.CreateCommand(Module.Prefix + "tq") - .Description("Quits current trivia after current question.") + .Description($"Quits current trivia after current question. | `{Prefix}tq`") .Do(async e => { TriviaGame trivia; diff --git a/NadekoBot/Modules/Games/GamesModule.cs b/NadekoBot/Modules/Games/GamesModule.cs index 2e222054..acdaf1b3 100644 --- a/NadekoBot/Modules/Games/GamesModule.cs +++ b/NadekoBot/Modules/Games/GamesModule.cs @@ -60,7 +60,7 @@ namespace NadekoBot.Modules.Games try { await e.Channel.SendMessage( - $":question: **Question**: `{question}` \n🎱 **8Ball Answers**: `{NadekoBot.Config._8BallResponses[rng.Next(0, NadekoBot.Config._8BallResponses.Length)]}`") + $":question: `Question` __**{question}**__ \n🎱 `8Ball Answers` __**{NadekoBot.Config._8BallResponses[rng.Next(0, NadekoBot.Config._8BallResponses.Length)]}**__") .ConfigureAwait(false); } catch { } diff --git a/NadekoBot/Modules/Help/Commands/HelpCommand.cs b/NadekoBot/Modules/Help/Commands/HelpCommand.cs index 4d3fa441..d0ba292b 100644 --- a/NadekoBot/Modules/Help/Commands/HelpCommand.cs +++ b/NadekoBot/Modules/Help/Commands/HelpCommand.cs @@ -31,7 +31,7 @@ namespace NadekoBot.Classes.Help.Commands if (alias != null) str = $" / `{ com.Aliases.FirstOrDefault()}`"; if (com != null) - await e.Channel.SendMessage($@"**__Help for:__ `{com.Text}`**" + str + $"\n**Desc:** {new Regex(@"\|").Replace(com.Description, "\n**Usage:**",1)}").ConfigureAwait(false); + await e.Channel.SendMessage($@"**__Help for:__ `{com.Text}`**" + str + $"\n**Desc:** {new Regex(@"\|").Replace(com.Description, "\n**Usage:**", 1)}").ConfigureAwait(false); }).ConfigureAwait(false); }; public static string HelpString { @@ -48,11 +48,11 @@ namespace NadekoBot.Classes.Help.Commands public Action DoGitFunc() => e => { string helpstr = -$@"######For more information and how to setup your own NadekoBot, go to: **http://github.com/Kwoth/NadekoBot/** -######You can donate on paypal: `nadekodiscordbot@gmail.com` +$@"######For more information and how to setup your own NadekoBot, go to: +######You can donate on patreon: +######or paypal: `nadekodiscordbot@gmail.com` -#NadekoBot List Of Commands -Version: `{NadekoStats.Instance.BotVersion}`"; +#NadekoBot List Of Commands "; string lastCategory = ""; @@ -80,16 +80,16 @@ Version: `{NadekoStats.Instance.BotVersion}`"; { cgb.CreateCommand(Module.Prefix + "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. | '-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. | `{Prefix}h !m q` or just `{Prefix}h` ") .Parameter("command", ParameterType.Unparsed) .Do(HelpFunc()); cgb.CreateCommand(Module.Prefix + "hgit") - .Description("Generates the commandlist.md file. **Bot Owner Only!**") + .Description($"Generates the commandlist.md file. **Bot Owner Only!** | `{Prefix}hgit`") .AddCheck(SimpleCheckers.OwnerOnly()) .Do(DoGitFunc()); cgb.CreateCommand(Module.Prefix + "readme") .Alias(Module.Prefix + "guide") - .Description("Sends a readme and a guide links to the channel.") + .Description($"Sends a readme and a guide links to the channel. | `{Prefix}readme` or `{Prefix}guide`") .Do(async e => await e.Channel.SendMessage( @"**Wiki with all info**: @@ -102,16 +102,15 @@ Version: `{NadekoStats.Instance.BotVersion}`"; cgb.CreateCommand(Module.Prefix + "donate") .Alias("~donate") - .Description("Instructions for helping the project!") + .Description($"Instructions for helping the project! | `{Prefix}donate` or `~donate`") .Do(async e => { await e.Channel.SendMessage( -$@"I've created a **paypal** email for nadeko, so if you wish to support the project, you can send your donations to `nadekodiscordbot@gmail.com` -Don't forget to leave your discord name or id in the message, so that I can reward people who help out. -You can join nadekobot server by typing {Module.Prefix}h and you will get an invite in a private message. +$@"You can support the project on patreon. or +You can send donations to `nadekodiscordbot@gmail.com` +Don't forget to leave your discord name or id in the message. -*If you want to support in some other way or on a different platform, please message me*" - ).ConfigureAwait(false); +**Thank you** ♥️").ConfigureAwait(false); }); } diff --git a/NadekoBot/Modules/Help/HelpModule.cs b/NadekoBot/Modules/Help/HelpModule.cs index 20e8279c..45e4dc76 100644 --- a/NadekoBot/Modules/Help/HelpModule.cs +++ b/NadekoBot/Modules/Help/HelpModule.cs @@ -29,7 +29,7 @@ namespace NadekoBot.Modules.Help cgb.CreateCommand(Prefix + "modules") .Alias(".modules") - .Description("List all bot modules.") + .Description($"List all bot modules. | `{Prefix}modules` or `.modules`") .Do(async e => { await e.Channel.SendMessage("`List of modules:` \n• " + string.Join("\n• ", NadekoBot.Client.GetService().Modules.Select(m => m.Name)) + $"\n`Type \"{Prefix}commands module_name\" to get a list of commands in that module.`") @@ -38,7 +38,7 @@ namespace NadekoBot.Modules.Help cgb.CreateCommand(Prefix + "commands") .Alias(".commands") - .Description("List all of the bot's commands from a certain module.") + .Description($"List all of the bot's commands from a certain module. | `{Prefix}commands` or `.commands`") .Parameter("module", ParameterType.Unparsed) .Do(async e => { diff --git a/NadekoBot/Modules/Music/Classes/MusicControls.cs b/NadekoBot/Modules/Music/Classes/MusicControls.cs index 847070eb..e13239cf 100644 --- a/NadekoBot/Modules/Music/Classes/MusicControls.cs +++ b/NadekoBot/Modules/Music/Classes/MusicControls.cs @@ -34,7 +34,7 @@ namespace NadekoBot.Modules.Music.Classes public IReadOnlyCollection Playlist => playlist; public Song CurrentSong { get; private set; } - private CancellationTokenSource SongCancelSource { get; set; } + public CancellationTokenSource SongCancelSource { get; private set; } private CancellationToken cancelToken { get; set; } public bool Paused { get; set; } diff --git a/NadekoBot/Modules/Music/Classes/Song.cs b/NadekoBot/Modules/Music/Classes/Song.cs index 08be13b8..d235776a 100644 --- a/NadekoBot/Modules/Music/Classes/Song.cs +++ b/NadekoBot/Modules/Music/Classes/Song.cs @@ -32,7 +32,6 @@ namespace NadekoBot.Modules.Music.Classes public SongInfo SongInfo { get; } public string QueuerName { get; set; } - private bool bufferingCompleted { get; set; } = false; public MusicPlayer MusicPlayer { get; set; } public string PrettyCurrentTime() @@ -73,78 +72,22 @@ namespace NadekoBot.Modules.Music.Classes return this; } - private Task BufferSong(string filename, CancellationToken cancelToken) => - Task.Factory.StartNew(async () => - { - Process p = null; - try - { - p = Process.Start(new ProcessStartInfo - { - FileName = "ffmpeg", - Arguments = $"-ss {skipTo} -i {SongInfo.Uri} -f s16le -ar 48000 -ac 2 pipe:1 -loglevel quiet", - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = false, - CreateNoWindow = true, - }); - var prebufferSize = 100ul.MiB(); - using (var outStream = new FileStream(filename, FileMode.Append, FileAccess.Write, FileShare.Read)) - { - byte[] buffer = new byte[81920]; - int bytesRead; - while ((bytesRead = await p.StandardOutput.BaseStream.ReadAsync(buffer, 0, buffer.Length, cancelToken).ConfigureAwait(false)) != 0) - { - await outStream.WriteAsync(buffer, 0, bytesRead, cancelToken).ConfigureAwait(false); - while ((ulong)outStream.Length - bytesSent > prebufferSize) - await Task.Delay(100, cancelToken); - } - } - - bufferingCompleted = true; - } - catch (System.ComponentModel.Win32Exception) { - var oldclr = Console.ForegroundColor; - Console.ForegroundColor = ConsoleColor.Red; - Console.WriteLine(@"You have not properly installed or configured FFMPEG. -Please install and configure FFMPEG to play music. -Check the guides for your platform on how to setup ffmpeg correctly: - Windows Guide: https://goo.gl/SCv72y - Linux Guide: https://goo.gl/rRhjCp"); - Console.ForegroundColor = oldclr; - } - catch (Exception ex) - { - Console.WriteLine($"Buffering stopped: {ex.Message}"); - } - finally - { - Console.WriteLine($"Buffering done."); - if (p != null) - { - try - { - p.Kill(); - } - catch { } - p.Dispose(); - } - } - }, TaskCreationOptions.LongRunning); - internal async Task Play(IAudioClient voiceClient, CancellationToken cancelToken) { var filename = Path.Combine(MusicModule.MusicDataPath, DateTime.Now.UnixTimestamp().ToString()); - var bufferTask = BufferSong(filename, cancelToken).ConfigureAwait(false); + SongBuffer sb = new SongBuffer(filename, SongInfo, skipTo); + var bufferTask = sb.BufferSong(cancelToken).ConfigureAwait(false); - var inStream = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.Read, FileShare.Write); + var inStream = new FileStream(sb.GetNextFile(), FileMode.OpenOrCreate, FileAccess.Read, FileShare.Write); ; bytesSent = 0; try { - var prebufferingTask = CheckPrebufferingAsync(inStream, cancelToken); + var attempt = 0; + + var prebufferingTask = CheckPrebufferingAsync(inStream, sb, cancelToken); var sw = new Stopwatch(); sw.Start(); var t = await Task.WhenAny(prebufferingTask, Task.Delay(5000, cancelToken)); @@ -162,7 +105,6 @@ Check the guides for your platform on how to setup ffmpeg correctly: Console.WriteLine("Prebuffering successfully completed in "+ sw.Elapsed); const int blockSize = 3840; - var attempt = 0; byte[] buffer = new byte[blockSize]; while (!cancelToken.IsCancellationRequested) { @@ -173,14 +115,31 @@ Check the guides for your platform on how to setup ffmpeg correctly: { bytesSent += (ulong)read; } - if (read == 0) - if (attempt++ == 20) + if (read < blockSize) + { + if (sb.IsNextFileReady()) { - voiceClient.Wait(); - break; + inStream.Dispose(); + inStream = new FileStream(sb.GetNextFile(), FileMode.Open, FileAccess.Read, FileShare.Write); + read += inStream.Read(buffer, read, buffer.Length - read); + attempt = 0; + } + if (read == 0) + { + if (sb.BufferingCompleted) + break; + if (attempt++ == 20) + { + voiceClient.Wait(); + MusicPlayer.SongCancelSource.Cancel(); + break; + } + else + await Task.Delay(100, cancelToken).ConfigureAwait(false); } else - await Task.Delay(100, cancelToken).ConfigureAwait(false); + attempt = 0; + } else attempt = 0; @@ -195,14 +154,16 @@ Check the guides for your platform on how to setup ffmpeg correctly: { await bufferTask; await Task.Run(() => voiceClient.Clear()); - inStream.Dispose(); - try { File.Delete(filename); } catch { } + if(inStream != null) + inStream.Dispose(); + Console.WriteLine("l"); + sb.CleanFiles(); } } - private async Task CheckPrebufferingAsync(Stream inStream, CancellationToken cancelToken) + private async Task CheckPrebufferingAsync(Stream inStream, SongBuffer sb, CancellationToken cancelToken) { - while (!bufferingCompleted && inStream.Length < 2.MiB()) + while (!sb.BufferingCompleted && inStream.Length < 2.MiB()) { await Task.Delay(100, cancelToken); } diff --git a/NadekoBot/Modules/Music/Classes/SongBuffer.cs b/NadekoBot/Modules/Music/Classes/SongBuffer.cs new file mode 100644 index 00000000..d9192940 --- /dev/null +++ b/NadekoBot/Modules/Music/Classes/SongBuffer.cs @@ -0,0 +1,159 @@ +using NadekoBot.Extensions; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace NadekoBot.Modules.Music.Classes +{ + /// + /// Create a buffer for a song file. It will create multiples files to ensure, that radio don't fill up disk space. + /// It also help for large music by deleting files that are already seen. + /// + class SongBuffer + { + + public SongBuffer(string basename, SongInfo songInfo, int skipTo) + { + Basename = basename; + SongInfo = songInfo; + SkipTo = skipTo; + } + + private string Basename; + + private SongInfo SongInfo; + + private int SkipTo; + + private static int MAX_FILE_SIZE = 20.MiB(); + + private long FileNumber = -1; + + private long NextFileToRead = 0; + + public bool BufferingCompleted { get; private set;} = false; + + private ulong CurrentBufferSize = 0; + + public Task BufferSong(CancellationToken cancelToken) => + Task.Factory.StartNew(async () => + { + Process p = null; + FileStream outStream = null; + try + { + p = Process.Start(new ProcessStartInfo + { + FileName = "ffmpeg", + Arguments = $"-ss {SkipTo} -i {SongInfo.Uri} -f s16le -ar 48000 -ac 2 pipe:1 -loglevel quiet", + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = false, + CreateNoWindow = true, + }); + + byte[] buffer = new byte[81920]; + int currentFileSize = 0; + ulong prebufferSize = 100ul.MiB(); + + outStream = new FileStream(Basename + "-" + ++FileNumber, FileMode.Append, FileAccess.Write, FileShare.Read); + while (!p.HasExited) //Also fix low bandwidth + { + int bytesRead = await p.StandardOutput.BaseStream.ReadAsync(buffer, 0, buffer.Length, cancelToken).ConfigureAwait(false); + if (currentFileSize >= MAX_FILE_SIZE) + { + try + { + outStream.Dispose(); + }catch { } + outStream = new FileStream(Basename + "-" + ++FileNumber, FileMode.Append, FileAccess.Write, FileShare.Read); + currentFileSize = bytesRead; + } + else + { + currentFileSize += bytesRead; + } + CurrentBufferSize += Convert.ToUInt64(bytesRead); + await outStream.WriteAsync(buffer, 0, bytesRead, cancelToken).ConfigureAwait(false); + while (CurrentBufferSize > prebufferSize) + await Task.Delay(100, cancelToken); + } + BufferingCompleted = true; + } + catch (System.ComponentModel.Win32Exception) + { + var oldclr = Console.ForegroundColor; + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine(@"You have not properly installed or configured FFMPEG. +Please install and configure FFMPEG to play music. +Check the guides for your platform on how to setup ffmpeg correctly: + Windows Guide: https://goo.gl/SCv72y + Linux Guide: https://goo.gl/rRhjCp"); + Console.ForegroundColor = oldclr; + } + catch (Exception ex) + { + Console.WriteLine($"Buffering stopped: {ex.Message}"); + } + finally + { + if(outStream != null) + outStream.Dispose(); + Console.WriteLine($"Buffering done."); + if (p != null) + { + try + { + p.Kill(); + } + catch { } + p.Dispose(); + } + } + }, TaskCreationOptions.LongRunning); + + /// + /// Return the next file to read, and delete the old one + /// + /// Name of the file to read + public string GetNextFile() + { + string filename = Basename + "-" + NextFileToRead; + + if (NextFileToRead != 0) + { + try + { + CurrentBufferSize -= Convert.ToUInt64(new FileInfo(Basename + "-" + (NextFileToRead - 1)).Length); + File.Delete(Basename + "-" + (NextFileToRead - 1)); + } + catch { } + } + NextFileToRead++; + return filename; + } + + public bool IsNextFileReady() + { + return NextFileToRead <= FileNumber; + } + + public void CleanFiles() + { + for (long i = NextFileToRead - 1 ; i <= FileNumber; i++) + { + try + { + File.Delete(Basename + "-" + i); + } + catch { } + } + } + } +} diff --git a/NadekoBot/Modules/Music/MusicModule.cs b/NadekoBot/Modules/Music/MusicModule.cs index e5c03915..3c4aa351 100644 --- a/NadekoBot/Modules/Music/MusicModule.cs +++ b/NadekoBot/Modules/Music/MusicModule.cs @@ -614,11 +614,11 @@ namespace NadekoBot.Modules.Music }; DbHandler.Instance.SaveAll(songInfos); DbHandler.Instance.Save(playlist); - DbHandler.Instance.InsertMany(songInfos.Select(s => new PlaylistSongInfo + DbHandler.Instance.Connection.InsertAll(songInfos.Select(s => new PlaylistSongInfo { PlaylistId = playlist.Id.Value, SongInfoId = s.Id.Value - })); + }), typeof(PlaylistSongInfo)); await e.Channel.SendMessage($"🎵 `Saved playlist as {name}-{playlist.Id}`").ConfigureAwait(false); @@ -718,7 +718,7 @@ namespace NadekoBot.Modules.Music }); cgb.CreateCommand(Prefix + "goto") - .Description($"Goes to a specific time in seconds in a song. | {Prefix}goto 30") + .Description($"Goes to a specific time in seconds in a song. | `{Prefix}goto 30`") .Parameter("time") .Do(async e => { @@ -756,21 +756,42 @@ namespace NadekoBot.Modules.Music cgb.CreateCommand(Prefix + "getlink") .Alias(Prefix + "gl") - .Description("Shows a link to the currently playing song.") + .Description($"Shows a link to the song in the queue by index, or the currently playing song by default. | `{Prefix}gl`") + .Parameter("index", ParameterType.Optional) .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}>").ConfigureAwait(false); + int index; + string arg = e.GetArg("index")?.Trim(); + if (!string.IsNullOrEmpty(arg) && int.TryParse(arg, out index)) + { + + var selSong = musicPlayer.Playlist.DefaultIfEmpty(null).ElementAtOrDefault(index - 1); + if (selSong == null) + { + await e.Channel.SendMessage("Could not select song, likely wrong index"); + + } + else + { + await e.Channel.SendMessage($"🎶`Selected song {selSong.SongInfo.Title}:` <{selSong.SongInfo.Query}>").ConfigureAwait(false); + } + } + else + { + var curSong = musicPlayer.CurrentSong; + if (curSong == null) + return; + await e.Channel.SendMessage($"🎶`Current song:` <{curSong.SongInfo.Query}>").ConfigureAwait(false); + } + }); cgb.CreateCommand(Prefix + "autoplay") .Alias(Prefix + "ap") - .Description("Toggles autoplay - When the song is finished, automatically queue a related youtube song. (Works only for youtube songs and when queue is empty)") + .Description($"Toggles autoplay - When the song is finished, automatically queue a related youtube song. (Works only for youtube songs and when queue is empty) | `{Prefix}ap`") .Do(async e => { @@ -818,7 +839,7 @@ namespace NadekoBot.Modules.Music lastFinishedMessage = await textCh.SendMessage($"🎵`Finished`{song.PrettyName}").ConfigureAwait(false); if (mp.Autoplay && mp.Playlist.Count == 0 && song.SongInfo.Provider == "YouTube") { - await QueueSong(queuer, textCh, voiceCh, await SearchHelper.GetRelatedVideoId(song.SongInfo.Query), silent, musicType).ConfigureAwait(false); + await QueueSong(queuer.Server.CurrentUser, textCh, voiceCh, (await SearchHelper.GetRelatedVideoIds(song.SongInfo.Query, 4)).ToList().Shuffle().FirstOrDefault(), silent, musicType).ConfigureAwait(false); } } catch (Exception e) diff --git a/NadekoBot/Modules/NSFW/NSFWModule.cs b/NadekoBot/Modules/NSFW/NSFWModule.cs index a94ab572..ac688fb7 100644 --- a/NadekoBot/Modules/NSFW/NSFWModule.cs +++ b/NadekoBot/Modules/NSFW/NSFWModule.cs @@ -4,6 +4,8 @@ using NadekoBot.Classes; using NadekoBot.Modules.Permissions.Classes; using Newtonsoft.Json.Linq; using System; +using System.Linq; +using System.Threading.Tasks; namespace NadekoBot.Modules.NSFW { @@ -27,16 +29,16 @@ namespace NadekoBot.Modules.NSFW .Do(async e => { var tag = e.GetArg("tag")?.Trim() ?? ""; - var gel = await SearchHelper.GetGelbooruImageLink("rating%3Aexplicit+" + tag).ConfigureAwait(false); - if (gel != null) - await e.Channel.SendMessage(":heart: Gelbooru: " + gel) - .ConfigureAwait(false); - var dan = await SearchHelper.GetDanbooruImageLink("rating%3Aexplicit+" + tag).ConfigureAwait(false); - if (dan != null) - await e.Channel.SendMessage(":heart: Danbooru: " + dan) - .ConfigureAwait(false); - if (dan == null && gel == null) + + var links = await Task.WhenAll(SearchHelper.GetGelbooruImageLink("rating%3Aexplicit+" + tag), SearchHelper.GetDanbooruImageLink("rating%3Aexplicit+" + tag)).ConfigureAwait(false); + + if (links.All(l => l == null)) + { await e.Channel.SendMessage("`No results.`"); + return; + } + + await e.Channel.SendMessage(String.Join("\n\n", links)).ConfigureAwait(false); }); cgb.CreateCommand(Prefix + "danbooru") .Description($"Shows a random hentai image from danbooru with a given tag. Tag is optional but preffered. (multiple tags are appended with +) | `{Prefix}danbooru yuri+kissing`") @@ -84,14 +86,14 @@ namespace NadekoBot.Modules.NSFW await e.Channel.SendMessage(await SearchHelper.GetE621ImageLink(tag).ConfigureAwait(false)).ConfigureAwait(false); }); cgb.CreateCommand(Prefix + "cp") - .Description("We all know where this will lead you to.") + .Description($"We all know where this will lead you to. | `{Prefix}cp`") .Parameter("anything", ParameterType.Unparsed) .Do(async e => { await e.Channel.SendMessage("http://i.imgur.com/MZkY1md.jpg").ConfigureAwait(false); }); cgb.CreateCommand(Prefix + "boobs") - .Description("Real adult content.") + .Description($"Real adult content. | `{Prefix}boobs`") .Do(async e => { try @@ -106,7 +108,7 @@ namespace NadekoBot.Modules.NSFW }); cgb.CreateCommand(Prefix + "butts") .Alias(Prefix + "ass", Prefix + "butt") - .Description("Real adult content.") + .Description($"Real adult content. | `{Prefix}butts` or `{Prefix}ass`") .Do(async e => { try diff --git a/NadekoBot/Modules/Permissions/Classes/PermissionChecker.cs b/NadekoBot/Modules/Permissions/Classes/PermissionChecker.cs index 412ce69a..0c6aa79b 100644 --- a/NadekoBot/Modules/Permissions/Classes/PermissionChecker.cs +++ b/NadekoBot/Modules/Permissions/Classes/PermissionChecker.cs @@ -49,7 +49,6 @@ namespace NadekoBot.Modules.Permissions.Classes { return false; } - if (timeBlackList.Contains(user.Id)) return false; @@ -64,9 +63,9 @@ namespace NadekoBot.Modules.Permissions.Classes PermissionsHandler.PermissionsDict.TryGetValue(user.Server.Id, out perms); AddUserCooldown(user.Server.Id, user.Id, command.Text.ToLower()); - if (commandCooldowns.Keys.Contains(user.Server.Id+":"+command.Text.ToLower())) + if (commandCooldowns.Keys.Contains(user.Server.Id + ":" + command.Text.ToLower())) { - if(perms?.Verbose == true) + if (perms?.Verbose == true) error = $"{user.Mention} You have a cooldown on that command."; return false; } @@ -150,7 +149,8 @@ namespace NadekoBot.Modules.Permissions.Classes } } - public void AddUserCooldown(ulong serverId, ulong userId, string commandName) { + public void AddUserCooldown(ulong serverId, ulong userId, string commandName) + { commandCooldowns.TryAdd(commandName, userId); var tosave = serverId + ":" + commandName; Task.Run(async () => @@ -158,7 +158,8 @@ namespace NadekoBot.Modules.Permissions.Classes ServerPermissions perms; PermissionsHandler.PermissionsDict.TryGetValue(serverId, out perms); int cd; - if (!perms.CommandCooldowns.TryGetValue(commandName,out cd)) { + if (!perms.CommandCooldowns.TryGetValue(commandName, out cd)) + { return; } if (commandCooldowns.TryAdd(tosave, userId)) diff --git a/NadekoBot/Modules/Permissions/Commands/FilterInvitesCommand.cs b/NadekoBot/Modules/Permissions/Commands/FilterInvitesCommand.cs index f65902c6..445558c3 100644 --- a/NadekoBot/Modules/Permissions/Commands/FilterInvitesCommand.cs +++ b/NadekoBot/Modules/Permissions/Commands/FilterInvitesCommand.cs @@ -55,7 +55,7 @@ namespace NadekoBot.Modules.Permissions.Commands .Alias(Module.Prefix + "cfi") .Description("Enables or disables automatic deleting of invites on the channel." + "If no channel supplied, it will default to current one. Use ALL to apply to all existing channels at once." + - " | ;cfi enable #general-chat") + $" | `{Prefix}cfi enable #general-chat`") .Parameter("bool") .Parameter("channel", ParameterType.Optional) .Do(async e => @@ -95,7 +95,7 @@ namespace NadekoBot.Modules.Permissions.Commands cgb.CreateCommand(Module.Prefix + "srvrfilterinv") .Alias(Module.Prefix + "sfi") - .Description("Enables or disables automatic deleting of invites on the server. | ;sfi disable") + .Description($"Enables or disables automatic deleting of invites on the server. | `{Prefix}sfi disable`") .Parameter("bool") .Do(async e => { diff --git a/NadekoBot/Modules/Permissions/Commands/FilterWordsCommand.cs b/NadekoBot/Modules/Permissions/Commands/FilterWordsCommand.cs index c187d398..b574ef23 100644 --- a/NadekoBot/Modules/Permissions/Commands/FilterWordsCommand.cs +++ b/NadekoBot/Modules/Permissions/Commands/FilterWordsCommand.cs @@ -53,7 +53,7 @@ namespace NadekoBot.Modules.Permissions.Commands .Alias(Module.Prefix + "cfw") .Description("Enables or disables automatic deleting of messages containing banned words on the channel." + "If no channel supplied, it will default to current one. Use ALL to apply to all existing channels at once." + - " | ;cfw enable #general-chat") + $" | `{Prefix}cfw enable #general-chat`") .Parameter("bool") .Parameter("channel", ParameterType.Optional) .Do(async e => @@ -89,7 +89,7 @@ namespace NadekoBot.Modules.Permissions.Commands cgb.CreateCommand(Module.Prefix + "addfilterword") .Alias(Module.Prefix + "afw") .Description("Adds a new word to the list of filtered words" + - " | ;afw poop") + $" | `{Prefix}afw poop`") .Parameter("word", ParameterType.Unparsed) .Do(async e => { @@ -111,7 +111,7 @@ namespace NadekoBot.Modules.Permissions.Commands cgb.CreateCommand(Module.Prefix + "rmvfilterword") .Alias(Module.Prefix + "rfw") .Description("Removes the word from the list of filtered words" + - " | ;rw poop") + $" | `{Prefix}rw poop`") .Parameter("word", ParameterType.Unparsed) .Do(async e => { @@ -133,7 +133,7 @@ namespace NadekoBot.Modules.Permissions.Commands cgb.CreateCommand(Module.Prefix + "lstfilterwords") .Alias(Module.Prefix + "lfw") .Description("Shows a list of filtered words" + - " | ;lfw") + $" | `{Prefix}lfw`") .Do(async e => { try @@ -152,7 +152,7 @@ namespace NadekoBot.Modules.Permissions.Commands cgb.CreateCommand(Module.Prefix + "srvrfilterwords") .Alias(Module.Prefix + "sfw") - .Description("Enables or disables automatic deleting of messages containing forbidden words on the server. | ;sfw disable") + .Description($"Enables or disables automatic deleting of messages containing forbidden words on the server. | `{Prefix}sfw disable`") .Parameter("bool") .Do(async e => { diff --git a/NadekoBot/Modules/Permissions/PermissionsModule.cs b/NadekoBot/Modules/Permissions/PermissionsModule.cs index c547bfe5..d2bc1840 100644 --- a/NadekoBot/Modules/Permissions/PermissionsModule.cs +++ b/NadekoBot/Modules/Permissions/PermissionsModule.cs @@ -33,7 +33,7 @@ namespace NadekoBot.Modules.Permissions cgb.CreateCommand(Prefix + "permrole") .Alias(Prefix + "pr") - .Description("Sets a role which can change permissions. Or supply no parameters to find out the current one. Default one is 'Nadeko'.") + .Description($"Sets a role which can change permissions. Or supply no parameters to find out the current one. Default one is 'Nadeko'. | `{Prefix}pr role`") .Parameter("role", ParameterType.Unparsed) .Do(async e => { @@ -158,7 +158,7 @@ namespace NadekoBot.Modules.Permissions cgb.CreateCommand(Prefix + "srvrperms") .Alias(Prefix + "sp") - .Description("Shows banned permissions for this server.") + .Description($"Shows banned permissions for this server. | `{Prefix}sp`") .Do(async e => { var perms = PermissionsHandler.GetServerPermissions(e.Server); @@ -813,7 +813,7 @@ namespace NadekoBot.Modules.Permissions cgb.CreateCommand(Prefix + "allcmdcooldowns") .Alias(Prefix + "acmdcds") - .Description("Shows a list of all commands and their respective cooldowns.") + .Description("Shows a list of all commands and their respective cooldowns. | `{Prefix}acmdcds`") .Do(async e => { ServerPermissions perms; diff --git a/NadekoBot/Modules/Pokemon/PokemonModule.cs b/NadekoBot/Modules/Pokemon/PokemonModule.cs index ae3ae0d9..d494fffa 100644 --- a/NadekoBot/Modules/Pokemon/PokemonModule.cs +++ b/NadekoBot/Modules/Pokemon/PokemonModule.cs @@ -196,7 +196,7 @@ namespace NadekoBot.Modules.Pokemon cgb.CreateCommand(Prefix + "movelist") .Alias(Prefix + "ml") - .Description("Lists the moves you are able to use") + .Description($"Lists the moves you are able to use | `{Prefix}ml`") .Do(async e => { var userType = GetPokeType(e.User.Id); @@ -210,7 +210,7 @@ namespace NadekoBot.Modules.Pokemon }); cgb.CreateCommand(Prefix + "heal") - .Description($"Heals someone. Revives those who fainted. Costs a {NadekoBot.Config.CurrencyName} | {Prefix}heal @someone") + .Description($"Heals someone. Revives those who fainted. Costs a {NadekoBot.Config.CurrencyName} | `{Prefix}heal @someone`") .Parameter("target", ParameterType.Unparsed) .Do(async e => { @@ -263,7 +263,7 @@ namespace NadekoBot.Modules.Pokemon }); cgb.CreateCommand(Prefix + "type") - .Description($"Get the poketype of the target. | {Prefix}type @someone") + .Description($"Get the poketype of the target. | `{Prefix}type @someone`") .Parameter("target", ParameterType.Unparsed) .Do(async e => { @@ -282,7 +282,7 @@ namespace NadekoBot.Modules.Pokemon }); cgb.CreateCommand(Prefix + "settype") - .Description($"Set your poketype. Costs a {NadekoBot.Config.CurrencyName}. | {Prefix}settype fire") + .Description($"Set your poketype. Costs a {NadekoBot.Config.CurrencyName}. | `{Prefix}settype fire`") .Parameter("targetType", ParameterType.Unparsed) .Do(async e => { @@ -319,11 +319,11 @@ namespace NadekoBot.Modules.Pokemon DbHandler.Instance.Delete(Dict[(long)e.User.Id]); } - DbHandler.Instance.InsertData(new UserPokeTypes + DbHandler.Instance.Connection.Insert(new UserPokeTypes { UserId = (long)e.User.Id, type = targetType.Name - }); + }, typeof(UserPokeTypes)); //Now for the response diff --git a/NadekoBot/Modules/Searches/Commands/ConverterCommand.cs b/NadekoBot/Modules/Searches/Commands/ConverterCommand.cs index 2383e718..ada8709a 100644 --- a/NadekoBot/Modules/Searches/Commands/ConverterCommand.cs +++ b/NadekoBot/Modules/Searches/Commands/ConverterCommand.cs @@ -32,7 +32,7 @@ namespace NadekoBot.Modules.Searches.Commands internal override void Init(CommandGroupBuilder cgb) { cgb.CreateCommand(Module.Prefix + "convert") - .Description("Convert quantities from>to. Like `~convert m>km 1000`") + .Description($"Convert quantities from>to. | `{Prefix}convert m>km 1000`") .Parameter("from-to", ParameterType.Required) .Parameter("quantity", ParameterType.Optional) .Do(ConvertFunc()); diff --git a/NadekoBot/Modules/Searches/Commands/EvalCommand.cs b/NadekoBot/Modules/Searches/Commands/EvalCommand.cs index ed469517..4dd5a9fe 100644 --- a/NadekoBot/Modules/Searches/Commands/EvalCommand.cs +++ b/NadekoBot/Modules/Searches/Commands/EvalCommand.cs @@ -17,7 +17,7 @@ namespace NadekoBot.Modules.Searches.Commands { cgb.CreateCommand(Module.Prefix + "calculate") .Alias(Module.Prefix + "calc") - .Description("Evaluate a mathematical expression. | ~calc 1+1") + .Description($"Evaluate a mathematical expression. | `{Prefix}calc 1+1`") .Parameter("expression", ParameterType.Unparsed) .Do(EvalFunc()); } diff --git a/NadekoBot/Modules/Searches/Commands/LoLCommands.cs b/NadekoBot/Modules/Searches/Commands/LoLCommands.cs index 8826beaf..5a5b766a 100644 --- a/NadekoBot/Modules/Searches/Commands/LoLCommands.cs +++ b/NadekoBot/Modules/Searches/Commands/LoLCommands.cs @@ -72,7 +72,7 @@ namespace NadekoBot.Modules.Searches.Commands internal override void Init(CommandGroupBuilder cgb) { cgb.CreateCommand(Module.Prefix + "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. |~lolchamp Riven or ~lolchamp Annie sup") + .Description($"Shows League Of Legends champion statistics. If there are spaces/apostrophes or in the name - omit them. Optional second parameter is a role. |`{Prefix}lolchamp Riven` or `{Prefix}lolchamp Annie sup`") .Parameter("champ", ParameterType.Required) .Parameter("position", ParameterType.Unparsed) .Do(async e => @@ -280,7 +280,7 @@ Assists: {general["assists"]} Ban: {general["banRate"]}% }); cgb.CreateCommand(Module.Prefix + "lolban") - .Description("Shows top 6 banned champions ordered by ban rate. Ban these champions and you will be Plat 5 in no time.") + .Description($"Shows top 6 banned champions ordered by ban rate. Ban these champions and you will be Plat 5 in no time. | `{Prefix}lolban`") .Do(async e => { diff --git a/NadekoBot/Modules/Searches/Commands/MemegenCommands.cs b/NadekoBot/Modules/Searches/Commands/MemegenCommands.cs index 5eff7c78..a7d23181 100644 --- a/NadekoBot/Modules/Searches/Commands/MemegenCommands.cs +++ b/NadekoBot/Modules/Searches/Commands/MemegenCommands.cs @@ -17,7 +17,7 @@ namespace NadekoBot.Modules.Searches.Commands internal override void Init(CommandGroupBuilder cgb) { cgb.CreateCommand(Prefix + "memelist") - .Description("Pulls a list of memes you can use with `~memegen` from http://memegen.link/templates/") + .Description($"Pulls a list of memes you can use with `~memegen` from http://memegen.link/templates/ | `{Prefix}memelist`") .Do(async e => { int i = 0; @@ -30,7 +30,7 @@ namespace NadekoBot.Modules.Searches.Commands }); cgb.CreateCommand(Prefix + "memegen") - .Description("Generates a meme from memelist with top and bottom text. | `~memegen biw \"gets iced coffee\" \"in the winter\"`") + .Description($"Generates a meme from memelist with top and bottom text. | `{Prefix}memegen biw \"gets iced coffee\" \"in the winter\"`") .Parameter("meme", ParameterType.Required) .Parameter("toptext", ParameterType.Required) .Parameter("bottext", ParameterType.Required) diff --git a/NadekoBot/Modules/Searches/Commands/OsuCommands.cs b/NadekoBot/Modules/Searches/Commands/OsuCommands.cs index 451e9a13..0532203d 100644 --- a/NadekoBot/Modules/Searches/Commands/OsuCommands.cs +++ b/NadekoBot/Modules/Searches/Commands/OsuCommands.cs @@ -17,7 +17,7 @@ namespace NadekoBot.Modules.Searches.Commands internal override void Init(CommandGroupBuilder cgb) { cgb.CreateCommand(Module.Prefix + "osu") - .Description("Shows osu stats for a player. | `~osu Name` or `~osu Name taiko`") + .Description($"Shows osu stats for a player. | `{Prefix}osu Name` or `{Prefix}osu Name taiko`") .Parameter("usr", ParameterType.Required) .Parameter("mode", ParameterType.Unparsed) .Do(async e => @@ -56,7 +56,7 @@ namespace NadekoBot.Modules.Searches.Commands }); cgb.CreateCommand(Module.Prefix + "osu b") - .Description("Shows information about an osu beatmap. |~osu b https://osu.ppy.sh/s/127712") + .Description($"Shows information about an osu beatmap. |`{Prefix}osu b` https://osu.ppy.sh/s/127712`") .Parameter("map", ParameterType.Unparsed) .Do(async e => { @@ -88,7 +88,7 @@ namespace NadekoBot.Modules.Searches.Commands }); cgb.CreateCommand(Module.Prefix + "osu top5") - .Description("Displays a user's top 5 plays. |~osu top5 Name") + .Description($"Displays a user's top 5 plays. |`{Prefix}osu top5 Name`") .Parameter("usr", ParameterType.Required) .Parameter("mode", ParameterType.Unparsed) .Do(async e => diff --git a/NadekoBot/Modules/Searches/Commands/PokemonSearchCommands.cs b/NadekoBot/Modules/Searches/Commands/PokemonSearchCommands.cs index a171abe9..b2c13dca 100644 --- a/NadekoBot/Modules/Searches/Commands/PokemonSearchCommands.cs +++ b/NadekoBot/Modules/Searches/Commands/PokemonSearchCommands.cs @@ -22,7 +22,7 @@ namespace NadekoBot.Modules.Searches.Commands { cgb.CreateCommand(Prefix + "pokemon") .Alias(Prefix + "poke") - .Description("Searches for a pokemon.") + .Description($"Searches for a pokemon. | `{Prefix}poke Sylveon`") .Parameter("pokemon", ParameterType.Unparsed) .Do(async e => { @@ -43,7 +43,7 @@ namespace NadekoBot.Modules.Searches.Commands cgb.CreateCommand(Prefix + "pokemonability") .Alias(Prefix + "pokeab") - .Description("Searches for a pokemon ability.") + .Description($"Searches for a pokemon ability. | `{Prefix}pokeab \"water gun\"`") .Parameter("abil", ParameterType.Unparsed) .Do(async e => { diff --git a/NadekoBot/Modules/Searches/Commands/StreamNotifications.cs b/NadekoBot/Modules/Searches/Commands/StreamNotifications.cs index efe521ff..f8720324 100644 --- a/NadekoBot/Modules/Searches/Commands/StreamNotifications.cs +++ b/NadekoBot/Modules/Searches/Commands/StreamNotifications.cs @@ -122,7 +122,7 @@ namespace NadekoBot.Modules.Searches.Commands cgb.CreateCommand(Module.Prefix + "hitbox") .Alias(Module.Prefix + "hb") .Description("Notifies this channel when a certain user starts streaming." + - " | ~hitbox SomeStreamer") + $" | `{Prefix}hitbox SomeStreamer`") .Parameter("username", ParameterType.Unparsed) .AddCheck(SimpleCheckers.ManageServer()) .Do(TrackStream(StreamNotificationConfig.StreamType.Hitbox)); @@ -130,7 +130,7 @@ namespace NadekoBot.Modules.Searches.Commands cgb.CreateCommand(Module.Prefix + "twitch") .Alias(Module.Prefix + "tw") .Description("Notifies this channel when a certain user starts streaming." + - " | ~twitch SomeStreamer") + $" | `{Prefix}twitch SomeStreamer`") .AddCheck(SimpleCheckers.ManageServer()) .Parameter("username", ParameterType.Unparsed) .Do(TrackStream(StreamNotificationConfig.StreamType.Twitch)); @@ -138,7 +138,7 @@ namespace NadekoBot.Modules.Searches.Commands cgb.CreateCommand(Module.Prefix + "beam") .Alias(Module.Prefix + "bm") .Description("Notifies this channel when a certain user starts streaming." + - " | ~beam SomeStreamer") + $" | `{Prefix}beam SomeStreamer`") .AddCheck(SimpleCheckers.ManageServer()) .Parameter("username", ParameterType.Unparsed) .Do(TrackStream(StreamNotificationConfig.StreamType.Beam)); @@ -146,7 +146,7 @@ namespace NadekoBot.Modules.Searches.Commands cgb.CreateCommand(Module.Prefix + "checkhitbox") .Alias(Module.Prefix + "chhb") .Description("Checks if a certain user is streaming on the hitbox platform." + - " | ~chhb SomeStreamer") + $" | `{Prefix}chhb SomeStreamer`") .Parameter("username", ParameterType.Unparsed) .AddCheck(SimpleCheckers.ManageServer()) .Do(async e => @@ -175,7 +175,7 @@ namespace NadekoBot.Modules.Searches.Commands cgb.CreateCommand(Module.Prefix + "checktwitch") .Alias(Module.Prefix + "chtw") .Description("Checks if a certain user is streaming on the twitch platform." + - " | ~chtw SomeStreamer") + $" | `{Prefix}chtw SomeStreamer`") .AddCheck(SimpleCheckers.ManageServer()) .Parameter("username", ParameterType.Unparsed) .Do(async e => @@ -204,7 +204,7 @@ namespace NadekoBot.Modules.Searches.Commands cgb.CreateCommand(Module.Prefix + "checkbeam") .Alias(Module.Prefix + "chbm") .Description("Checks if a certain user is streaming on the beam platform." + - " | ~chbm SomeStreamer") + $" | `{Prefix}chbm SomeStreamer`") .AddCheck(SimpleCheckers.ManageServer()) .Parameter("username", ParameterType.Unparsed) .Do(async e => @@ -233,7 +233,7 @@ namespace NadekoBot.Modules.Searches.Commands cgb.CreateCommand(Module.Prefix + "removestream") .Alias(Module.Prefix + "rms") .Description("Removes notifications of a certain streamer on this channel." + - " | ~rms SomeGuy") + $" | `{Prefix}rms SomeGuy`") .AddCheck(SimpleCheckers.ManageServer()) .Parameter("username", ParameterType.Unparsed) .Do(async e => @@ -261,7 +261,7 @@ namespace NadekoBot.Modules.Searches.Commands cgb.CreateCommand(Module.Prefix + "liststreams") .Alias(Module.Prefix + "ls") .Description("Lists all streams you are following on this server." + - " | ~ls") + $" | `{Prefix}ls`") .Do(async e => { diff --git a/NadekoBot/Modules/Searches/Commands/WowJokes.cs b/NadekoBot/Modules/Searches/Commands/WowJokes.cs index da2f99ae..b3e67eed 100644 --- a/NadekoBot/Modules/Searches/Commands/WowJokes.cs +++ b/NadekoBot/Modules/Searches/Commands/WowJokes.cs @@ -22,7 +22,7 @@ namespace NadekoBot.Modules.Searches.Commands { cgb.CreateCommand(Module.Prefix + "wowjoke") - .Description("Get one of Kwoth's penultimate WoW jokes.") + .Description($"Get one of Kwoth's penultimate WoW jokes. | `{Prefix}wowjoke`") .Do(async e => { if (!jokes.Any()) diff --git a/NadekoBot/Modules/Searches/SearchesModule.cs b/NadekoBot/Modules/Searches/SearchesModule.cs index 45b50c33..2662107a 100644 --- a/NadekoBot/Modules/Searches/SearchesModule.cs +++ b/NadekoBot/Modules/Searches/SearchesModule.cs @@ -86,7 +86,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 cgb.CreateCommand(Prefix + "ani") .Alias(Prefix + "anime", Prefix + "aq") .Parameter("query", ParameterType.Unparsed) - .Description("Queries anilist for an anime and shows the first result.") + .Description($"Queries anilist for an anime and shows the first result. | `{Prefix}aq aquarion evol`") .Do(async e => { if (!(await SearchHelper.ValidateQuery(e.Channel, e.GetArg("query")).ConfigureAwait(false))) return; @@ -106,7 +106,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 cgb.CreateCommand(Prefix + "imdb") .Parameter("query", ParameterType.Unparsed) - .Description($"Queries imdb for movies or series, show first result. | `{Prefix}imdb query`") + .Description($"Queries imdb for movies or series, show first result. | `{Prefix}imdb Batman vs Superman`") .Do(async e => { if (!(await SearchHelper.ValidateQuery(e.Channel, e.GetArg("query")).ConfigureAwait(false))) return; @@ -130,7 +130,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 cgb.CreateCommand(Prefix + "mang") .Alias(Prefix + "manga").Alias(Prefix + "mq") .Parameter("query", ParameterType.Unparsed) - .Description($"Queries anilist for a manga and shows the first result. | `{Prefix}mq query`") + .Description($"Queries anilist for a manga and shows the first result. | `{Prefix}mq Shingeki no kyojin`") .Do(async e => { if (!(await SearchHelper.ValidateQuery(e.Channel, e.GetArg("query")).ConfigureAwait(false))) return; @@ -149,7 +149,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 cgb.CreateCommand(Prefix + "randomcat") .Alias(Prefix + "meow") - .Description("Shows a random cat image.") + .Description($"Shows a random cat image. | `{Prefix}meow`") .Do(async e => { await e.Channel.SendMessage(JObject.Parse( @@ -159,7 +159,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 cgb.CreateCommand(Prefix + "randomdog") .Alias(Prefix + "woof") - .Description("Shows a random dog image.") + .Description($"Shows a random dog image. | `{Prefix}woof`") .Do(async e => { await e.Channel.SendMessage("http://random.dog/" + await SearchHelper.GetResponseStringAsync("http://random.dog/woof").ConfigureAwait(false)).ConfigureAwait(false); @@ -341,7 +341,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 }); cgb.CreateCommand(Prefix + "quote") - .Description("Shows a random quote.") + .Description($"Shows a random quote. | `{Prefix}quote`") .Do(async e => { var quote = NadekoBot.Config.Quotes[rng.Next(0, NadekoBot.Config.Quotes.Count)].ToString(); @@ -349,7 +349,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 }); cgb.CreateCommand(Prefix + "catfact") - .Description("Shows a random catfact from ") + .Description($"Shows a random catfact from | `{Prefix}catfact`") .Do(async e => { var response = await SearchHelper.GetResponseStringAsync("http://catfacts-api.appspot.com/api/facts").ConfigureAwait(false); @@ -360,7 +360,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 cgb.CreateCommand(Prefix + "yomama") .Alias(Prefix + "ym") - .Description("Shows a random joke from ") + .Description($"Shows a random joke from | `{Prefix}ym`") .Do(async e => { var response = await SearchHelper.GetResponseStringAsync("http://api.yomomma.info/").ConfigureAwait(false); @@ -369,7 +369,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 cgb.CreateCommand(Prefix + "randjoke") .Alias(Prefix + "rj") - .Description("Shows a random joke from ") + .Description($"Shows a random joke from | `{Prefix}rj`") .Do(async e => { var response = await SearchHelper.GetResponseStringAsync("http://tambal.azurewebsites.net/joke/random").ConfigureAwait(false); @@ -378,7 +378,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 cgb.CreateCommand(Prefix + "chucknorris") .Alias(Prefix + "cn") - .Description("Shows a random chucknorris joke from ") + .Description($"Shows a random chucknorris joke from | `{Prefix}cn`") .Do(async e => { var response = await SearchHelper.GetResponseStringAsync("http://api.icndb.com/jokes/random/").ConfigureAwait(false); @@ -387,7 +387,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 cgb.CreateCommand(Prefix + "magicitem") .Alias(Prefix + "mi") - .Description("Shows a random magicitem from ") + .Description($"Shows a random magicitem from | `{Prefix}mi`") .Do(async e => { var magicItems = JsonConvert.DeserializeObject>(File.ReadAllText("data/magicitems.json")); @@ -397,7 +397,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 }); cgb.CreateCommand(Prefix + "revav") - .Description($"Returns a google reverse image search for someone's avatar. | `{Prefix}revav \"@SomeGuy\"") + .Description($"Returns a google reverse image search for someone's avatar. | `{Prefix}revav \"@SomeGuy\"`") .Parameter("user", ParameterType.Unparsed) .Do(async e => { @@ -502,7 +502,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】 cgb.CreateCommand(Prefix + "av") .Alias(Prefix + "avatar") .Parameter("mention", ParameterType.Required) - .Description($"Shows a mentioned person's avatar. | `{Prefix}av @X`") + .Description($"Shows a mentioned person's avatar. | `{Prefix}av \"@SomeGuy\"`") .Do(async e => { var usr = e.Channel.FindUsers(e.GetArg("mention")).FirstOrDefault(); diff --git a/NadekoBot/Modules/Translator/ValidLanguagesCommand.cs b/NadekoBot/Modules/Translator/ValidLanguagesCommand.cs index ede25f13..438e77de 100644 --- a/NadekoBot/Modules/Translator/ValidLanguagesCommand.cs +++ b/NadekoBot/Modules/Translator/ValidLanguagesCommand.cs @@ -13,7 +13,7 @@ namespace NadekoBot.Modules.Translator internal override void Init(CommandGroupBuilder cgb) { cgb.CreateCommand(Module.Prefix + "translangs") - .Description("List the valid languages for translation.") + .Description($"List the valid languages for translation. | `{Prefix}translangs` or `{Prefix}translangs language`") .Parameter("search", ParameterType.Optional) .Do(ListLanguagesFunc()); } diff --git a/NadekoBot/Modules/Trello/TrelloModule.cs b/NadekoBot/Modules/Trello/TrelloModule.cs index b144a2cf..176ca2b8 100644 --- a/NadekoBot/Modules/Trello/TrelloModule.cs +++ b/NadekoBot/Modules/Trello/TrelloModule.cs @@ -71,7 +71,7 @@ namespace NadekoBot.Modules.Trello cgb.CreateCommand(Prefix + "bind") .Description("Bind a trello bot to a single channel. " + "You will receive notifications from your board when something is added or edited." + - $" | `{Prefix}bind [board_id]`") + $" **Bot Owner Only!**| `{Prefix}bind [board_id]`") .Parameter("board_id", Discord.Commands.ParameterType.Required) .Do(async e => { @@ -92,7 +92,7 @@ namespace NadekoBot.Modules.Trello }); cgb.CreateCommand(Prefix + "unbind") - .Description("Unbinds a bot from the channel and board.") + .Description($"Unbinds a bot from the channel and board. **Bot Owner Only!**| `{Prefix}unbind`") .Do(async e => { if (!NadekoBot.IsOwner(e.User.Id)) return; @@ -106,7 +106,7 @@ namespace NadekoBot.Modules.Trello cgb.CreateCommand(Prefix + "lists") .Alias(Prefix + "list") - .Description("Lists all lists yo ;)") + .Description($"Lists all lists, yo ;) **Bot Owner Only!**| `{Prefix}list`") .Do(async e => { if (!NadekoBot.IsOwner(e.User.Id)) return; @@ -116,7 +116,7 @@ namespace NadekoBot.Modules.Trello }); cgb.CreateCommand(Prefix + "cards") - .Description($"Lists all cards from the supplied list. You can supply either a name or an index. | `{Prefix}cards index`") + .Description($"Lists all cards from the supplied list. You can supply either a name or an index. **Bot Owner Only!**| `{Prefix}cards index`") .Parameter("list_name", Discord.Commands.ParameterType.Unparsed) .Do(async e => { diff --git a/NadekoBot/Modules/Utility/Commands/InfoCommands.cs b/NadekoBot/Modules/Utility/Commands/InfoCommands.cs index 7d14a16f..da1bcd0c 100644 --- a/NadekoBot/Modules/Utility/Commands/InfoCommands.cs +++ b/NadekoBot/Modules/Utility/Commands/InfoCommands.cs @@ -18,7 +18,7 @@ namespace NadekoBot.Modules.Utility.Commands { cgb.CreateCommand(Module.Prefix + "serverinfo") .Alias(Module.Prefix + "sinfo") - .Description($"Shows info about the server the bot is on. If no channel is supplied, it defaults to current one. |{Module.Prefix}sinfo Some Server") + .Description($"Shows info about the server the bot is on. If no channel is supplied, it defaults to current one. |`{Module.Prefix}sinfo Some Server`") .Parameter("server", ParameterType.Optional) .Do(async e => { @@ -49,7 +49,7 @@ namespace NadekoBot.Modules.Utility.Commands cgb.CreateCommand(Module.Prefix + "channelinfo") .Alias(Module.Prefix + "cinfo") - .Description($"Shows info about the channel. If no channel is supplied, it defaults to current one. |{Module.Prefix}cinfo #some-channel") + .Description($"Shows info about the channel. If no channel is supplied, it defaults to current one. |`{Module.Prefix}cinfo #some-channel`") .Parameter("channel", ParameterType.Optional) .Do(async e => { @@ -71,7 +71,7 @@ namespace NadekoBot.Modules.Utility.Commands cgb.CreateCommand(Module.Prefix + "userinfo") .Alias(Module.Prefix + "uinfo") - .Description($"Shows info about the user. If no user is supplied, it defaults a user running the command. |{Module.Prefix}uinfo @SomeUser") + .Description($"Shows info about the user. If no user is supplied, it defaults a user running the command. |`{Module.Prefix}uinfo @SomeUser`") .Parameter("user", ParameterType.Optional) .Do(async e => { diff --git a/NadekoBot/Modules/Utility/Commands/Remind.cs b/NadekoBot/Modules/Utility/Commands/Remind.cs index dabd4158..808f4b11 100644 --- a/NadekoBot/Modules/Utility/Commands/Remind.cs +++ b/NadekoBot/Modules/Utility/Commands/Remind.cs @@ -88,7 +88,7 @@ namespace NadekoBot.Modules.Utility.Commands .Description("Sends a message to you or a channel after certain amount of time. " + "First argument is me/here/'channelname'. Second argument is time in a descending order (mo>w>d>h>m) example: 1w5d3h10m. " + "Third argument is a (multiword)message. " + - " | `.remind me 1d5h Do something` or `.remind #general Start now!`") + $" | `{Prefix}remind me 1d5h Do something` or `{Prefix}remind #general Start now!`") .Parameter("meorchannel", ParameterType.Required) .Parameter("time", ParameterType.Required) .Parameter("message", ParameterType.Unparsed) @@ -171,7 +171,7 @@ namespace NadekoBot.Modules.Utility.Commands UserId = (long)e.User.Id, ServerId = (long)e.Server.Id }; - DbHandler.Instance.InsertData(rem); + DbHandler.Instance.Connection.Insert(rem); reminders.Add(StartNewReminder(rem)); @@ -180,7 +180,7 @@ namespace NadekoBot.Modules.Utility.Commands cgb.CreateCommand(Module.Prefix + "remindmsg") .Description("Sets message for when the remind is triggered. " + " Available placeholders are %user% - user who ran the command, %message% -" + - " Message specified in the remind, %target% - target channel of the remind. **Bot Owner Only!**") + $" Message specified in the remind, %target% - target channel of the remind. **Bot Owner Only!** | `{Prefix}remindmsg do something else`") .Parameter("msg", ParameterType.Unparsed) .AddCheck(SimpleCheckers.OwnerOnly()) .Do(async e => diff --git a/NadekoBot/Modules/Utility/UtilityModule.cs b/NadekoBot/Modules/Utility/UtilityModule.cs index bd172c08..f63fc564 100644 --- a/NadekoBot/Modules/Utility/UtilityModule.cs +++ b/NadekoBot/Modules/Utility/UtilityModule.cs @@ -48,7 +48,7 @@ namespace NadekoBot.Modules.Utility if (arr.Length == 0) await e.Channel.SendMessage("Nobody. (not 100% sure)").ConfigureAwait(false); else - await e.Channel.SendMessage("```xl\n" + string.Join("\n", arr.GroupBy(item => (i++) / 3).Select(ig => string.Concat(ig.Select(el => $" {el,-35}")))) + "\n```").ConfigureAwait(false); + await e.Channel.SendMessage("```xl\n" + string.Join("\n", arr.GroupBy(item => (i++) / 3).Select(ig => string.Concat(ig.Select(el => $"• {el,-35}")))) + "\n```").ConfigureAwait(false); }); cgb.CreateCommand(Prefix + "inrole") @@ -87,7 +87,7 @@ namespace NadekoBot.Modules.Utility }); cgb.CreateCommand(Prefix + "checkmyperms") - .Description("Checks your userspecific permissions on this channel.") + .Description($"Checks your userspecific permissions on this channel. | `{Prefix}checkmyperms`") .Do(async e => { var output = "```\n"; @@ -100,21 +100,21 @@ namespace NadekoBot.Modules.Utility }); cgb.CreateCommand(Prefix + "stats") - .Description("Shows some basic stats for Nadeko.") + .Description($"Shows some basic stats for Nadeko. | `{Prefix}stats`") .Do(async e => { await e.Channel.SendMessage(await NadekoStats.Instance.GetStats()).ConfigureAwait(false); }); cgb.CreateCommand(Prefix + "dysyd") - .Description("Shows some basic stats for Nadeko.") + .Description($"Shows some basic stats for Nadeko. | `{Prefix}dysyd`") .Do(async e => { await e.Channel.SendMessage((await NadekoStats.Instance.GetStats()).Matrix().TrimTo(1990)).ConfigureAwait(false); }); cgb.CreateCommand(Prefix + "userid").Alias(Prefix + "uid") - .Description($"Shows user ID. | `{Prefix}uid` or `{Prefix}uid \"@SomeGuy\"") + .Description($"Shows user ID. | `{Prefix}uid` or `{Prefix}uid \"@SomeGuy\"`") .Parameter("user", ParameterType.Unparsed) .Do(async e => { @@ -134,7 +134,7 @@ namespace NadekoBot.Modules.Utility .Do(async e => await e.Channel.SendMessage("This server's ID is " + e.Server.Id).ConfigureAwait(false)); cgb.CreateCommand(Prefix + "roles") - .Description("List all roles on this server or a single user if specified.") + .Description("List all roles on this server or a single user if specified. | `{Prefix}roles`") .Parameter("user", ParameterType.Unparsed) .Do(async e => { @@ -143,10 +143,10 @@ namespace NadekoBot.Modules.Utility var usr = e.Server.FindUsers(e.GetArg("user")).FirstOrDefault(); if (usr == null) return; - await e.Channel.SendMessage($"`List of roles for **{usr.Name}**:` \n " + string.Join("\n ", usr.Roles)).ConfigureAwait(false); + await e.Channel.SendMessage($"`List of roles for **{usr.Name}**:` \n• " + string.Join("\n• ", usr.Roles)).ConfigureAwait(false); return; } - await e.Channel.SendMessage("`List of roles:` \n " + string.Join("\n ", e.Server.Roles)).ConfigureAwait(false); + await e.Channel.SendMessage("`List of roles:` \n• " + string.Join("\n• ", e.Server.Roles)).ConfigureAwait(false); }); diff --git a/NadekoBot/NadekoBot.cs b/NadekoBot/NadekoBot.cs index ad68beca..b706b95d 100644 --- a/NadekoBot/NadekoBot.cs +++ b/NadekoBot/NadekoBot.cs @@ -117,12 +117,12 @@ namespace NadekoBot Client = new DiscordClient(new DiscordConfigBuilder() { MessageCacheSize = 10, - ConnectionTimeout = 120000, + ConnectionTimeout = 180000, LogLevel = LogSeverity.Warning, LogHandler = (s, e) => Console.WriteLine($"Severity: {e.Severity}" + - $"Message: {e.Message}" + - $"ExceptionMessage: {e.Exception?.Message ?? "-"}"), + $"ExceptionMessage: {e.Exception?.Message ?? "-"}" + + $"Message: {e.Message}"), }); //create a command service @@ -197,7 +197,7 @@ namespace NadekoBot return; } #if NADEKO_RELEASE - await Task.Delay(100000).ConfigureAwait(false); + await Task.Delay(150000).ConfigureAwait(false); #else await Task.Delay(1000).ConfigureAwait(false); #endif diff --git a/NadekoBot/NadekoBot.csproj b/NadekoBot/NadekoBot.csproj index bc22b90f..341f1850 100644 --- a/NadekoBot/NadekoBot.csproj +++ b/NadekoBot/NadekoBot.csproj @@ -162,7 +162,6 @@ lib\ScaredFingers.UnitsConversion.dll - @@ -202,6 +201,8 @@ + + @@ -215,6 +216,7 @@ + @@ -264,7 +266,6 @@ - @@ -296,8 +297,6 @@ Resources.resx - - @@ -550,6 +549,13 @@ + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + [Wiki](https://github.com/Kwoth/NadekoBot/wiki) diff --git a/commandlist.md b/commandlist.md index d055dc88..fd405bd1 100644 --- a/commandlist.md +++ b/commandlist.md @@ -1,62 +1,63 @@ ######For more information and how to setup your own NadekoBot, go to: **http://github.com/Kwoth/NadekoBot/** -######You can donate on paypal: `nadekodiscordbot@gmail.com` +######You can donate on patreon: `https://patreon.com/nadekobot` +######or paypal: `nadekodiscordbot@gmail.com` #NadekoBot List Of Commands -Version: `NadekoBot v0.9.6051.26856` +Version: `NadekoBot v0.9.6054.4837` ### Help Command and aliases | Description | Usage ----------------|--------------|------- -`-h`, `-help`, `@BotName help`, `@BotName h`, `~h` | Either shows a help for a single command, or PMs you help link if no arguments are specified. | '-h !m q' or just '-h' -`-hgit` | Generates the commandlist.md file. **Bot Owner Only!** -`-readme`, `-guide` | Sends a readme and a guide links to the channel. -`-donate`, `~donate` | Instructions for helping the project! -`-modules`, `.modules` | List all bot modules. -`-commands`, `.commands` | List all of the bot's commands from a certain module. +`-h`, `-help`, `@BotName help`, `@BotName h`, `~h` | Either shows a help for a single command, or PMs you help link if no arguments are specified. | `-h !m q` or just `-h` +`-hgit` | Generates the commandlist.md file. **Bot Owner Only!** | `-hgit` +`-readme`, `-guide` | Sends a readme and a guide links to the channel. | `-readme` or `-guide` +`-donate`, `~donate` | Instructions for helping the project! | `{Prefix}donate` or `~donate` +`-modules`, `.modules` | List all bot modules. | `{Prefix}modules` or `.modules` +`-commands`, `.commands` | List all of the bot's commands from a certain module. | `{Prefix}commands` or `.commands` ### Administration Command and aliases | Description | Usage ----------------|--------------|------- -`.grdel` | Toggles automatic deletion of greet and bye messages. -`.greet` | Toggles anouncements on the current channel when someone joins the server. -`.greetmsg` | Sets a new join announcement message. Type %user% if you want to mention the new member. Using it with no message will show the current greet message. | .greetmsg Welcome to the server, %user%. -`.bye` | Toggles anouncements on the current channel when someone leaves the server. -`.byemsg` | Sets a new leave announcement message. Type %user% if you want to mention the new member. Using it with no message will show the current bye message. | .byemsg %user% has left the server. -`.byepm` | Toggles whether the good bye messages will be sent in a PM or in the text channel. -`.greetpm` | Toggles whether the greet messages will be sent in a PM or in the text channel. -`.spmom` | Toggles whether mentions of other offline users on your server will send a pm to them. -`.logserver` | Toggles logging in this channel. Logs every message sent/deleted/edited on the server. **Bot Owner Only!** -`.logignore` | Toggles whether the .logserver command ignores this channel. Useful if you have hidden admin channel and public log channel. -`.userpresence` | Starts logging to this channel when someone from the server goes online/offline/idle. -`.voicepresence` | Toggles logging to this channel whenever someone joins or leaves a voice channel you are in right now. -`.repeatinvoke`, `.repinv` | Immediately shows the repeat message and restarts the timer. +`.grdel` | Toggles automatic deletion of greet and bye messages. | `.grdel` +`.greet` | Toggles anouncements on the current channel when someone joins the server. | `.greet` +`.greetmsg` | Sets a new join announcement message. Type %user% if you want to mention the new member. Using it with no message will show the current greet message. | `.greetmsg Welcome to the server, %user%.` +`.bye` | Toggles anouncements on the current channel when someone leaves the server. | `.bye` +`.byemsg` | Sets a new leave announcement message. Type %user% if you want to mention the new member. Using it with no message will show the current bye message. | `.byemsg %user% has left the server.` +`.byepm` | Toggles whether the good bye messages will be sent in a PM or in the text channel. | `.byepm` +`.greetpm` | Toggles whether the greet messages will be sent in a PM or in the text channel. | `.greetpm` +`.spmom` | Toggles whether mentions of other offline users on your server will send a pm to them. | `.spmom` +`.logserver` | Toggles logging in this channel. Logs every message sent/deleted/edited on the server. **Bot Owner Only!** | `.logserver` +`.logignore` | Toggles whether the .logserver command ignores this channel. Useful if you have hidden admin channel and public log channel. | `.logignore` +`.userpresence` | Starts logging to this channel when someone from the server goes online/offline/idle. | `.userpresence` +`.voicepresence` | Toggles logging to this channel whenever someone joins or leaves a voice channel you are in right now. | `{Prefix}voicerpresence` +`.repeatinvoke`, `.repinv` | Immediately shows the repeat message and restarts the timer. | `{Prefix}repinv` `.repeat` | Repeat a message every X minutes. If no parameters are specified, repeat is disabled. Requires manage messages. | `.repeat 5 Hello there` -`.rotateplaying`, `.ropl` | Toggles rotation of playing status of the dynamic strings you specified earlier. -`.addplaying`, `.adpl` | Adds a specified string to the list of playing strings to rotate. Supported placeholders: %servers%, %users%, %playing%, %queued%, %trivia% -`.listplaying`, `.lipl` | Lists all playing statuses with their corresponding number. -`.removeplaying`, `.repl`, `.rmpl` | Removes a playing string on a given number. -`.slowmode` | Toggles slow mode. When ON, users will be able to send only 1 message every 5 seconds. -`.cleanv+t`, `.cv+t` | Deletes all text channels ending in `-voice` for which voicechannels are not found. **Use at your own risk.** -`.voice+text`, `.v+t` | Creates a text channel for each voice channel only users in that voice channel can see.If you are server owner, keep in mind you will see them all the time regardless. -`.scsc` | Starts an instance of cross server channel. You will get a token as a DMthat other people will use to tune in to the same instance -`.jcsc` | Joins current channel to an instance of cross server channel using the token. -`.lcsc` | Leaves Cross server channel instance from this channel +`.rotateplaying`, `.ropl` | Toggles rotation of playing status of the dynamic strings you specified earlier. | `.ropl` +`.addplaying`, `.adpl` | Adds a specified string to the list of playing strings to rotate. Supported placeholders: %servers%, %users%, %playing%, %queued%, %trivia% | `.adpl` +`.listplaying`, `.lipl` | Lists all playing statuses with their corresponding number. | `.lipl` +`.removeplaying`, `.repl`, `.rmpl` | Removes a playing string on a given number. | `.rmpl` +`.slowmode` | Toggles slow mode. When ON, users will be able to send only 1 message every 5 seconds. | `.slowmode` +`.cleanv+t`, `.cv+t` | Deletes all text channels ending in `-voice` for which voicechannels are not found. **Use at your own risk.** | `.cleanv+t` +`.voice+text`, `.v+t` | Creates a text channel for each voice channel only users in that voice channel can see.If you are server owner, keep in mind you will see them all the time regardless. | `.voice+text` +`.scsc` | Starts an instance of cross server channel. You will get a token as a DM that other people will use to tune in to the same instance. | `.scsc` +`.jcsc` | Joins current channel to an instance of cross server channel using the token. | `.jcsc` +`.lcsc` | Leaves Cross server channel instance from this channel. | `.lcsc` `.asar` | Adds a role, or list of roles separated by whitespace(use quotations for multiword roles) to the list of self-assignable roles. | .asar Gamer -`.rsar` | Removes a specified role from the list of self-assignable roles. -`.lsar` | Lists all self-assignable roles. -`.togglexclsar`, `.tesar` | toggle whether the self-assigned roles should be exclusive +`.rsar` | Removes a specified role from the list of self-assignable roles. | `.rsar` +`.lsar` | Lists all self-assignable roles. | `.lsar` +`.togglexclsar`, `.tesar` | toggle whether the self-assigned roles should be exclusive | `.tesar` `.iam` | Adds a role to you that you choose. Role must be on a list of self-assignable roles. | .iam Gamer `.iamnot`, `.iamn` | Removes a role to you that you choose. Role must be on a list of self-assignable roles. | .iamn Gamer -`.addcustreact`, `.acr` | Add a custom reaction. Guide here: **Bot Owner Only!** | .acr "hello" I love saying hello to %user% -`.listcustreact`, `.lcr` | Lists custom reactions (paginated with 30 commands per page). Use 'all' instead of page number to get all custom reactions DM-ed to you. | .lcr 1 -`.showcustreact`, `.scr` | Shows all possible responses from a single custom reaction. | .scr %mention% bb +`.addcustreact`, `.acr` | Add a custom reaction. Guide here: **Bot Owner Only!** | `.acr "hello" I love saying hello to %user%` +`.listcustreact`, `.lcr` | Lists custom reactions (paginated with 30 commands per page). Use 'all' instead of page number to get all custom reactions DM-ed to you. | `.lcr 1` +`.showcustreact`, `.scr` | Shows all possible responses from a single custom reaction. | `.scr %mention% bb` `.editcustreact`, `.ecr` | Edits a custom reaction, arguments are custom reactions name, index to change, and a (multiword) message **Bot Owner Only** | `.ecr "%mention% disguise" 2 Test 123` -`.delcustreact`, `.dcr` | Deletes a custom reaction with given name (and index) +`.delcustreact`, `.dcr` | Deletes a custom reaction with given name (and index). | `.dcr index` `.autoassignrole`, `.aar` | Automaticaly assigns a specified role to every user who joins the server. Type `.aar` to disable, `.aar Role Name` to enable `.leave` | Makes Nadeko leave the server. Either name or id required. | `.leave 123123123331` -`.listincidents`, `.lin` | List all UNREAD incidents and flags them as read. -`.listallincidents`, `.lain` | Sends you a file containing all incidents and flags them as read. -`.delmsgoncmd` | Toggles the automatic deletion of user's successful command message to prevent chat flood. Server Manager Only. -`.restart` | Restarts the bot. Might not work. **Bot Owner Only** +`.listincidents`, `.lin` | List all UNREAD incidents and flags them as read. | `.lin` +`.listallincidents`, `.lain` | Sends you a file containing all incidents and flags them as read. | `.lain` +`.delmsgoncmd` | Toggles the automatic deletion of user's successful command message to prevent chat flood. Server Manager Only. | `.delmsgoncmd` +`.restart` | Restarts the bot. Might not work. **Bot Owner Only** | `.restart` `.setrole`, `.sr` | Sets a role for a given user. | `.sr @User Guest` `.removerole`, `.rr` | Removes a role from a given user. | `.rr @User Admin` `.renamerole`, `.renr` | Renames a role. Role you are renaming must be lower than bot's highest role. | `.renr "First role" SecondRole` @@ -76,15 +77,15 @@ Command and aliases | Description | Usage `.creatxtchanl`, `.ctch` | Creates a new text channel with a given name. | `.ctch TextChannelName` `.settopic`, `.st` | Sets a topic on the current channel. | `.st My new topic` `.setchanlname`, `.schn` | Changed the name of the current channel.| `.schn NewName` -`.heap` | Shows allocated memory - **Bot Owner Only!** +`.heap` | Shows allocated memory - **Bot Owner Only!** | `.heap` `.prune`, `.clr` | `.prune` removes all nadeko's messages in the last 100 messages.`.prune X` removes last X messages from the channel (up to 100)`.prune @Someone` removes all Someone's messages in the last 100 messages.`.prune @Someone X` removes last X 'Someone's' messages in the channel. | `.prune` or `.prune 5` or `.prune @Someone` or `.prune @Someone X` -`.die` | Shuts the bot down and notifies users about the restart. **Bot Owner Only!** +`.die` | Shuts the bot down and notifies users about the restart. **Bot Owner Only!** | `.die` `.setname`, `.newnm` | Give the bot a new name. **Bot Owner Only!** | .newnm BotName `.newavatar`, `.setavatar` | Sets a new avatar image for the NadekoBot. Argument is a direct link to an image. **Bot Owner Only!** | `.setavatar https://i.ytimg.com/vi/WDudkR1eTMM/maxresdefault.jpg` `.setgame` | Sets the bots game. **Bot Owner Only!** | `.setgame Playing with kwoth` `.send` | Send a message to someone on a different server through the bot. **Bot Owner Only!** | `.send serverid|u:user_id Send this to a user!` or `.send serverid|c:channel_id Send this to a channel!` `.mentionrole`, `.menro` | Mentions every person from the provided role or roles (separated by a ',') on this server. Requires you to have mention everyone permission. | `.menro RoleName` -`.unstuck` | Clears the message queue. **Bot Owner Only!** +`.unstuck` | Clears the message queue. **Bot Owner Only!** | `.unstuck` `.donators` | List of lovely people who donated to keep this project alive. `.donadd` | Add a donator to the database. | `.donadd Donate Amount` `.announce` | Sends a message to all servers' general channel bot is connected to.**Bot Owner Only!** | `.announce Useless spam` @@ -94,16 +95,16 @@ Command and aliases | Description | Usage Command and aliases | Description | Usage ----------------|--------------|------- `.remind` | Sends a message to you or a channel after certain amount of time. First argument is me/here/'channelname'. Second argument is time in a descending order (mo>w>d>h>m) example: 1w5d3h10m. Third argument is a (multiword)message. | `.remind me 1d5h Do something` or `.remind #general Start now!` -`.remindmsg` | Sets message for when the remind is triggered. Available placeholders are %user% - user who ran the command, %message% - Message specified in the remind, %target% - target channel of the remind. **Bot Owner Only!** -`.serverinfo`, `.sinfo` | Shows info about the server the bot is on. If no channel is supplied, it defaults to current one. | .sinfo Some Server -`.channelinfo`, `.cinfo` | Shows info about the channel. If no channel is supplied, it defaults to current one. | .cinfo #some-channel -`.userinfo`, `.uinfo` | Shows info about the user. If no user is supplied, it defaults a user running the command. | .uinfo @SomeUser +`.remindmsg` | Sets message for when the remind is triggered. Available placeholders are %user% - user who ran the command, %message% - Message specified in the remind, %target% - target channel of the remind. **Bot Owner Only!** | `.remindmsg do something else` +`.serverinfo`, `.sinfo` | Shows info about the server the bot is on. If no channel is supplied, it defaults to current one. | `.sinfo Some Server` +`.channelinfo`, `.cinfo` | Shows info about the channel. If no channel is supplied, it defaults to current one. | `.cinfo #some-channel` +`.userinfo`, `.uinfo` | Shows info about the user. If no user is supplied, it defaults a user running the command. | `.uinfo @SomeUser` `.whoplays` | Shows a list of users who are playing the specified game. | `.whoplays Overwatch` `.inrole` | Lists every person from the provided role or roles (separated by a ',') on this server. If the list is too long for 1 message, you must have Manage Messages permission. | `.inrole Role` -`.checkmyperms` | Checks your userspecific permissions on this channel. -`.stats` | Shows some basic stats for Nadeko. -`.dysyd` | Shows some basic stats for Nadeko. -`.userid`, `.uid` | Shows user ID. | `.uid` or `.uid "@SomeGuy" +`.checkmyperms` | Checks your userspecific permissions on this channel. | `.checkmyperms` +`.stats` | Shows some basic stats for Nadeko. | `.stats` +`.dysyd` | Shows some basic stats for Nadeko. | `.dysyd` +`.userid`, `.uid` | Shows user ID. | `.uid` or `.uid "@SomeGuy"` `.channelid`, `.cid` | Shows current channel ID. | `.cid` `.serverid`, `.sid` | Shows current server ID. | `.sid` `.roles` | List all roles on this server or a single user if specified. @@ -119,12 +120,12 @@ Command and aliases | Description | Usage `;rmvfilterword`, `;rfw` | Removes the word from the list of filtered words | ;rw poop `;lstfilterwords`, `;lfw` | Shows a list of filtered words | ;lfw `;srvrfilterwords`, `;sfw` | Enables or disables automatic deleting of messages containing forbidden words on the server. | ;sfw disable -`;permrole`, `;pr` | Sets a role which can change permissions. Or supply no parameters to find out the current one. Default one is 'Nadeko'. +`;permrole`, `;pr` | Sets a role which can change permissions. Or supply no parameters to find out the current one. Default one is 'Nadeko'. | `;pr role` `;rolepermscopy`, `;rpc` | Copies BOT PERMISSIONS (not discord permissions) from one role to another. | `;rpc Some Role ~ Some other role` `;chnlpermscopy`, `;cpc` | Copies BOT PERMISSIONS (not discord permissions) from one channel to another. | `;cpc Some Channel ~ Some other channel` `;usrpermscopy`, `;upc` | Copies BOT PERMISSIONS (not discord permissions) from one role to another. | `;upc @SomeUser ~ @SomeOtherUser` `;verbose`, `;v` | Sets whether to show when a command/module is blocked. | `;verbose true` -`;srvrperms`, `;sp` | Shows banned permissions for this server. +`;srvrperms`, `;sp` | Shows banned permissions for this server. | `;sp` `;roleperms`, `;rp` | Shows banned permissions for a certain role. No argument means for everyone. | `;rp AwesomeRole` `;chnlperms`, `;cp` | Shows banned permissions for a certain channel. No argument means for this channel. | `;cp #dev` `;userperms`, `;up` | Shows banned permissions for a certain user. No argument means for yourself. | `;up Kwoth` @@ -157,48 +158,48 @@ Command and aliases | Description | Usage `...` | Shows a random quote with a specified name. | `... abc` `..qdel`, `..quotedelete` | Deletes all quotes with the specified keyword. You have to either be bot owner or the creator of the quote to delete it. | `..qdel abc` `@BotName rip` | Shows a grave image of someone with a start year | @NadekoBot rip @Someone 2000 -`@BotName die` | Works only for the owner. Shuts the bot down. -`@BotName do you love me` | Replies with positive answer only to the bot owner. -`@BotName how are you`, `@BotName how are you?` | Replies positive only if bot owner is online. -`@BotName fire` | Shows a unicode fire message. Optional parameter [x] tells her how many times to repeat the fire. | @NadekoBot fire [x] -`@BotName dump` | Dumps all of the invites it can to dump.txt.** Owner Only.** -`@BotName ab` | Try to get 'abalabahaha' +`@BotName die` | Works only for the owner. Shuts the bot down. | `@NadekoBot die` +`@BotName do you love me` | Replies with positive answer only to the bot owner. | `@NadekoBot do you love me` +`@BotName how are you`, `@BotName how are you?` | Replies positive only if bot owner is online. | `@NadekoBot how are you` +`@BotName fire` | Shows a unicode fire message. Optional parameter [x] tells her how many times to repeat the fire. | `@NadekoBot fire [x]` +`@BotName dump` | Dumps all of the invites it can to dump.txt.** Owner Only.** | `@NadekoBot dump` +`@BotName ab` | Try to get 'abalabahaha'| `@NadekoBot ab` ### Gambling Command and aliases | Description | Usage ----------------|--------------|------- -`$draw` | Draws a card from the deck.If you supply number [x], she draws up to 5 cards from the deck. | $draw [x] -`$shuffle`, `$sh` | Reshuffles all cards back into the deck. +`$draw` | Draws a card from the deck.If you supply number [x], she draws up to 5 cards from the deck. | `$draw [x]` +`$shuffle`, `$sh` | Reshuffles all cards back into the deck.|`$shuffle` `$flip` | Flips coin(s) - heads or tails, and shows an image. | `$flip` or `$flip 3` `$betflip`, `$bf` | Bet to guess will the result be heads or tails. Guessing award you double flowers you've bet. | `$bf 5 heads` or `$bf 3 t` -`$roll` | Rolls 0-100. If you supply a number [x] it rolls up to 30 normal dice. If you split 2 numbers with letter d (xdy) it will roll x dice from 1 to y. | $roll or $roll 7 or $roll 3d5 -`$rolluo` | Rolls 0-100. If you supply a number [x] it rolls up to 30 normal dice (unordered). If you split 2 numbers with letter d (xdy) it will roll x dice from 1 to y. | $roll or $roll 7 or $roll 3d5 +`$roll` | Rolls 0-100. If you supply a number [x] it rolls up to 30 normal dice. If you split 2 numbers with letter d (xdy) it will roll x dice from 1 to y. | `$roll` or `$roll 7` or `$roll 3d5` +`$rolluo` | Rolls 0-100. If you supply a number [x] it rolls up to 30 normal dice (unordered). If you split 2 numbers with letter d (xdy) it will roll x dice from 1 to y. | `$roll` or `$roll` 7 or `$roll 3d5` `$nroll` | Rolls in a given range. | `$nroll 5` (rolls 0-5) or `$nroll 5-15` -`$race` | Starts a new animal race. +`$race` | Starts a new animal race. | `$race` `$joinrace`, `$jr` | Joins a new race. You can specify an amount of flowers for betting (optional). You will get YourBet*(participants-1) back if you win. | `$jr` or `$jr 5` -`$raffle` | Prints a name and ID of a random user from the online list from the (optional) role. | `$raffle` or `$raffle RoleName +`$raffle` | Prints a name and ID of a random user from the online list from the (optional) role. | `$raffle` or `$raffle RoleName` `$$$` | Check how much NadekoFlowers a person has. (Defaults to yourself) | `$$$` or `$$$ @Someone` -`$give` | Give someone a certain amount of NadekoFlowers +`$give` | Give someone a certain amount of NadekoFlowers|`$give 1 "@SomeGuy"` `$award` | Gives someone a certain amount of flowers. **Bot Owner Only!** | `$award 100 @person` `$take` | Takes a certain amount of flowers from someone. **Bot Owner Only!** | `$take 1 "@someguy"` -`$betroll`, `$br` | Bets a certain amount of NadekoFlowers and rolls a dice. Rolling over 66 yields x2 flowers, over 90 - x3 and 100 x10. | $br 5 -`$leaderboard`, `$lb` | +`$betroll`, `$br` | Bets a certain amount of NadekoFlowers and rolls a dice. Rolling over 66 yields x2 flowers, over 90 - x3 and 100 x10. | `$br 5` +`$leaderboard`, `$lb` | Displays bot currency leaderboard | $lb ### Games Command and aliases | Description | Usage ----------------|--------------|------- `>t` | Starts a game of trivia. You can add nohint to prevent hints.First player to get to 10 points wins by default. You can specify a different number. 30 seconds per question. | `>t nohint` or `>t 5 nohint` -`>tl` | Shows a current trivia leaderboard. -`>tq` | Quits current trivia after current question. -`>typestart` | Starts a typing contest. -`>typestop` | Stops a typing contest on the current channel. -`>typeadd` | Adds a new article to the typing contest. Owner only. -`>poll` | Creates a poll, only person who has manage server permission can do it. | >poll Question?;Answer1;Answ 2;A_3 -`>pollend` | Stops active poll on this server and prints the results in this channel. -`>pick` | Picks a flower planted in this channel. -`>plant` | Spend a flower to plant it in this channel. (If bot is restarted or crashes, flower will be lost) +`>tl` | Shows a current trivia leaderboard. | `>tl` +`>tq` | Quits current trivia after current question. | `>tq` +`>typestart` | Starts a typing contest. | `>typestart` +`>typestop` | Stops a typing contest on the current channel. | `>typestop` +`>typeadd` | Adds a new article to the typing contest. Owner only. | `>typeadd wordswords` +`>poll` | Creates a poll, only person who has manage server permission can do it. | `>poll Question?;Answer1;Answ 2;A_3` +`>pollend` | Stops active poll on this server and prints the results in this channel. | `>pollend` +`>pick` | Picks a flower planted in this channel. | `>pick` +`>plant` | Spend a flower to plant it in this channel. (If bot is restarted or crashes, flower will be lost) | `>plant` `>gencurrency`, `>gc` | Toggles currency generation on this channel. Every posted message will have 2% chance to spawn a NadekoFlower. Optional parameter cooldown time in minutes, 5 minutes by default. Requires Manage Messages permission. | `>gc` or `>gc 60` -`>leet` | Converts a text to leetspeak with 6 (1-6) severity levels | >leet 3 Hello +`>leet` | Converts a text to leetspeak with 6 (1-6) severity levels | `>leet 3 Hello` `>choose` | Chooses a thing from a list of things | `>choose Get up;Sleep;Sleep more` `>8ball` | Ask the 8ball a yes/no question. | `>8ball should i do something` `>rps` | Play a game of rocket paperclip scissors with Nadeko. | `>rps scissors` @@ -237,37 +238,37 @@ Command and aliases | Description | Usage `!!load` | Loads a playlist under a certain name. | `!!load classical-1` `!!playlists`, `!!pls` | Lists all playlists. Paginated. 20 per page. Default page is 0. | `!!pls 1` `!!deleteplaylist`, `!!delpls` | Deletes a saved playlist. Only if you made it or if you are the bot owner. | `!!delpls animu-5` -`!!goto` | Goes to a specific time in seconds in a song. | !!goto 30 +`!!goto` | Goes to a specific time in seconds in a song. | `!!goto 30` `!!getlink`, `!!gl` | Shows a link to the currently playing song. `!!autoplay`, `!!ap` | Toggles autoplay - When the song is finished, automatically queue a related youtube song. (Works only for youtube songs and when queue is empty) ### Searches Command and aliases | Description | Usage ----------------|--------------|------- -`~lolchamp` | Shows League Of Legends champion statistics. If there are spaces/apostrophes or in the name - omit them. Optional second parameter is a role. | ~lolchamp Riven or ~lolchamp Annie sup -`~lolban` | Shows top 6 banned champions ordered by ban rate. Ban these champions and you will be Plat 5 in no time. -`~hitbox`, `~hb` | Notifies this channel when a certain user starts streaming. | ~hitbox SomeStreamer -`~twitch`, `~tw` | Notifies this channel when a certain user starts streaming. | ~twitch SomeStreamer -`~beam`, `~bm` | Notifies this channel when a certain user starts streaming. | ~beam SomeStreamer -`~checkhitbox`, `~chhb` | Checks if a certain user is streaming on the hitbox platform. | ~chhb SomeStreamer -`~checktwitch`, `~chtw` | Checks if a certain user is streaming on the twitch platform. | ~chtw SomeStreamer -`~checkbeam`, `~chbm` | Checks if a certain user is streaming on the beam platform. | ~chbm SomeStreamer -`~removestream`, `~rms` | Removes notifications of a certain streamer on this channel. | ~rms SomeGuy -`~liststreams`, `~ls` | Lists all streams you are following on this server. | ~ls -`~convert` | Convert quantities from>to. Like `~convert m>km 1000` +`~lolchamp` | Shows League Of Legends champion statistics. If there are spaces/apostrophes or in the name - omit them. Optional second parameter is a role. | `~lolchamp Riven` or `~lolchamp Annie sup` +`~lolban` | Shows top 6 banned champions ordered by ban rate. Ban these champions and you will be Plat 5 in no time. | `~lolban` +`~hitbox`, `~hb` | Notifies this channel when a certain user starts streaming. | `~hitbox SomeStreamer` +`~twitch`, `~tw` | Notifies this channel when a certain user starts streaming. | `~twitch SomeStreamer` +`~beam`, `~bm` | Notifies this channel when a certain user starts streaming. | `~beam SomeStreamer` +`~checkhitbox`, `~chhb` | Checks if a certain user is streaming on the hitbox platform. | `~chhb SomeStreamer` +`~checktwitch`, `~chtw` | Checks if a certain user is streaming on the twitch platform. | `~chtw SomeStreamer` +`~checkbeam`, `~chbm` | Checks if a certain user is streaming on the beam platform. | `~chbm SomeStreamer` +`~removestream`, `~rms` | Removes notifications of a certain streamer on this channel. | `~rms SomeGuy` +`~liststreams`, `~ls` | Lists all streams you are following on this server. | `~ls` +`~convert` | Convert quantities from>to. | `~convert m>km 1000` `~convertlist` | List of the convertable dimensions and currencies. -`~wowjoke` | Get one of Kwoth's penultimate WoW jokes. +`~wowjoke` | Get one of Kwoth's penultimate WoW jokes. | `~wowjoke` `~calculate`, `~calc` | Evaluate a mathematical expression. | ~calc 1+1 `~osu` | Shows osu stats for a player. | `~osu Name` or `~osu Name taiko` -`~osu b` | Shows information about an osu beatmap. | ~osu b https://osu.ppy.sh/s/127712 +`~osu b` | Shows information about an osu beatmap. | `~osu b` https://osu.ppy.sh/s/127712` `~osu top5` | Displays a user's top 5 plays. | ~osu top5 Name -`~pokemon`, `~poke` | Searches for a pokemon. -`~pokemonability`, `~pokeab` | Searches for a pokemon ability. -`~memelist` | Pulls a list of memes you can use with `~memegen` from http://memegen.link/templates/ +`~pokemon`, `~poke` | Searches for a pokemon. | `~poke Sylveon` +`~pokemonability`, `~pokeab` | Searches for a pokemon ability. | `~pokeab "water gun"` +`~memelist` | Pulls a list of memes you can use with `~memegen` from http://memegen.link/templates/ | `~memelist` `~memegen` | Generates a meme from memelist with top and bottom text. | `~memegen biw "gets iced coffee" "in the winter"` `~we` | Shows weather data for a specified city and a country. BOTH ARE REQUIRED. Use country abbrevations. | `~we Moscow RF` `~yt` | Searches youtubes and shows the first result | `~yt query` -`~ani`, `~anime`, `~aq` | Queries anilist for an anime and shows the first result. +`~ani`, `~anime`, `~aq` | Queries anilist for an anime and shows the first result. | `~aq aquerion evol` `~imdb` | Queries imdb for movies or series, show first result. | `~imdb query` `~mang`, `~manga`, `~mq` | Queries anilist for a manga and shows the first result. | `~mq query` `~randomcat`, `~meow` | Shows a random cat image. @@ -279,13 +280,13 @@ Command and aliases | Description | Usage `~hs` | Searches for a Hearthstone card and shows its image. Takes a while to complete. | `~hs Ysera` `~ud` | Searches Urban Dictionary for a word. | `~ud Pineapple` `~#` | Searches Tagdef.com for a hashtag. | `~# ff` -`~quote` | Shows a random quote. -`~catfact` | Shows a random catfact from -`~yomama`, `~ym` | Shows a random joke from -`~randjoke`, `~rj` | Shows a random joke from -`~chucknorris`, `~cn` | Shows a random chucknorris joke from -`~magicitem`, `~mi` | Shows a random magicitem from -`~revav` | Returns a google reverse image search for someone's avatar. | `~revav "@SomeGuy" +`~quote` | Shows a random quote. | `~quote` +`~catfact` | Shows a random catfact from | `~catfact` +`~yomama`, `~ym` | Shows a random joke from | `~ym` +`~randjoke`, `~rj` | Shows a random joke from | `~rj` +`~chucknorris`, `~cn` | Shows a random chucknorris joke from | `~cn` +`~magicitem`, `~mi` | Shows a random magicitem from | `~mi` +`~revav` | Returns a google reverse image search for someone's avatar. | `~revav "@SomeGuy"` `~revimg` | Returns a google reverse image search for an image from a link. | `~revav Image link` `~safebooru` | Shows a random image from safebooru with a given tag. Tag is optional but preffered. (multiple tags are appended with +) | `~safebooru yuri+kissing` `~wiki` | Gives you back a wikipedia link | `~wiki query` @@ -301,15 +302,15 @@ Command and aliases | Description | Usage `~gelbooru` | Shows a random hentai image from gelbooru with a given tag. Tag is optional but preffered. (multiple tags are appended with +) | `~gelbooru yuri+kissing` `~rule34` | Shows a random image from rule34.xx with a given tag. Tag is optional but preffered. (multiple tags are appended with +) | `~rule34 yuri+kissing` `~e621` | Shows a random hentai image from e621.net with a given tag. Tag is optional but preffered. Use spaces for multiple tags. | `~e621 yuri kissing` -`~cp` | We all know where this will lead you to. -`~boobs` | Real adult content. -`~butts`, `~ass`, `~butt` | Real adult content. +`~cp` | We all know where this will lead you to. | `~cp` +`~boobs` | Real adult content. | `~boobs` +`~butts`, `~ass`, `~butt` | Real adult content. | `~butts` or `~ass` ### ClashOfClans Command and aliases | Description | Usage ----------------|--------------|------- `,createwar`, `,cw` | Creates a new war by specifying a size (>10 and multiple of 5) and enemy clan name. | ,cw 15 The Enemy Clan -`,startwar`, `,sw` | Starts a war with a given number. | `,sw 1` +`,startwar`, `,sw` | Starts a war with a given number. `,listwar`, `,lw` | Shows the active war claims by a number. Shows all wars in a short way if no number is specified. | ,lw [war_number] or ,lw `,claim`, `,call`, `,c` | Claims a certain base from a certain war. You can supply a name in the third optional argument to claim in someone else's place. | ,call [war_number] [base_number] [optional_other_name] `,claimfinish`, `,cf`, `,cf3`, `,claimfinish3` | Finish your claim with 3 stars if you destroyed a base. Optional second argument finishes for someone else. | ,cf [war_number] [optional_other_name] @@ -322,16 +323,16 @@ Command and aliases | Description | Usage Command and aliases | Description | Usage ----------------|--------------|------- `>attack` | Attacks a target with the given move. Use `>movelist` to see a list of moves your type can use. | `>attack "vine whip" @someguy` -`>movelist`, `>ml` | Lists the moves you are able to use -`>heal` | Heals someone. Revives those who fainted. Costs a NadekoFlower | >heal @someone -`>type` | Get the poketype of the target. | >type @someone -`>settype` | Set your poketype. Costs a NadekoFlower. | >settype fire +`>movelist`, `>ml` | Lists the moves you are able to use | `>ml` +`>heal` | Heals someone. Revives those who fainted. Costs a NadekoFlower | `>heal @someone` +`>type` | Get the poketype of the target. | `>type @someone` +`>settype` | Set your poketype. Costs a NadekoFlower. | `>settype fire` ### Translator Command and aliases | Description | Usage ----------------|--------------|------- `~translate`, `~trans` | Translates from>to text. From the given language to the destiation language. | `~trans en>fr Hello` -`~translangs` | List the valid languages for translation. +`~translangs` | List the valid languages for translation. | `{Prefix}translangs` or `{Prefix}translangs language` ### Customreactions Command and aliases | Description | Usage diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 00000000..9cec30e0 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1 @@ +Hai, this will be docs of nakeda \ No newline at end of file