Merge remote-tracking branch 'refs/remotes/Kwoth/1.0' into 1.0-fearnlj01

This commit is contained in:
Jordan Fearnley 2016-11-10 23:14:14 +00:00
commit 8c39c33eba
54 changed files with 2863 additions and 415 deletions

2
.gitignore vendored
View File

@ -2,7 +2,7 @@
src/NadekoBot/credentials.json
src/NadekoBot/data/NadekoBot.db
src/NadekoBot/musicdata
src/NadekoBot/data/musicdata
# Created by https://www.gitignore.io/api/visualstudio,visualstudiocode,windows,linux,macos

View File

@ -1,5 +1,5 @@
![img](https://ci.appveyor.com/api/projects/status/gmu6b3ltc80hr3k9?svg=true)
[![Discord](https://discordapp.com/api/servers/117523346618318850/widget.png)](https://discord.gg/0ehQwTK2RBjAxzEY)
[![Discord](https://discordapp.com/api/guilds/117523346618318850/widget.png)](https://discord.gg/0ehQwTK2RBjAxzEY)
[![Documentation Status](https://readthedocs.org/projects/nadekobot/badge/?version=latest)](http://nadekobot.readthedocs.io/en/1.0/?badge=latest)
# NadekoBot

View File

@ -1,9 +1,23 @@
For more information and how to setup your own NadekoBot, go to: <http://github.com/Kwoth/NadekoBot/wiki>
You can support the project on patreon: <https://patreon.com/nadekobot> or paypal: `nadekodiscordbot@gmail.com`
##Table Of Contents
- [Help](#help)
- [Administration](#administration)
- [ClashOfClans](#clashofclans)
- [CustomReactions](#customreactions)
- [Gambling](#gambling)
- [Games](#games)
- [Music](#music)
- [NSFW](#nsfw)
- [Permissions](#permissions)
- [Searches](#searches)
- [Utility](#utility)
### Administration
Command and aliases | Description | Usage
----------------|--------------|-------
`.resetperms` | Resets BOT's permissions module on this server to the default value. **Requires Administrator server permission.** | `.resetperms`
`.restart` | Restarts the bot. Might not work. **Bot owner only.** | `.restart`
`.delmsgoncmd` | Toggles the automatic deletion of user's successful command message to prevent chat flood. **Requires Administrator server permission.** | `.delmsgoncmd`
`.setrole` `.sr` | Sets a role for a given user. **Requires ManageRoles server permission.** | `.sr @User Guest`
`.removerole` `.rr` | Removes a role from a given user. **Requires ManageRoles server permission.** | `.rr @User Admin`
@ -12,9 +26,9 @@ Command and aliases | Description | Usage
`.createrole` `.cr` | Creates a role with a given name. **Requires ManageRoles server permission.** | `.cr Awesome Role`
`.rolecolor` `.rc` | Set a role's color to the hex or 0-255 rgb color value provided. **Requires ManageRoles server permission.** | `.rc Admin 255 200 100` or `.rc Admin ffba55`
`.ban` `.b` | Bans a user by ID or name with an optional message. **Requires BanMembers server permission.** | `.b "@some Guy" Your behaviour is toxic.`
`.softban` `.sb` | Bans and then unbans a user by ID or name with an optional message. **Requires BanMembers server permission.** | `.sb "@some Guy" Your behaviour is toxic.`
`.softban` `.sb` | Bans and then unbans a user by ID or name with an optional message. **Requires KickMembers server permission.** **Requires ManageMessages server permission.** | `.sb "@some Guy" Your behaviour is toxic.`
`.kick` `.k` | Kicks a mentioned user. **Requires KickMembers server permission.** | `.k "@some Guy" Your behaviour is toxic.`
`.setmuterole` | Sets a name of the role which will be assigned to people who should be muted. Default is nadeko-mute. After specifying this role, restart commands which use mute as punishment. **Requires ManageRoles server permission.** | `.setmuterole Silenced`
`.setmuterole` | Sets a name of the role which will be assigned to people who should be muted. Default is nadeko-mute. **Requires ManageRoles server permission.** | `.setmuterole Silenced`
`.mute` | Mutes a mentioned user both from speaking and chatting. **Requires ManageRoles server permission.** **Requires MuteMembers server permission.** | `.mute @Someone`
`.unmute` | Unmutes a mentioned user previously muted with `.mute` command. **Requires ManageRoles server permission.** **Requires MuteMembers server permission.** | `.unmute @Someone`
`.chatmute` | Prevents a mentioned user from chatting in text channels. **Requires ManageRoles server permission.** | `.chatmute @Someone`
@ -34,7 +48,7 @@ Command and aliases | Description | Usage
`.setname` `.newnm` | Gives the bot a new name. **Bot owner only.** | `.newnm BotName`
`.setavatar` `.setav` | Sets a new avatar image for the NadekoBot. Argument is a direct link to an image. **Bot owner only.** | `.setav http://i.imgur.com/xTG3a1I.jpg`
`.setgame` | Sets the bots game. **Bot owner only.** | `.setgame with snakes`
`.setstream` | Sets the bots stream. First argument is the twitch link, second argument is stream name. **Bot owner only.** | `.setstream https://www.twitch.tv/masterkwoth Developing Nakedo`
`.setstream` | Sets the bots stream. First argument is the twitch link, second argument is stream name. **Bot owner only.** | `.setstream TWITCHLINK Hello`
`.send` | Sends a message to someone on a different server through the bot. Separate server and channel/user ids with `|` and prepend channel id with `c:` and user id with `u:`. **Bot owner only.** | `.send serverid|c:channelid` or `.send serverid|u:userid`
`.announce` | Sends a message to all servers' general channel bot is connected to. **Bot owner only.** | `.announce Useless spam`
`.savechat` | Saves a number of messages to a text file and sends it to you. **Bot owner only.** | `.savechat 150`
@ -80,6 +94,8 @@ Command and aliases | Description | Usage
`.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. **Requires ManageRoles server permission.** **Requires ManageChannels server permission.** | `.voice+text`
`.cleanvplust` `.cv+t` | Deletes all text channels ending in `-voice` for which voicechannels are not found. Use at your own risk. **Requires ManageChannels server permission.** **Requires ManageRoles server permission.** | `.cleanv+t`
###### [Back to TOC](#table-of-contents)
### ClashOfClans
Command and aliases | Description | Usage
----------------|--------------|-------
@ -93,6 +109,8 @@ Command and aliases | Description | Usage
`,endwar` `,ew` | Ends the war with a given index. | `,ew [war_number]`
`,unclaim` `,ucall` `,uc` | Removes your claim from a certain war. Optional second argument denotes a person in whose place to unclaim | `,uc [war_number] [optional_other_name]`
###### [Back to TOC](#table-of-contents)
### CustomReactions
Command and aliases | Description | Usage
----------------|--------------|-------
@ -101,6 +119,8 @@ Command and aliases | Description | Usage
`.showcustreact` `.scr` | Shows a custom reaction's response on a given ID. | `.scr 1`
`.delcustreact` `.dcr` | Deletes a custom reaction on a specific index. If ran in DM, it is bot owner only and deletes a global custom reaction. If ran in a server, it requires Administration priviledges and removes server custom reaction. | `.dcr 5`
###### [Back to TOC](#table-of-contents)
### Gambling
Command and aliases | Description | Usage
----------------|--------------|-------
@ -121,6 +141,8 @@ Command and aliases | Description | Usage
`$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 awards you 1.8x the currency you've bet. | `$bf 5 heads` or `$bf 3 t`
###### [Back to TOC](#table-of-contents)
### Games
Command and aliases | Description | Usage
----------------|--------------|-------
@ -132,16 +154,21 @@ Command and aliases | Description | Usage
`>poll` | Creates a poll which requires users to send the number of the voting option to the bot. **Requires ManageMessages server permission.** | `>poll Question?;Answer1;Answ 2;A_3`
`>publicpoll` `>ppoll` | Creates a public poll which requires users to type a number of the voting option in the channel command is ran in. **Requires ManageMessages server permission.** | `>ppoll Question?;Answer1;Answ 2;A_3`
`>pollend` | Stops active poll on this server and prints the results in this channel. **Requires ManageMessages server permission.** | `>pollend`
`>cleverbot` | Toggles cleverbot session. When enabled, the bot will reply to messages starting with bot mention in the server. Custom reactions starting with %mention% won't work if cleverbot is enabled. **Requires ManageMessages server permission.** | `>cleverbot`
`>pick` | Picks the currency planted in this channel. | `>pick`
`>plant` | Spend a unit of currency to plant it in this channel. (If bot is restarted or crashes, the currency will be lost) | `>plant`
`>gencurrency` `>gc` | Toggles currency generation on this channel. Every posted message will have chance to spawn currency. Chance is specified by the Bot Owner. (default is 2%) **Requires ManageMessages server permission.** | `>gc`
`>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. **Bot owner only.** | `>typeadd wordswords`
`>typelist` | Lists added typing articles with their IDs. 15 per page. | `>typelist` or `>typelist 3`
`>typedel` | Deletes a typing article given the ID. **Bot owner only.** | `>typedel 3`
`>trivia` `>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` or `>t 5 nohint`
`>tl` | Shows a current trivia leaderboard. | `>tl`
`>tq` | Quits current trivia after current question. | `>tq`
###### [Back to TOC](#table-of-contents)
### Help
Command and aliases | Description | Usage
----------------|--------------|-------
@ -152,10 +179,12 @@ Command and aliases | Description | Usage
`-readme` `-guide` | Sends a readme and a guide links to the channel. | `-readme` or `-guide`
`-donate` | Instructions for helping the project financially. | `-donate`
###### [Back to TOC](#table-of-contents)
### Music
Command and aliases | Description | Usage
----------------|--------------|-------
`!!next` `!!n` | Goes to the next song in the queue. You have to be in the same voice channel as the bot. | `!!n`
`!!next` `!!n` | Goes to the next song in the queue. You have to be in the same voice channel as the bot. You can skip multiple songs, but in that case songs will not be requeued if !!rcs or !!rpl is enabled. | `!!n` or `!!n 5`
`!!stop` `!!s` | Stops the music and clears the playlist. Stays in the channel. | `!!s`
`!!destroy` `!!d` | Completely stops the music and unbinds the bot from the channel. (may cause weird behaviour) | `!!d`
`!!pause` `!!p` | Pauses or Unpauses the song. | `!!p`
@ -185,12 +214,16 @@ Command and aliases | Description | Usage
`!!getlink` `!!gl` | Shows a link to the song in the queue by index, or the currently playing song by default. | `!!gl`
`!!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) | `!!ap`
###### [Back to TOC](#table-of-contents)
### NSFW
Command and aliases | Description | Usage
----------------|--------------|-------
`~hentai` | Shows a 2 random images (from gelbooru and danbooru) with a given tag. Tag is optional but preferred. Only 1 tag allowed. | `~hentai yuri`
`~hentai` | Shows a hentai image from a random website (gelbooru or danbooru or konachan or atfbooru) with a given tag. Tag is optional but preferred. Only 1 tag allowed. | `~hentai yuri`
`~hentaibomb` | Shows a total 4 images (from gelbooru, danbooru, konachan and atfbooru). Tag is optional but preferred. | `~hentaibomb yuri`
`~atfbooru` `~atf` | Shows a random hentai image from atfbooru with a given tag. Tag is optional but preferred. | `~atfbooru yuri+kissing`
`~danbooru` | Shows a random hentai image from danbooru with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `~danbooru yuri+kissing`
`~konachan` | Shows a random hentai image from konachan with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `~konachan yuri`
`~konachan` | Shows a random hentai image from konachan with a given tag. Tag is optional but preferred. | `~konachan yuri`
`~gelbooru` | Shows a random hentai image from gelbooru with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `~gelbooru yuri+kissing`
`~rule34` | Shows a random image from rule34.xx with a given tag. Tag is optional but preferred. (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 preferred. Use spaces for multiple tags. | `~e621 yuri kissing`
@ -198,6 +231,8 @@ Command and aliases | Description | Usage
`~boobs` | Real adult content. | `~boobs`
`~butts` `~ass` `~butt` | Real adult content. | `~butts` or `~ass`
###### [Back to TOC](#table-of-contents)
### Permissions
Command and aliases | Description | Usage
----------------|--------------|-------
@ -230,6 +265,8 @@ Command and aliases | Description | Usage
`;fw` | Adds or removes (if it exists) a word from the list of filtered words. Use`;sfw` or `;cfw` to toggle filtering. | `;fw poop`
`;lstfilterwords` `;lfw` | Shows a list of filtered words. | `;lfw`
###### [Back to TOC](#table-of-contents)
### Searches
Command and aliases | Description | Usage
----------------|--------------|-------
@ -241,6 +278,7 @@ Command and aliases | Description | Usage
`~img` `~i` | Pulls the first image found using a search parameter. Use ~ir for different results. | `~i cute kitten`
`~ir` | Pulls a random image using a search parameter. | `~ir cute kitten`
`~lmgtfy` | Google something for an idiot. | `~lmgtfy query`
`~shorten` | Attempts to shorten an URL, if it fails, returns the input URL. | `~shorten https://google.com`
`~google` `~g` | Get a google search link for some terms. | `~google query`
`~hearthstone` `~hs` | Searches for a Hearthstone card and shows its image. Takes a while to complete. | `~hs Ysera`
`~urbandict` `~ud` | Searches Urban Dictionary for a word. | `~ud Pineapple`
@ -252,12 +290,10 @@ Command and aliases | Description | Usage
`~wikipedia` `~wiki` | Gives you back a wikipedia link | `~wiki query`
`~color` `~clr` | Shows you what color corresponds to that hex. | `~clr 00ff00`
`~videocall` | Creates a private <http://www.appear.in> video call link for you and other mentioned people. The link is sent to mentioned people via a private message. | `~videocall "@SomeGuy"`
`~av` `~avatar` | Shows a mentioned person's avatar. | `~av "@SomeGuy"`
`~avatar` `~av` | Shows a mentioned person's avatar. | `~av "@SomeGuy"`
`~lolban` | Shows top banned champions ordered by ban rate. | `~lolban`
`~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"`
`~translate` `~trans` | Translates from>to text. From the given language to the destination language. | `~trans en>fr Hello`
`~translangs` | Lists the valid languages for translation. | `~translangs`
`~anime` `~ani` `~aq` | Queries anilist for an anime and shows the first result. | `~ani aquarion evol`
`~manga` `~mang` `~mq` | Queries anilist for a manga and shows the first result. | `~mq Shingeki no kyojin`
`~yomama` `~ym` | Shows a random joke from <http://api.yomomma.info/> | `~ym`
@ -278,8 +314,14 @@ Command and aliases | Description | Usage
`~liststreams` `~ls` | Lists all streams you are following on this server. | `~ls`
`~removestream` `~rms` | Removes notifications of a certain streamer on this channel. **Requires ManageMessages server permission.** | `~rms SomeGuy`
`~checkstream` `~cs` | Checks if a user is online on a certain streaming platform. | `~cs twitch MyFavStreamer`
`~translate` `~trans` | Translates from>to text. From the given language to the destination language. | `~trans en>fr Hello`
`~autotrans` `~at` | Starts automatic translation of all messages by users who set their `~atl` in this channel. You can set "del" argument to automatically delete all translated user messages. **Requires Administrator server permission.** **Bot owner only.** | `~at` or `~at del`
`~autotranslang` `~atl` | `~atl en>fr` | Sets your source and target language to be used with `~at`. Specify no arguments to remove previously set value.
`~translangs` | Lists the valid languages for translation. | `~translangs`
`~xkcd` | Shows a XKCD comic. No arguments will retrieve random one. Number argument will retrieve a specific comic, and "latest" will get the latest one. | `~xkcd` or `~xkcd 1400` or `~xkcd latest`
###### [Back to TOC](#table-of-contents)
### Utility
Command and aliases | Description | Usage
----------------|--------------|-------
@ -293,17 +335,19 @@ Command and aliases | Description | Usage
`.channeltopic` `.ct` | Sends current channel's topic as a message. | `.ct`
`.stats` | Shows some basic stats for Nadeko. | `.stats`
`.showemojis` `.se` | Shows a name and a link to every SPECIAL emoji in the message. | `.se A message full of SPECIAL emojis`
`.listservers` | Lists servers the bot is on with some basic info. 15 per page. **Bot owner only.** | `.listservers 3`
`.calculate` `.calc` | Evaluate a mathematical expression. | `.calc 1+1`
`.calcops` | Shows all available operations in .calc command | `.calcops`
`.togethertube` `.totube` | Creates a new room on <https://togethertube.com> and shows the link in the chat. | `.totube`
`.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`
`.listquotes` `.liqu` | `.liqu` or `.liqu 3` | Lists all quotes on the server ordered alphabetically. 15 Per page.
`...` | Shows a random quote with a specified name. | `... abc`
`..` | Adds a new quote with the specified name and message. | `.. sayhi Hi`
`.deletequote` `.delq` | Deletes a random quote with the specified keyword. You have to either be server Administrator or the creator of the quote to delete it. | `.delq abc`
`.delallq` `.daq` | Deletes all quotes on a specified keyword. **Requires Administrator server permission.** | `.delallq kek`
`.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!`
`.remindtemplate` | 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.** | `.remindtemplate %user%, you gotta do %message%!`
`.remindtemplate` | 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.** | `.remindtemplate %user%, do %message%!`
`.convertlist` | List of the convertible dimensions and currencies. | `.convertlist`
`.convert` | Convert quantities. Use `.convertlist` to see supported dimensions and currencies. | `.convert m km 1000`

View File

@ -34,25 +34,25 @@ Setting up your API keys
====================
####This part is completely optional, **However it is necessary for music to work properly**
- **GoogleAPIKey** - Required for Youtube Song Search, Playlist queuing, and URL Shortener. `~i` and `~img`.
- You can get this api Key [here](https://console.developers.google.com/apis)
You can get this api Key [here](https://console.developers.google.com/apis)
- **SoundCloudClientID** - Required to queue soundloud songs from sc links.
- You will need to create a new app [here](http://soundcloud.com/you/apps). **Please note you must be logged into SoundCloud**
You will need to create a new app [here](http://soundcloud.com/you/apps). **Please note you must be logged into SoundCloud**
- Simply click Register a new application and enter a name.
- Copy the Client ID and click "save app" then paste the Client Id it into your `credentials.json`
- **MashapeKey** - Required for Urban Disctionary, Hashtag search, and Hearthstone cards.
- You need to create an account on their [api marketplace](https://market.mashape.com/), after that go to `market.mashape.com/YOURNAMEHERE/applications/default-application` and press **Get the keys** in the top right corner.
You need to create an account on their [api marketplace](https://market.mashape.com/), after that go to `market.mashape.com/YOURNAMEHERE/applications/default-application` and press **Get the keys** in the top right corner.
- Copy the key and paste it into `credentials.json`
- **LOLAPIKey** - Required for all League of Legends commands.
- You can get this key [here](http://api.champion.gg/)
You can get this key [here](http://api.champion.gg/)
- **OsuAPIKey** - Required for Osu commands
- You can get this key [here](https://osu.ppy.sh/p/api) **You will need to log in and like the soundcloud it may take a few tries**
You can get this key [here](https://osu.ppy.sh/p/api) **You will need to log in and like the soundcloud it may take a few tries**
- **CarbonKey** -This key is for Carobnitex.net stats.
- Most likely unnecessary **Needed only if your bot is listed on Carbonitex.net**
Most likely unnecessary **Needed only if your bot is listed on Carbonitex.net**
Additional options
====================
- **TotalShards** - Required if the bot will be connected to more than 2500 servers
- Most likely unnecessary to change until your bot is added to more than 2000 servers
Most likely unnecessary to change until your bot is added to more than 2000 servers
[//]: # (- **Db** - Allows for advanced database configuration )
[//]: # ( - Leave this with the `null` value for standard operation - change this to `examples` to [This is only a comment so doesn't need proper detail])
@ -63,3 +63,5 @@ In the folder where `NadekoBot.exe` is located you should also see a `Data` fold
`config.json` contains user specific commands, such as: if DM's sent to the bot are forwarded to you, Blacklisted Ids, Servers, and channels...etc.
**If you do not see** `config.json` **you need to rename** `config_example.json` **to** `config.json`
[CleverBot APIs]: https://cleverbot.io/keys

View File

@ -1,54 +1,3 @@
# 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
## There is no docker image for 1.0 nadeko right now. Soon.

View File

@ -0,0 +1,781 @@
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using NadekoBot.Services.Database.Impl;
namespace NadekoBot.Migrations
{
[DbContext(typeof(NadekoSqliteContext))]
[Migration("20161107213222_Cleverbot")]
partial class Cleverbot
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
modelBuilder
.HasAnnotation("ProductVersion", "1.0.0-rtm-21431");
modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistItem", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int?>("BotConfigId");
b.Property<ulong>("ItemId");
b.Property<int>("Type");
b.HasKey("Id");
b.HasIndex("BotConfigId");
b.ToTable("BlacklistItem");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.BotConfig", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<ulong>("BufferSize");
b.Property<float>("CurrencyGenerationChance");
b.Property<int>("CurrencyGenerationCooldown");
b.Property<string>("CurrencyName");
b.Property<string>("CurrencyPluralName");
b.Property<string>("CurrencySign");
b.Property<string>("DMHelpString");
b.Property<bool>("ForwardMessages");
b.Property<bool>("ForwardToAllOwners");
b.Property<string>("HelpString");
b.Property<int>("MigrationVersion");
b.Property<string>("RemindMessageFormat");
b.Property<bool>("RotatingStatuses");
b.HasKey("Id");
b.ToTable("BotConfig");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashCaller", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<bool>("BaseDestroyed");
b.Property<string>("CallUser");
b.Property<int>("ClashWarId");
b.Property<int?>("SequenceNumber");
b.Property<int>("Stars");
b.Property<DateTime>("TimeAdded");
b.HasKey("Id");
b.HasIndex("ClashWarId");
b.ToTable("ClashCallers");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashWar", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<ulong>("ChannelId");
b.Property<string>("EnemyClan");
b.Property<ulong>("GuildId");
b.Property<int>("Size");
b.Property<DateTime>("StartedAt");
b.Property<int>("WarState");
b.HasKey("Id");
b.ToTable("ClashOfClans");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("CommandName");
b.Property<int?>("GuildConfigId");
b.Property<int>("Seconds");
b.HasKey("Id");
b.HasIndex("GuildConfigId");
b.ToTable("CommandCooldown");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.ConvertUnit", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("InternalTrigger");
b.Property<decimal>("Modifier");
b.Property<string>("UnitType");
b.HasKey("Id");
b.ToTable("ConversionUnits");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.Currency", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<long>("Amount");
b.Property<ulong>("UserId");
b.HasKey("Id");
b.HasIndex("UserId")
.IsUnique();
b.ToTable("Currency");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.CurrencyTransaction", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<long>("Amount");
b.Property<string>("Reason");
b.Property<ulong>("UserId");
b.HasKey("Id");
b.ToTable("CurrencyTransactions");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.CustomReaction", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<ulong?>("GuildId");
b.Property<bool>("IsRegex");
b.Property<bool>("OwnerOnly");
b.Property<string>("Response");
b.Property<string>("Trigger");
b.HasKey("Id");
b.ToTable("CustomReactions");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.Donator", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("Amount");
b.Property<string>("Name");
b.Property<ulong>("UserId");
b.HasKey("Id");
b.HasIndex("UserId")
.IsUnique();
b.ToTable("Donators");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.EightBallResponse", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int?>("BotConfigId");
b.Property<string>("Text");
b.HasKey("Id");
b.HasIndex("BotConfigId");
b.ToTable("EightBallResponses");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<ulong>("ChannelId");
b.Property<int?>("GuildConfigId");
b.Property<int?>("GuildConfigId1");
b.HasKey("Id");
b.HasIndex("GuildConfigId");
b.HasIndex("GuildConfigId1");
b.ToTable("FilterChannelId");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int?>("GuildConfigId");
b.Property<string>("Word");
b.HasKey("Id");
b.HasIndex("GuildConfigId");
b.ToTable("FilteredWord");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.FollowedStream", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<ulong>("ChannelId");
b.Property<int?>("GuildConfigId");
b.Property<ulong>("GuildId");
b.Property<int>("Type");
b.Property<string>("Username");
b.HasKey("Id");
b.HasIndex("GuildConfigId");
b.ToTable("FollowedStream");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<ulong>("ChannelId");
b.Property<int?>("GuildConfigId");
b.HasKey("Id");
b.HasIndex("GuildConfigId");
b.ToTable("GCChannelId");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<ulong>("AutoAssignRoleId");
b.Property<bool>("AutoDeleteByeMessages");
b.Property<bool>("AutoDeleteGreetMessages");
b.Property<int>("AutoDeleteGreetMessagesTimer");
b.Property<bool>("AutoDeleteSelfAssignedRoleMessages");
b.Property<ulong>("ByeMessageChannelId");
b.Property<string>("ChannelByeMessageText");
b.Property<string>("ChannelGreetMessageText");
b.Property<bool>("CleverbotEnabled");
b.Property<float>("DefaultMusicVolume");
b.Property<bool>("DeleteMessageOnCommand");
b.Property<string>("DmGreetMessageText");
b.Property<bool>("ExclusiveSelfAssignedRoles");
b.Property<bool>("FilterInvites");
b.Property<bool>("FilterWords");
b.Property<ulong>("GreetMessageChannelId");
b.Property<ulong>("GuildId");
b.Property<int?>("LogSettingId");
b.Property<string>("MuteRoleName");
b.Property<string>("PermissionRole");
b.Property<int?>("RootPermissionId");
b.Property<bool>("SendChannelByeMessage");
b.Property<bool>("SendChannelGreetMessage");
b.Property<bool>("SendDmGreetMessage");
b.Property<bool>("VerbosePermissions");
b.Property<bool>("VoicePlusTextEnabled");
b.HasKey("Id");
b.HasIndex("GuildId")
.IsUnique();
b.HasIndex("LogSettingId");
b.HasIndex("RootPermissionId");
b.ToTable("GuildConfigs");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogChannel", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<ulong>("ChannelId");
b.Property<int?>("LogSettingId");
b.HasKey("Id");
b.HasIndex("LogSettingId");
b.ToTable("IgnoredLogChannels");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<ulong>("ChannelId");
b.Property<int?>("LogSettingId");
b.HasKey("Id");
b.HasIndex("LogSettingId");
b.ToTable("IgnoredVoicePresenceCHannels");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.LogSetting", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<bool>("ChannelCreated");
b.Property<bool>("ChannelDestroyed");
b.Property<ulong>("ChannelId");
b.Property<bool>("ChannelUpdated");
b.Property<bool>("IsLogging");
b.Property<bool>("LogUserPresence");
b.Property<bool>("LogVoicePresence");
b.Property<bool>("MessageDeleted");
b.Property<bool>("MessageUpdated");
b.Property<bool>("UserBanned");
b.Property<bool>("UserJoined");
b.Property<bool>("UserLeft");
b.Property<ulong>("UserPresenceChannelId");
b.Property<bool>("UserUnbanned");
b.Property<bool>("UserUpdated");
b.Property<ulong>("VoicePresenceChannelId");
b.HasKey("Id");
b.ToTable("LogSettings");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.ModulePrefix", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int?>("BotConfigId");
b.Property<string>("ModuleName");
b.Property<string>("Prefix");
b.HasKey("Id");
b.HasIndex("BotConfigId");
b.ToTable("ModulePrefixes");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlaylist", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Author");
b.Property<ulong>("AuthorId");
b.Property<string>("Name");
b.HasKey("Id");
b.ToTable("MusicPlaylists");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.Permission", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int?>("NextId");
b.Property<int>("PrimaryTarget");
b.Property<ulong>("PrimaryTargetId");
b.Property<int>("SecondaryTarget");
b.Property<string>("SecondaryTargetName");
b.Property<bool>("State");
b.HasKey("Id");
b.HasIndex("NextId")
.IsUnique();
b.ToTable("Permission");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int?>("BotConfigId");
b.Property<string>("Status");
b.HasKey("Id");
b.HasIndex("BotConfigId");
b.ToTable("PlayingStatus");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int?>("MusicPlaylistId");
b.Property<string>("Provider");
b.Property<int>("ProviderType");
b.Property<string>("Query");
b.Property<string>("Title");
b.Property<string>("Uri");
b.HasKey("Id");
b.HasIndex("MusicPlaylistId");
b.ToTable("PlaylistSong");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.Quote", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<ulong>("AuthorId");
b.Property<string>("AuthorName")
.IsRequired();
b.Property<ulong>("GuildId");
b.Property<string>("Keyword")
.IsRequired();
b.Property<string>("Text")
.IsRequired();
b.HasKey("Id");
b.ToTable("Quotes");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.RaceAnimal", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int?>("BotConfigId");
b.Property<string>("Icon");
b.Property<string>("Name");
b.HasKey("Id");
b.HasIndex("BotConfigId");
b.ToTable("RaceAnimals");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.Reminder", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<ulong>("ChannelId");
b.Property<bool>("IsPrivate");
b.Property<string>("Message");
b.Property<ulong>("ServerId");
b.Property<ulong>("UserId");
b.Property<DateTime>("When");
b.HasKey("Id");
b.ToTable("Reminders");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.Repeater", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<ulong>("ChannelId");
b.Property<ulong>("GuildId");
b.Property<TimeSpan>("Interval");
b.Property<string>("Message");
b.HasKey("Id");
b.HasIndex("ChannelId")
.IsUnique();
b.ToTable("Repeaters");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.SelfAssignedRole", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<ulong>("GuildId");
b.Property<ulong>("RoleId");
b.HasKey("Id");
b.HasIndex("GuildId", "RoleId")
.IsUnique();
b.ToTable("SelfAssignableRoles");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistItem", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
.WithMany("Blacklist")
.HasForeignKey("BotConfigId");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashCaller", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.ClashWar", "ClashWar")
.WithMany("Bases")
.HasForeignKey("ClashWarId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
.WithMany("CommandCooldowns")
.HasForeignKey("GuildConfigId");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.EightBallResponse", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
.WithMany("EightBallResponses")
.HasForeignKey("BotConfigId");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
.WithMany("FilterInvitesChannelIds")
.HasForeignKey("GuildConfigId");
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
.WithMany("FilterWordsChannelIds")
.HasForeignKey("GuildConfigId1");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
.WithMany("FilteredWords")
.HasForeignKey("GuildConfigId");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.FollowedStream", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
.WithMany("FollowedStreams")
.HasForeignKey("GuildConfigId");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
.WithMany("GenerateCurrencyChannelIds")
.HasForeignKey("GuildConfigId");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting")
.WithMany()
.HasForeignKey("LogSettingId");
b.HasOne("NadekoBot.Services.Database.Models.Permission", "RootPermission")
.WithMany()
.HasForeignKey("RootPermissionId");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogChannel", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting")
.WithMany("IgnoredChannels")
.HasForeignKey("LogSettingId");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting")
.WithMany("IgnoredVoicePresenceChannelIds")
.HasForeignKey("LogSettingId");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.ModulePrefix", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
.WithMany("ModulePrefixes")
.HasForeignKey("BotConfigId");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.Permission", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.Permission", "Next")
.WithOne("Previous")
.HasForeignKey("NadekoBot.Services.Database.Models.Permission", "NextId");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
.WithMany("RotatingStatusMessages")
.HasForeignKey("BotConfigId");
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.MusicPlaylist")
.WithMany("Songs")
.HasForeignKey("MusicPlaylistId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("NadekoBot.Services.Database.Models.RaceAnimal", b =>
{
b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
.WithMany("RaceAnimals")
.HasForeignKey("BotConfigId");
});
}
}
}

View File

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations
{
public partial class Cleverbot : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "CleverbotEnabled",
table: "GuildConfigs",
nullable: false,
defaultValue: false);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "CleverbotEnabled",
table: "GuildConfigs");
}
}
}

View File

@ -332,6 +332,8 @@ namespace NadekoBot.Migrations
b.Property<string>("ChannelGreetMessageText");
b.Property<bool>("CleverbotEnabled");
b.Property<float>("DefaultMusicVolume");
b.Property<bool>("DeleteMessageOnCommand");

View File

@ -36,7 +36,7 @@ namespace NadekoBot.Modules.Administration
{
using (var uow = DbHandler.UnitOfWork())
{
var configs = uow.GuildConfigs.GetAll();
var configs = NadekoBot.AllGuildConfigs;
GuildMuteRoles = new ConcurrentDictionary<ulong, string>(configs
.Where(c=>!string.IsNullOrWhiteSpace(c.MuteRoleName))
.ToDictionary(c => c.GuildId, c => c.MuteRoleName));
@ -87,9 +87,13 @@ namespace NadekoBot.Modules.Administration
}
foreach (var toOverwrite in guild.GetTextChannels())
{
try
{
await toOverwrite.AddPermissionOverwriteAsync(muteRole, new OverwritePermissions(sendMessages: PermValue.Deny, attachFiles: PermValue.Deny))
.ConfigureAwait(false);
}
catch { }
await Task.Delay(200).ConfigureAwait(false);
}
}
@ -311,7 +315,8 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.BanMembers)]
[RequirePermission(GuildPermission.KickMembers)]
[RequirePermission(GuildPermission.ManageMessages)]
public async Task Softban(IUserMessage umsg, IGuildUser user, [Remainder] string msg = null)
{
var channel = (ITextChannel)umsg.Channel;

View File

@ -36,7 +36,6 @@ namespace NadekoBot.Modules.Administration
public int UserThreshold { get; set; }
public int Seconds { get; set; }
public PunishmentAction Action { get; set; }
public IRole MuteRole { get; set; }
public int UsersCount { get; set; }
public ConcurrentHashSet<IGuildUser> RaidUsers { get; set; } = new ConcurrentHashSet<IGuildUser>();
}
@ -45,7 +44,6 @@ namespace NadekoBot.Modules.Administration
{
public PunishmentAction Action { get; set; }
public int MessageThreshold { get; set; } = 3;
public IRole MuteRole { get; set; }
public ConcurrentDictionary<ulong, UserSpamStats> UserStats { get; set; }
= new ConcurrentDictionary<ulong, UserSpamStats>();
}
@ -114,9 +112,9 @@ namespace NadekoBot.Modules.Administration
{
if (spamSettings.UserStats.TryRemove(msg.Author.Id, out stats))
{
var log = await PunishUser((IGuildUser)msg.Author, spamSettings.Action, spamSettings.MuteRole, ProtectionType.Spamming)
await PunishUsers(spamSettings.Action, await GetMuteRole(channel.Guild), ProtectionType.Spamming, (IGuildUser)msg.Author)
.ConfigureAwait(false);
await channel.Guild.SendMessageToOwnerAsync(log).ConfigureAwait(false); }
}
}
}
catch { }
@ -142,16 +140,11 @@ namespace NadekoBot.Modules.Administration
if (settings.UsersCount >= settings.UserThreshold)
{
var users = settings.RaidUsers.ToList();
var users = settings.RaidUsers.ToArray();
settings.RaidUsers.Clear();
string msg = "";
foreach (var gu in users)
{
msg += await PunishUser(gu, settings.Action, settings.MuteRole, ProtectionType.Raiding).ConfigureAwait(false);
}
try { await usr.Guild.SendMessageToOwnerAsync(msg).ConfigureAwait(false); } catch { }
}
await PunishUsers(settings.Action, await GetMuteRole(usr.Guild), ProtectionType.Raiding, users).ConfigureAwait(false);
}
await Task.Delay(1000 * settings.Seconds).ConfigureAwait(false);
settings.RaidUsers.TryRemove(usr);
@ -162,7 +155,9 @@ namespace NadekoBot.Modules.Administration
};
}
private async Task<string> PunishUser(IGuildUser gu, PunishmentAction action, IRole muteRole, ProtectionType pt)
private async Task PunishUsers(PunishmentAction action, IRole muteRole, ProtectionType pt, params IGuildUser[] gus)
{
foreach (var gu in gus)
{
switch (action)
{
@ -170,7 +165,6 @@ namespace NadekoBot.Modules.Administration
try
{
await gu.AddRolesAsync(muteRole);
return $"{Format.Bold(gu.ToString())} was **MUTED** due to `{pt}` protection on **{gu.Guild.Name}** server.\n";
}
catch (Exception ex) { _log.Warn(ex, "I can't apply punishement"); }
break;
@ -188,8 +182,6 @@ namespace NadekoBot.Modules.Administration
// try it twice, really don't want to ban user if
// only kick has been specified as the punishement
}
return $"{Format.Bold(gu.ToString())} was **KICKED** due to `{pt}` protection on **{gu.Guild.Name}** server.\n";
}
catch (Exception ex) { _log.Warn(ex, "I can't apply punishment"); }
break;
@ -197,14 +189,14 @@ namespace NadekoBot.Modules.Administration
try
{
await gu.Guild.AddBanAsync(gu, 7);
return $"{Format.Bold(gu.ToString())} was **BANNED** due to `{pt}` protection on **{gu.Guild.Name}** server.\n";
}
catch (Exception ex) { _log.Warn(ex, "I can't apply punishment"); }
break;
default:
break;
}
return String.Empty;
}
await LogCommands.TriggeredAntiProtection(gus, action, pt).ConfigureAwait(false);
}
@ -227,10 +219,9 @@ namespace NadekoBot.Modules.Administration
return;
}
IRole muteRole;
try
{
muteRole = await GetMuteRole(channel.Guild).ConfigureAwait(false);
await GetMuteRole(channel.Guild).ConfigureAwait(false);
}
catch (Exception ex)
{
@ -246,7 +237,6 @@ namespace NadekoBot.Modules.Administration
Action = action,
Seconds = seconds,
UserThreshold = userThreshold,
MuteRole = muteRole,
};
antiRaidGuilds.AddOrUpdate(channel.Guild.Id, setting, (id, old) => setting);
@ -271,10 +261,22 @@ namespace NadekoBot.Modules.Administration
}
else
{
try
{
await GetMuteRole(channel.Guild).ConfigureAwait(false);
}
catch (Exception ex)
{
await channel.SendMessageAsync("Failed creating a mute role. Give me ManageRoles permission" +
"or create 'nadeko-mute' role with disabled SendMessages and try again.")
.ConfigureAwait(false);
_log.Warn(ex);
return;
}
if (antiSpamGuilds.TryAdd(channel.Guild.Id, new AntiSpamSetting()
{
Action = action,
MuteRole = await GetMuteRole(channel.Guild).ConfigureAwait(false),
MessageThreshold = messageCount,
}))
await channel.SendMessageAsync("`Anti-Spam feature enabled on this server.`").ConfigureAwait(false);

View File

@ -80,7 +80,7 @@ namespace NadekoBot.Modules.Administration
{
var firstOwnerChannel = ownerChannels.First();
if (firstOwnerChannel.Recipient.Id != msg.Author.Id)
try { await firstOwnerChannel.SendMessageAsync(msg.Content).ConfigureAwait(false); } catch { }
try { await firstOwnerChannel.SendMessageAsync(toSend).ConfigureAwait(false); } catch { }
}
}
}

View File

@ -22,31 +22,29 @@ namespace NadekoBot.Modules.Administration
[Group]
public class LogCommands
{
private ShardedDiscordClient _client { get; }
private Logger _log { get; }
private static ShardedDiscordClient _client { get; }
private static Logger _log { get; }
private string prettyCurrentTime => $"【{DateTime.Now:HH:mm:ss}】";
private static string prettyCurrentTime => $"【{DateTime.Now:HH:mm:ss}】";
public ConcurrentDictionary<ulong, LogSetting> GuildLogSettings { get; }
public static ConcurrentDictionary<ulong, LogSetting> GuildLogSettings { get; }
private ConcurrentDictionary<ITextChannel, List<string>> UserPresenceUpdates { get; } = new ConcurrentDictionary<ITextChannel, List<string>>();
private Timer t;
private static ConcurrentDictionary<ITextChannel, List<string>> UserPresenceUpdates { get; } = new ConcurrentDictionary<ITextChannel, List<string>>();
private static Timer timerReference { get; }
private IGoogleApiService _google { get; }
public LogCommands(ShardedDiscordClient client, IGoogleApiService google)
static LogCommands()
{
_client = client;
_google = google;
_client = NadekoBot.Client;
_log = LogManager.GetCurrentClassLogger();
using (var uow = DbHandler.UnitOfWork())
{
GuildLogSettings = new ConcurrentDictionary<ulong, LogSetting>(uow.GuildConfigs
.GetAll()
GuildLogSettings = new ConcurrentDictionary<ulong, LogSetting>(NadekoBot.AllGuildConfigs
.ToDictionary(g => g.GuildId, g => g.LogSetting));
}
t = new Timer(async (state) =>
timerReference = new Timer(async (state) =>
{
try
{
@ -64,8 +62,10 @@ namespace NadekoBot.Modules.Administration
_log.Warn(ex);
}
}, null, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(10));
}
public LogCommands(ShardedDiscordClient client)
{
//_client.MessageReceived += _client_MessageReceived;
_client.MessageUpdated += _client_MessageUpdated;
_client.MessageDeleted += _client_MessageDeleted;
@ -82,6 +82,36 @@ namespace NadekoBot.Modules.Administration
_client.ChannelUpdated += _client_ChannelUpdated;
}
public static async Task TriggeredAntiProtection(IGuildUser[] users, PunishmentAction action, ProtectionType protection)
{
if (users.Length == 0)
return;
LogSetting logSetting;
if (!GuildLogSettings.TryGetValue(users.First().Guild.Id, out logSetting)
|| !logSetting.IsLogging)
return;
ITextChannel logChannel;
if ((logChannel = TryGetLogChannel(users.First().Guild, logSetting)) == null)
return;
var punishment = "";
if (action == PunishmentAction.Mute)
{
punishment = "MUTED";
}
else if (action == PunishmentAction.Kick)
{
punishment = "KICKED";
}
else if (action == PunishmentAction.Ban)
{
punishment = "BANNED";
}
await logChannel.SendMessageAsync(String.Join("\n",users.Select(user=>$"{Format.Bold(user.ToString())} was **{punishment}** due to `{protection}` protection on **{user.Guild.Name}** server.")))
.ConfigureAwait(false);
}
private Task _client_UserUpdated(IGuildUser before, IGuildUser after)
{
LogSetting logSetting;
@ -385,7 +415,7 @@ namespace NadekoBot.Modules.Administration
👤`{msg.Author.Username}`: {msg.Resolve(userHandling: UserMentionHandling.NameAndDiscriminator)}";
if (msg.Attachments.Any())
str += $"{Environment.NewLine}`Attachements`: {string.Join(", ", msg.Attachments.Select(a => a.ProxyUrl))}";
await logChannel.SendMessageAsync(str).ConfigureAwait(false);
await logChannel.SendMessageAsync(str.SanitizeMentions()).ConfigureAwait(false);
}
catch (Exception ex) { _log.Warn(ex); }
});
@ -422,8 +452,8 @@ namespace NadekoBot.Modules.Administration
{
try { await logChannel.SendMessageAsync($@"🕔`{prettyCurrentTime}` **Message** 📝 `#{channel.Name}`
👤`{before.Author.Username}`
`Old:` {before.Resolve(userHandling: UserMentionHandling.NameAndDiscriminator)}
`New:` {after.Resolve(userHandling: UserMentionHandling.NameAndDiscriminator)}").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
`Old:` {before.Resolve(userHandling: UserMentionHandling.NameAndDiscriminator).SanitizeMentions()}
`New:` {after.Resolve(userHandling: UserMentionHandling.NameAndDiscriminator).SanitizeMentions()}").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
});
return Task.CompletedTask;
@ -462,7 +492,7 @@ namespace NadekoBot.Modules.Administration
// }
private enum LogChannelType { Text, Voice, UserPresence };
private ITextChannel TryGetLogChannel(IGuild guild, LogSetting logSetting, LogChannelType logChannelType = LogChannelType.Text)
private static ITextChannel TryGetLogChannel(IGuild guild, LogSetting logSetting, LogChannelType logChannelType = LogChannelType.Text)
{
ulong id = 0;
switch (logChannelType)

View File

@ -159,7 +159,7 @@ namespace NadekoBot.Modules.Administration
return old;
});
await channel.SendMessageAsync($"Repeating \"{rep.Repeater.Message}\" every {rep.Repeater.Interval} minutes").ConfigureAwait(false);
await channel.SendMessageAsync($"Repeating \"{rep.Repeater.Message}\" every {rep.Repeater.Interval.Days} days, {rep.Repeater.Interval.Hours} hours and {rep.Repeater.Interval.Minutes} minutes.").ConfigureAwait(false);
}
}
}

View File

@ -75,9 +75,9 @@ namespace NadekoBot.Modules.Administration
MigrateDb0_9(uow);
//NOW save it
botConfig.MigrationVersion = 1;
_log.Warn("Writing to disc");
uow.Complete();
botConfig.MigrationVersion = 1;
}
}
@ -128,18 +128,19 @@ namespace NadekoBot.Modules.Administration
}
var com2 = db.CreateCommand();
com.CommandText = "SELECT * FROM CurrencyState";
com.CommandText = "SELECT * FROM CurrencyState GROUP BY UserId";
i = 0;
var reader2 = com.ExecuteReader();
while (reader2.Read())
{
_log.Info(++i);
uow.Currency.Add(new Currency()
var curr = new Currency()
{
Amount = (long)reader2["Value"],
UserId = (ulong)(long)reader2["UserId"]
});
};
uow.Currency.Add(curr);
}
db.Close();
try { File.Move("data/nadekobot.sqlite", "data/DELETE_ME_nadekobot.sqlite"); } catch { }

View File

@ -67,7 +67,7 @@ namespace NadekoBot.Modules.Administration
}
finally
{
await Task.Delay(15000);
await Task.Delay(TimeSpan.FromMinutes(1));
}
} while (true);
});

