diff --git a/NadekoBot.sln b/NadekoBot.sln index e844576d..7b8981b8 100644 --- a/NadekoBot.sln +++ b/NadekoBot.sln @@ -16,8 +16,6 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net", "discord.net\ EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net.Commands", "discord.net\src\Discord.Net.Commands\Discord.Net.Commands.xproj", "{078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "tests", "src\tests\tests.xproj", "{14CBADA0-971C-44E3-B331-C7D01DD74F0B}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -43,18 +41,11 @@ Global {078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.GlobalNadeko|Any CPU.Build.0 = GlobalNadeko|Any CPU {078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.Release|Any CPU.ActiveCfg = Release|Any CPU {078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.Release|Any CPU.Build.0 = Release|Any CPU - {14CBADA0-971C-44E3-B331-C7D01DD74F0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {14CBADA0-971C-44E3-B331-C7D01DD74F0B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {14CBADA0-971C-44E3-B331-C7D01DD74F0B}.GlobalNadeko|Any CPU.ActiveCfg = GlobalNadeko|Any CPU - {14CBADA0-971C-44E3-B331-C7D01DD74F0B}.GlobalNadeko|Any CPU.Build.0 = GlobalNadeko|Any CPU - {14CBADA0-971C-44E3-B331-C7D01DD74F0B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {14CBADA0-971C-44E3-B331-C7D01DD74F0B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {45EC1473-C678-4857-A544-07DFE0D0B478} = {04929013-5BAB-42B0-B9B2-8F2BB8F16AF2} - {14CBADA0-971C-44E3-B331-C7D01DD74F0B} = {04929013-5BAB-42B0-B9B2-8F2BB8F16AF2} EndGlobalSection EndGlobal diff --git a/docs/Commands List.md b/docs/Commands List.md index 70dd28a0..e889dcac 100644 --- a/docs/Commands List.md +++ b/docs/Commands List.md @@ -34,7 +34,7 @@ Command and aliases | Description | Usage `.savechat` | Saves a number of messages to a text file and sends it to you. | `.savechat 150` **Bot owner only.** `.mentionrole` `.menro` | Mentions every person from the provided role or roles (separated by a ',') on this server. Requires you to have mention everyone permission. | `.menro RoleName` **Requires MentionEveryone server permission.** `.donators` | List of lovely people who donated to keep this project alive. | `.donators` -`.donadd` | Add a donator to the database. **Kwoth Only** | `.donadd Donate Amount` **Bot owner only.** +`.donadd` | Add a donator to the database. | `.donadd Donate Amount` **Bot owner only.** `.autoassignrole` `.aar` | Automaticaly assigns a specified role to every user who joins the server. | `.aar` to disable, `.aar Role Name` to enable **Requires ManageRoles server permission.** `.scsc` | Starts an instance of cross server channel. You will get a token as a DM that other people will use to tune in to the same instance. | `.scsc` **Bot owner only.** `.jcsc` | Joins current channel to an instance of cross server channel using the token. | `.jcsc TokenHere` **Requires ManageServer server permission.** @@ -53,7 +53,7 @@ Command and aliases | Description | Usage `.listplaying` `.lipl` | Lists all playing statuses with their corresponding number. | `.lipl` **Bot owner only.** `.removeplaying` `.rmpl` `.repl` | Removes a playing string on a given number. | `.rmpl` **Bot owner only.** `.slowmode` | Toggles slow mode. When ON, users will be able to send only 1 message every 5 seconds. | `.slowmode` **Requires ManageMessages server permission.** -`.asar` | Adds a role, or list of roles separated by whitespace(use quotations for multiword roles) to the list of self-assignable roles. | `.asar Gamer` **Requires ManageRoles server permission.** +`.asar` | Adds a role to the list of self-assignable roles. | `.asar Gamer` **Requires ManageRoles server permission.** `.rsar` | Removes a specified role from the list of self-assignable roles. | `.rsar` **Requires ManageRoles server permission.** `.lsar` | Lists all self-assignable roles. | `.lsar` `.togglexclsar` `.tesar` | Toggles whether the self-assigned roles are exclusive. (So that any person can have only one of the self assignable roles) | `.tesar` **Requires ManageRoles server permission.** @@ -78,38 +78,39 @@ Command and aliases | Description | Usage `,startwar` `,sw` | Starts a war with a given number. | `,sw 15` `,listwar` `,lw` | Shows the active war claims by a number. Shows all wars in a short way if no number is specified. | `,lw [war_number] or ,lw` `,claim` `,call` `,c` | Claims a certain base from a certain war. You can supply a name in the third optional argument to claim in someone else's place. | `,call [war_number] [base_number] [optional_other_name]` -`,claimfinish1` `,cf1` | Finish your claim with 1 star if you destroyed a base. First argument is the war number, optional second argument finishes for someone else. | `,cf1 2 SomeGirl` -`,claimfinish2` `,cf2` | Finish your claim with 2 stars if you destroyed a base. First argument is the war number, optional second argument finishes for someone else. | `,cf2 1 SomeGuy` -`,claimfinish` `,cf` | Finish your claim with 3 stars if you destroyed a base. First argument is the war number, optional second argument finishes for someone else. | `,cf 1 Someone` +`,claimfinish1` `,cf1` | Finish your claim with 1 star if you destroyed a base. First argument is the war number, optional second argument is a base number if you want to finish for someone else. | `,cf1 1` or `,cf1 1 5` +`,claimfinish2` `,cf2` | Finish your claim with 2 stars if you destroyed a base. First argument is the war number, optional second argument is a base number if you want to finish for someone else. | `,cf2 1` or `,cf2 1 5` +`,claimfinish` `,cf` | Finish your claim with 3 stars if you destroyed a base. First argument is the war number, optional second argument is a base number if you want to finish for someone else. | `,cf 1` or `,cf 1 5` `,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]` ### CustomReactions Command and aliases | Description | Usage ----------------|--------------|------- -`#addcustreact` `#acr` | Add a custom reaction with a trigger and a response. Running this command in server requires Administration permission. Running this command in DM is Bot Owner only and adds a new global custom reaction. Guide here: | `.acr "hello" Hi there %user%` -`#listcustreact` `#lcr` | Lists global or server custom reactions (15 commands per page). Running the command in DM will list global custom reactions, while running it in server will list that server's custom reactions. | `.lcr 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` +`.addcustreact` `.acr` | Add a custom reaction with a trigger and a response. Running this command in server requires Administration permission. Running this command in DM is Bot Owner only and adds a new global custom reaction. Guide here: | `.acr "hello" Hi there %user%` +`.listcustreact` `.lcr` | Lists global or server custom reactions (15 commands per page). Running the command in DM will list global custom reactions, while running it in server will list that server's custom reactions. | `.lcr 1` +`.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` ### Gambling Command and aliases | Description | Usage ----------------|--------------|------- -`xraffle` | Prints a name and ID of a random user from the online list from the (optional) role. | `$raffle` or `$raffle RoleName` -`xcash` `x$$` | Check how much NadekoFlowers a person has. (Defaults to yourself) | `$$$` or `$$$ @SomeGuy` -`xgive` | Give someone a certain amount of currency. | `$give 1 "@SomeGuy"` -`xaward` | Awards someone a certain amount of currency. | `$award 100 @person` **Bot owner only.** -`xtake` | Takes a certain amount of flowers from someone. | `$take 1 "@someguy"` **Bot owner only.** -`xbetroll` `xbr` | Bets a certain amount of NadekoFlowers and rolls a dice. Rolling over 66 yields x2 flowers, over 90 - x3 and 100 x10. | `$br 5` -`xleaderboard` `xlb` | Displays bot currency leaderboard. | `$lb` -`xrace` | Starts a new animal race. | `$race` -`xjoinrace` `xjr` | Joins a new race. You can specify an amount of flowers for betting (optional). You will get YourBet*(participants-1) back if you win. | `$jr` or `$jr 5` -`xroll` | Rolls 0-100. If you supply a number [x] it rolls up to 30 normal dice. If you split 2 numbers with letter d (xdy) it will roll x dice from 1 to y. | `$roll` or `$roll 7` or `$roll 3d5` -`xrolluo` | Rolls X normal dice (up to 30) unordered. If you split 2 numbers with letter d (xdy) it will roll x dice from 1 to y. | `$rolluo` or `$rolluo 7` or `$rolluo 3d5` -`xnroll` | Rolls in a given range. | `$nroll 5` (rolls 0-5) or `$nroll 5-15` -`xdraw` | Draws a card from the deck.If you supply number X, she draws up to 5 cards from the deck. | `$draw` or `$draw 5` -`xshuffle` `xsh` | Reshuffles all cards back into the deck. | `$sh` -`xflip` | Flips coin(s) - heads or tails, and shows an image. | `$flip` or `$flip 3` -`xbetflip` `xbf` | Bet to guess will the result be heads or tails. Guessing awards you double flowers you've bet. | `$bf 5 heads` or `$bf 3 t` +`$raffle` | Prints a name and ID of a random user from the online list from the (optional) role. | `$raffle` or `$raffle RoleName` +`$cash` `$$$` | Check how much NadekoFlowers a person has. (Defaults to yourself) | `$$$` or `$$$ @SomeGuy` +`$give` | Give someone a certain amount of currency. | `$give 1 "@SomeGuy"` +`$award` | Awards someone a certain amount of currency. | `$award 100 @person` **Bot owner only.** +`$take` | Takes a certain amount of flowers from someone. | `$take 1 "@someguy"` **Bot owner only.** +`$betroll` `$br` | Bets a certain amount of NadekoFlowers and rolls a dice. Rolling over 66 yields x2 flowers, over 90 - x3 and 100 x10. | `$br 5` +`$leaderboard` `$lb` | Displays bot currency leaderboard. | `$lb` +`$race` | Starts a new animal race. | `$race` +`$joinrace` `$jr` | Joins a new race. You can specify an amount of flowers for betting (optional). You will get YourBet*(participants-1) back if you win. | `$jr` or `$jr 5` +`$roll` | Rolls 0-100. If you supply a number [x] it rolls up to 30 normal dice. If you split 2 numbers with letter d (xdy) it will roll x dice from 1 to y. | `$roll` or `$roll 7` or `$roll 3d5` +`$rolluo` | Rolls X normal dice (up to 30) unordered. If you split 2 numbers with letter d (xdy) it will roll x dice from 1 to y. | `$rolluo` or `$rolluo 7` or `$rolluo 3d5` +`$nroll` | Rolls in a given range. | `$nroll 5` (rolls 0-5) or `$nroll 5-15` +`$draw` | Draws a card from the deck.If you supply number X, she draws up to 5 cards from the deck. | `$draw` or `$draw 5` +`$shuffle` `$sh` | Reshuffles all cards back into the deck. | `$sh` +`$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 double flowers you've bet. | `$bf 5 heads` or `$bf 3 t` ### Games Command and aliases | Description | Usage @@ -223,7 +224,7 @@ Command and aliases | Description | Usage ----------------|--------------|------- `~weather` `~we` | Shows weather data for a specified city and a country. BOTH ARE REQUIRED. Use country abbrevations. | `~we Moscow RF` `~youtube` `~yt` | Searches youtubes and shows the first result | `~yt query` -`~imdb` | Queries imdb for movies or series, show first result. | `~imdb Batman vs Superman` +`~imdb` `~omdb` | Queries omdb for movies or series, show first result. | `~imdb Batman vs Superman` `~randomcat` `~meow` | Shows a random cat image. | `~meow` `~randomdog` `~woof` | Shows a random dog image. | `~woof` `~img` `~i` | Pulls the first image found using a search parameter. Use ~ir for different results. | `~i cute kitten` @@ -257,7 +258,7 @@ Command and aliases | Description | Usage `~osub` | Shows information about an osu beatmap. | `~osub https://osu.ppy.sh/s/127712` `~osu5` | Displays a user's top 5 plays. | `~osu5 Name` `~pokemon` `~poke` | Searches for a pokemon. | `~poke Sylveon` -`~pokemonability` `~pokeab` | Searches for a pokemon ability. | `~pokeab "water gun"` +`~pokemonability` `~pokeab` | Searches for a pokemon ability. | `~pokeab overgrow` `~hitbox` `~hb` | Notifies this channel when a certain user starts streaming. | `~hitbox SomeStreamer` **Requires ManageMessages server permission.** `~twitch` `~tw` | Notifies this channel when a certain user starts streaming. | `~twitch SomeStreamer` **Requires ManageMessages server permission.** `~beam` `~bm` | Notifies this channel when a certain user starts streaming. | `~beam SomeStreamer` **Requires ManageMessages server permission.** @@ -274,7 +275,7 @@ Command and aliases | Description | Usage `.userid` `.uid` | Shows user ID. | `.uid` or `.uid "@SomeGuy"` `.channelid` `.cid` | Shows current channel ID. | `.cid` `.serverid` `.sid` | Shows current server ID. | `.sid` -`.roles` | List all roles on this server or a single user if specified. | `.roles` +`.roles` | List roles on this server or a roles of a specific user if specified. Paginated. 20 roles per page. | `.roles 2` or `.roles @Someone` `.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 SPECIALemojis` diff --git a/docs/Custom Reactions.md b/docs/Custom Reactions.md index d2e6f40d..1f2d4600 100644 --- a/docs/Custom Reactions.md +++ b/docs/Custom Reactions.md @@ -35,7 +35,6 @@ There are currently three different placeholders which we will look at, with mor |`%mention`|The `%mention%` placeholder is triggered when you type `@BotName` - It's important to note that if you've given the bot a custom nickname, this trigger won't work!|```.acr "Hello %mention%" I, %mention%, also say hello!```|Input: "Hello @BotName" Output: "I, @BotName, also say hello!"| |`%user%`|The `%user%` placeholder mentions the person who said the command|`.acr "Who am I?" You are %user%!`|Input: "Who am I?" Output: "You are @Username!"| |`%rng%`|The `%rng%` placeholder generates a random number between 0 and 10|`.acr "Random number" %rng%`|Input: "Random number" Output: "2"| - -[//]: # (|`%target%`|The `%target%` placeholder is used to make Nadeko Mention another person or phrase|`.acr "Say this: " %target%|Input: "Say this: I, @BotName, am a parrot!". Output: "I, @BotName, am a parrot!".|) +|`%target%`|The `%target%` placeholder is used to make Nadeko Mention another person or phrase, it is only supported as part of the response|`.acr "Say this: " %target%`|Input: "Say this: I, @BotName, am a parrot!". Output: "I, @BotName, am a parrot!".| Thanks to Nekai for being creative. <3 diff --git a/src/NadekoBot/Migrations/20161015005020_CurrencyTransaction.Designer.cs b/src/NadekoBot/Migrations/20161015005020_CurrencyTransaction.Designer.cs new file mode 100644 index 00000000..09af6235 --- /dev/null +++ b/src/NadekoBot/Migrations/20161015005020_CurrencyTransaction.Designer.cs @@ -0,0 +1,775 @@ +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("20161015005020_CurrencyTransaction")] + partial class CurrencyTransaction + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { + modelBuilder + .HasAnnotation("ProductVersion", "1.0.0-rtm-21431"); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BotConfigId"); + + b.Property("ItemId"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.HasIndex("BotConfigId"); + + b.ToTable("BlacklistItem"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.BotConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BufferSize"); + + b.Property("CurrencyGenerationChance"); + + b.Property("CurrencyGenerationCooldown"); + + b.Property("CurrencyName"); + + b.Property("CurrencyPluralName"); + + b.Property("CurrencySign"); + + b.Property("DMHelpString"); + + b.Property("ForwardMessages"); + + b.Property("ForwardToAllOwners"); + + b.Property("HelpString"); + + b.Property("MigrationVersion"); + + b.Property("RemindMessageFormat"); + + b.Property("RotatingStatuses"); + + b.HasKey("Id"); + + b.ToTable("BotConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashCaller", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BaseDestroyed"); + + b.Property("CallUser"); + + b.Property("ClashWarId"); + + b.Property("Stars"); + + b.Property("TimeAdded"); + + b.HasKey("Id"); + + b.HasIndex("ClashWarId"); + + b.ToTable("ClashCallers"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashWar", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("EnemyClan"); + + b.Property("GuildId"); + + b.Property("Size"); + + b.Property("StartedAt"); + + b.Property("WarState"); + + b.HasKey("Id"); + + b.ToTable("ClashOfClans"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("CommandName"); + + b.Property("GuildConfigId"); + + b.Property("Seconds"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("CommandCooldown"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ConvertUnit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("InternalTrigger"); + + b.Property("Modifier"); + + b.Property("UnitType"); + + b.HasKey("Id"); + + b.ToTable("ConversionUnits"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Currency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Amount"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("Currency"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CurrencyTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Amount"); + + b.Property("Reason"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.ToTable("CurrencyTransactions"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CustomReaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("GuildId"); + + b.Property("IsRegex"); + + b.Property("OwnerOnly"); + + b.Property("Response"); + + b.Property("Trigger"); + + b.HasKey("Id"); + + b.ToTable("CustomReactions"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Donator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Amount"); + + b.Property("Name"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("Donators"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.EightBallResponse", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BotConfigId"); + + b.Property("Text"); + + b.HasKey("Id"); + + b.HasIndex("BotConfigId"); + + b.ToTable("EightBallResponses"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("GuildConfigId"); + + b.Property("GuildConfigId1"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.HasIndex("GuildConfigId1"); + + b.ToTable("FilterChannelId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("GuildConfigId"); + + b.Property("Word"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilteredWord"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FollowedStream", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("GuildConfigId"); + + b.Property("GuildId"); + + b.Property("Type"); + + b.Property("Username"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FollowedStream"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("GuildConfigId"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("GCChannelId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AutoAssignRoleId"); + + b.Property("AutoDeleteByeMessages"); + + b.Property("AutoDeleteGreetMessages"); + + b.Property("AutoDeleteGreetMessagesTimer"); + + b.Property("AutoDeleteSelfAssignedRoleMessages"); + + b.Property("ByeMessageChannelId"); + + b.Property("ChannelByeMessageText"); + + b.Property("ChannelGreetMessageText"); + + b.Property("DefaultMusicVolume"); + + b.Property("DeleteMessageOnCommand"); + + b.Property("DmGreetMessageText"); + + b.Property("ExclusiveSelfAssignedRoles"); + + b.Property("FilterInvites"); + + b.Property("FilterWords"); + + b.Property("GreetMessageChannelId"); + + b.Property("GuildId"); + + b.Property("LogSettingId"); + + b.Property("PermissionRole"); + + b.Property("RootPermissionId"); + + b.Property("SendChannelByeMessage"); + + b.Property("SendChannelGreetMessage"); + + b.Property("SendDmGreetMessage"); + + b.Property("VerbosePermissions"); + + b.Property("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("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("LogSettingId"); + + b.HasKey("Id"); + + b.HasIndex("LogSettingId"); + + b.ToTable("IgnoredLogChannels"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("LogSettingId"); + + b.HasKey("Id"); + + b.HasIndex("LogSettingId"); + + b.ToTable("IgnoredVoicePresenceCHannels"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.LogSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelCreated"); + + b.Property("ChannelDestroyed"); + + b.Property("ChannelId"); + + b.Property("ChannelUpdated"); + + b.Property("IsLogging"); + + b.Property("LogUserPresence"); + + b.Property("LogVoicePresence"); + + b.Property("MessageDeleted"); + + b.Property("MessageUpdated"); + + b.Property("UserBanned"); + + b.Property("UserJoined"); + + b.Property("UserLeft"); + + b.Property("UserPresenceChannelId"); + + b.Property("UserUnbanned"); + + b.Property("UserUpdated"); + + b.Property("VoicePresenceChannelId"); + + b.HasKey("Id"); + + b.ToTable("LogSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ModulePrefix", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BotConfigId"); + + b.Property("ModuleName"); + + b.Property("Prefix"); + + b.HasKey("Id"); + + b.HasIndex("BotConfigId"); + + b.ToTable("ModulePrefixes"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlaylist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Author"); + + b.Property("AuthorId"); + + b.Property("Name"); + + b.HasKey("Id"); + + b.ToTable("MusicPlaylists"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Permission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("NextId"); + + b.Property("PrimaryTarget"); + + b.Property("PrimaryTargetId"); + + b.Property("SecondaryTarget"); + + b.Property("SecondaryTargetName"); + + b.Property("State"); + + b.HasKey("Id"); + + b.HasIndex("NextId") + .IsUnique(); + + b.ToTable("Permission"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BotConfigId"); + + b.Property("Status"); + + b.HasKey("Id"); + + b.HasIndex("BotConfigId"); + + b.ToTable("PlayingStatus"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("MusicPlaylistId"); + + b.Property("Provider"); + + b.Property("ProviderType"); + + b.Property("Query"); + + b.Property("Title"); + + b.Property("Uri"); + + b.HasKey("Id"); + + b.HasIndex("MusicPlaylistId"); + + b.ToTable("PlaylistSong"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Quote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AuthorId"); + + b.Property("AuthorName") + .IsRequired(); + + b.Property("GuildId"); + + b.Property("Keyword") + .IsRequired(); + + b.Property("Text") + .IsRequired(); + + b.HasKey("Id"); + + b.ToTable("Quotes"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.RaceAnimal", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BotConfigId"); + + b.Property("Icon"); + + b.Property("Name"); + + b.HasKey("Id"); + + b.HasIndex("BotConfigId"); + + b.ToTable("RaceAnimals"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Reminder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("IsPrivate"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("UserId"); + + b.Property("When"); + + b.HasKey("Id"); + + b.ToTable("Reminders"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Repeater", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("GuildId"); + + b.Property("Interval"); + + b.Property("Message"); + + b.HasKey("Id"); + + b.HasIndex("ChannelId") + .IsUnique(); + + b.ToTable("Repeaters"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SelfAssignedRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("GuildId"); + + b.Property("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"); + }); + } + } +} diff --git a/src/NadekoBot/Migrations/20161015005020_CurrencyTransaction.cs b/src/NadekoBot/Migrations/20161015005020_CurrencyTransaction.cs new file mode 100644 index 00000000..5d0b61d4 --- /dev/null +++ b/src/NadekoBot/Migrations/20161015005020_CurrencyTransaction.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace NadekoBot.Migrations +{ + public partial class CurrencyTransaction : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "CurrencyTransactions", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Autoincrement", true), + Amount = table.Column(nullable: false), + Reason = table.Column(nullable: true), + UserId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_CurrencyTransactions", x => x.Id); + }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "CurrencyTransactions"); + } + } +} diff --git a/src/NadekoBot/Migrations/20161015102407_coc.Designer.cs b/src/NadekoBot/Migrations/20161015102407_coc.Designer.cs new file mode 100644 index 00000000..f05d500c --- /dev/null +++ b/src/NadekoBot/Migrations/20161015102407_coc.Designer.cs @@ -0,0 +1,777 @@ +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("20161015102407_coc")] + partial class coc + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { + modelBuilder + .HasAnnotation("ProductVersion", "1.0.0-rtm-21431"); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BotConfigId"); + + b.Property("ItemId"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.HasIndex("BotConfigId"); + + b.ToTable("BlacklistItem"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.BotConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BufferSize"); + + b.Property("CurrencyGenerationChance"); + + b.Property("CurrencyGenerationCooldown"); + + b.Property("CurrencyName"); + + b.Property("CurrencyPluralName"); + + b.Property("CurrencySign"); + + b.Property("DMHelpString"); + + b.Property("ForwardMessages"); + + b.Property("ForwardToAllOwners"); + + b.Property("HelpString"); + + b.Property("MigrationVersion"); + + b.Property("RemindMessageFormat"); + + b.Property("RotatingStatuses"); + + b.HasKey("Id"); + + b.ToTable("BotConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashCaller", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BaseDestroyed"); + + b.Property("CallUser"); + + b.Property("ClashWarId"); + + b.Property("SequenceNumber"); + + b.Property("Stars"); + + b.Property("TimeAdded"); + + b.HasKey("Id"); + + b.HasIndex("ClashWarId"); + + b.ToTable("ClashCallers"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashWar", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("EnemyClan"); + + b.Property("GuildId"); + + b.Property("Size"); + + b.Property("StartedAt"); + + b.Property("WarState"); + + b.HasKey("Id"); + + b.ToTable("ClashOfClans"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("CommandName"); + + b.Property("GuildConfigId"); + + b.Property("Seconds"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("CommandCooldown"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ConvertUnit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("InternalTrigger"); + + b.Property("Modifier"); + + b.Property("UnitType"); + + b.HasKey("Id"); + + b.ToTable("ConversionUnits"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Currency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Amount"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("Currency"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CurrencyTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Amount"); + + b.Property("Reason"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.ToTable("CurrencyTransactions"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CustomReaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("GuildId"); + + b.Property("IsRegex"); + + b.Property("OwnerOnly"); + + b.Property("Response"); + + b.Property("Trigger"); + + b.HasKey("Id"); + + b.ToTable("CustomReactions"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Donator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Amount"); + + b.Property("Name"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("Donators"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.EightBallResponse", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BotConfigId"); + + b.Property("Text"); + + b.HasKey("Id"); + + b.HasIndex("BotConfigId"); + + b.ToTable("EightBallResponses"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("GuildConfigId"); + + b.Property("GuildConfigId1"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.HasIndex("GuildConfigId1"); + + b.ToTable("FilterChannelId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("GuildConfigId"); + + b.Property("Word"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilteredWord"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FollowedStream", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("GuildConfigId"); + + b.Property("GuildId"); + + b.Property("Type"); + + b.Property("Username"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FollowedStream"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("GuildConfigId"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("GCChannelId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AutoAssignRoleId"); + + b.Property("AutoDeleteByeMessages"); + + b.Property("AutoDeleteGreetMessages"); + + b.Property("AutoDeleteGreetMessagesTimer"); + + b.Property("AutoDeleteSelfAssignedRoleMessages"); + + b.Property("ByeMessageChannelId"); + + b.Property("ChannelByeMessageText"); + + b.Property("ChannelGreetMessageText"); + + b.Property("DefaultMusicVolume"); + + b.Property("DeleteMessageOnCommand"); + + b.Property("DmGreetMessageText"); + + b.Property("ExclusiveSelfAssignedRoles"); + + b.Property("FilterInvites"); + + b.Property("FilterWords"); + + b.Property("GreetMessageChannelId"); + + b.Property("GuildId"); + + b.Property("LogSettingId"); + + b.Property("PermissionRole"); + + b.Property("RootPermissionId"); + + b.Property("SendChannelByeMessage"); + + b.Property("SendChannelGreetMessage"); + + b.Property("SendDmGreetMessage"); + + b.Property("VerbosePermissions"); + + b.Property("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("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("LogSettingId"); + + b.HasKey("Id"); + + b.HasIndex("LogSettingId"); + + b.ToTable("IgnoredLogChannels"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("LogSettingId"); + + b.HasKey("Id"); + + b.HasIndex("LogSettingId"); + + b.ToTable("IgnoredVoicePresenceCHannels"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.LogSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelCreated"); + + b.Property("ChannelDestroyed"); + + b.Property("ChannelId"); + + b.Property("ChannelUpdated"); + + b.Property("IsLogging"); + + b.Property("LogUserPresence"); + + b.Property("LogVoicePresence"); + + b.Property("MessageDeleted"); + + b.Property("MessageUpdated"); + + b.Property("UserBanned"); + + b.Property("UserJoined"); + + b.Property("UserLeft"); + + b.Property("UserPresenceChannelId"); + + b.Property("UserUnbanned"); + + b.Property("UserUpdated"); + + b.Property("VoicePresenceChannelId"); + + b.HasKey("Id"); + + b.ToTable("LogSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ModulePrefix", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BotConfigId"); + + b.Property("ModuleName"); + + b.Property("Prefix"); + + b.HasKey("Id"); + + b.HasIndex("BotConfigId"); + + b.ToTable("ModulePrefixes"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlaylist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Author"); + + b.Property("AuthorId"); + + b.Property("Name"); + + b.HasKey("Id"); + + b.ToTable("MusicPlaylists"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Permission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("NextId"); + + b.Property("PrimaryTarget"); + + b.Property("PrimaryTargetId"); + + b.Property("SecondaryTarget"); + + b.Property("SecondaryTargetName"); + + b.Property("State"); + + b.HasKey("Id"); + + b.HasIndex("NextId") + .IsUnique(); + + b.ToTable("Permission"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BotConfigId"); + + b.Property("Status"); + + b.HasKey("Id"); + + b.HasIndex("BotConfigId"); + + b.ToTable("PlayingStatus"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("MusicPlaylistId"); + + b.Property("Provider"); + + b.Property("ProviderType"); + + b.Property("Query"); + + b.Property("Title"); + + b.Property("Uri"); + + b.HasKey("Id"); + + b.HasIndex("MusicPlaylistId"); + + b.ToTable("PlaylistSong"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Quote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AuthorId"); + + b.Property("AuthorName") + .IsRequired(); + + b.Property("GuildId"); + + b.Property("Keyword") + .IsRequired(); + + b.Property("Text") + .IsRequired(); + + b.HasKey("Id"); + + b.ToTable("Quotes"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.RaceAnimal", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BotConfigId"); + + b.Property("Icon"); + + b.Property("Name"); + + b.HasKey("Id"); + + b.HasIndex("BotConfigId"); + + b.ToTable("RaceAnimals"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Reminder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("IsPrivate"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("UserId"); + + b.Property("When"); + + b.HasKey("Id"); + + b.ToTable("Reminders"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Repeater", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("GuildId"); + + b.Property("Interval"); + + b.Property("Message"); + + b.HasKey("Id"); + + b.HasIndex("ChannelId") + .IsUnique(); + + b.ToTable("Repeaters"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SelfAssignedRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("GuildId"); + + b.Property("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"); + }); + } + } +} diff --git a/src/NadekoBot/Migrations/20161015102407_coc.cs b/src/NadekoBot/Migrations/20161015102407_coc.cs new file mode 100644 index 00000000..e1d42e8c --- /dev/null +++ b/src/NadekoBot/Migrations/20161015102407_coc.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace NadekoBot.Migrations +{ + public partial class coc : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "SequenceNumber", + table: "ClashCallers", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "SequenceNumber", + table: "ClashCallers"); + } + } +} diff --git a/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs b/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs index ee91013c..be1f7786 100644 --- a/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs +++ b/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs @@ -80,6 +80,8 @@ namespace NadekoBot.Migrations b.Property("ClashWarId"); + b.Property("SequenceNumber"); + b.Property("Stars"); b.Property("TimeAdded"); @@ -164,6 +166,22 @@ namespace NadekoBot.Migrations b.ToTable("Currency"); }); + modelBuilder.Entity("NadekoBot.Services.Database.Models.CurrencyTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Amount"); + + b.Property("Reason"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.ToTable("CurrencyTransactions"); + }); + modelBuilder.Entity("NadekoBot.Services.Database.Models.CustomReaction", b => { b.Property("Id") diff --git a/src/NadekoBot/Modules/Administration/Administration.cs b/src/NadekoBot/Modules/Administration/Administration.cs index de1c466f..b3a7cd36 100644 --- a/src/NadekoBot/Modules/Administration/Administration.cs +++ b/src/NadekoBot/Modules/Administration/Administration.cs @@ -35,6 +35,7 @@ namespace NadekoBot.Modules.Administration if (channel == null) return; + //todo cache this bool shouldDelete; using (var uow = DbHandler.UnitOfWork()) { @@ -531,7 +532,7 @@ namespace NadekoBot.Modules.Administration if (string.IsNullOrWhiteSpace(newName)) return; - await NadekoBot.Client.GetCurrentUser().ModifyAsync(u => u.Username = newName).ConfigureAwait(false); + await (await NadekoBot.Client.GetCurrentUserAsync()).ModifyAsync(u => u.Username = newName).ConfigureAwait(false); await channel.SendMessageAsync($"Successfully changed name to {newName}").ConfigureAwait(false); } @@ -554,7 +555,7 @@ namespace NadekoBot.Modules.Administration await sr.CopyToAsync(imgStream); imgStream.Position = 0; - await NadekoBot.Client.GetCurrentUser().ModifyAsync(u => u.Avatar = imgStream).ConfigureAwait(false); + await (await NadekoBot.Client.GetCurrentUserAsync().ConfigureAwait(false)).ModifyAsync(u => u.Avatar = imgStream).ConfigureAwait(false); } } @@ -695,12 +696,14 @@ namespace NadekoBot.Modules.Administration await channel.SendMessageAsync(send).ConfigureAwait(false); } + IGuild nadekoSupportServer; [NadekoCommand, Usage, Description, Aliases] [RequireContext(ContextType.Guild)] public async Task Donators(IUserMessage umsg) { var channel = (ITextChannel)umsg.Channel; IEnumerable donatorsOrdered; + using (var uow = DbHandler.UnitOfWork()) { donatorsOrdered = uow.Donators.GetDonatorsOrdered(); @@ -708,6 +711,18 @@ namespace NadekoBot.Modules.Administration string str = $"**Thanks to the people listed below for making this project happen!**\n"; await channel.SendMessageAsync(str + string.Join("⭐", donatorsOrdered.Select(d => d.Name))).ConfigureAwait(false); + + nadekoSupportServer = nadekoSupportServer ?? NadekoBot.Client.GetGuild(117523346618318850); + + if (nadekoSupportServer == null) + return; + + var patreonRole = nadekoSupportServer.GetRole(236667642088259585); + if (patreonRole == null) + return; + + var usrs = nadekoSupportServer.GetUsers().Where(u => u.Roles.Contains(patreonRole)); + await channel.SendMessageAsync("\n`Patreon supporters:`\n" + string.Join("⭐", usrs.Select(d => d.Username))).ConfigureAwait(false); } diff --git a/src/NadekoBot/Modules/Administration/Commands/AutoAssignRoleCommands.cs b/src/NadekoBot/Modules/Administration/Commands/AutoAssignRoleCommands.cs index 968f9dd9..dd35927c 100644 --- a/src/NadekoBot/Modules/Administration/Commands/AutoAssignRoleCommands.cs +++ b/src/NadekoBot/Modules/Administration/Commands/AutoAssignRoleCommands.cs @@ -28,7 +28,6 @@ namespace NadekoBot.Modules.Administration { conf = uow.GuildConfigs.For(user.Guild.Id); } - var aarType = conf.AutoAssignRoleId.GetType(); if (conf.AutoAssignRoleId == 0) return; diff --git a/src/NadekoBot/Modules/Administration/Commands/Migration.cs b/src/NadekoBot/Modules/Administration/Commands/Migration.cs index cd7ae2f8..feb3aab0 100644 --- a/src/NadekoBot/Modules/Administration/Commands/Migration.cs +++ b/src/NadekoBot/Modules/Administration/Commands/Migration.cs @@ -411,11 +411,11 @@ namespace NadekoBot.Modules.Administration { return cr.Value.Select(res => new CustomReaction() { - GuildId = 0, + GuildId = null, IsRegex = false, OwnerOnly = false, Response = res, - Trigger = cr.Key, + Trigger = cr.Key.ToLowerInvariant(), }); }).ToArray()); diff --git a/src/NadekoBot/Modules/Administration/Commands/PlayingRotateCommands.cs b/src/NadekoBot/Modules/Administration/Commands/PlayingRotateCommands.cs index ab8721e8..bf6030bb 100644 --- a/src/NadekoBot/Modules/Administration/Commands/PlayingRotateCommands.cs +++ b/src/NadekoBot/Modules/Administration/Commands/PlayingRotateCommands.cs @@ -2,6 +2,7 @@ using Discord.Commands; using Discord.WebSocket; using NadekoBot.Attributes; +using NadekoBot.Extensions; using NadekoBot.Services; using NadekoBot.Services.Database; using NadekoBot.Services.Database.Models; @@ -21,6 +22,18 @@ namespace NadekoBot.Modules.Administration public class PlayingRotateCommands { private Logger _log { get; } + public static List RotatingStatusMessages { get; } + public static bool RotatingStatuses { get; private set; } = false; + + static PlayingRotateCommands() + { + using (var uow = DbHandler.UnitOfWork()) + { + var conf = uow.BotConfig.GetOrCreate(); + RotatingStatusMessages = conf.RotatingStatusMessages; + RotatingStatuses = conf.RotatingStatuses; + } + } public PlayingRotateCommands() { @@ -32,26 +45,22 @@ namespace NadekoBot.Modules.Administration { try { - BotConfig conf; - using (var uow = DbHandler.UnitOfWork()) - { - conf = uow.BotConfig.GetOrCreate(); - } - - if (!conf.RotatingStatuses) + if (!RotatingStatuses) continue; else { - if (index >= conf.RotatingStatusMessages.Count) + if (index >= RotatingStatusMessages.Count) index = 0; - if (!conf.RotatingStatusMessages.Any()) + if (!RotatingStatusMessages.Any()) continue; - - await NadekoBot.Client - .GetCurrentUser() - .ModifyStatusAsync(mpp => mpp.Game = new Game(conf.RotatingStatusMessages[index++].Status)) - .ConfigureAwait(false); + var status = RotatingStatusMessages[index++].Status; + if (string.IsNullOrWhiteSpace(status)) + continue; + PlayingPlaceholders.ForEach(e => status = status.Replace(e.Key, e.Value())); + await (await NadekoBot.Client.GetCurrentUserAsync()) + .ModifyStatusAsync(mpp => mpp.Game = new Game(status)) + .ConfigureAwait(false); } } catch (Exception ex) @@ -91,16 +100,15 @@ namespace NadekoBot.Modules.Administration public async Task RotatePlaying(IUserMessage umsg) { var channel = (ITextChannel)umsg.Channel; - - bool status; + using (var uow = DbHandler.UnitOfWork()) { var config = uow.BotConfig.GetOrCreate(); - status = config.RotatingStatuses = !config.RotatingStatuses; + RotatingStatuses = config.RotatingStatuses = !config.RotatingStatuses; await uow.CompleteAsync(); } - if (status) + if (RotatingStatuses) await channel.SendMessageAsync("`Rotating playing status enabled.`"); else await channel.SendMessageAsync("`Rotating playing status disabled.`"); @@ -116,7 +124,9 @@ namespace NadekoBot.Modules.Administration using (var uow = DbHandler.UnitOfWork()) { var config = uow.BotConfig.GetOrCreate(); - config.RotatingStatusMessages.Add(new PlayingStatus { Status = status }); + var toAdd = new PlayingStatus { Status = status }; + config.RotatingStatusMessages.Add(toAdd); + RotatingStatusMessages.Add(toAdd); await uow.CompleteAsync(); } @@ -129,19 +139,14 @@ namespace NadekoBot.Modules.Administration public async Task ListPlaying(IUserMessage umsg) { var channel = (ITextChannel)umsg.Channel; + - List statuses; - using (var uow = DbHandler.UnitOfWork()) - { - statuses = uow.BotConfig.GetOrCreate().RotatingStatusMessages; - } - - if (!statuses.Any()) + if (!RotatingStatusMessages.Any()) await channel.SendMessageAsync("`No rotating playing statuses set.`"); else { var i = 1; - await channel.SendMessageAsync($"{umsg.Author.Mention} `Here is a list of rotating statuses:`\n\n\t" + string.Join("\n\t", statuses.Select(rs => $"`{i++}.` {rs.Status}"))); + await channel.SendMessageAsync($"{umsg.Author.Mention} `Here is a list of rotating statuses:`\n\n\t" + string.Join("\n\t", RotatingStatusMessages.Select(rs => $"`{i++}.` {rs.Status}"))); } } @@ -163,6 +168,7 @@ namespace NadekoBot.Modules.Administration return; msg = config.RotatingStatusMessages[index].Status; config.RotatingStatusMessages.RemoveAt(index); + RotatingStatusMessages.RemoveAt(index); await uow.CompleteAsync(); } await channel.SendMessageAsync($"`Removed the the playing message:` {msg}").ConfigureAwait(false); diff --git a/src/NadekoBot/Modules/Administration/Commands/ServerGreetCommands.cs b/src/NadekoBot/Modules/Administration/Commands/ServerGreetCommands.cs index fba659ff..8d6e7f16 100644 --- a/src/NadekoBot/Modules/Administration/Commands/ServerGreetCommands.cs +++ b/src/NadekoBot/Modules/Administration/Commands/ServerGreetCommands.cs @@ -43,7 +43,7 @@ namespace NadekoBot.Modules.Administration if (channel == null) //maybe warn the server owner that the channel is missing return; - var msg = conf.ChannelByeMessageText.Replace("%user%", user.Username + $" ({user.Id})").Replace("%server%", user.Guild.Name); + var msg = conf.ChannelByeMessageText.Replace("%user%", user.Username).Replace("%id%", user.Id.ToString()).Replace("%server%", user.Guild.Name); if (string.IsNullOrWhiteSpace(msg)) return; try @@ -78,7 +78,7 @@ namespace NadekoBot.Modules.Administration var channel = (await user.Guild.GetTextChannelsAsync()).SingleOrDefault(c => c.Id == conf.GreetMessageChannelId); if (channel != null) //maybe warn the server owner that the channel is missing { - var msg = conf.ChannelGreetMessageText.Replace("%user%", user.Mention).Replace("%server%", user.Guild.Name); + var msg = conf.ChannelGreetMessageText.Replace("%user%", user.Mention).Replace("%id%", user.Id.ToString()).Replace("%server%", user.Guild.Name); if (!string.IsNullOrWhiteSpace(msg)) { try diff --git a/src/NadekoBot/Modules/ClashOfClans/ClashOfClans.cs b/src/NadekoBot/Modules/ClashOfClans/ClashOfClans.cs index ae5fc69a..1f084c4c 100644 --- a/src/NadekoBot/Modules/ClashOfClans/ClashOfClans.cs +++ b/src/NadekoBot/Modules/ClashOfClans/ClashOfClans.cs @@ -21,23 +21,21 @@ namespace NadekoBot.Modules.ClashOfClans static ClashOfClans() { - //using (var uow = DbHandler.UnitOfWork()) - //{ - // ClashWars = new ConcurrentDictionary>( - // uow.ClashOfClans - // .GetAllWars() - // .Select(cw => { - // if (cw == null || cw.Bases == null) - // return null; - // cw.Channel = NadekoBot.Client.GetGuild(cw.GuildId) - // ?.GetTextChannel(cw.ChannelId); - // cw.Bases.Capacity = cw.Size; - // return cw; - // }) - // .Where(cw => cw?.Channel != null) - // .GroupBy(cw => cw.GuildId) - // .ToDictionary(g => g.Key, g => g.ToList())); - //} + using (var uow = DbHandler.UnitOfWork()) + { + ClashWars = new ConcurrentDictionary>( + uow.ClashOfClans + .GetAllWars() + .Select(cw => + { + cw.Channel = NadekoBot.Client.GetGuild(cw.GuildId) + ?.GetTextChannel(cw.ChannelId); + return cw; + }) + .Where(cw => cw?.Channel != null) + .GroupBy(cw => cw.GuildId) + .ToDictionary(g => g.Key, g => g.ToList())); + } } public ClashOfClans(ILocalization loc, CommandService cmds, ShardedDiscordClient client) : base(loc, cmds, client) { @@ -46,9 +44,9 @@ namespace NadekoBot.Modules.ClashOfClans private static async Task CheckWar(TimeSpan callExpire, ClashWar war) { var Bases = war.Bases; - for (var i = 0; i < Bases.Capacity; i++) + for (var i = 0; i < Bases.Count; i++) { - if (Bases[i] == null) continue; + if (Bases[i].CallUser == null) continue; if (!Bases[i].BaseDestroyed && DateTime.UtcNow - Bases[i].TimeAdded >= callExpire) { Bases[i] = null; @@ -84,7 +82,6 @@ namespace NadekoBot.Modules.ClashOfClans var cw = await CreateWar(enemyClan, size, channel.Guild.Id, umsg.Channel.Id); - //cw.Start(); wars.Add(cw); await channel.SendMessageAsync($"❗🔰**CREATED CLAN WAR AGAINST {cw.ShortPrint()}**").ConfigureAwait(false); @@ -191,26 +188,26 @@ namespace NadekoBot.Modules.ClashOfClans [NadekoCommand, Usage, Description, Aliases] [RequireContext(ContextType.Guild)] - public async Task ClaimFinish1(IUserMessage umsg, int number, int baseNumber, [Remainder] string other_name = null) + public async Task ClaimFinish1(IUserMessage umsg, int number, int baseNumber = 0) { var channel = (ITextChannel)umsg.Channel; - await FinishClaim(umsg, number, baseNumber, other_name, 1); + await FinishClaim(umsg, number, baseNumber - 1, 1); } [NadekoCommand, Usage, Description, Aliases] [RequireContext(ContextType.Guild)] - public async Task ClaimFinish2(IUserMessage umsg, int number, int baseNumber, [Remainder] string other_name = null) + public async Task ClaimFinish2(IUserMessage umsg, int number, int baseNumber = 0) { var channel = (ITextChannel)umsg.Channel; - await FinishClaim(umsg, number, baseNumber, other_name, 2); + await FinishClaim(umsg, number, baseNumber - 1, 2); } [NadekoCommand, Usage, Description, Aliases] [RequireContext(ContextType.Guild)] - public async Task ClaimFinish(IUserMessage umsg, int number, int baseNumber, [Remainder] string other_name = null) + public async Task ClaimFinish(IUserMessage umsg, int number, int baseNumber = 0) { var channel = (ITextChannel)umsg.Channel; - await FinishClaim(umsg, number, baseNumber, other_name); + await FinishClaim(umsg, number, baseNumber - 1); } [NadekoCommand, Usage, Description, Aliases] @@ -263,7 +260,7 @@ namespace NadekoBot.Modules.ClashOfClans } } - private async Task FinishClaim(IUserMessage umsg, int number, int baseNumber, [Remainder] string other_name, int stars = 3) + private async Task FinishClaim(IUserMessage umsg, int number, int baseNumber, int stars = 3) { var channel = (ITextChannel)umsg.Channel; var warInfo = GetWarInfo(umsg, number); @@ -272,17 +269,19 @@ namespace NadekoBot.Modules.ClashOfClans await channel.SendMessageAsync("💢🔰 **That war does not exist.**").ConfigureAwait(false); return; } - var usr = - string.IsNullOrWhiteSpace(other_name) ? - umsg.Author.Username : - other_name; - var war = warInfo.Item1[warInfo.Item2]; try { - var baseNum = war.FinishClaim(usr, stars); - SaveWar(war); - await channel.SendMessageAsync($"❗🔰{umsg.Author.Mention} **DESTROYED** a base #{baseNum + 1} in a war against {war.ShortPrint()}").ConfigureAwait(false); + if (baseNumber == -1) + { + baseNumber = war.FinishClaim(umsg.Author.Username, stars); + SaveWar(war); + } + else + { + war.FinishClaim(baseNumber, stars); + } + await channel.SendMessageAsync($"❗🔰{umsg.Author.Mention} **DESTROYED** a base #{baseNumber + 1} in a war against {war.ShortPrint()}").ConfigureAwait(false); } catch (Exception ex) { @@ -324,6 +323,16 @@ namespace NadekoBot.Modules.ClashOfClans Channel = NadekoBot.Client.GetGuild(serverId) ?.GetTextChannel(channelId) }; + cw.Bases.Capacity = size; + for (int i = 0; i < size; i++) + { + cw.Bases.Add(new ClashCaller() + { + CallUser = null, + SequenceNumber = i, + }); + } + Console.WriteLine(cw.Bases.Capacity); uow.ClashOfClans.Add(cw); await uow.CompleteAsync(); return cw; diff --git a/src/NadekoBot/Modules/ClashOfClans/Extensions.cs b/src/NadekoBot/Modules/ClashOfClans/Extensions.cs index b367f0a6..d2103edd 100644 --- a/src/NadekoBot/Modules/ClashOfClans/Extensions.cs +++ b/src/NadekoBot/Modules/ClashOfClans/Extensions.cs @@ -30,21 +30,20 @@ namespace NadekoBot.Modules.ClashOfClans public static void Call(this ClashWar cw, string u, int baseNumber) { - if (baseNumber < 0 || baseNumber >= cw.Bases.Capacity) + if (baseNumber < 0 || baseNumber >= cw.Bases.Count) throw new ArgumentException("Invalid base number"); - if (cw.Bases[baseNumber] != null) + if (cw.Bases[baseNumber].CallUser != null) throw new ArgumentException("That base is already claimed."); - for (var i = 0; i < cw.Bases.Capacity; i++) + for (var i = 0; i < cw.Bases.Count; i++) { if (cw.Bases[i]?.BaseDestroyed == false && cw.Bases[i]?.CallUser == u) throw new ArgumentException($"@{u} You already claimed base #{i + 1}. You can't claim a new one."); } - cw.Bases[baseNumber] = new ClashCaller() { - CallUser = u.Trim(), - TimeAdded = DateTime.UtcNow, - BaseDestroyed = false - }; + var cc = cw.Bases[baseNumber]; + cc.CallUser = u.Trim(); + cc.TimeAdded = DateTime.UtcNow; + cc.BaseDestroyed = false; } public static void Start(this ClashWar cw) @@ -56,7 +55,7 @@ namespace NadekoBot.Modules.ClashOfClans //Started = true; cw.WarState = StateOfWar.Started; cw.StartedAt = DateTime.UtcNow; - foreach (var b in cw.Bases.Where(b => b != null)) + foreach (var b in cw.Bases.Where(b => b.CallUser != null)) { b.ResetTime(); } @@ -65,10 +64,10 @@ namespace NadekoBot.Modules.ClashOfClans public static int Uncall(this ClashWar cw, string user) { user = user.Trim(); - for (var i = 0; i < cw.Bases.Capacity; i++) + for (var i = 0; i < cw.Bases.Count; i++) { if (cw.Bases[i]?.CallUser != user) continue; - cw.Bases[i] = null; + cw.Bases[i].CallUser = null; return i; } throw new InvalidOperationException("You are not participating in that war."); @@ -85,9 +84,9 @@ namespace NadekoBot.Modules.ClashOfClans if (cw.WarState == StateOfWar.Created) sb.AppendLine("`not started`"); var twoHours = new TimeSpan(2, 0, 0); - for (var i = 0; i < cw.Bases.Capacity; i++) + for (var i = 0; i < cw.Bases.Count; i++) { - if (cw.Bases[i] == null) + if (cw.Bases[i].CallUser == null) { sb.AppendLine($"`{i + 1}.` ❌*unclaimed*"); } @@ -111,7 +110,7 @@ namespace NadekoBot.Modules.ClashOfClans public static int FinishClaim(this ClashWar cw, string user, int stars = 3) { user = user.Trim(); - for (var i = 0; i < cw.Bases.Capacity; i++) + for (var i = 0; i < cw.Bases.Count; i++) { if (cw.Bases[i]?.BaseDestroyed != false || cw.Bases[i]?.CallUser != user) continue; cw.Bases[i].BaseDestroyed = true; @@ -120,5 +119,16 @@ namespace NadekoBot.Modules.ClashOfClans } throw new InvalidOperationException($"@{user} You are either not participating in that war, or you already destroyed a base."); } + + public static void FinishClaim(this ClashWar cw, int index, int stars = 3) + { + if (index < 0 || index > cw.Bases.Count) + throw new ArgumentOutOfRangeException(nameof(index)); + var toFinish = cw.Bases[index]; + if (toFinish.BaseDestroyed != false) throw new InvalidOperationException("That base is already destroyed."); + if (toFinish.CallUser == null) throw new InvalidOperationException("That base is unclaimed."); + toFinish.BaseDestroyed = true; + toFinish.Stars = stars; + } } } \ No newline at end of file diff --git a/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs b/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs index a8c71001..efbf1217 100644 --- a/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs +++ b/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs @@ -24,8 +24,8 @@ namespace NadekoBot.Modules.CustomReactions using (var uow = DbHandler.UnitOfWork()) { var items = uow.CustomReactions.GetAll(); - GuildReactions = new ConcurrentDictionary>(items.Where(g => g.GuildId != null).GroupBy(k => k.GuildId.Value).ToDictionary(g => g.Key, g => new ConcurrentHashSet(g))); - GlobalReactions = new ConcurrentHashSet(items.Where(g => g.GuildId == null)); + GuildReactions = new ConcurrentDictionary>(items.Where(g => g.GuildId != null && g.GuildId != 0).GroupBy(k => k.GuildId.Value).ToDictionary(g => g.Key, g => new ConcurrentHashSet(g))); + GlobalReactions = new ConcurrentHashSet(items.Where(g => g.GuildId == null || g.GuildId == 0)); } } public CustomReactions(ILocalization loc, CommandService cmds, ShardedDiscordClient client) : base(loc, cmds, client) @@ -33,7 +33,7 @@ namespace NadekoBot.Modules.CustomReactions client.MessageReceived += (imsg) => { var umsg = imsg as IUserMessage; - if (umsg == null) + if (umsg == null || imsg.Author.IsBot) return Task.CompletedTask; var channel = umsg.Channel as ITextChannel; @@ -42,19 +42,29 @@ namespace NadekoBot.Modules.CustomReactions var t = Task.Run(async () => { - var content = umsg.Content.ToLowerInvariant(); + var content = umsg.Content.Trim().ToLowerInvariant(); ConcurrentHashSet reactions; GuildReactions.TryGetValue(channel.Guild.Id, out reactions); if (reactions != null && reactions.Any()) { - var reaction = reactions.Where(cr => cr.TriggerWithContext(umsg) == content).Shuffle().FirstOrDefault(); + var reaction = reactions.Where(cr => { + var hasTarget = cr.Response.ToLowerInvariant().Contains("%target%"); + var trigger = cr.TriggerWithContext(umsg).Trim().ToLowerInvariant(); + return ((hasTarget && content.StartsWith(trigger + " ")) || content == trigger); + }).Shuffle().FirstOrDefault(); if (reaction != null) { try { await channel.SendMessageAsync(reaction.ResponseWithContext(umsg)).ConfigureAwait(false); } catch { } return; } } - var greaction = GlobalReactions.Where(cr => cr.TriggerWithContext(umsg) == content).Shuffle().FirstOrDefault(); + var greaction = GlobalReactions.Where(cr => + { + var hasTarget = cr.Response.ToLowerInvariant().Contains("%target%"); + var trigger = cr.TriggerWithContext(umsg).Trim().ToLowerInvariant(); + return ((hasTarget && content.StartsWith(trigger + " ")) || content == trigger); + }).Shuffle().FirstOrDefault(); + if (greaction != null) { try { await channel.SendMessageAsync(greaction.ResponseWithContext(umsg)).ConfigureAwait(false); } catch { } @@ -124,10 +134,32 @@ namespace NadekoBot.Modules.CustomReactions if (customReactions == null || !customReactions.Any()) await imsg.Channel.SendMessageAsync("`No custom reactions found`").ConfigureAwait(false); else - await imsg.Channel.SendMessageAsync(string.Join("\n", customReactions.OrderBy(cr => cr.Trigger).Skip((page - 1) * 10).Take(10))) + await imsg.Channel.SendMessageAsync($"`Page {page} of custom reactions:`\n" + string.Join("\n", customReactions.OrderBy(cr => cr.Trigger).Skip((page - 1) * 15).Take(15).Select(cr => $"`#{cr.Id}` `Trigger:` {cr.Trigger}"))) .ConfigureAwait(false); } + [NadekoCommand, Usage, Description, Aliases] + public async Task ShowCustReact(IUserMessage imsg, int id) + { + var channel = imsg.Channel as ITextChannel; + + ConcurrentHashSet customReactions; + if (channel == null) + customReactions = GlobalReactions; + else + customReactions = GuildReactions.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet()); + + var found = customReactions.FirstOrDefault(cr => cr.Id == id); + + if (found == null) + await imsg.Channel.SendMessageAsync("`No custom reaction found with that id.`").ConfigureAwait(false); + else + { + await imsg.Channel.SendMessageAsync($"`Custom reaction #{id}`\n`Trigger:` {found.Trigger}\n`Response:` {found.Response}") + .ConfigureAwait(false); + } + } + [NadekoCommand, Usage, Description, Aliases] public async Task DelCustReact(IUserMessage imsg, int id) { @@ -147,16 +179,16 @@ namespace NadekoBot.Modules.CustomReactions if (toDelete == null) //not found return; - if (toDelete.GuildId == null && channel == null) + if ((toDelete.GuildId == null || toDelete.GuildId == 0) && channel == null) { uow.CustomReactions.Remove(toDelete); GlobalReactions.RemoveWhere(cr => cr.Id == toDelete.Id); success = true; } - else if (toDelete.GuildId != null && channel?.Guild.Id == toDelete.GuildId) + else if ((toDelete.GuildId != null && toDelete.GuildId != 0) && channel?.Guild.Id == toDelete.GuildId) { uow.CustomReactions.Remove(toDelete); - GuildReactions.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet()).RemoveWhere(cr=>cr.Id == toDelete.Id); + GuildReactions.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet()).RemoveWhere(cr => cr.Id == toDelete.Id); success = true; } if(success) diff --git a/src/NadekoBot/Modules/CustomReactions/Extensions.cs b/src/NadekoBot/Modules/CustomReactions/Extensions.cs index 147d6dcf..91c3db20 100644 --- a/src/NadekoBot/Modules/CustomReactions/Extensions.cs +++ b/src/NadekoBot/Modules/CustomReactions/Extensions.cs @@ -12,27 +12,45 @@ namespace NadekoBot.Modules.CustomReactions { public static class Extensions { + public static Dictionary> responsePlaceholders = new Dictionary>() + { + {"%target%", (ctx, trigger) => { return ctx.Content.ToLowerInvariant().Substring(trigger.Length); } } + }; + public static Dictionary> placeholders = new Dictionary>() { {"%mention%", (ctx) => { return $"<@{NadekoBot.Client.GetCurrentUser().Id}>"; } }, {"%user%", (ctx) => { return ctx.Author.Mention; } }, - {"%target%", (ctx) => { return ctx.MentionedUsers.Shuffle().FirstOrDefault()?.Mention ?? "Nobody"; } }, {"%rng%", (ctx) => { return new NadekoRandom().Next(0,10).ToString(); } } }; - private static string ResolveCRString(this string str, IUserMessage ctx) + private static string ResolveTriggerString(this string str, IUserMessage ctx) { foreach (var ph in placeholders) { - str = str.Replace(ph.Key, ph.Value(ctx)); + str = str.ToLowerInvariant().Replace(ph.Key, ph.Value(ctx)); + } + return str; + } + + private static string ResolveResponseString(this string str, IUserMessage ctx, string resolvedTrigger) + { + foreach (var ph in placeholders) + { + str = str.ToLowerInvariant().Replace(ph.Key.ToLowerInvariant(), ph.Value(ctx)); + } + + foreach (var ph in responsePlaceholders) + { + str = str.ToLowerInvariant().Replace(ph.Key.ToLowerInvariant(), ph.Value(ctx, resolvedTrigger)); } return str; } public static string TriggerWithContext(this CustomReaction cr, IUserMessage ctx) - => cr.Trigger.ResolveCRString(ctx); + => cr.Trigger.ResolveTriggerString(ctx); public static string ResponseWithContext(this CustomReaction cr, IUserMessage ctx) - => cr.Response.ResolveCRString(ctx); + => cr.Response.ResolveResponseString(ctx, cr.Trigger.ResolveTriggerString(ctx)); } } diff --git a/src/NadekoBot/Modules/Gambling/Gambling.cs b/src/NadekoBot/Modules/Gambling/Gambling.cs index 6335295f..33278f2d 100644 --- a/src/NadekoBot/Modules/Gambling/Gambling.cs +++ b/src/NadekoBot/Modules/Gambling/Gambling.cs @@ -87,7 +87,7 @@ namespace NadekoBot.Modules.Gambling public async Task Give(IUserMessage umsg, long amount, [Remainder] IGuildUser receiver) { var channel = (ITextChannel)umsg.Channel; - if (amount <= 0) + if (amount <= 0 || umsg.Author.Id == receiver.Id) return; var success = await CurrencyHandler.RemoveCurrencyAsync((IGuildUser)umsg.Author, $"Gift to {receiver.Username} ({receiver.Id}).", amount, true).ConfigureAwait(false); if (!success) @@ -96,7 +96,7 @@ namespace NadekoBot.Modules.Gambling return; } await CurrencyHandler.AddCurrencyAsync(receiver, $"Gift from {umsg.Author.Username} ({umsg.Author.Id}).", amount, true).ConfigureAwait(false); - await channel.SendMessageAsync($"{umsg.Author.Mention} successfully sent {amount} {Gambling.CurrencyPluralName}s to {receiver.Mention}!").ConfigureAwait(false); + await channel.SendMessageAsync($"{umsg.Author.Mention} successfully sent {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} to {receiver.Mention}!").ConfigureAwait(false); } [NadekoCommand, Usage, Description, Aliases] @@ -117,7 +117,7 @@ namespace NadekoBot.Modules.Gambling await CurrencyHandler.AddCurrencyAsync(usrId, $"Awarded by bot owner. ({umsg.Author.Username}/{umsg.Author.Id})", (int)amount).ConfigureAwait(false); - await channel.SendMessageAsync($"{umsg.Author.Mention} successfully awarded {amount} {Gambling.CurrencyName}s to <@{usrId}>!").ConfigureAwait(false); + await channel.SendMessageAsync($"{umsg.Author.Mention} successfully awarded {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} to <@{usrId}>!").ConfigureAwait(false); } [NadekoCommand, Usage, Description, Aliases] @@ -130,9 +130,9 @@ namespace NadekoBot.Modules.Gambling return; if(await CurrencyHandler.RemoveCurrencyAsync(user, $"Taken by bot owner.({umsg.Author.Username}/{umsg.Author.Id})", amount, true).ConfigureAwait(false)) - await channel.SendMessageAsync($"{umsg.Author.Mention} successfully took {amount} {Gambling.CurrencyPluralName} from {user}!").ConfigureAwait(false); + await channel.SendMessageAsync($"{umsg.Author.Mention} successfully took {amount} {(amount == 1? Gambling.CurrencyName : Gambling.CurrencyPluralName)} from {user}!").ConfigureAwait(false); else - await channel.SendMessageAsync($"{umsg.Author.Mention} was unable to take {amount} {Gambling.CurrencyPluralName} from {user} because the user doesn't have that much {Gambling.CurrencyPluralName}!").ConfigureAwait(false); + await channel.SendMessageAsync($"{umsg.Author.Mention} was unable to take {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} from {user} because the user doesn't have that much {Gambling.CurrencyPluralName}!").ConfigureAwait(false); } @@ -146,9 +146,9 @@ namespace NadekoBot.Modules.Gambling return; if(await CurrencyHandler.RemoveCurrencyAsync(usrId, $"Taken by bot owner.({umsg.Author.Username}/{umsg.Author.Id})", amount).ConfigureAwait(false)) - await channel.SendMessageAsync($"{umsg.Author.Mention} successfully took {amount} {Gambling.CurrencyName}s from <@{usrId}>!").ConfigureAwait(false); + await channel.SendMessageAsync($"{umsg.Author.Mention} successfully took {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} from <@{usrId}>!").ConfigureAwait(false); else - await channel.SendMessageAsync($"{umsg.Author.Mention} was unable to take {amount} {Gambling.CurrencyPluralName} from `{usrId}` because the user doesn't have that much {Gambling.CurrencyPluralName}!").ConfigureAwait(false); + await channel.SendMessageAsync($"{umsg.Author.Mention} was unable to take {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} from `{usrId}` because the user doesn't have that much {Gambling.CurrencyPluralName}!").ConfigureAwait(false); } [NadekoCommand, Usage, Description, Aliases] diff --git a/src/NadekoBot/Modules/Games/Commands/PollCommands.cs b/src/NadekoBot/Modules/Games/Commands/PollCommands.cs index 5daf7add..c31fc654 100644 --- a/src/NadekoBot/Modules/Games/Commands/PollCommands.cs +++ b/src/NadekoBot/Modules/Games/Commands/PollCommands.cs @@ -128,7 +128,7 @@ namespace NadekoBot.Modules.Games return; if (participants.TryAdd(msg.Author, vote)) { - try { await (ch as ITextChannel).SendMessageAsync($"Thanks for voting **{msg.Author.Username}**.").ConfigureAwait(false); } catch { } + try { await ((IMessageChannel)ch).SendMessageAsync($"Thanks for voting **{msg.Author.Username}**.").ConfigureAwait(false); } catch { } } }); return Task.CompletedTask; diff --git a/src/NadekoBot/Modules/Music/Classes/MusicControls.cs b/src/NadekoBot/Modules/Music/Classes/MusicControls.cs index fa4e2302..941a89b9 100644 --- a/src/NadekoBot/Modules/Music/Classes/MusicControls.cs +++ b/src/NadekoBot/Modules/Music/Classes/MusicControls.cs @@ -111,7 +111,7 @@ namespace NadekoBot.Modules.Music.Classes if (CurrentSong == null) continue; - + OnStarted(this, CurrentSong); await CurrentSong.Play(audioClient, cancelToken); @@ -122,8 +122,9 @@ namespace NadekoBot.Modules.Music.Classes if (RepeatSong) AddSong(CurrentSong, 0); - + } + catch (OperationCanceledException) { } finally { if (!cancelToken.IsCancellationRequested) @@ -250,9 +251,10 @@ namespace NadekoBot.Modules.Music.Classes RepeatSong = false; Destroyed = true; playlist.Clear(); + + try { await audioClient.DisconnectAsync(); } catch { } if (!SongCancelSource.IsCancellationRequested) SongCancelSource.Cancel(); - await audioClient.DisconnectAsync(); }); } diff --git a/src/NadekoBot/Modules/Music/Classes/Song.cs b/src/NadekoBot/Modules/Music/Classes/Song.cs index 00757f92..db2c72f8 100644 --- a/src/NadekoBot/Modules/Music/Classes/Song.cs +++ b/src/NadekoBot/Modules/Music/Classes/Song.cs @@ -53,7 +53,7 @@ namespace NadekoBot.Modules.Music.Classes private Logger _log; public int SkipTo { - get { return SkipTo; } + get { return skipTo; } set { skipTo = value; bytesSent = (ulong)skipTo * 3840 * 50; diff --git a/src/NadekoBot/Modules/Music/Music.cs b/src/NadekoBot/Modules/Music/Music.cs index 3e45fd48..61f04fba 100644 --- a/src/NadekoBot/Modules/Music/Music.cs +++ b/src/NadekoBot/Modules/Music/Music.cs @@ -72,9 +72,10 @@ namespace NadekoBot.Modules.Music var channel = (ITextChannel)umsg.Channel; MusicPlayer musicPlayer; - if (!MusicPlayers.TryRemove(channel.Guild.Id, out musicPlayer)) return Task.CompletedTask; + if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) return Task.CompletedTask; if (((IGuildUser)umsg.Author).VoiceChannel == musicPlayer.PlaybackVoiceChannel) - musicPlayer.Destroy(); + if(MusicPlayers.TryRemove(channel.Guild.Id, out musicPlayer)) + musicPlayer.Destroy(); return Task.CompletedTask; } diff --git a/src/NadekoBot/Modules/Permissions/PermissionExtensions.cs b/src/NadekoBot/Modules/Permissions/PermissionExtensions.cs index 783e2b90..991f25cd 100644 --- a/src/NadekoBot/Modules/Permissions/PermissionExtensions.cs +++ b/src/NadekoBot/Modules/Permissions/PermissionExtensions.cs @@ -136,7 +136,10 @@ namespace NadekoBot.Modules.Permissions com += $"<#{perm.PrimaryTargetId}>"; break; case PrimaryPermissionType.Role: - com += $"<@&{perm.PrimaryTargetId}>"; + if(guild == null) + com += $"<@&{perm.PrimaryTargetId}>"; + else + com += guild.GetRole(perm.PrimaryTargetId).ToString() ?? $"<@{perm.PrimaryTargetId}>"; break; case PrimaryPermissionType.Server: break; diff --git a/src/NadekoBot/Modules/Permissions/Permissions.cs b/src/NadekoBot/Modules/Permissions/Permissions.cs index d8e2d167..1ebb4433 100644 --- a/src/NadekoBot/Modules/Permissions/Permissions.cs +++ b/src/NadekoBot/Modules/Permissions/Permissions.cs @@ -11,12 +11,39 @@ using Discord; using NadekoBot.Services.Database; using NadekoBot.Services.Database.Models; using Discord.API; +using System.Collections.Concurrent; namespace NadekoBot.Modules.Permissions { [NadekoModule("Permissions", ";")] public partial class Permissions : DiscordModule { + public class PermissionCache + { + public string PermRole { get; set; } + public bool Verbose { get; set; } = true; + public Permission RootPermission { get; set; } + } + + //guildid, root permission + public static ConcurrentDictionary Cache; + + static Permissions() + { + using (var uow = DbHandler.UnitOfWork()) + { + Cache = new ConcurrentDictionary(uow.GuildConfigs + .PermissionsForAll() + .ToDictionary(k => k.GuildId, + v => new PermissionCache() + { + RootPermission = v.RootPermission, + Verbose = v.VerbosePermissions, + PermRole = v.PermissionRole + })); + } + } + public Permissions(ILocalization loc, CommandService cmds, ShardedDiscordClient client) : base(loc, cmds, client) { } @@ -31,6 +58,12 @@ namespace NadekoBot.Modules.Permissions { var config = uow.GuildConfigs.For(channel.Guild.Id); config.VerbosePermissions = action.Value; + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = Permission.GetDefaultRoot(), + Verbose = config.VerbosePermissions + }, (id, old) => { old.Verbose = config.VerbosePermissions; return old; }); await uow.CompleteAsync().ConfigureAwait(false); } @@ -52,6 +85,12 @@ namespace NadekoBot.Modules.Permissions } else { config.PermissionRole = role.Name.Trim(); + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = Permission.GetDefaultRoot(), + Verbose = config.VerbosePermissions + }, (id, old) => { old.PermRole = role.Name.Trim(); return old; }); await uow.CompleteAsync().ConfigureAwait(false); } } @@ -107,6 +146,12 @@ namespace NadekoBot.Modules.Permissions { p = perms.RemoveAt(index); } + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = config.RootPermission, + Verbose = config.VerbosePermissions + }, (id, old) => { old.RootPermission = config.RootPermission; return old; }); await uow.CompleteAsync().ConfigureAwait(false); } @@ -216,6 +261,12 @@ namespace NadekoBot.Modules.Permissions } config.RootPermission = fromPerm.GetRoot(); + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = config.RootPermission, + Verbose = config.VerbosePermissions + }, (id, old) => { old.RootPermission = config.RootPermission; return old; }); await uow.CompleteAsync().ConfigureAwait(false); } await channel.SendMessageAsync($"`Moved permission:` \"{fromPerm.GetCommand(channel.Guild)}\" `from #{++from} to #{++to}.`").ConfigureAwait(false); @@ -244,7 +295,14 @@ namespace NadekoBot.Modules.Permissions SecondaryTargetName = command.Text.ToLowerInvariant(), State = action.Value, }; - uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = config.RootPermission, + Verbose = config.VerbosePermissions + }, (id, old) => { old.RootPermission = config.RootPermission; return old; }); + await uow.CompleteAsync().ConfigureAwait(false); } await channel.SendMessageAsync($"{(action.Value ? "Allowed" : "Denied")} usage of `{command.Text}` command on this server.").ConfigureAwait(false); @@ -266,7 +324,13 @@ namespace NadekoBot.Modules.Permissions SecondaryTargetName = module.Name.ToLowerInvariant(), State = action.Value, }; - uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = config.RootPermission, + Verbose = config.VerbosePermissions + }, (id, old) => { old.RootPermission = config.RootPermission; return old; }); await uow.CompleteAsync().ConfigureAwait(false); } await channel.SendMessageAsync($"{(action.Value ? "Allowed" : "Denied")} usage of `{module.Name}` module on this server.").ConfigureAwait(false); @@ -288,7 +352,13 @@ namespace NadekoBot.Modules.Permissions SecondaryTargetName = command.Text.ToLowerInvariant(), State = action.Value, }; - uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = config.RootPermission, + Verbose = config.VerbosePermissions + }, (id, old) => { old.RootPermission = config.RootPermission; return old; }); await uow.CompleteAsync().ConfigureAwait(false); } await channel.SendMessageAsync($"{(action.Value ? "Allowed" : "Denied")} usage of `{command.Text}` command for `{user}` user.").ConfigureAwait(false); @@ -310,7 +380,13 @@ namespace NadekoBot.Modules.Permissions SecondaryTargetName = module.Name.ToLowerInvariant(), State = action.Value, }; - uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = config.RootPermission, + Verbose = config.VerbosePermissions + }, (id, old) => { old.RootPermission = config.RootPermission; return old; }); await uow.CompleteAsync().ConfigureAwait(false); } await channel.SendMessageAsync($"{(action.Value ? "Allowed" : "Denied")} usage of `{module.Name}` module for `{user}` user.").ConfigureAwait(false); @@ -332,7 +408,13 @@ namespace NadekoBot.Modules.Permissions SecondaryTargetName = command.Text.ToLowerInvariant(), State = action.Value, }; - uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = config.RootPermission, + Verbose = config.VerbosePermissions + }, (id, old) => { old.RootPermission = config.RootPermission; return old; }); await uow.CompleteAsync().ConfigureAwait(false); } await channel.SendMessageAsync($"{(action.Value ? "Allowed" : "Denied")} usage of `{command.Text}` command for `{role}` role.").ConfigureAwait(false); @@ -354,7 +436,13 @@ namespace NadekoBot.Modules.Permissions SecondaryTargetName = module.Name.ToLowerInvariant(), State = action.Value, }; - uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = config.RootPermission, + Verbose = config.VerbosePermissions + }, (id, old) => { old.RootPermission = config.RootPermission; return old; }); await uow.CompleteAsync().ConfigureAwait(false); } await channel.SendMessageAsync($"{(action.Value ? "Allowed" : "Denied")} usage of `{module.Name}` module for `{role}` role.").ConfigureAwait(false); @@ -377,7 +465,13 @@ namespace NadekoBot.Modules.Permissions SecondaryTargetName = command.Text.ToLowerInvariant(), State = action.Value, }; - uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = config.RootPermission, + Verbose = config.VerbosePermissions + }, (id, old) => { old.RootPermission = config.RootPermission; return old; }); await uow.CompleteAsync().ConfigureAwait(false); } } @@ -403,7 +497,13 @@ namespace NadekoBot.Modules.Permissions SecondaryTargetName = module.Name.ToLowerInvariant(), State = action.Value, }; - uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = config.RootPermission, + Verbose = config.VerbosePermissions + }, (id, old) => { old.RootPermission = config.RootPermission; return old; }); await uow.CompleteAsync().ConfigureAwait(false); } await channel.SendMessageAsync($"{(action.Value ? "Allowed" : "Denied")} usage of `{module.Name}` module for `{chnl}` channel.").ConfigureAwait(false); @@ -425,7 +525,13 @@ namespace NadekoBot.Modules.Permissions SecondaryTargetName = "*", State = action.Value, }; - uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = config.RootPermission, + Verbose = config.VerbosePermissions + }, (id, old) => { old.RootPermission = config.RootPermission; return old; }); await uow.CompleteAsync().ConfigureAwait(false); } await channel.SendMessageAsync($"{(action.Value ? "Allowed" : "Denied")} usage of `ALL MODULES` for `{chnl}` channel.").ConfigureAwait(false); @@ -447,7 +553,13 @@ namespace NadekoBot.Modules.Permissions SecondaryTargetName = "*", State = action.Value, }; - uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = config.RootPermission, + Verbose = config.VerbosePermissions + }, (id, old) => { old.RootPermission = config.RootPermission; return old; }); await uow.CompleteAsync().ConfigureAwait(false); } await channel.SendMessageAsync($"{(action.Value ? "Allowed" : "Denied")} usage of `ALL MODULES` for `{role}` role.").ConfigureAwait(false); @@ -469,7 +581,13 @@ namespace NadekoBot.Modules.Permissions SecondaryTargetName = "*", State = action.Value, }; - uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = config.RootPermission, + Verbose = config.VerbosePermissions + }, (id, old) => { old.RootPermission = config.RootPermission; return old; }); await uow.CompleteAsync().ConfigureAwait(false); } await channel.SendMessageAsync($"{(action.Value ? "Allowed" : "Denied")} usage of `ALL MODULES` for `{user}` user.").ConfigureAwait(false); @@ -502,7 +620,13 @@ namespace NadekoBot.Modules.Permissions State = true, }; - uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, allowUser); + var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, allowUser); + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = config.RootPermission, + Verbose = config.VerbosePermissions + }, (id, old) => { old.RootPermission = config.RootPermission; return old; }); await uow.CompleteAsync().ConfigureAwait(false); } await channel.SendMessageAsync($"{(action.Value ? "Allowed" : "Denied")} usage of `ALL MODULES` on this server.").ConfigureAwait(false); diff --git a/src/NadekoBot/Modules/Searches/Commands/IMDB/ImdbScraper.cs b/src/NadekoBot/Modules/Searches/Commands/IMDB/ImdbScraper.cs deleted file mode 100644 index ce8f8a37..00000000 --- a/src/NadekoBot/Modules/Searches/Commands/IMDB/ImdbScraper.cs +++ /dev/null @@ -1,175 +0,0 @@ -using NadekoBot.Extensions; -using NadekoBot.Modules.Searches.Models; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Text.RegularExpressions; -using System.Threading.Tasks; - -/******************************************************************************* -* Free ASP.net IMDb Scraper API for the new IMDb Template. -* Author: Abhinay Rathore -* Website: http://www.AbhinayRathore.com -* Blog: http://web3o.blogspot.com -* More Info: http://web3o.blogspot.com/2010/11/aspnetc-imdb-scraping-api.html - -* Updated By: Gergo Torcsvari -* Last Updated: Feb, 2016 -*******************************************************************************/ - -namespace NadekoBot.Modules.Searches.IMDB -{ - public static class ImdbScraper - { - //Search Engine URLs - private static string GoogleSearch = "https://www.google.com/search?q=imdb+"; - //Constructor - public static async Task ImdbScrape(string MovieName, bool GetExtraInfo = true) - { - ImdbMovie mov = new ImdbMovie(); - string imdbUrl = await GetIMDbUrlAsync(System.Uri.EscapeUriString(MovieName)); - mov.Status = false; - if (!string.IsNullOrWhiteSpace(imdbUrl)) - { - await ParseIMDbPage(imdbUrl, GetExtraInfo, mov); - } - - return mov; - } - - public static async Task ImdbScrapeFromId(string imdbId, bool GetExtraInfo = true) - { - ImdbMovie mov = new ImdbMovie(); - string imdbUrl = "http://www.imdb.com/title/" + imdbId + "/"; - mov.Status = false; - await ParseIMDbPage(imdbUrl, GetExtraInfo, mov); - return mov; - } - - public static async Task GetIMDBId(string MovieName) - { - string imdbUrl = await GetIMDbUrlAsync(System.Uri.EscapeUriString(MovieName)); - return Match(@"http://www.imdb.com/title/(tt\d{7})", imdbUrl); - } - //Get IMDb URL from search results - private static async Task GetIMDbUrlAsync(string MovieName) - { - string url = GoogleSearch + MovieName; - string html = await GetUrlDataAsync(url); - List imdbUrls = MatchAll(@".*?", html); - if (imdbUrls.Count > 0) - return (string)imdbUrls[0]; - else return String.Empty; - } - //Parse IMDb page data - private static async Task ParseIMDbPage(string imdbUrl, bool GetExtraInfo, ImdbMovie mov) - { - string html = await GetUrlDataAsync(imdbUrl + "combined"); - mov.Id = Match(@"", html); - if (!string.IsNullOrEmpty(mov.Id)) - { - mov.Status = true; - mov.Title = Match(@"(IMDb \- )*(.*?) \(.*?", html, 2); - mov.OriginalTitle = Match(@"title-extra"">(.*?)<", html); - mov.Year = Match(@".*?\(.*?(\d{4}).*?\).*?", Match(@"(.*?)", html)); - mov.Rating = Match(@"(\d.\d)/10", html); - mov.Genres = MatchAll(@"(.*?)", Match(@"Genre.?:(.*?)(|See more)", html)).Cast().ToList(); - mov.Plot = Match(@"Plot:.*?
(.*?)(.*?", html); - if (!string.IsNullOrEmpty(mov.Poster) && mov.Poster.IndexOf("media-imdb.com") > 0) - { - mov.Poster = Regex.Replace(mov.Poster, @"_V1.*?.jpg", "_V1._SY200.jpg"); - } - else - { - mov.Poster = string.Empty; - } - mov.ImdbURL = "http://www.imdb.com/title/" + mov.Id + "/"; - if (GetExtraInfo) - { - string plotHtml = await GetUrlDataAsync(imdbUrl + "plotsummary"); - await GetReleaseDatesAndAka(mov); - } - } - } - //Get all release dates and aka-s - private static async Task GetReleaseDatesAndAka(ImdbMovie mov) - { - Dictionary release = new Dictionary(); - string releasehtml = await GetUrlDataAsync("http://www.imdb.com/title/" + mov.Id + "/releaseinfo"); - foreach (string r in MatchAll(@"(.*?)", Match(@"\n*?(.*?)
", releasehtml))) - { - Match rd = new Regex(@"(.*?)\n*?.*?(.*?)", RegexOptions.Multiline).Match(r); - release[StripHTML(rd.Groups[1].Value.Trim())] = StripHTML(rd.Groups[2].Value.Trim()); - } - //mov.ReleaseDates = release; - - Dictionary aka = new Dictionary(); - List list = MatchAll(@".*?(.*?)", Match(@"\n*?(.*?)
", releasehtml)); - foreach (string r in list) - { - Match rd = new Regex(@"\n*?.*?(.*?)\n*?.*?(.*?)", RegexOptions.Multiline).Match(r); - aka[StripHTML(rd.Groups[1].Value.Trim())] = StripHTML(rd.Groups[2].Value.Trim()); - } - mov.Aka = aka; - - - - } - //Get all media images - private static async Task> GetMediaImages(ImdbMovie mov) - { - List list = new List(); - string mediaurl = "http://www.imdb.com/title/" + mov.Id + "/mediaindex"; - string mediahtml = await GetUrlDataAsync(mediaurl); - int pagecount = MatchAll(@"
", Match(@"(.*?)", mediahtml)).Count; - for (int p = 1; p <= pagecount + 1; p++) - { - mediahtml = await GetUrlDataAsync(mediaurl + "?page=" + p); - foreach (Match m in new Regex(@"src=""(.*?)""", RegexOptions.Multiline).Matches(Match(@"
(.*?)
", mediahtml))) - { - String image = m.Groups[1].Value; - list.Add(Regex.Replace(image, @"_V1\..*?.jpg", "_V1._SY0.jpg")); - } - } - return list; - } - //Get Recommended Titles - private static async Task> GetRecommendedTitlesAsync(ImdbMovie mov) - { - List list = new List(); - string recUrl = "http://www.imdb.com/widget/recommendations/_ajax/get_more_recs?specs=p13nsims%3A" + mov.Id; - string json = await GetUrlDataAsync(recUrl); - return MatchAll(@"title=\\""(.*?)\\""", json); - } - /*******************************[ Helper Methods ]********************************/ - //Match single instance - private static string Match(string regex, string html, int i = 1) - { - return new Regex(regex, RegexOptions.Multiline | RegexOptions.IgnoreCase).Match(html).Groups[i].ToString().Trim(); - } - //Match all instances and return as List - private static List MatchAll(string regex, string html, int i = 1) - { - List list = new List(); - foreach (Match m in new Regex(regex, RegexOptions.Multiline).Matches(html)) - list.Add(m.Groups[i].Value.Trim()); - return list; - } - //Strip HTML Tags - private static string StripHTML(string inputString) - { - return Regex.Replace(inputString, @"<.*?>", string.Empty); - } - //Get URL Data - private static async Task GetUrlDataAsync(string url) - { - using (var http = new HttpClient()) - { - http.AddFakeHeaders(); - return await http.GetStringAsync(url); - } - } - } -} \ No newline at end of file diff --git a/src/NadekoBot/Modules/Searches/Commands/Models/ImdbMovie.cs b/src/NadekoBot/Modules/Searches/Commands/Models/ImdbMovie.cs index f4fa1770..318eb6dc 100644 --- a/src/NadekoBot/Modules/Searches/Commands/Models/ImdbMovie.cs +++ b/src/NadekoBot/Modules/Searches/Commands/Models/ImdbMovie.cs @@ -26,7 +26,7 @@ $@"`Title:` {WebUtility.HtmlDecode(Title)} {(string.IsNullOrEmpty(OriginalTitle) `Genre:` {GenresAsString} `Link:` <{ImdbURL}> `Plot:` {System.Net.WebUtility.HtmlDecode(Plot.TrimTo(500))} -`img:` " + Poster; +`Poster:` " + NadekoBot.Google.ShortenUrl(Poster).GetAwaiter().GetResult(); public string GenresAsString => string.Join(", ", Genres); } diff --git a/src/NadekoBot/Modules/Searches/Commands/OMDB/OmdbProvider.cs b/src/NadekoBot/Modules/Searches/Commands/OMDB/OmdbProvider.cs new file mode 100644 index 00000000..12032805 --- /dev/null +++ b/src/NadekoBot/Modules/Searches/Commands/OMDB/OmdbProvider.cs @@ -0,0 +1,46 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; + +namespace NadekoBot.Modules.Searches.Commands.OMDB +{ + public static class OmdbProvider + { + private const string queryUrl = "http://www.omdbapi.com/?t={0}&y=&plot=full&r=json"; + + public static async Task FindMovie(string name) + { + using (var http = new HttpClient()) + { + var res = await http.GetStringAsync(String.Format(queryUrl,name.Trim().Replace(' ','+'))).ConfigureAwait(false); + var movie = JsonConvert.DeserializeObject(res); + + movie.Poster = await NadekoBot.Google.ShortenUrl(movie.Poster); + return movie; + } + } + } + + public class OmdbMovie + { + public string Title { get; set; } + public string Year { get; set; } + public string ImdbRating { get; set; } + public string ImdbId { get; set; } + public string Genre { get; set; } + public string Plot { get; set; } + public string Poster { get; set; } + + public override string ToString() => +$@"`Title:` {Title} +`Year:` {Year} +`Rating:` {ImdbRating} +`Genre:` {Genre} +`Link:` http://www.imdb.com/title/{ImdbId}/ +`Plot:` {Plot}"; + } +} diff --git a/src/NadekoBot/Modules/Searches/Searches.cs b/src/NadekoBot/Modules/Searches/Searches.cs index 5f676709..8118e011 100644 --- a/src/NadekoBot/Modules/Searches/Searches.cs +++ b/src/NadekoBot/Modules/Searches/Searches.cs @@ -12,11 +12,11 @@ using System.Text.RegularExpressions; using System.Net; using Discord.WebSocket; using NadekoBot.Modules.Searches.Models; -using NadekoBot.Modules.Searches.IMDB; using System.Collections.Generic; using ImageProcessorCore; using NadekoBot.Extensions; using System.IO; +using NadekoBot.Modules.Searches.Commands.OMDB; namespace NadekoBot.Modules.Searches { @@ -74,21 +74,14 @@ $@"🌍 **Weather for** 【{obj["target"]}】 if (!(await ValidateQuery(channel, query).ConfigureAwait(false))) return; await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false); - string result; - try - { - var movie = await ImdbScraper.ImdbScrape(query, true); - if (movie.Status) result = movie.ToString(); - else result = "Failed to find that movie."; - } - catch (Exception ex) + + var movie = await OmdbProvider.FindMovie(query); + if (movie == null) { await channel.SendMessageAsync("Failed to find that movie.").ConfigureAwait(false); - _log.Warn(ex); return; } - - await channel.SendMessageAsync(result.ToString()).ConfigureAwait(false); + await channel.SendMessageAsync(movie.ToString()).ConfigureAwait(false); } [NadekoCommand, Usage, Description, Aliases] diff --git a/src/NadekoBot/Modules/Utility/Commands/UnitConversion.cs b/src/NadekoBot/Modules/Utility/Commands/UnitConversion.cs index 0f86bcbc..12a4b8f3 100644 --- a/src/NadekoBot/Modules/Utility/Commands/UnitConversion.cs +++ b/src/NadekoBot/Modules/Utility/Commands/UnitConversion.cs @@ -66,35 +66,40 @@ namespace NadekoBot.Modules.Utility } public async Task UpdateCurrency() - { - var currencyRates = await UpdateCurrencyRates(); - var unitTypeString = "currency"; - var range = currencyRates.ConversionRates.Select(u => new ConvertUnit() + {try { - InternalTrigger = u.Key, - Modifier = u.Value, - UnitType = unitTypeString - }).ToArray(); - var baseType = new ConvertUnit() - { - Triggers = new[] { currencyRates.Base }, - Modifier = decimal.One, - UnitType = unitTypeString - }; - var toRemove = Units.Where(u => u.UnitType == unitTypeString); + var currencyRates = await UpdateCurrencyRates(); + var unitTypeString = "currency"; + var range = currencyRates.ConversionRates.Select(u => new ConvertUnit() + { + InternalTrigger = u.Key, + Modifier = u.Value, + UnitType = unitTypeString + }).ToArray(); + var baseType = new ConvertUnit() + { + Triggers = new[] { currencyRates.Base }, + Modifier = decimal.One, + UnitType = unitTypeString + }; + var toRemove = Units.Where(u => u.UnitType == unitTypeString); - using (var uow = DbHandler.UnitOfWork()) - { - uow.ConverterUnits.RemoveRange(toRemove.ToArray()); - uow.ConverterUnits.Add(baseType); - uow.ConverterUnits.AddRange(range); + using (var uow = DbHandler.UnitOfWork()) + { + uow.ConverterUnits.RemoveRange(toRemove.ToArray()); + uow.ConverterUnits.Add(baseType); + uow.ConverterUnits.AddRange(range); - await uow.CompleteAsync().ConfigureAwait(false); + await uow.CompleteAsync().ConfigureAwait(false); + } + Units.RemoveAll(u => u.UnitType == unitTypeString); + Units.Add(baseType); + Units.AddRange(range); + _log.Info("Updated Currency"); + } + catch { + _log.Warn("Failed updating currency."); } - Units.RemoveAll(u => u.UnitType == unitTypeString); - Units.Add(baseType); - Units.AddRange(range); - _log.Info("Updated Currency"); } [NadekoCommand, Usage, Description, Aliases] [RequireContext(ContextType.Guild)] @@ -143,10 +148,10 @@ namespace NadekoBot.Modules.Utility break; } //from Kelvin to target - switch (targetUnit.Triggers.First()) + switch (targetUnit.Triggers.First().ToUpperInvariant()) { case "C": - res = value - 273.15m; //celcius! + res = res - 273.15m; //celcius! break; case "F": res = res * (9m / 5m) - 459.67m; diff --git a/src/NadekoBot/Resources/CommandStrings.Designer.cs b/src/NadekoBot/Resources/CommandStrings.Designer.cs index aa85279f..48332af8 100644 --- a/src/NadekoBot/Resources/CommandStrings.Designer.cs +++ b/src/NadekoBot/Resources/CommandStrings.Designer.cs @@ -366,7 +366,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to Adds a role, or list of roles separated by whitespace(use quotations for multiword roles) to the list of self-assignable roles.. + /// Looks up a localized string similar to Adds a role to the list of self-assignable roles.. /// public static string asar_desc { get { @@ -1338,7 +1338,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to Finish your claim with 3 stars if you destroyed a base. First argument is the war number, optional second argument finishes for someone else.. + /// Looks up a localized string similar to Finish your claim with 3 stars if you destroyed a base. First argument is the war number, optional second argument is a base number if you want to finish for someone else.. /// public static string claimfinish_desc { get { @@ -1347,7 +1347,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to `,cf 1 Someone`. + /// Looks up a localized string similar to `,cf 1` or `,cf 1 5`. /// public static string claimfinish_usage { get { @@ -1365,7 +1365,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to Finish your claim with 1 star if you destroyed a base. First argument is the war number, optional second argument finishes for someone else.. + /// Looks up a localized string similar to Finish your claim with 1 star if you destroyed a base. First argument is the war number, optional second argument is a base number if you want to finish for someone else.. /// public static string claimfinish1_desc { get { @@ -1374,7 +1374,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to `,cf1 2 SomeGirl`. + /// Looks up a localized string similar to `,cf1 1` or `,cf1 1 5`. /// public static string claimfinish1_usage { get { @@ -1392,7 +1392,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to Finish your claim with 2 stars if you destroyed a base. First argument is the war number, optional second argument finishes for someone else.. + /// Looks up a localized string similar to Finish your claim with 2 stars if you destroyed a base. First argument is the war number, optional second argument is a base number if you want to finish for someone else.. /// public static string claimfinish2_desc { get { @@ -1401,7 +1401,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to `,cf2 1 SomeGuy`. + /// Looks up a localized string similar to `,cf2 1` or `,cf2 1 5`. /// public static string claimfinish2_usage { get { @@ -2067,7 +2067,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to Add a donator to the database. **Kwoth Only**. + /// Looks up a localized string similar to Add a donator to the database.. /// public static string donadd_desc { get { @@ -3111,7 +3111,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to imdb. + /// Looks up a localized string similar to imdb omdb. /// public static string imdb_cmd { get { @@ -3120,7 +3120,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to Queries imdb for movies or series, show first result.. + /// Looks up a localized string similar to Queries omdb for movies or series, show first result.. /// public static string imdb_desc { get { @@ -4641,7 +4641,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to `~pokeab "water gun"`. + /// Looks up a localized string similar to `~pokeab overgrow`. /// public static string pokemonability_usage { get { @@ -5550,7 +5550,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to List all roles on this server or a single user if specified.. + /// Looks up a localized string similar to List roles on this server or a roles of a specific user if specified. Paginated. 20 roles per page.. /// public static string roles_desc { get { @@ -5559,7 +5559,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to `.roles`. + /// Looks up a localized string similar to `.roles 2` or `.roles @Someone`. /// public static string roles_usage { get { @@ -6171,7 +6171,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to Shows all possible responses from a single custom reaction.. + /// Looks up a localized string similar to Shows a custom reaction's response on a given ID.. /// public static string showcustreact_desc { get { @@ -6180,7 +6180,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to `.scr %mention% bb`. + /// Looks up a localized string similar to `.scr 1`. /// public static string showcustreact_usage { get { diff --git a/src/NadekoBot/Resources/CommandStrings.resx b/src/NadekoBot/Resources/CommandStrings.resx index 3072d75f..426ab5f7 100644 --- a/src/NadekoBot/Resources/CommandStrings.resx +++ b/src/NadekoBot/Resources/CommandStrings.resx @@ -382,7 +382,7 @@ asar - Adds a role, or list of roles separated by whitespace(use quotations for multiword roles) to the list of self-assignable roles. + Adds a role to the list of self-assignable roles. `.asar Gamer` @@ -454,10 +454,10 @@ showcustreact scr - Shows all possible responses from a single custom reaction. + Shows a custom reaction's response on a given ID. - `.scr %mention% bb` + `.scr 1` editcustreact ecr @@ -796,7 +796,7 @@ donadd - Add a donator to the database. **Kwoth Only** + Add a donator to the database. `.donadd Donate Amount` @@ -940,10 +940,10 @@ roles - List all roles on this server or a single user if specified. + List roles on this server or a roles of a specific user if specified. Paginated. 20 roles per page. - `.roles` + `.roles 2` or `.roles @Someone` channeltopic ct @@ -1996,7 +1996,7 @@ Searches for a pokemon ability. - `~pokeab "water gun"` + `~pokeab overgrow` memelist @@ -2044,10 +2044,10 @@ `~ani aquarion evol` - imdb + imdb omdb - Queries imdb for movies or series, show first result. + Queries omdb for movies or series, show first result. `~imdb Batman vs Superman` @@ -2362,28 +2362,28 @@ claimfinish cf - Finish your claim with 3 stars if you destroyed a base. First argument is the war number, optional second argument finishes for someone else. + Finish your claim with 3 stars if you destroyed a base. First argument is the war number, optional second argument is a base number if you want to finish for someone else. - `,cf 1 Someone` + `,cf 1` or `,cf 1 5` claimfinish2 cf2 - Finish your claim with 2 stars if you destroyed a base. First argument is the war number, optional second argument finishes for someone else. + Finish your claim with 2 stars if you destroyed a base. First argument is the war number, optional second argument is a base number if you want to finish for someone else. - `,cf2 1 SomeGuy` + `,cf2 1` or `,cf2 1 5` claimfinish1 cf1 - Finish your claim with 1 star if you destroyed a base. First argument is the war number, optional second argument finishes for someone else. + Finish your claim with 1 star if you destroyed a base. First argument is the war number, optional second argument is a base number if you want to finish for someone else. - `,cf1 2 SomeGirl` + `,cf1 1` or `,cf1 1 5` unclaim ucall uc diff --git a/src/NadekoBot/Services/CommandHandler.cs b/src/NadekoBot/Services/CommandHandler.cs index 21bce20e..628e883a 100644 --- a/src/NadekoBot/Services/CommandHandler.cs +++ b/src/NadekoBot/Services/CommandHandler.cs @@ -129,7 +129,7 @@ namespace NadekoBot.Services { var t = await ExecuteCommand(usrMsg, usrMsg.Content, guild, usrMsg.Author, MultiMatchHandling.Best); var command = t.Item1; - var verbose = t.Item2; + var permCache = t.Item2; var result = t.Item3; sw.Stop(); var channel = (usrMsg.Channel as ITextChannel); @@ -165,7 +165,7 @@ namespace NadekoBot.Services ); if (guild != null && command != null && result.Error == CommandError.Exception) { - if (verbose) + if (permCache != null && permCache.Verbose) try { await msg.Channel.SendMessageAsync(":warning: " + result.ErrorReason).ConfigureAwait(false); } catch { } } } @@ -189,10 +189,10 @@ namespace NadekoBot.Services return; } - public async Task> ExecuteCommand(IUserMessage message, string input, IGuild guild, IUser user, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Best) { + public async Task> ExecuteCommand(IUserMessage message, string input, IGuild guild, IUser user, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Best) { var searchResult = _commandService.Search(message, input); if (!searchResult.IsSuccess) - return new Tuple(null, false, searchResult); + return new Tuple(null, null, searchResult); var commands = searchResult.Commands; for (int i = commands.Count - 1; i >= 0; i--) @@ -201,7 +201,7 @@ namespace NadekoBot.Services if (!preconditionResult.IsSuccess) { if (commands.Count == 1) - return new Tuple(null, false, searchResult); + return new Tuple(null, null, searchResult); else continue; } @@ -225,55 +225,55 @@ namespace NadekoBot.Services if (!parseResult.IsSuccess) { if (commands.Count == 1) - return new Tuple(null, false, parseResult); + return new Tuple(null, null, parseResult); else continue; } } - bool verbose = false; - Permission rootPerm = null; - string permRole = ""; - if (guild != null) - { - using (var uow = DbHandler.UnitOfWork()) - { - var config = uow.GuildConfigs.PermissionsFor(guild.Id); - verbose = config.VerbosePermissions; - rootPerm = config.RootPermission; - permRole = config.PermissionRole.Trim().ToLowerInvariant(); - } - } - _log.Info("Permissions retrieved"); + var cmd = commands[i]; bool resetCommand = cmd.Name == "ResetPermissions"; - //check permissions + PermissionCache pc; if (guild != null) { - int index; - if (!resetCommand && !rootPerm.AsEnumerable().CheckPermissions(message, cmd.Text, cmd.Module.Name, out index)) + pc = Permissions.Cache.GetOrAdd(guild.Id, (id) => { - var returnMsg = $"Permission number #{index + 1} **{rootPerm.GetAt(index).GetCommand()}** is preventing this action."; - return new Tuple(cmd, verbose, SearchResult.FromError(CommandError.Exception, returnMsg)); + using (var uow = DbHandler.UnitOfWork()) + { + var config = uow.GuildConfigs.PermissionsFor(guild.Id); + return new PermissionCache() + { + Verbose = config.VerbosePermissions, + RootPermission = config.RootPermission, + PermRole = config.PermissionRole.Trim().ToLowerInvariant(), + }; + } + }); + int index; + if (!resetCommand && !pc.RootPermission.AsEnumerable().CheckPermissions(message, cmd.Text, cmd.Module.Name, out index)) + { + var returnMsg = $"Permission number #{index + 1} **{pc.RootPermission.GetAt(index).GetCommand()}** is preventing this action."; + return new Tuple(cmd, pc, SearchResult.FromError(CommandError.Exception, returnMsg)); } if (cmd.Module.Source.Name == typeof(Permissions).Name) //permissions, you must have special role { - if (!((IGuildUser)user).Roles.Any(r => r.Name.Trim().ToLowerInvariant() == permRole)) + if (!((IGuildUser)user).Roles.Any(r => r.Name.Trim().ToLowerInvariant() == pc.PermRole.Trim().ToLowerInvariant())) { - return new Tuple(cmd, false, SearchResult.FromError(CommandError.Exception, $"You need the **{permRole}** role in order to use permission commands.")); + return new Tuple(cmd, pc, SearchResult.FromError(CommandError.Exception, $"You need the **{pc.PermRole}** role in order to use permission commands.")); } } } if (CmdCdsCommands.HasCooldown(cmd, guild, user)) - return new Tuple(cmd, false, SearchResult.FromError(CommandError.Exception, $"That command is on cooldown for you.")); + return new Tuple(cmd, null, SearchResult.FromError(CommandError.Exception, $"That command is on cooldown for you.")); - return new Tuple(commands[i], false, await commands[i].Execute(message, parseResult)); + return new Tuple(commands[i], null, await commands[i].Execute(message, parseResult)); } - return new Tuple(null, false, SearchResult.FromError(CommandError.UnknownCommand, "This input does not match any overload.")); + return new Tuple(null, null, SearchResult.FromError(CommandError.UnknownCommand, "This input does not match any overload.")); } } diff --git a/src/NadekoBot/Services/CurrencyHandler.cs b/src/NadekoBot/Services/CurrencyHandler.cs index 2c0128b3..6b9f26f7 100644 --- a/src/NadekoBot/Services/CurrencyHandler.cs +++ b/src/NadekoBot/Services/CurrencyHandler.cs @@ -7,6 +7,7 @@ using Discord; using NadekoBot.Services.Database; using NadekoBot.Extensions; using NadekoBot.Modules.Gambling; +using NadekoBot.Services.Database.Models; namespace NadekoBot.Services { @@ -33,6 +34,12 @@ namespace NadekoBot.Services var success = uow.Currency.TryUpdateState(authorId, -amount); if (!success) return false; + uow.CurrencyTransactions.Add(new CurrencyTransaction() + { + UserId = authorId, + Reason = reason, + Amount = amount, + }); await uow.CompleteAsync().ConfigureAwait(false); } @@ -56,6 +63,12 @@ namespace NadekoBot.Services using (var uow = DbHandler.UnitOfWork()) { uow.Currency.TryUpdateState(receiverId, amount); + uow.CurrencyTransactions.Add(new CurrencyTransaction() + { + UserId = receiverId, + Reason = reason, + Amount = amount, + }); await uow.CompleteAsync(); } } diff --git a/src/NadekoBot/Services/Database/IUnitOfWork.cs b/src/NadekoBot/Services/Database/IUnitOfWork.cs index a56fafdb..3704bf2f 100644 --- a/src/NadekoBot/Services/Database/IUnitOfWork.cs +++ b/src/NadekoBot/Services/Database/IUnitOfWork.cs @@ -22,6 +22,7 @@ namespace NadekoBot.Services.Database IUnitConverterRepository ConverterUnits { get; } ICustomReactionRepository CustomReactions { get; } ICurrencyRepository Currency { get; } + ICurrencyTransactionsRepository CurrencyTransactions { get; } IMusicPlaylistRepository MusicPlaylists { get; } int Complete(); diff --git a/src/NadekoBot/Services/Database/Models/ClashCaller.cs b/src/NadekoBot/Services/Database/Models/ClashCaller.cs index 2f875049..719ef9ee 100644 --- a/src/NadekoBot/Services/Database/Models/ClashCaller.cs +++ b/src/NadekoBot/Services/Database/Models/ClashCaller.cs @@ -9,6 +9,7 @@ namespace NadekoBot.Services.Database.Models { public class ClashCaller : DbEntity { + public int? SequenceNumber { get; set; } = null; public string CallUser { get; set; } public DateTime TimeAdded { get; set; } diff --git a/src/NadekoBot/Services/Database/Models/CurrencyTransaction.cs b/src/NadekoBot/Services/Database/Models/CurrencyTransaction.cs new file mode 100644 index 00000000..be36ca5f --- /dev/null +++ b/src/NadekoBot/Services/Database/Models/CurrencyTransaction.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NadekoBot.Services.Database.Models +{ + public class CurrencyTransaction : DbEntity + { + public long Amount { get; set; } + public string Reason { get; set; } + public ulong UserId { get; set; } + } +} diff --git a/src/NadekoBot/Services/Database/NadekoContext.cs b/src/NadekoBot/Services/Database/NadekoContext.cs index 0f0b5325..156df04a 100644 --- a/src/NadekoBot/Services/Database/NadekoContext.cs +++ b/src/NadekoBot/Services/Database/NadekoContext.cs @@ -24,6 +24,7 @@ namespace NadekoBot.Services.Database public DbSet ConversionUnits { get; set; } public DbSet MusicPlaylists { get; set; } public DbSet CustomReactions { get; set; } + public DbSet CurrencyTransactions { get; set; } //logging public DbSet LogSettings { get; set; } diff --git a/src/NadekoBot/Services/Database/Repositories/ICurrencyTransactionsRepository.cs b/src/NadekoBot/Services/Database/Repositories/ICurrencyTransactionsRepository.cs new file mode 100644 index 00000000..9cada99b --- /dev/null +++ b/src/NadekoBot/Services/Database/Repositories/ICurrencyTransactionsRepository.cs @@ -0,0 +1,13 @@ +using NadekoBot.Services.Database.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NadekoBot.Services.Database.Repositories +{ + public interface ICurrencyTransactionsRepository : IRepository + { + } +} diff --git a/src/NadekoBot/Services/Database/Repositories/IGuildConfigRepository.cs b/src/NadekoBot/Services/Database/Repositories/IGuildConfigRepository.cs index e6797de1..7a780380 100644 --- a/src/NadekoBot/Services/Database/Repositories/IGuildConfigRepository.cs +++ b/src/NadekoBot/Services/Database/Repositories/IGuildConfigRepository.cs @@ -12,7 +12,8 @@ namespace NadekoBot.Services.Database.Repositories { GuildConfig For(ulong guildId); GuildConfig PermissionsFor(ulong guildId); - void SetNewRootPermission(ulong guildId, Permission p); + IEnumerable PermissionsForAll(); + GuildConfig SetNewRootPermission(ulong guildId, Permission p); IEnumerable GetAllFollowedStreams(); } } diff --git a/src/NadekoBot/Services/Database/Repositories/Impl/ClashOfClansRepository.cs b/src/NadekoBot/Services/Database/Repositories/Impl/ClashOfClansRepository.cs index 78b2aaf3..bbe12205 100644 --- a/src/NadekoBot/Services/Database/Repositories/Impl/ClashOfClansRepository.cs +++ b/src/NadekoBot/Services/Database/Repositories/Impl/ClashOfClansRepository.cs @@ -16,8 +16,10 @@ namespace NadekoBot.Services.Database.Repositories.Impl public IEnumerable GetAllWars() { - return _set.Include(cw => cw.Bases) + var toReturn = _set.Include(cw => cw.Bases) .ToList(); + toReturn.ForEach(cw => cw.Bases = cw.Bases.Where(w => w.SequenceNumber != null).OrderBy(w => w.SequenceNumber).ToList()); + return toReturn; } } } diff --git a/src/NadekoBot/Services/Database/Repositories/Impl/CurrencyTransactionsRepository.cs b/src/NadekoBot/Services/Database/Repositories/Impl/CurrencyTransactionsRepository.cs new file mode 100644 index 00000000..8a8bffe8 --- /dev/null +++ b/src/NadekoBot/Services/Database/Repositories/Impl/CurrencyTransactionsRepository.cs @@ -0,0 +1,17 @@ +using NadekoBot.Services.Database.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; + +namespace NadekoBot.Services.Database.Repositories.Impl +{ + public class CurrencyTransactionsRepository : Repository, ICurrencyTransactionsRepository + { + public CurrencyTransactionsRepository(DbContext context) : base(context) + { + } + } +} diff --git a/src/NadekoBot/Services/Database/Repositories/Impl/GuildConfigRepository.cs b/src/NadekoBot/Services/Database/Repositories/Impl/GuildConfigRepository.cs index 0e9151bb..1b3c1501 100644 --- a/src/NadekoBot/Services/Database/Repositories/Impl/GuildConfigRepository.cs +++ b/src/NadekoBot/Services/Database/Repositories/Impl/GuildConfigRepository.cs @@ -90,12 +90,28 @@ namespace NadekoBot.Services.Database.Repositories.Impl return config; } + public IEnumerable PermissionsForAll() + { + var query = _set.Include(gc => gc.RootPermission); + + //todo this is possibly a disaster for performance + //What i could do instead is count the number of permissions in the permission table for this guild + // and make a for loop with those. + // or just select permissions for this guild and manually chain them + for (int i = 0; i < 60; i++) + { + query = query.ThenInclude(gc => gc.Next); + } + + return query.ToList(); + } + public IEnumerable GetAllFollowedStreams() => _set.Include(gc => gc.FollowedStreams) .SelectMany(gc => gc.FollowedStreams) .ToList(); - public void SetNewRootPermission(ulong guildId, Permission p) + public GuildConfig SetNewRootPermission(ulong guildId, Permission p) { var data = _set .Include(gc => gc.RootPermission) @@ -103,6 +119,7 @@ namespace NadekoBot.Services.Database.Repositories.Impl data.RootPermission.Prepend(p); data.RootPermission = p; + return data; } } } diff --git a/src/NadekoBot/Services/Database/UnitOfWork.cs b/src/NadekoBot/Services/Database/UnitOfWork.cs index 43cc5f6d..b4dd1e8b 100644 --- a/src/NadekoBot/Services/Database/UnitOfWork.cs +++ b/src/NadekoBot/Services/Database/UnitOfWork.cs @@ -39,6 +39,9 @@ namespace NadekoBot.Services.Database private ICurrencyRepository _currency; public ICurrencyRepository Currency => _currency ?? (_currency = new CurrencyRepository(_context)); + private ICurrencyTransactionsRepository _currencyTransactions; + public ICurrencyTransactionsRepository CurrencyTransactions => _currencyTransactions ?? (_currencyTransactions = new CurrencyTransactionsRepository(_context)); + private IUnitConverterRepository _conUnits; public IUnitConverterRepository ConverterUnits => _conUnits ?? (_conUnits = new UnitConverterRepository(_context)); diff --git a/src/NadekoBot/Services/Impl/BotCredentials.cs b/src/NadekoBot/Services/Impl/BotCredentials.cs index 9343efd9..52af1934 100644 --- a/src/NadekoBot/Services/Impl/BotCredentials.cs +++ b/src/NadekoBot/Services/Impl/BotCredentials.cs @@ -33,6 +33,8 @@ namespace NadekoBot.Services.Impl public BotCredentials() { _log = LogManager.GetCurrentClassLogger(); + + try { File.WriteAllText("./credentials_example.json", JsonConvert.SerializeObject(new CredentialsModel(), Formatting.Indented)); } catch { } if (File.Exists("./credentials.json")) { var cm = JsonConvert.DeserializeObject(File.ReadAllText("./credentials.json")); @@ -52,23 +54,23 @@ namespace NadekoBot.Services.Impl } else { - File.WriteAllText("./credentials_example.json", JsonConvert.SerializeObject(new CredentialsModel(), Formatting.Indented)); - _log.Fatal($"credentials.json is missing. Failed to start. Example written to {Path.GetFullPath("./credentials_example.json")}"); + _log.Fatal($"credentials.json is missing. Failed to start. Example is in {Path.GetFullPath("./credentials_example.json")}"); throw new FileNotFoundException(); } + } private class CredentialsModel { - public ulong ClientId { get; set; } + public ulong ClientId { get; set; } = 123123123; public ulong? BotId { get; set; } - public string Token { get; set; } - public ulong[] OwnerIds { get; set; } - public string LoLApiKey { get; set; } - public string GoogleApiKey { get; set; } - public string MashapeKey { get; set; } - public string OsuApiKey { get; set; } - public string SoundCloudClientId { get; set; } + public string Token { get; set; } = ""; + public ulong[] OwnerIds { get; set; } = new ulong[1]; + public string LoLApiKey { get; set; } = ""; + public string GoogleApiKey { get; set; } = ""; + public string MashapeKey { get; set; } = ""; + public string OsuApiKey { get; set; } = ""; + public string SoundCloudClientId { get; set; } = ""; public DB Db { get; set; } public int TotalShards { get; set; } = 1; } diff --git a/src/NadekoBot/Services/Impl/GoogleApiService.cs b/src/NadekoBot/Services/Impl/GoogleApiService.cs index 4d74e290..712dc4a9 100644 --- a/src/NadekoBot/Services/Impl/GoogleApiService.cs +++ b/src/NadekoBot/Services/Impl/GoogleApiService.cs @@ -7,6 +7,7 @@ using Google.Apis.Services; using System.Text.RegularExpressions; using Google.Apis.Urlshortener.v1; using Google.Apis.Urlshortener.v1.Data; +using NLog; namespace NadekoBot.Services.Impl { @@ -14,6 +15,7 @@ namespace NadekoBot.Services.Impl { private YouTubeService yt; private UrlshortenerService sh; + private Logger _log { get; } public GoogleApiService() { @@ -23,6 +25,8 @@ namespace NadekoBot.Services.Impl ApiKey = NadekoBot.Credentials.GoogleApiKey }; + _log = LogManager.GetCurrentClassLogger(); + yt = new YouTubeService(bcs); sh = new UrlshortenerService(bcs); } @@ -85,9 +89,16 @@ namespace NadekoBot.Services.Impl { if (string.IsNullOrWhiteSpace(url)) throw new ArgumentNullException(nameof(url)); - - var response = await sh.Url.Insert(new Url { LongUrl = url }).ExecuteAsync(); - return response.Id; + try + { + var response = await sh.Url.Insert(new Url { LongUrl = url }).ExecuteAsync(); + return response.Id; + } + catch (Exception ex) + { + _log.Warn(ex); + return url; + } } public async Task> GetPlaylistTracksAsync(string playlistId, int count = 50) @@ -108,7 +119,7 @@ namespace NadekoBot.Services.Impl count -= toGet; var query = yt.PlaylistItems.List("contentDetails"); - query.MaxResults = count; + query.MaxResults = toGet; query.PlaylistId = playlistId; query.PageToken = nextPageToken; diff --git a/src/NadekoBot/Services/Impl/StatsService.cs b/src/NadekoBot/Services/Impl/StatsService.cs index a2ec5b65..1c84cf63 100644 --- a/src/NadekoBot/Services/Impl/StatsService.cs +++ b/src/NadekoBot/Services/Impl/StatsService.cs @@ -33,17 +33,17 @@ namespace NadekoBot.Services.Impl this.client.Disconnected += _ => Reset(); } - public Task Print() + public async Task Print() { - var curUser = client.GetCurrentUser(); - return Task.FromResult($@"`Author: Kwoth` `Library: Discord.Net` + var curUser = await client.GetCurrentUserAsync(); + return $@"`Author: Kwoth` `Library: Discord.Net` `Bot Version: {BotVersion}` `Bot id: {curUser.Id}` `Owners' Ids: {string.Join(", ", NadekoBot.Credentials.OwnerIds)}` `Uptime: {GetUptimeString()}` `Servers: {client.GetGuilds().Count} | TextChannels: {client.GetGuilds().SelectMany(g => g.GetChannels().Where(c => c is ITextChannel)).Count()} | VoiceChannels: {client.GetGuilds().SelectMany(g => g.GetChannels().Where(c => c is IVoiceChannel)).Count()}` `Commands Ran this session: {commandsRan}` -`Messages: {messageCounter} ({messageCounter / (double)GetUptime().TotalSeconds:F2}/sec)` `Heap: {Heap} MB`"); +`Messages: {messageCounter} ({messageCounter / (double)GetUptime().TotalSeconds:F2}/sec)` `Heap: {Heap} MB`"; } public Task Reset() diff --git a/src/NadekoBot/ShardedDiscordClient.cs b/src/NadekoBot/ShardedDiscordClient.cs index 30bc3139..b119df42 100644 --- a/src/NadekoBot/ShardedDiscordClient.cs +++ b/src/NadekoBot/ShardedDiscordClient.cs @@ -64,8 +64,11 @@ namespace NadekoBot Clients = clientList.AsReadOnly(); } - public ISelfUser GetCurrentUser() => - Clients.Select(c => c.GetCurrentUser()).FirstOrDefault(u => u != null); + public ISelfUser GetCurrentUser() => + Clients[0].GetCurrentUser(); + + public Task GetCurrentUserAsync() => + Clients[0].GetCurrentUserAsync(); public IReadOnlyCollection GetGuilds() => Clients.SelectMany(c => c.GetGuilds()).ToArray(); @@ -74,7 +77,7 @@ namespace NadekoBot Clients.Select(c => c.GetGuild(id)).FirstOrDefault(g => g != null); public Task GetDMChannelAsync(ulong channelId) => - Clients.Select(async c => await c.GetDMChannelAsync(channelId).ConfigureAwait(false)).FirstOrDefault(c => c != null); + Clients[0].GetDMChannelAsync(channelId); internal Task LoginAsync(TokenType tokenType, string token) => Task.WhenAll(Clients.Select(async c => { await c.LoginAsync(tokenType, token); _log.Info($"Shard #{c.ShardId} logged in."); })); diff --git a/src/NadekoBot/_Extensions/Extensions.cs b/src/NadekoBot/_Extensions/Extensions.cs index 43283a64..6fe6b13c 100644 --- a/src/NadekoBot/_Extensions/Extensions.cs +++ b/src/NadekoBot/_Extensions/Extensions.cs @@ -24,6 +24,15 @@ namespace NadekoBot.Extensions http.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); } + public static IEnumerable ForEach(this IEnumerable elems, Action exec) + { + foreach (var elem in elems) + { + exec(elem); + } + return elems; + } + public static void AddRange(this HashSet target, IEnumerable elements) where T : class { foreach (var item in elements) diff --git a/src/NadekoBot/credentials_example.json b/src/NadekoBot/credentials_example.json new file mode 100644 index 00000000..31a9414f --- /dev/null +++ b/src/NadekoBot/credentials_example.json @@ -0,0 +1,15 @@ +{ + "ClientId": 123123123, + "BotId": null, + "Token": "", + "OwnerIds": [ + 0 + ], + "LoLApiKey": "", + "GoogleApiKey": "", + "MashapeKey": "", + "OsuApiKey": "", + "SoundCloudClientId": "", + "Db": null, + "TotalShards": 1 +} \ No newline at end of file