View File

@ -25,7 +25,7 @@ namespace NadekoBot.Modules.Administration
{
using (var uow = DbHandler.UnitOfWork())
{
voicePlusTextCache = new ConcurrentHashSet<ulong>(uow.GuildConfigs.GetAll().Where(g => g.VoicePlusTextEnabled).Select(g => g.GuildId));
voicePlusTextCache = new ConcurrentHashSet<ulong>(NadekoBot.AllGuildConfigs.Where(g => g.VoicePlusTextEnabled).Select(g => g.GuildId));
}
NadekoBot.Client.UserVoiceStateUpdated += UserUpdatedEventHandler;
}
@ -114,7 +114,7 @@ namespace NadekoBot.Modules.Administration
var channel = (ITextChannel)msg.Channel;
var guild = channel.Guild;
var botUser = guild.GetCurrentUser();
var botUser = await guild.GetCurrentUserAsync().ConfigureAwait(false);
if (!botUser.GuildPermissions.ManageRoles || !botUser.GuildPermissions.ManageChannels)
{
await channel.SendMessageAsync(":anger: `I require atleast manage roles and manage channels permissions to enable this feature (preffered Administration permission).`");
@ -166,7 +166,8 @@ namespace NadekoBot.Modules.Administration
{
var channel = (ITextChannel)msg.Channel;
var guild = channel.Guild;
if (!guild.GetCurrentUser().GuildPermissions.Administrator)
var botUser = await guild.GetCurrentUserAsync().ConfigureAwait(false);
if (!botUser.GuildPermissions.Administrator)
{
await channel.SendMessageAsync("`I need Administrator permission to do that.`").ConfigureAwait(false);
return;

View File

@ -19,6 +19,7 @@ namespace NadekoBot.Modules.CustomReactions
{
public static ConcurrentHashSet<CustomReaction> GlobalReactions { get; } = new ConcurrentHashSet<CustomReaction>();
public static ConcurrentDictionary<ulong, ConcurrentHashSet<CustomReaction>> GuildReactions { get; } = new ConcurrentDictionary<ulong, ConcurrentHashSet<CustomReaction>>();
static CustomReactions()
{
using (var uow = DbHandler.UnitOfWork())
@ -30,18 +31,14 @@ namespace NadekoBot.Modules.CustomReactions
}
public CustomReactions(ILocalization loc, CommandService cmds, ShardedDiscordClient client) : base(loc, cmds, client)
{
client.MessageReceived += (imsg) =>
{
var umsg = imsg as IUserMessage;
if (umsg == null || imsg.Author.IsBot)
return Task.CompletedTask;
}
public static async Task<bool> TryExecuteCustomReaction(IUserMessage umsg)
{
var channel = umsg.Channel as ITextChannel;
if (channel == null)
return Task.CompletedTask;
return false;
var t = Task.Run(async () =>
{
var content = umsg.Content.Trim().ToLowerInvariant();
ConcurrentHashSet<CustomReaction> reactions;
GuildReactions.TryGetValue(channel.Guild.Id, out reactions);
@ -55,7 +52,7 @@ namespace NadekoBot.Modules.CustomReactions
if (reaction != null)
{
try { await channel.SendMessageAsync(reaction.ResponseWithContext(umsg)).ConfigureAwait(false); } catch { }
return;
return true;
}
}
var greaction = GlobalReactions.Where(cr =>
@ -68,11 +65,9 @@ namespace NadekoBot.Modules.CustomReactions
if (greaction != null)
{
try { await channel.SendMessageAsync(greaction.ResponseWithContext(umsg)).ConfigureAwait(false); } catch { }
return;
return true;
}
});
return Task.CompletedTask;
};
return false;
}
[NadekoCommand, Usage, Description, Aliases]
@ -115,7 +110,7 @@ namespace NadekoBot.Modules.CustomReactions
reactions.Add(cr);
}
await imsg.Channel.SendMessageAsync($"`Added new custom reaction:`\n\t`Trigger:` {key}\n\t`Response:` {message}").ConfigureAwait(false);
await imsg.Channel.SendMessageAsync($"`Added new custom reaction {cr.Id}:`\n\t`Trigger:` {key}\n\t`Response:` {message}").ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]

View File

@ -46,13 +46,6 @@ namespace NadekoBot.Modules.Gambling
if (amount < 0)
amount = 0;
if (amount > 0)
if (!await CurrencyHandler.RemoveCurrencyAsync((IGuildUser)umsg.Author, "BetRace", amount, true).ConfigureAwait(false))
{
try { await channel.SendMessageAsync($"{umsg.Author.Mention} You don't have enough {Gambling.CurrencyName}s.").ConfigureAwait(false); } catch { }
return;
}
AnimalRace ar;
if (!AnimalRaces.TryGetValue(channel.Guild.Id, out ar))
@ -225,28 +218,33 @@ namespace NadekoBot.Modules.Gambling
}
}
public async Task<bool> JoinRace(IGuildUser u, int amount = 0)
public async Task JoinRace(IGuildUser u, int amount = 0)
{
var animal = "";
if (!animals.TryDequeue(out animal))
{
await raceChannel.SendMessageAsync($"{u.Mention} `There is no running race on this server.`");
return false;
return;
}
var p = new Participant(u, animal, amount);
if (participants.Contains(p))
{
await raceChannel.SendMessageAsync($"{u.Mention} `You already joined this race.`");
return false;
return;
}
if (Started)
{
await raceChannel.SendMessageAsync($"{u.Mention} `Race is already started`");
return false;
return;
}
if (amount > 0)
if (!await CurrencyHandler.RemoveCurrencyAsync((IGuildUser)u, "BetRace", amount, true).ConfigureAwait(false))
{
try { await raceChannel.SendMessageAsync($"{u.Mention} You don't have enough {Gambling.CurrencyName}s.").ConfigureAwait(false); } catch { }
return;
}
participants.Add(p);
await raceChannel.SendMessageAsync($"{u.Mention} **joined the race as a {p.Animal}" + (amount > 0 ? $" and bet {amount} {(amount == 1? CurrencyName : CurrencyPluralName)}!**" : "**"));
return true;
await raceChannel.SendMessageAsync($"{u.Mention} **joined the race as a {p.Animal}" + (amount > 0 ? $" and bet {amount} {CurrencySign}!**" : "**"));
}
}

View File

@ -0,0 +1,125 @@
using Discord;
using Discord.Commands;
using NadekoBot.Attributes;
using NadekoBot.Services;
using NadekoBot.Services.Database;
using Newtonsoft.Json;
using NLog;
using Services.CleverBotApi;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace NadekoBot.Modules.Games
{
public partial class Games
{
[Group]
public class CleverBotCommands
{
private static Logger _log { get; }
class CleverAnswer {
public string Status { get; set; }
public string Response { get; set; }
}
//user#discrim is the key
public static ConcurrentHashSet<string> ChannelsInConversation { get; } = new ConcurrentHashSet<string>();
public static ConcurrentDictionary<ulong, ChatterBotSession> CleverbotGuilds { get; } = new ConcurrentDictionary<ulong, ChatterBotSession>();
static CleverBotCommands()
{
_log = LogManager.GetCurrentClassLogger();
using (var uow = DbHandler.UnitOfWork())
{
var bot = ChatterBotFactory.Create(ChatterBotType.CLEVERBOT);
CleverbotGuilds = new ConcurrentDictionary<ulong, ChatterBotSession>(
uow.GuildConfigs.GetAll()
.Where(gc => gc.CleverbotEnabled)
.ToDictionary(gc => gc.GuildId, gc => bot.CreateSession()));
}
}
public static async Task<bool> TryAsk(IUserMessage msg) {
var channel = msg.Channel as ITextChannel;
if (channel == null)
return false;
ChatterBotSession cleverbot;
if (!CleverbotGuilds.TryGetValue(channel.Guild.Id, out cleverbot))
return false;
var nadekoId = NadekoBot.Client.GetCurrentUser().Id;
var normalMention = $"<@{nadekoId}> ";
var nickMention = $"<@!{nadekoId}> ";
string message;
if (msg.Content.StartsWith(normalMention))
{
message = msg.Content.Substring(normalMention.Length).Trim();
}
else if (msg.Content.StartsWith(nickMention))
{
message = msg.Content.Substring(nickMention.Length).Trim();
}
else
{
return false;
}
await msg.Channel.TriggerTypingAsync().ConfigureAwait(false);
var response = await cleverbot.Think(message).ConfigureAwait(false);
try
{
await msg.Channel.SendMessageAsync(response).ConfigureAwait(false);
}
catch (Exception ex)
{
_log.Warn(ex, "Eror sending response");
await msg.Channel.SendMessageAsync(msg.Author.Mention+" "+response).ConfigureAwait(false); // try twice :\
}
return true;
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequirePermission(ChannelPermission.ManageMessages)]
public async Task Cleverbot(IUserMessage imsg)
{
var channel = (ITextChannel)imsg.Channel;
ChatterBotSession throwaway;
if (CleverbotGuilds.TryRemove(channel.Guild.Id, out throwaway))
{
using (var uow = DbHandler.UnitOfWork())
{
uow.GuildConfigs.SetCleverbotEnabled(channel.Guild.Id, false);
await uow.CompleteAsync().ConfigureAwait(false);
}
await channel.SendMessageAsync($"{imsg.Author.Mention} `Disabled cleverbot on this server.`").ConfigureAwait(false);
return;
}
var cleverbot = ChatterBotFactory.Create(ChatterBotType.CLEVERBOT);
var session = cleverbot.CreateSession();
CleverbotGuilds.TryAdd(channel.Guild.Id, session);
using (var uow = DbHandler.UnitOfWork())
{
uow.GuildConfigs.SetCleverbotEnabled(channel.Guild.Id, true);
await uow.CompleteAsync().ConfigureAwait(false);
}
await channel.SendMessageAsync($"{imsg.Author.Mention} `Enabled cleverbot on this server.`").ConfigureAwait(false);
}
}
}
}

View File

@ -54,7 +54,7 @@ namespace NadekoBot.Modules.Games
{
var conf = uow.BotConfig.GetOrCreate();
var x =
generationChannels = new ConcurrentHashSet<ulong>(uow.GuildConfigs.GetAll()
generationChannels = new ConcurrentHashSet<ulong>(NadekoBot.AllGuildConfigs
.SelectMany(c => c.GenerateCurrencyChannelIds.Select(obj=>obj.ChannelId)));
chance = conf.CurrencyGenerationChance;
cooldown = conf.CurrencyGenerationCooldown;

View File

@ -218,6 +218,47 @@ namespace NadekoBot.Modules.Games
await channel.SendMessageAsync("Added new article for typing game.").ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task Typelist(IUserMessage imsg, int page = 1)
{
var channel = (ITextChannel)imsg.Channel;
if (page < 1)
return;
var articles = TypingArticles.Skip((page - 1) * 15).Take(15);
if (!articles.Any())
{
await channel.SendMessageAsync($"{imsg.Author.Mention} `No articles found on that page.`").ConfigureAwait(false);
return;
}
var i = (page - 1) * 15;
await channel.SendMessageAsync(String.Join("\n", articles.Select(a => $"`#{++i}` - {a.Text.TrimTo(50)}")))
.ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[OwnerOnly]
public async Task Typedel(IUserMessage imsg, int index)
{
var channel = (ITextChannel)imsg.Channel;
index -= 1;
if (index < 0 || index >= TypingArticles.Count)
return;
var removed = TypingArticles[index];
TypingArticles.RemoveAt(index);
File.WriteAllText(typingArticlesPath, JsonConvert.SerializeObject(TypingArticles));
await channel.SendMessageAsync($"`Removed typing article:` #{index + 1} - {removed.Text.TrimTo(50)}")
.ConfigureAwait(false);
}
}
}
}

View File

@ -125,13 +125,23 @@ namespace NadekoBot.Modules.Help
public Task Hgit(IUserMessage umsg)
{
var helpstr = new StringBuilder();
var lastModule = "";
helpstr.AppendLine(@"For more information and how to setup your own NadekoBot, go to: <http://github.com/Kwoth/NadekoBot/wiki>
You can support the project on patreon: <https://patreon.com/nadekobot> or paypal: `nadekodiscordbot@gmail.com`");
helpstr.AppendLine("##Table Of Contents");
helpstr.AppendLine(string.Join("\n", NadekoBot.CommandService.Modules.Where(m => m.Name.ToLowerInvariant() != "help").OrderBy(m => m.Name).Prepend(NadekoBot.CommandService.Modules.FirstOrDefault(m=>m.Name.ToLowerInvariant()=="help")).Select(m => $"- [{m.Name}](#{m.Name.ToLowerInvariant()})")));
helpstr.AppendLine();
string lastModule = null;
foreach (var com in _commands.Commands.OrderBy(com=>com.Module.Name).GroupBy(c=>c.Text).Select(g=>g.First()))
{
if (com.Module.Name != lastModule)
{
helpstr.AppendLine("\n### " + com.Module.Name + " ");
if (lastModule != null)
{
helpstr.AppendLine();
helpstr.AppendLine("###### [Back to TOC](#table-of-contents)");
}
helpstr.AppendLine();
helpstr.AppendLine("### " + com.Module.Name + " ");
helpstr.AppendLine("Command and aliases | Description | Usage");
helpstr.AppendLine("----------------|--------------|-------");
lastModule = com.Module.Name;

View File

@ -38,14 +38,23 @@ namespace NadekoBot.Modules.Music
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public Task Next(IUserMessage umsg)
public Task Next(IUserMessage umsg, int skipCount = 1)
{
var channel = (ITextChannel)umsg.Channel;
if (skipCount < 1)
return Task.CompletedTask;
MusicPlayer musicPlayer;
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) return Task.CompletedTask;
if (musicPlayer.PlaybackVoiceChannel == ((IGuildUser)umsg.Author).VoiceChannel)
{
while (--skipCount > 0)
{
musicPlayer.RemoveSongAt(0);
}
musicPlayer.Next();
}
return Task.CompletedTask;
}

View File

@ -30,17 +30,71 @@ namespace NadekoBot.Modules.NSFW
tag = tag?.Trim() ?? "";
var links = await Task.WhenAll(GetGelbooruImageLink("rating%3Aexplicit+" + tag), GetDanbooruImageLink("rating%3Aexplicit+" + tag)).ConfigureAwait(false);
tag = "rating%3Aexplicit+" + tag;
var rng = new NadekoRandom();
Task<string> provider = Task.FromResult("");
switch (rng.Next(0,4))
{
case 0:
provider = GetDanbooruImageLink(tag);
break;
case 1:
provider = GetGelbooruImageLink(tag);
break;
case 2:
provider = GetATFbooruImageLink(tag);
break;
case 3:
provider = GetKonachanImageLink(tag);
break;
default:
break;
}
var link = await provider.ConfigureAwait(false);
if (string.IsNullOrWhiteSpace(link))
await channel.SendMessageAsync("Search yielded no results ;(").ConfigureAwait(false);
else
await channel.SendMessageAsync(link).ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task HentaiBomb(IUserMessage umsg, [Remainder] string tag = null)
{
var channel = (ITextChannel)umsg.Channel;
tag = tag?.Trim() ?? "";
tag = "rating%3Aexplicit+" + tag;
var links = await Task.WhenAll(GetGelbooruImageLink(tag),
GetDanbooruImageLink(tag),
GetKonachanImageLink(tag),
GetATFbooruImageLink(tag)).ConfigureAwait(false);
if (links.All(l => l == null))
{
await channel.SendMessageAsync("`No results.`");
await channel.SendMessageAsync("`No results.`").ConfigureAwait(false);
return;
}
await channel.SendMessageAsync(String.Join("\n\n", links)).ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task ATFbooru(IUserMessage umsg, [Remainder] string tag = null)
{
var channel = (ITextChannel)umsg.Channel;
tag = tag?.Trim() ?? "";
var link = await GetATFbooruImageLink(tag).ConfigureAwait(false);
if (string.IsNullOrWhiteSpace(link))
await channel.SendMessageAsync("Search yielded no results ;(").ConfigureAwait(false);
else
await channel.SendMessageAsync(link).ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task Danbooru(IUserMessage umsg, [Remainder] string tag = null)
@ -50,7 +104,7 @@ namespace NadekoBot.Modules.NSFW
tag = tag?.Trim() ?? "";
var link = await GetDanbooruImageLink(tag).ConfigureAwait(false);
if (string.IsNullOrWhiteSpace(link))
await channel.SendMessageAsync("Search yielded no results ;(");
await channel.SendMessageAsync("Search yielded no results ;(").ConfigureAwait(false);
else
await channel.SendMessageAsync(link).ConfigureAwait(false);
}
@ -64,7 +118,7 @@ namespace NadekoBot.Modules.NSFW
tag = tag?.Trim() ?? "";
var link = await GetKonachanImageLink(tag).ConfigureAwait(false);
if (string.IsNullOrWhiteSpace(link))
await channel.SendMessageAsync("Search yielded no results ;(");
await channel.SendMessageAsync("Search yielded no results ;(").ConfigureAwait(false);
else
await channel.SendMessageAsync(link).ConfigureAwait(false);
}
@ -78,7 +132,7 @@ namespace NadekoBot.Modules.NSFW
tag = tag?.Trim() ?? "";
var link = await GetGelbooruImageLink(tag).ConfigureAwait(false);
if (string.IsNullOrWhiteSpace(link))
await channel.SendMessageAsync("Search yielded no results ;(");
await channel.SendMessageAsync("Search yielded no results ;(").ConfigureAwait(false);
else
await channel.SendMessageAsync(link).ConfigureAwait(false);
}
@ -92,7 +146,7 @@ namespace NadekoBot.Modules.NSFW
tag = tag?.Trim() ?? "";
var link = await GetRule34ImageLink(tag).ConfigureAwait(false);
if (string.IsNullOrWhiteSpace(link))
await channel.SendMessageAsync("Search yielded no results ;(");
await channel.SendMessageAsync("Search yielded no results ;(").ConfigureAwait(false);
else
await channel.SendMessageAsync(link).ConfigureAwait(false);
}
@ -106,7 +160,7 @@ namespace NadekoBot.Modules.NSFW
tag = tag?.Trim() ?? "";
var link = await GetE621ImageLink(tag).ConfigureAwait(false);
if (string.IsNullOrWhiteSpace(link))
await channel.SendMessageAsync("Search yielded no results ;(");
await channel.SendMessageAsync("Search yielded no results ;(").ConfigureAwait(false);
else
await channel.SendMessageAsync(link).ConfigureAwait(false);
}
@ -176,7 +230,7 @@ namespace NadekoBot.Modules.NSFW
if (matches.Count == 0)
return null;
return await NadekoBot.Google.ShortenUrl(matches[rng.Next(0, matches.Count)].Groups["ll"].Value).ConfigureAwait(false);
return matches[rng.Next(0, matches.Count)].Groups["ll"].Value;
}
}
@ -255,5 +309,25 @@ namespace NadekoBot.Modules.NSFW
return "Error, do you have too many tags?";
}
}
public static async Task<string> GetATFbooruImageLink(string tag)
{
var rng = new NadekoRandom();
var link = $"https://atfbooru.ninja/posts?" +
$"limit=100";
if (!string.IsNullOrWhiteSpace(tag))
link += $"&tags={tag.Replace(" ", "+")}";
using (var http = new HttpClient())
{
var webpage = await http.GetStringAsync(link).ConfigureAwait(false);
var matches = Regex.Matches(webpage, "data-file-url=\"(?<id>.*?)\"");
if (matches.Count == 0)
return null;
return $"https://atfbooru.ninja" +
$"{matches[rng.Next(0, matches.Count)].Groups["id"].Value}";
}
}
}
}

View File

@ -80,7 +80,7 @@ namespace NadekoBot.Modules.Permissions
}
await uow.CompleteAsync().ConfigureAwait(false);
}
if (action == AddRemove.Rem)
if (action == AddRemove.Add)
{
TriviaGame tg;
switch (type)

View File

@ -33,7 +33,7 @@ namespace NadekoBot.Modules.Permissions
{
using (var uow = DbHandler.UnitOfWork())
{
var configs = uow.GuildConfigs.GetAll();
var configs = NadekoBot.AllGuildConfigs;
commandCooldowns = new ConcurrentDictionary<ulong, ConcurrentHashSet<CommandCooldown>>(configs.ToDictionary(k => k.GuildId, v => new ConcurrentHashSet<CommandCooldown>(v.CommandCooldowns)));
}
}

View File

@ -46,7 +46,7 @@ namespace NadekoBot.Modules.Permissions
{
using (var uow = DbHandler.UnitOfWork())
{
var guildConfigs = uow.GuildConfigs.GetAll();
var guildConfigs = NadekoBot.AllGuildConfigs;
InviteFilteringServers = new ConcurrentHashSet<ulong>(guildConfigs.Where(gc => gc.FilterInvites).Select(gc => gc.GuildId));
InviteFilteringChannels = new ConcurrentHashSet<ulong>(guildConfigs.SelectMany(gc => gc.FilterInvitesChannelIds.Select(fci => fci.ChannelId)));

View File

@ -58,7 +58,7 @@ namespace NadekoBot.Modules.Searches
{
if (i % 2 == 0 && i != 0)
sb.AppendLine();
sb.Append($"`{i + 1}.` **{dataList[i]["name"]}** ");
sb.Append($"`{i + 1}.` **{dataList[i]["name"]}** {dataList[i]["general"]["banRate"]}% ");
//sb.AppendLine($" ({dataList[i]["general"]["banRate"]}%)");
}
@ -67,7 +67,7 @@ namespace NadekoBot.Modules.Searches
}
catch (Exception)
{
await channel.SendMessageAsync($":anger: Fail: Champion.gg didsabled ban data until next patch. Sorry for the inconvenience.").ConfigureAwait(false);
await channel.SendMessageAsync($":anger: `Something went wrong.`").ConfigureAwait(false);
}
}
}

View File

@ -6,11 +6,68 @@ using System;
using System.Threading.Tasks;
using NadekoBot.Services;
using Discord.WebSocket;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;
namespace NadekoBot.Modules.Searches
{
public partial class Searches
{
public struct UserChannelPair
{
public ulong UserId { get; set; }
public ulong ChannelId { get; set; }
}
[Group]
public class TranslateCommands
{
private static ConcurrentDictionary<ulong, bool> TranslatedChannels { get; }
private static ConcurrentDictionary<UserChannelPair, string> UserLanguages { get; }
static TranslateCommands()
{
TranslatedChannels = new ConcurrentDictionary<ulong, bool>();
UserLanguages = new ConcurrentDictionary<UserChannelPair, string>();
NadekoBot.Client.MessageReceived += (msg) =>
{
var umsg = msg as IUserMessage;
if(umsg == null)
return Task.CompletedTask;
bool autoDelete;
if (!TranslatedChannels.TryGetValue(umsg.Channel.Id, out autoDelete))
return Task.CompletedTask;
var t = Task.Run(async () =>
{
var key = new UserChannelPair()
{
UserId = umsg.Author.Id,
ChannelId = umsg.Channel.Id,
};
string langs;
if (!UserLanguages.TryGetValue(key, out langs))
return;
try
{
var text = await TranslateInternal(umsg, langs, umsg.Resolve(UserMentionHandling.Ignore), true)
.ConfigureAwait(false);
if (autoDelete)
try { await umsg.DeleteAsync().ConfigureAwait(false); } catch { }
await umsg.Channel.SendMessageAsync($"{umsg.Author.Mention} `:` "+text.Replace("<@ ", "<@").Replace("<@! ", "<@!")).ConfigureAwait(false);
}
catch { }
});
return Task.CompletedTask;
};
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task Translate(IUserMessage umsg, string langs, [Remainder] string text = null)
@ -18,25 +75,98 @@ namespace NadekoBot.Modules.Searches
var channel = (ITextChannel)umsg.Channel;
try
{
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false);
var translation = await TranslateInternal(umsg, langs, text);
await channel.SendMessageAsync(translation).ConfigureAwait(false);
}
catch
{
await channel.SendMessageAsync("Bad input format, or something went wrong...").ConfigureAwait(false);
}
}
private static async Task<string> TranslateInternal(IUserMessage umsg, string langs, [Remainder] string text = null, bool silent = false)
{
var langarr = langs.ToLowerInvariant().Split('>');
if (langarr.Length != 2)
return;
throw new ArgumentException();
string from = langarr[0];
string to = langarr[1];
text = text?.Trim();
if (string.IsNullOrWhiteSpace(text))
return;
throw new ArgumentException();
return await GoogleTranslator.Instance.Translate(text, from, to).ConfigureAwait(false);
}
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false);
string translation = await GoogleTranslator.Instance.Translate(text, from, to).ConfigureAwait(false);
await channel.SendMessageAsync(translation).ConfigureAwait(false);
}
catch (Exception ex)
public enum AutoDeleteAutoTranslate
{
Console.WriteLine(ex);
await channel.SendMessageAsync("Bad input format, or something went wrong...").ConfigureAwait(false);
Del,
Nodel
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.Administrator)]
[OwnerOnly]
public async Task AutoTranslate(IUserMessage msg, AutoDeleteAutoTranslate autoDelete = AutoDeleteAutoTranslate.Nodel)
{
var channel = (ITextChannel)msg.Channel;
if (autoDelete == AutoDeleteAutoTranslate.Del)
{
TranslatedChannels.AddOrUpdate(channel.Id, true, (key, val) => true);
try { await channel.SendMessageAsync("`Started automatic translation of messages on this channel. User messages will be auto-deleted.`").ConfigureAwait(false); } catch { }
return;
}
bool throwaway;
if (TranslatedChannels.TryRemove(channel.Id, out throwaway))
{
try { await channel.SendMessageAsync("`Stopped automatic translation of messages on this channel.`").ConfigureAwait(false); } catch { }
return;
}
else if (TranslatedChannels.TryAdd(channel.Id, autoDelete == AutoDeleteAutoTranslate.Del))
{
try { await channel.SendMessageAsync("`Started automatic translation of messages on this channel.`").ConfigureAwait(false); } catch { }
}
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task AutoTransLang(IUserMessage msg, [Remainder] string langs = null)
{
var channel = (ITextChannel)msg.Channel;
var ucp = new UserChannelPair
{
UserId = msg.Author.Id,
ChannelId = msg.Channel.Id,
};
if (string.IsNullOrWhiteSpace(langs))
{
if (UserLanguages.TryRemove(ucp, out langs))
await channel.SendMessageAsync($"{msg.Author.Mention}'s auto-translate language has been removed.").ConfigureAwait(false);
return;
}
var langarr = langs.ToLowerInvariant().Split('>');
if (langarr.Length != 2)
return;
var from = langarr[0];
var to = langarr[1];
if (!GoogleTranslator.Instance.Languages.Contains(from) || !GoogleTranslator.Instance.Languages.Contains(to))
{
try { await channel.SendMessageAsync("`Invalid source and/or target Language.`").ConfigureAwait(false); } catch { }
return;
}
UserLanguages.AddOrUpdate(ucp, langs, (key, val) => langs);
await channel.SendMessageAsync(":ok:").ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
@ -50,3 +180,4 @@ namespace NadekoBot.Modules.Searches
}
}
}

View File

@ -4,6 +4,7 @@ using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Linq;
using System.Text;
using System.Net.Http;
using NadekoBot.Services;
using System.Threading.Tasks;
@ -184,6 +185,16 @@ $@"🌍 **Weather for** 【{obj["target"]}】
.ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task Shorten(IUserMessage msg, [Remainder] string arg)
{
if (string.IsNullOrWhiteSpace(arg))
return;
await msg.Channel.SendMessageAsync(await NadekoBot.Google.ShortenUrl(arg).ConfigureAwait(false));
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task Google(IUserMessage umsg, [Remainder] string terms = null)
@ -206,9 +217,16 @@ $@"🌍 **Weather for** 【{obj["target"]}】
var arg = name;
if (string.IsNullOrWhiteSpace(arg))
{
await channel.SendMessageAsync("💢 Please enter a card name to search for.").ConfigureAwait(false);
await channel.SendMessageAsync("💢 `Please enter a card name to search for.`").ConfigureAwait(false);
return;
}
if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.MashapeKey))
{
await channel.SendMessageAsync("💢 `Bot owner didn't specify MashapeApiKey. You can't use this functionality.`").ConfigureAwait(false);
return;
}
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false);
string response = "";
using (var http = new HttpClient())
@ -256,10 +274,16 @@ $@"🌍 **Weather for** 【{obj["target"]}】
{
var channel = (ITextChannel)umsg.Channel;
if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.MashapeKey))
{
await channel.SendMessageAsync("💢 `Bot owner didn't specify MashapeApiKey. You can't use this functionality.`").ConfigureAwait(false);
return;
}
var arg = query;
if (string.IsNullOrWhiteSpace(arg))
{
await channel.SendMessageAsync("💢 Please enter a search term.").ConfigureAwait(false);
await channel.SendMessageAsync("💢 `Please enter a search term.`").ConfigureAwait(false);
return;
}
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false);
@ -271,7 +295,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
try
{
var items = JObject.Parse(res);
var sb = new System.Text.StringBuilder();
var sb = new StringBuilder();
sb.AppendLine($"`Term:` {items["list"][0]["word"].ToString()}");
sb.AppendLine($"`Definition:` {items["list"][0]["definition"].ToString()}");
sb.Append($"`Link:` <{await _google.ShortenUrl(items["list"][0]["permalink"].ToString()).ConfigureAwait(false)}>");
@ -293,9 +317,15 @@ $@"🌍 **Weather for** 【{obj["target"]}】
var arg = query;
if (string.IsNullOrWhiteSpace(arg))
{
await channel.SendMessageAsync("💢 Please enter a search term.").ConfigureAwait(false);
await channel.SendMessageAsync("💢 `Please enter a search term.`").ConfigureAwait(false);
return;
}
if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.MashapeKey))
{
await channel.SendMessageAsync("💢 `Bot owner didn't specify MashapeApiKey. You can't use this functionality.`").ConfigureAwait(false);
return;
}
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false);
string res = "";
using (var http = new HttpClient())
@ -464,6 +494,114 @@ $@"🌍 **Weather for** 【{obj["target"]}】
}
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task Wikia(IUserMessage umsg, string target, [Remainder] string query = null)
{
var channel = (ITextChannel)umsg.Channel;
if (string.IsNullOrWhiteSpace(target) || string.IsNullOrWhiteSpace(query))
{
await channel.SendMessageAsync("💢 Please enter a target wikia, followed by search query.").ConfigureAwait(false);
return;
}
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false);
using (var http = new HttpClient())
{
http.DefaultRequestHeaders.Clear();
try
{
var res = await http.GetStringAsync($"http://www.{Uri.EscapeUriString(target)}.wikia.com/api/v1/Search/List?query={Uri.EscapeUriString(query)}&limit=25&minArticleQuality=10&batch=1&namespaces=0%2C14").ConfigureAwait(false);
var items = JObject.Parse(res);
var found = items["items"][0];
var response = $@"`Title:` {found["title"].ToString()}
`Quality:` {found["quality"]}
`URL:` {await NadekoBot.Google.ShortenUrl(found["url"].ToString()).ConfigureAwait(false)}";
await channel.SendMessageAsync(response);
}
catch
{
await channel.SendMessageAsync($"💢 Failed finding `{query}`.").ConfigureAwait(false);
}
}
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task MCPing(IUserMessage umsg, [Remainder] string query = null)
{
var channel = (ITextChannel)umsg.Channel;
var arg = query;
if (string.IsNullOrWhiteSpace(arg))
{
await channel.SendMessageAsync("💢 Please enter a `ip:port`.").ConfigureAwait(false);
return;
}
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false);
using (var http = new HttpClient())
{
http.DefaultRequestHeaders.Clear();
string ip = arg.Split(':')[0];
string port = arg.Split(':')[1];
var res = await http.GetStringAsync($"https://api.minetools.eu/ping/{Uri.EscapeUriString(ip)}/{Uri.EscapeUriString(port)}").ConfigureAwait(false);
try
{
var items = JObject.Parse(res);
var sb = new StringBuilder();
int ping = (int)Math.Ceiling(Double.Parse(items["latency"].ToString()));
sb.AppendLine($"`Server:` {arg}");
sb.AppendLine($"`Version:` {items["version"]["name"].ToString()} / Protocol {items["version"]["protocol"].ToString()}");
sb.AppendLine($"`Description:` {items["description"].ToString()}");
sb.AppendLine($"`Online Players:` {items["players"]["online"].ToString()}/{items["players"]["max"].ToString()}");
sb.Append($"`Latency:` {ping}");
await channel.SendMessageAsync(sb.ToString());
}
catch
{
await channel.SendMessageAsync($"💢 Failed finding `{arg}`.").ConfigureAwait(false);
}
}
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task MCQ(IUserMessage umsg, [Remainder] string query = null)
{
var channel = (ITextChannel)umsg.Channel;
var arg = query;
if (string.IsNullOrWhiteSpace(arg))
{
await channel.SendMessageAsync("💢 Please enter a `ip:port`.").ConfigureAwait(false);
return;
}
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false);
using (var http = new HttpClient())
{
http.DefaultRequestHeaders.Clear();
try
{
string ip = arg.Split(':')[0];
string port = arg.Split(':')[1];
var res = await http.GetStringAsync($"https://api.minetools.eu/query/{Uri.EscapeUriString(ip)}/{Uri.EscapeUriString(port)}").ConfigureAwait(false);
var items = JObject.Parse(res);
var sb = new StringBuilder();
sb.AppendLine($"`Server:` {arg.ToString()} 〘Status: {items["status"]}〙");
sb.AppendLine($"`Player List (First 5):`");
foreach (var item in items["Playerlist"].Take(5))
{
sb.AppendLine($":rosette: {item}");
}
sb.AppendLine($"`Online Players:` {items["Players"]} / {items["MaxPlayers"]}");
sb.AppendLine($"`Plugins:` {items["Plugins"]}");
sb.Append($"`Version:` {items["Version"]}");
await channel.SendMessageAsync(sb.ToString());
}
catch
{
await channel.SendMessageAsync($"💢 Failed finding server `{arg}`.").ConfigureAwait(false);
}
}
}
public static async Task<bool> ValidateQuery(ITextChannel ch, string query)
{
if (!string.IsNullOrEmpty(query.Trim())) return true;

View File

@ -15,6 +15,30 @@ namespace NadekoBot.Modules.Utility
{
public partial class Utility
{
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task ListQuotes(IUserMessage imsg, int page = 1)
{
var channel = (ITextChannel)imsg.Channel;
page -= 1;
if (page < 0)
return;
IEnumerable<Quote> quotes;
using (var uow = DbHandler.UnitOfWork())
{
quotes = uow.Quotes.GetGroup(page * 16, 16);
}
if (quotes.Any())
await channel.SendMessageAsync($"`Page {page + 1} of quotes:`\n```xl\n" + String.Join("\n", quotes.Select((q) => $"{q.Keyword,-20} by {q.AuthorName}")) + "\n```")
.ConfigureAwait(false);
else
await channel.SendMessageAsync("`No quotes on this page.`").ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task ShowQuote(IUserMessage umsg, [Remainder] string keyword)

View File

@ -11,6 +11,8 @@ using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Reflection;
using Discord.WebSocket;
using System.Net.Http;
using System.IO;
namespace NadekoBot.Modules.Utility
{
@ -167,13 +169,65 @@ namespace NadekoBot.Modules.Utility
{
var matches = emojiFinder.Matches(emojis);
var result = string.Join("\n", matches.Cast<Match>()
.Select(m => $"`Name:` {m.Groups["name"]} `Link:` http://discordapp.com/api/emojis/{m.Groups["id"]}.png"));
await msg.Channel.SendMessageAsync(result).ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[OwnerOnly]
public async Task ListServers(IUserMessage imsg, int page = 1)
{
var channel = (ITextChannel)imsg.Channel;
page -= 1;
if (page < 0)
return;
var guilds = NadekoBot.Client.GetGuilds().OrderBy(g => g.Name).Skip((page - 1) * 15).Take(15);
if (!guilds.Any())
{
await channel.SendMessageAsync("`No servers found on that page.`").ConfigureAwait(false);
return;
}
await channel.SendMessageAsync(String.Join("\n", guilds.Select(g => $"`Name:` {g.Name} `Id:` {g.Id} `Members:` {g.GetUsers().Count} `OwnerId:`{g.OwnerId}"))).ConfigureAwait(false);
}
//[NadekoCommand, Usage, Description, Aliases]
//[RequireContext(ContextType.Guild)]
//public async Task TextToImage(IUserMessage msg, [Remainder] string arg)
//{
// var channel = (ITextChannel)msg.Channel;
// const string bgName = "xbiy3";
// if (string.IsNullOrWhiteSpace(arg))
// return;
// using (var http = new HttpClient())
// {
// http.AddFakeHeaders();
// http.DefaultRequestHeaders.Add("Host", "www.tagsmaker.com");
// http.DefaultRequestHeaders.Add("Referer", "http://www.tagsmaker.com/");
// http.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
// http.DefaultRequestHeaders.Add("Alt-Used", "www.tagsmaker.com:443");
// var res = await http.GetAsync($"http://www.tagsmaker.com/tagsmaker.php?background_name=0011&tag_text={arg}&font_name=applejuiced&text_color=white&text_size=48&text_alignment=middle").ConfigureAwait(false);
// var img = res.RequestMessage.RequestUri.Segments[1].Replace("image-", "").Replace("tag-", "");
// var imgStream = await http.GetStreamAsync($"http://www.tagsmaker.com/upload/www.tagsmaker.com_{ img.ToString() }.png");
// var ms = new MemoryStream();
// await imgStream.CopyToAsync(ms).ConfigureAwait(false);
// ms.Position = 0;
// await channel.SendFileAsync(ms, arg+".png", "Provided by www.tagsmaker.com").ConfigureAwait(false);
// }
//}
}
}

View File

@ -19,6 +19,7 @@ using Module = Discord.Commands.Module;
using NadekoBot.TypeReaders;
using System.Collections.Concurrent;
using NadekoBot.Modules.Music;
using NadekoBot.Services.Database.Models;
namespace NadekoBot
{
@ -38,6 +39,16 @@ namespace NadekoBot
public static ConcurrentDictionary<string, string> ModulePrefixes { get; private set; }
public static bool Ready { get; private set; }
public static IEnumerable<GuildConfig> AllGuildConfigs { get; }
static NadekoBot()
{
using (var uow = DbHandler.UnitOfWork())
{
AllGuildConfigs = uow.GuildConfigs.GetAll();
}
}
public async Task RunAsync(string[] args)
{
SetupLogger();

View File

@ -464,6 +464,33 @@ namespace NadekoBot.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to atfbooru atf.
/// </summary>
public static string atfbooru_cmd {
get {
return ResourceManager.GetString("atfbooru_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Shows a random hentai image from atfbooru with a given tag. Tag is optional but preferred..
/// </summary>
public static string atfbooru_desc {
get {
return ResourceManager.GetString("atfbooru_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}atfbooru yuri+kissing`.
/// </summary>
public static string atfbooru_usage {
get {
return ResourceManager.GetString("atfbooru_usage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to autoassignrole aar.
/// </summary>
@ -519,7 +546,61 @@ namespace NadekoBot.Resources {
}
/// <summary>
/// Looks up a localized string similar to av avatar.
/// Looks up a localized string similar to autotranslang atl.
/// </summary>
public static string autotranslang_cmd {
get {
return ResourceManager.GetString("autotranslang_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}atl en&gt;fr`.
/// </summary>
public static string autotranslang_desc {
get {
return ResourceManager.GetString("autotranslang_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Sets your source and target language to be used with `{0}at`. Specify no arguments to remove previously set value..
/// </summary>
public static string autotranslang_usage {
get {
return ResourceManager.GetString("autotranslang_usage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to autotrans at.
/// </summary>
public static string autotranslate_cmd {
get {
return ResourceManager.GetString("autotranslate_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Starts automatic translation of all messages by users who set their `{0}atl` in this channel. You can set &quot;del&quot; argument to automatically delete all translated user messages..
/// </summary>
public static string autotranslate_desc {
get {
return ResourceManager.GetString("autotranslate_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}at` or `{0}at del`.
/// </summary>
public static string autotranslate_usage {
get {
return ResourceManager.GetString("autotranslate_usage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to avatar av.
/// </summary>
public static string avatar_cmd {
get {
@ -1463,6 +1544,33 @@ namespace NadekoBot.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to cleverbot.
/// </summary>
public static string cleverbot_cmd {
get {
return ResourceManager.GetString("cleverbot_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Toggles cleverbot session. When enabled, the bot will reply to messages starting with bot mention in the server. Custom reactions starting with %mention% won&apos;t work if cleverbot is enabled..
/// </summary>
public static string cleverbot_desc {
get {
return ResourceManager.GetString("cleverbot_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}cleverbot`.
/// </summary>
public static string cleverbot_usage {
get {
return ResourceManager.GetString("cleverbot_usage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to cmdcooldown cmdcd.
/// </summary>
@ -2769,7 +2877,7 @@ namespace NadekoBot.Resources {
}
/// <summary>
/// Looks up a localized string similar to Shows a 2 random images (from gelbooru and danbooru) with a given tag. Tag is optional but preferred. Only 1 tag allowed..
/// Looks up a localized string similar to Shows a hentai image from a random website (gelbooru or danbooru or konachan or atfbooru) with a given tag. Tag is optional but preferred. Only 1 tag allowed..
/// </summary>
public static string hentai_desc {
get {
@ -2786,6 +2894,33 @@ namespace NadekoBot.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to hentaibomb.
/// </summary>
public static string hentaibomb_cmd {
get {
return ResourceManager.GetString("hentaibomb_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Shows a total 4 images (from gelbooru, danbooru, konachan and atfbooru). Tag is optional but preferred..
/// </summary>
public static string hentaibomb_desc {
get {
return ResourceManager.GetString("hentaibomb_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}hentaibomb yuri`.
/// </summary>
public static string hentaibomb_usage {
get {
return ResourceManager.GetString("hentaibomb_usage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to hgit.
/// </summary>
@ -3093,7 +3228,7 @@ namespace NadekoBot.Resources {
}
/// <summary>
/// Looks up a localized string similar to Shows a random hentai image from konachan with a given tag. Tag is optional but preferred. (multiple tags are appended with +).
/// Looks up a localized string similar to Shows a random hentai image from konachan with a given tag. Tag is optional but preferred..
/// </summary>
public static string konachan_desc {
get {
@ -3353,6 +3488,60 @@ namespace NadekoBot.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to listquotes liqu.
/// </summary>
public static string listquotes_cmd {
get {
return ResourceManager.GetString("listquotes_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}liqu` or `{0}liqu 3`.
/// </summary>
public static string listquotes_desc {
get {
return ResourceManager.GetString("listquotes_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Lists all quotes on the server ordered alphabetically. 15 Per page..
/// </summary>
public static string listquotes_usage {
get {
return ResourceManager.GetString("listquotes_usage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to listservers.
/// </summary>
public static string listservers_cmd {
get {
return ResourceManager.GetString("listservers_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Lists servers the bot is on with some basic info. 15 per page..
/// </summary>
public static string listservers_desc {
get {
return ResourceManager.GetString("listservers_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}listservers 3`.
/// </summary>
public static string listservers_usage {
get {
return ResourceManager.GetString("listservers_usage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to liststreams ls.
/// </summary>
@ -3758,6 +3947,60 @@ namespace NadekoBot.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to minecraftping mcping.
/// </summary>
public static string mcping_cmd {
get {
return ResourceManager.GetString("mcping_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Pings a minecraft server..
/// </summary>
public static string mcping_desc {
get {
return ResourceManager.GetString("mcping_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}mcping 127.0.0.1:25565`.
/// </summary>
public static string mcping_usage {
get {
return ResourceManager.GetString("mcping_usage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to minecraftquery mcq.
/// </summary>
public static string mcq_cmd {
get {
return ResourceManager.GetString("mcq_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Finds information about a minecraft server..
/// </summary>
public static string mcq_desc {
get {
return ResourceManager.GetString("mcq_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}mcq server:ip`.
/// </summary>
public static string mcq_usage {
get {
return ResourceManager.GetString("mcq_usage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to memegen.
/// </summary>
@ -4011,7 +4254,7 @@ namespace NadekoBot.Resources {
}
/// <summary>
/// Looks up a localized string similar to Goes to the next song in the queue. You have to be in the same voice channel as the bot..
/// Looks up a localized string similar to Goes to the next song in the queue. You have to be in the same voice channel as the bot. You can skip multiple songs, but in that case songs will not be requeued if {0}rcs or {0}rpl is enabled..
/// </summary>
public static string next_desc {
get {
@ -4020,7 +4263,7 @@ namespace NadekoBot.Resources {
}
/// <summary>
/// Looks up a localized string similar to `{0}n`.
/// Looks up a localized string similar to `{0}n` or `{0}n 5`.
/// </summary>
public static string next_usage {
get {
@ -4776,7 +5019,7 @@ namespace NadekoBot.Resources {
}
/// <summary>
/// Looks up a localized string similar to `{0}remindtemplate %user%, you gotta do %message%!`.
/// Looks up a localized string similar to `{0}remindtemplate %user%, do %message%!`.
/// </summary>
public static string remindtemplate_usage {
get {
@ -5793,7 +6036,7 @@ namespace NadekoBot.Resources {
}
/// <summary>
/// Looks up a localized string similar to Sets a name of the role which will be assigned to people who should be muted. Default is nadeko-mute. After specifying this role, restart commands which use mute as punishment..
/// Looks up a localized string similar to Sets a name of the role which will be assigned to people who should be muted. Default is nadeko-mute..
/// </summary>
public static string setmuterole_desc {
get {
@ -5883,7 +6126,7 @@ namespace NadekoBot.Resources {
}
/// <summary>
/// Looks up a localized string similar to `{0}setstream https://www.twitch.tv/masterkwoth Developing Nakedo`.
/// Looks up a localized string similar to `{0}setstream TWITCHLINK Hello`.
/// </summary>
public static string setstream_usage {
get {
@ -5918,6 +6161,33 @@ namespace NadekoBot.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to shorten.
/// </summary>
public static string shorten_cmd {
get {
return ResourceManager.GetString("shorten_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Attempts to shorten an URL, if it fails, returns the input URL..
/// </summary>
public static string shorten_desc {
get {
return ResourceManager.GetString("shorten_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}shorten https://google.com`.
/// </summary>
public static string shorten_usage {
get {
return ResourceManager.GetString("shorten_usage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to showcustreact scr.
/// </summary>
@ -6620,6 +6890,60 @@ namespace NadekoBot.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to typedel.
/// </summary>
public static string typedel_cmd {
get {
return ResourceManager.GetString("typedel_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Deletes a typing article given the ID..
/// </summary>
public static string typedel_desc {
get {
return ResourceManager.GetString("typedel_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}typedel 3`.
/// </summary>
public static string typedel_usage {
get {
return ResourceManager.GetString("typedel_usage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to typelist.
/// </summary>
public static string typelist_cmd {
get {
return ResourceManager.GetString("typelist_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Lists added typing articles with their IDs. 15 per page..
/// </summary>
public static string typelist_desc {
get {
return ResourceManager.GetString("typelist_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}typelist` or `{0}typelist 3`.
/// </summary>
public static string typelist_usage {
get {
return ResourceManager.GetString("typelist_usage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to typestart.
/// </summary>
@ -7241,6 +7565,33 @@ namespace NadekoBot.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to wikia.
/// </summary>
public static string wikia_cmd {
get {
return ResourceManager.GetString("wikia_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Gives you back a wikia link.
/// </summary>
public static string wikia_desc {
get {
return ResourceManager.GetString("wikia_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}wikia mtg Vigilance` or `{0}wikia mlp Dashy`.
/// </summary>
public static string wikia_usage {
get {
return ResourceManager.GetString("wikia_usage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to wowjoke.
/// </summary>

View File

@ -790,7 +790,7 @@
<value>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.</value>
</data>
<data name="remindtemplate_usage" xml:space="preserve">
<value>`{0}remindtemplate %user%, you gotta do %message%!`</value>
<value>`{0}remindtemplate %user%, do %message%!`</value>
</data>
<data name="serverinfo_cmd" xml:space="preserve">
<value>serverinfo sinfo</value>
@ -1426,10 +1426,10 @@
<value>next n</value>
</data>
<data name="next_desc" xml:space="preserve">
<value>Goes to the next song in the queue. You have to be in the same voice channel as the bot.</value>
<value>Goes to the next song in the queue. You have to be in the same voice channel as the bot. You can skip multiple songs, but in that case songs will not be requeued if {0}rcs or {0}rpl is enabled.</value>
</data>
<data name="next_usage" xml:space="preserve">
<value>`{0}n`</value>
<value>`{0}n` or `{0}n 5`</value>
</data>
<data name="stop_cmd" xml:space="preserve">
<value>stop s</value>
@ -2089,7 +2089,7 @@
<value>`{0}videocall "@SomeGuy"`</value>
</data>
<data name="avatar_cmd" xml:space="preserve">
<value>av avatar</value>
<value>avatar av</value>
</data>
<data name="avatar_desc" xml:space="preserve">
<value>Shows a mentioned person's avatar.</value>
@ -2101,7 +2101,7 @@
<value>hentai</value>
</data>
<data name="hentai_desc" xml:space="preserve">
<value>Shows a 2 random images (from gelbooru and danbooru) with a given tag. Tag is optional but preferred. Only 1 tag allowed.</value>
<value>Shows a hentai image from a random website (gelbooru or danbooru or konachan or atfbooru) with a given tag. Tag is optional but preferred. Only 1 tag allowed.</value>
</data>
<data name="hentai_usage" xml:space="preserve">
<value>`{0}hentai yuri`</value>
@ -2115,6 +2115,15 @@
<data name="danbooru_usage" xml:space="preserve">
<value>`{0}danbooru yuri+kissing`</value>
</data>
<data name="atfbooru_cmd" xml:space="preserve">
<value>atfbooru atf</value>
</data>
<data name="atfbooru_desc" xml:space="preserve">
<value>Shows a random hentai image from atfbooru with a given tag. Tag is optional but preferred.</value>
</data>
<data name="atfbooru_usage" xml:space="preserve">
<value>`{0}atfbooru yuri+kissing`</value>
</data>
<data name="gelbooru_cmd" xml:space="preserve">
<value>gelbooru</value>
</data>
@ -2452,7 +2461,7 @@
<value>konachan</value>
</data>
<data name="konachan_desc" xml:space="preserve">
<value>Shows a random hentai image from konachan with a given tag. Tag is optional but preferred. (multiple tags are appended with +)</value>
<value>Shows a random hentai image from konachan with a given tag. Tag is optional but preferred.</value>
</data>
<data name="konachan_usage" xml:space="preserve">
<value>`{0}konachan yuri`</value>
@ -2461,7 +2470,7 @@
<value>setmuterole</value>
</data>
<data name="setmuterole_desc" xml:space="preserve">
<value>Sets a name of the role which will be assigned to people who should be muted. Default is nadeko-mute. After specifying this role, restart commands which use mute as punishment.</value>
<value>Sets a name of the role which will be assigned to people who should be muted. Default is nadeko-mute.</value>
</data>
<data name="setmuterole_usage" xml:space="preserve">
<value>`{0}setmuterole Silenced`</value>
@ -2482,7 +2491,7 @@
<value>Sets the bots stream. First argument is the twitch link, second argument is stream name.</value>
</data>
<data name="setstream_usage" xml:space="preserve">
<value>`{0}setstream https://www.twitch.tv/masterkwoth Developing Nakedo`</value>
<value>`{0}setstream TWITCHLINK Hello`</value>
</data>
<data name="chatunmute_cmd" xml:space="preserve">
<value>chatunmute</value>
@ -2547,4 +2556,112 @@
<data name="publicpoll_usage" xml:space="preserve">
<value>`{0}ppoll Question?;Answer1;Answ 2;A_3`</value>
</data>
<data name="autotranslang_cmd" xml:space="preserve">
<value>autotranslang atl</value>
</data>
<data name="autotranslang_desc" xml:space="preserve">
<value>`{0}atl en&gt;fr`</value>
</data>
<data name="autotranslang_usage" xml:space="preserve">
<value>Sets your source and target language to be used with `{0}at`. Specify no arguments to remove previously set value.</value>
</data>
<data name="autotranslate_cmd" xml:space="preserve">
<value>autotrans at</value>
</data>
<data name="autotranslate_desc" xml:space="preserve">
<value>Starts automatic translation of all messages by users who set their `{0}atl` in this channel. You can set "del" argument to automatically delete all translated user messages.</value>
</data>
<data name="autotranslate_usage" xml:space="preserve">
<value>`{0}at` or `{0}at del`</value>
</data>
<data name="listquotes_cmd" xml:space="preserve">
<value>listquotes liqu</value>
</data>
<data name="listquotes_desc" xml:space="preserve">
<value>`{0}liqu` or `{0}liqu 3`</value>
</data>
<data name="listquotes_usage" xml:space="preserve">
<value>Lists all quotes on the server ordered alphabetically. 15 Per page.</value>
</data>
<data name="typedel_cmd" xml:space="preserve">
<value>typedel</value>
</data>
<data name="typedel_desc" xml:space="preserve">
<value>Deletes a typing article given the ID.</value>
</data>
<data name="typedel_usage" xml:space="preserve">
<value>`{0}typedel 3`</value>
</data>
<data name="typelist_cmd" xml:space="preserve">
<value>typelist</value>
</data>
<data name="typelist_desc" xml:space="preserve">
<value>Lists added typing articles with their IDs. 15 per page.</value>
</data>
<data name="typelist_usage" xml:space="preserve">
<value>`{0}typelist` or `{0}typelist 3`</value>
</data>
<data name="listservers_cmd" xml:space="preserve">
<value>listservers</value>
</data>
<data name="listservers_desc" xml:space="preserve">
<value>Lists servers the bot is on with some basic info. 15 per page.</value>
</data>
<data name="listservers_usage" xml:space="preserve">
<value>`{0}listservers 3`</value>
</data>
<data name="hentaibomb_cmd" xml:space="preserve">
<value>hentaibomb</value>
</data>
<data name="hentaibomb_desc" xml:space="preserve">
<value>Shows a total 4 images (from gelbooru, danbooru, konachan and atfbooru). Tag is optional but preferred.</value>
</data>
<data name="hentaibomb_usage" xml:space="preserve">
<value>`{0}hentaibomb yuri`</value>
</data>
<data name="cleverbot_cmd" xml:space="preserve">
<value>cleverbot</value>
</data>
<data name="cleverbot_desc" xml:space="preserve">
<value>Toggles cleverbot session. When enabled, the bot will reply to messages starting with bot mention in the server. Custom reactions starting with %mention% won't work if cleverbot is enabled.</value>
</data>
<data name="cleverbot_usage" xml:space="preserve">
<value>`{0}cleverbot`</value>
</data>
<data name="shorten_cmd" xml:space="preserve">
<value>shorten</value>
</data>
<data name="shorten_desc" xml:space="preserve">
<value>Attempts to shorten an URL, if it fails, returns the input URL.</value>
</data>
<data name="shorten_usage" xml:space="preserve">
<value>`{0}shorten https://google.com`</value>
</data>
<data name="mcping_cmd" xml:space="preserve">
<value>minecraftping mcping</value>
</data>
<data name="mcping_desc" xml:space="preserve">
<value>Pings a minecraft server.</value>
</data>
<data name="mcping_usage" xml:space="preserve">
<value>`{0}mcping 127.0.0.1:25565`</value>
</data>
<data name="mcq_cmd" xml:space="preserve">
<value>minecraftquery mcq</value>
</data>
<data name="mcq_desc" xml:space="preserve">
<value>Finds information about a minecraft server.</value>
</data>
<data name="mcq_usage" xml:space="preserve">
<value>`{0}mcq server:ip`</value>
</data>
<data name="wikia_cmd" xml:space="preserve">
<value>wikia</value>
</data>
<data name="wikia_desc" xml:space="preserve">
<value>Gives you back a wikia link</value>
</data>
<data name="wikia_usage" xml:space="preserve">
<value>`{0}wikia mtg Vigilance` or `{0}wikia mlp Dashy`</value>
</data>
</root>

View File

@ -0,0 +1,25 @@
/*
ChatterBotAPI
Copyright (C) 2011 pierredavidbelanger@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Services.CleverBotApi
{
public interface ChatterBot
{
ChatterBotSession CreateSession();
}
}

View File

@ -0,0 +1,45 @@
using System;
/*
ChatterBotAPI
Copyright (C) 2011 pierredavidbelanger@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Services.CleverBotApi
{
public class ChatterBotFactory
{
public static ChatterBot Create(ChatterBotType type)
{
return Create(type, null);
}
public static ChatterBot Create(ChatterBotType type, object arg)
{
switch (type)
{
case ChatterBotType.CLEVERBOT:
return new Cleverbot("http://www.cleverbot.com/", "http://www.cleverbot.com/webservicemin?uc=165", 26);
case ChatterBotType.JABBERWACKY:
return new Cleverbot("http://jabberwacky.com", "http://jabberwacky.com/webservicemin", 20);
case ChatterBotType.PANDORABOTS:
if (arg == null) throw new ArgumentException("PANDORABOTS needs a botid arg", nameof(arg));
return new Pandorabots(arg.ToString());
}
return null;
}
}
}

View File

@ -0,0 +1,28 @@
/*
ChatterBotAPI
Copyright (C) 2011 pierredavidbelanger@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System.Threading.Tasks;
namespace Services.CleverBotApi
{
public interface ChatterBotSession
{
Task<ChatterBotThought> Think(ChatterBotThought thought);
Task<string> Think(string text);
}
}

View File

@ -0,0 +1,26 @@
/*
ChatterBotAPI
Copyright (C) 2011 pierredavidbelanger@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Services.CleverBotApi
{
public class ChatterBotThought
{
public string[] Emotions { get; set; }
public string Text { get; set; }
}
}

View File

@ -0,0 +1,27 @@
/*
ChatterBotAPI
Copyright (C) 2011 pierredavidbelanger@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Services.CleverBotApi
{
public enum ChatterBotType
{
CLEVERBOT,
JABBERWACKY,
PANDORABOTS
}
}

View File

@ -0,0 +1,116 @@
using System.Collections.Generic;
using System.Net;
using System.Threading.Tasks;
/*
ChatterBotAPI
Copyright (C) 2011 pierredavidbelanger@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Services.CleverBotApi
{
internal class Cleverbot : ChatterBot
{
private readonly int endIndex;
private readonly string baseUrl;
private readonly string url;
public Cleverbot(string baseUrl, string url, int endIndex)
{
this.baseUrl = baseUrl;
this.url = url;
this.endIndex = endIndex;
}
public ChatterBotSession CreateSession()
{
return new CleverbotSession(baseUrl, url, endIndex);
}
}
internal class CleverbotSession : ChatterBotSession
{
private readonly int endIndex;
private readonly string url;
private readonly IDictionary<string, string> vars;
private readonly CookieCollection cookies;
public CleverbotSession(string baseUrl, string url, int endIndex)
{
this.url = url;
this.endIndex = endIndex;
vars = new Dictionary<string, string>();
//vars["start"] = "y";
vars["stimulus"] = "";
vars["islearning"] = "1";
vars["icognoid"] = "wsf";
//vars["fno"] = "0";
//vars["sub"] = "Say";
//vars["cleanslate"] = "false";
cookies = Utils.GetCookies(baseUrl);
}
public async Task<ChatterBotThought> Think(ChatterBotThought thought)
{
vars["stimulus"] = thought.Text;
var formData = Utils.ParametersToWWWFormURLEncoded(vars);
var formDataToDigest = formData.Substring(9, endIndex);
var formDataDigest = Utils.MD5(formDataToDigest);
vars["icognocheck"] = formDataDigest;
var response = await Utils.Post(url, vars, cookies).ConfigureAwait(false);
var responseValues = response.Split('\r');
//vars[""] = Utils.StringAtIndex(responseValues, 0); ??
vars["sessionid"] = Utils.StringAtIndex(responseValues, 1);
vars["logurl"] = Utils.StringAtIndex(responseValues, 2);
vars["vText8"] = Utils.StringAtIndex(responseValues, 3);
vars["vText7"] = Utils.StringAtIndex(responseValues, 4);
vars["vText6"] = Utils.StringAtIndex(responseValues, 5);
vars["vText5"] = Utils.StringAtIndex(responseValues, 6);
vars["vText4"] = Utils.StringAtIndex(responseValues, 7);
vars["vText3"] = Utils.StringAtIndex(responseValues, 8);
vars["vText2"] = Utils.StringAtIndex(responseValues, 9);
vars["prevref"] = Utils.StringAtIndex(responseValues, 10);
//vars[""] = Utils.StringAtIndex(responseValues, 11); ??
// vars["emotionalhistory"] = Utils.StringAtIndex(responseValues, 12);
// vars["ttsLocMP3"] = Utils.StringAtIndex(responseValues, 13);
// vars["ttsLocTXT"] = Utils.StringAtIndex(responseValues, 14);
// vars["ttsLocTXT3"] = Utils.StringAtIndex(responseValues, 15);
// vars["ttsText"] = Utils.StringAtIndex(responseValues, 16);
// vars["lineRef"] = Utils.StringAtIndex(responseValues, 17);
// vars["lineURL"] = Utils.StringAtIndex(responseValues, 18);
// vars["linePOST"] = Utils.StringAtIndex(responseValues, 19);
// vars["lineChoices"] = Utils.StringAtIndex(responseValues, 20);
// vars["lineChoicesAbbrev"] = Utils.StringAtIndex(responseValues, 21);
// vars["typingData"] = Utils.StringAtIndex(responseValues, 22);
// vars["divert"] = Utils.StringAtIndex(responseValues, 23);
var responseThought = new ChatterBotThought();
responseThought.Text = Utils.StringAtIndex(responseValues, 0);
return responseThought;
}
public async Task<string> Think(string text)
{
return (await Think(new ChatterBotThought {Text = text}).ConfigureAwait(false)).Text;
}
}
}

View File

@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
/*
ChatterBotAPI
Copyright (C) 2011 pierredavidbelanger@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Services.CleverBotApi
{
internal class Pandorabots : ChatterBot
{
private readonly string botid;
public Pandorabots(string botid)
{
this.botid = botid;
}
public ChatterBotSession CreateSession()
{
return new PandorabotsSession(botid);
}
}
internal class PandorabotsSession : ChatterBotSession
{
private readonly IDictionary<string, string> vars;
public PandorabotsSession(string botid)
{
vars = new Dictionary<string, string>();
vars["botid"] = botid;
vars["custid"] = Guid.NewGuid().ToString();
}
public async Task<ChatterBotThought> Think(ChatterBotThought thought)
{
vars["input"] = thought.Text;
var response = await Utils.Post("http://www.pandorabots.com/pandora/talk-xml", vars, null).ConfigureAwait(false);
var responseThought = new ChatterBotThought();
responseThought.Text = Utils.XPathSearch(response, "//result/that/text()");
return responseThought;
}
public async Task<string> Think(string text)
{
return (await Think(new ChatterBotThought {Text = text}).ConfigureAwait(false)).Text;
}
}
}

View File

@ -0,0 +1,148 @@
using NadekoBot.Extensions;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Xml.XPath;
/*
ChatterBotAPI
Copyright (C) 2011 pierredavidbelanger@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Services.CleverBotApi
{
internal static class Utils
{
public static string ParametersToWWWFormURLEncoded(IDictionary<string, string> parameters)
{
string wwwFormUrlEncoded = null;
foreach (var parameterKey in parameters.Keys)
{
var parameterValue = parameters[parameterKey];
var parameter = string.Format("{0}={1}", System.Uri.EscapeDataString(parameterKey), System.Uri.EscapeDataString(parameterValue));
if (wwwFormUrlEncoded == null)
{
wwwFormUrlEncoded = parameter;
}
else
{
wwwFormUrlEncoded = string.Format("{0}&{1}", wwwFormUrlEncoded, parameter);
}
}
return wwwFormUrlEncoded;
}
public static string MD5(string input)
{
// step 1, calculate MD5 hash from input
var md5 = System.Security.Cryptography.MD5.Create();
var inputBytes = Encoding.ASCII.GetBytes(input);
var hash = md5.ComputeHash(inputBytes);
// step 2, convert byte array to hex string
var sb = new StringBuilder();
for (var i = 0; i < hash.Length; i++)
{
sb.Append(hash[i].ToString("X2"));
}
return sb.ToString();
}
public static CookieCollection GetCookies(string url)
{
CookieContainer container = new CookieContainer();
HttpResponseMessage res;
using (var handler = new HttpClientHandler() { CookieContainer = container })
using (var http = new HttpClient(handler))
{
http.AddFakeHeaders();
http.DefaultRequestHeaders.Add("ContentType", "text/html");
res = http.GetAsync(url).GetAwaiter().GetResult();
}
var response = res.Content.ReadAsStringAsync().GetAwaiter().GetResult();
return container.GetCookies(res.RequestMessage.RequestUri);
}
public static async Task<string> Post(string url, IDictionary<string, string> parameters, CookieCollection cookies)
{
var postData = ParametersToWWWFormURLEncoded(parameters);
var postDataBytes = Encoding.ASCII.GetBytes(postData);
var request = (HttpWebRequest)WebRequest.Create(url);
if (cookies != null)
{
var container = new CookieContainer();
container.Add(new Uri(url), cookies);
request.CookieContainer = container;
}
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
using (var outputStream = await request.GetRequestStreamAsync())
{
outputStream.Write(postDataBytes, 0, postDataBytes.Length);
outputStream.Flush();
var response = (HttpWebResponse)await request.GetResponseAsync();
using (var responseStreamReader = new StreamReader(response.GetResponseStream()))
{
return responseStreamReader.ReadToEnd().Trim();
}
}
//HttpClientHandler handler;
//var uri = new Uri(url);
//if (cookies == null)
// handler = new HttpClientHandler();
//else
//{
// var cookieContainer = new CookieContainer();
// cookieContainer.Add(uri, cookies);
// handler = new HttpClientHandler() { CookieContainer = cookieContainer };
//}
//using (handler)
//using (var http = new HttpClient(handler))
//{
// var res = await http.PostAsync(url, new FormUrlEncodedContent(parameters)).ConfigureAwait(false);
// return await res.Content.ReadAsStringAsync().ConfigureAwait(false);
//}
}
public static string XPathSearch(string input, string expression)
{
var document = new XPathDocument(new MemoryStream(Encoding.ASCII.GetBytes(input)));
var navigator = document.CreateNavigator();
return navigator.SelectSingleNode(expression).Value.Trim();
}
public static string StringAtIndex(string[] strings, int index)
{
if (index >= strings.Length) return "";
return strings[index];
}
}
}

View File

@ -18,6 +18,8 @@ using static NadekoBot.Modules.Permissions.Permissions;
using System.Collections.Concurrent;
using NadekoBot.Modules.Help;
using static NadekoBot.Modules.Administration.Administration;
using NadekoBot.Modules.CustomReactions;
using NadekoBot.Modules.Games;
namespace NadekoBot.Services
{
@ -110,6 +112,7 @@ namespace NadekoBot.Services
_log.Warn("I do not have permission to filter words in channel with id " + usrMsg.Channel.Id, ex);
}
}
}
BlacklistItem blacklistedItem;
if ((blacklistedItem = Permissions.BlacklistCommands.BlacklistedItems.FirstOrDefault(bi =>
@ -119,7 +122,27 @@ namespace NadekoBot.Services
{
return;
}
try
{
var cleverbotExecuted = await Games.CleverBotCommands.TryAsk(usrMsg);
if (cleverbotExecuted)
return;
}
catch (Exception ex) { _log.Warn(ex, "Error in cleverbot"); }
try
{
// maybe this message is a custom reaction
var crExecuted = await CustomReactions.TryExecuteCustomReaction(usrMsg).ConfigureAwait(false);
//if it was, don't execute the command
if (crExecuted)
return;
}
catch { }
var throwaway = Task.Run(async () =>
{
var sw = new Stopwatch();

View File

@ -59,6 +59,7 @@ namespace NadekoBot.Services.Database.Models
public HashSet<FilterChannelId> FilterWordsChannelIds { get; set; } = new HashSet<FilterChannelId>();
public string MuteRoleName { get; set; }
public bool CleverbotEnabled { get; set; }
}
public class FilterChannelId :DbEntity

View File

@ -15,5 +15,6 @@ namespace NadekoBot.Services.Database.Repositories
IEnumerable<GuildConfig> PermissionsForAll();
GuildConfig SetNewRootPermission(ulong guildId, Permission p);
IEnumerable<FollowedStream> GetAllFollowedStreams();
void SetCleverbotEnabled(ulong id, bool cleverbotEnabled);
}
}

View File

@ -11,5 +11,6 @@ namespace NadekoBot.Services.Database.Repositories
{
IEnumerable<Quote> GetAllQuotesByKeyword(ulong guildId, string keyword);
Task<Quote> GetRandomQuoteByKeywordAsync(ulong guildId, string keyword);
IEnumerable<Quote> GetGroup(int skip, int take);
}
}

View File

@ -121,5 +121,15 @@ namespace NadekoBot.Services.Database.Repositories.Impl
data.RootPermission = p;
return data;
}
public void SetCleverbotEnabled(ulong id, bool cleverbotEnabled)
{
var conf = _set.FirstOrDefault(gc => gc.GuildId == id);
if (conf == null)
return;
conf.CleverbotEnabled = cleverbotEnabled;
}
}
}

View File

@ -18,6 +18,9 @@ namespace NadekoBot.Services.Database.Repositories.Impl
public IEnumerable<Quote> GetAllQuotesByKeyword(ulong guildId, string keyword) =>
_set.Where(q => q.GuildId == guildId && q.Keyword == keyword);
public IEnumerable<Quote> GetGroup(int skip, int take) =>
_set.OrderBy(q => q.Keyword).Skip(skip).Take(take).ToList();
public Task<Quote> GetRandomQuoteByKeywordAsync(ulong guildId, string keyword)
{
var rng = new NadekoRandom();

View File

@ -19,18 +19,19 @@ namespace NadekoBot.Services
static DbHandler() { }
private DbHandler() {
switch (NadekoBot.Credentials.Db.Type.ToUpperInvariant())
{
case "SQLITE":
dbType = typeof(NadekoSqliteContext);
break;
//case "SQLSERVER":
// dbType = typeof(NadekoSqlServerContext);
//switch (NadekoBot.Credentials.Db.Type.ToUpperInvariant())
//{
// case "SQLITE":
// dbType = typeof(NadekoSqliteContext);
// break;
// //case "SQLSERVER":
// // dbType = typeof(NadekoSqlServerContext);
// // break;
// default:
// break;
default:
break;
}
//}
}
public NadekoContext GetDbContext() =>

View File

@ -91,6 +91,10 @@ namespace NadekoBot.Services.Impl
{
if (string.IsNullOrWhiteSpace(url))
throw new ArgumentNullException(nameof(url));
if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.GoogleApiKey))
return url;
try
{
var response = await sh.Url.Insert(new Url { LongUrl = url }).ExecuteAsync();

View File

@ -19,7 +19,7 @@ namespace NadekoBot.Services.Impl
private DateTime started;
private int commandsRan = 0;
public const string BotVersion = "1.0-rc1";
public const string BotVersion = "1.0-rc2";
public string Heap => Math.Round((double)GC.GetTotalMemory(false) / 1.MiB(), 2).ToString();

View File

@ -11533,7 +11533,7 @@
},
{
"Question": "What is the capital of the Canadian province of British Columbia",
"Answer": "victor1a"
"Answer": "victoria"
},
{
"Question": "What is the capital of the US state of Delaware",

View File

@ -7,7 +7,7 @@
"emitEntryPoint": true,
"allowUnsafe": true,
"compile": {
"exclude": [ "data" ]
"exclude": [ "data", "credentials.json", "credentials_example.json" ]
},
"copyToOutput": {
"include": [ "data" ],
@ -41,7 +41,8 @@
},
"Discord.Net": {
"target": "project"
}
},
"System.Xml.XPath": "4.0.1"
},
"tools": {
"Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final"