diff --git a/docs/Commands List.md b/docs/Commands List.md index 3537e8b7..3f2af4f9 100644 --- a/docs/Commands List.md +++ b/docs/Commands List.md @@ -57,10 +57,10 @@ Command and aliases | Description | Usage `.lcsc` | Leaves Cross server channel instance from this channel. **Requires ManageServer server permission.** | `.lcsc` `.fwmsgs` | Toggles forwarding of non-command messages sent to bot's DM to the bot owners **Bot Owner only.** | `.fwmsgs` `.fwtoall` | Toggles whether messages will be forwarded to all bot owners or only to the first one specified in the credentials.json **Bot Owner only.** | `.fwtoall` -`.logserver` | Logs server activity in this channel. **Requires Administrator server permission.** **Bot Owner only.** | `.logserver` +`.logserver` | Enables or Disables ALL log events. If enabled, all log events will log to this channel. **Requires Administrator server permission.** **Bot Owner only.** | `.logserver enable` or `.logserver disable` `.logignore` | Toggles whether the .logserver command ignores this channel. Useful if you have hidden admin channel and public log channel. **Requires Administrator server permission.** **Bot Owner only.** | `.logignore` -`.userpresence` | Starts logging to this channel when someone from the server goes online/offline/idle. **Requires Administrator server permission.** | `.userpresence` -`.voicepresence` | Toggles logging to this channel whenever someone joins or leaves a voice channel you are currently in. **Requires Administrator server permission.** | `.voicepresence` +`.logevents` | Shows a list of all events you can subscribe to with `.log` **Requires Administrator server permission.** | `.logevents` +`.log` | Toggles logging event. Disables it if it's active anywhere on the server. Enables if it's not active. Use `.logevents` to see a lit of all events you can subscribe to. **Requires Administrator server permission.** | `.log userpresence` or `.log userbanned` `.repeatinvoke` `.repinv` | Immediately shows the repeat message and restarts the timer. **Requires ManageMessages server permission.** | `.repinv` `.repeat` | Repeat a message every X minutes. If no parameters are specified, repeat is disabled. **Requires ManageMessages server permission.** | `.repeat 5 Hello there` `.migratedata` | Migrate data from old bot configuration **Bot Owner only.** | `.migratedata` @@ -158,10 +158,11 @@ Command and aliases | Description | Usage `>poll` | Creates a poll which requires users to send the number of the voting option to the bot. **Requires ManageMessages server permission.** | `>poll Question?;Answer1;Answ 2;A_3` `>publicpoll` `>ppoll` | Creates a public poll which requires users to type a number of the voting option in the channel command is ran in. **Requires ManageMessages server permission.** | `>ppoll Question?;Answer1;Answ 2;A_3` `>pollend` | Stops active poll on this server and prints the results in this channel. **Requires ManageMessages server permission.** | `>pollend` +`>acrophobia` `>acro` | Starts an Acrophobia game. Second argment is optional round length in seconds. (default is 60) | `>acro` or `>acro 30` `>cleverbot` | Toggles cleverbot session. When enabled, the bot will reply to messages starting with bot mention in the server. Custom reactions starting with %mention% won't work if cleverbot is enabled. **Requires ManageMessages server permission.** | `>cleverbot` `>hangmanlist` | Shows a list of hangman term types. | `> hangmanlist` `>hangman` | Starts a game of hangman in the channel. Use `>hangmanlist` to see a list of available term types. Defaults to 'all'. | `>hangman` or `>hangman movies` -`>pick` | Picks the currency planted in this channel. | `>pick` +`>pick` | Picks the currency planted in this channel. 60 seconds cooldown. | `>pick` `>plant` | Spend a unit of currency to plant it in this channel. (If bot is restarted or crashes, the currency will be lost) | `>plant` `>gencurrency` `>gc` | Toggles currency generation on this channel. Every posted message will have chance to spawn currency. Chance is specified by the Bot Owner. (default is 2%) **Requires ManageMessages server permission.** | `>gc` `>typestart` | Starts a typing contest. | `>typestart` @@ -248,13 +249,13 @@ Command and aliases | Description | Usage `;removeperm` `;rp` | Removes a permission from a given position in Permissions list. | `;rp 1` `;moveperm` `;mp` | Moves permission from one position to another in Permissions list. | `;mp 2 4` `;srvrcmd` `;sc` | Sets a command's permission at the server level. | `;sc "command name" disable` -`;srvrmdl` `;sm` | Sets a module's permission at the server level. | `;sm "module name" enable` +`;srvrmdl` `;sm` | Sets a module's permission at the server level. | `;sm ModuleName enable` `;usrcmd` `;uc` | Sets a command's permission at the user level. | `;uc "command name" enable SomeUsername` -`;usrmdl` `;um` | Sets a module's permission at the user level. | `;um "module name" enable SomeUsername` +`;usrmdl` `;um` | Sets a module's permission at the user level. | `;um ModuleName enable SomeUsername` `;rolecmd` `;rc` | Sets a command's permission at the role level. | `;rc "command name" disable MyRole` -`;rolemdl` `;rm` | Sets a module's permission at the role level. | `;rm "module name" enable MyRole` +`;rolemdl` `;rm` | Sets a module's permission at the role level. | `;rm ModuleName enable MyRole` `;chnlcmd` `;cc` | Sets a command's permission at the channel level. | `;cc "command name" enable SomeChannel` -`;chnlmdl` `;cm` | Sets a module's permission at the channel level. | `;cm "module name" enable SomeChannel` +`;chnlmdl` `;cm` | Sets a module's permission at the channel level. | `;cm ModuleName enable SomeChannel` `;allchnlmdls` `;acm` | Enable or disable all modules in a specified channel. | `;acm enable #SomeChannel` `;allrolemdls` `;arm` | Enable or disable all modules for a specific role. | `;arm [enable/disable] MyRole` `;allusrmdls` `;aum` | Enable or disable all modules for a specific user. | `;aum enable @someone` @@ -287,7 +288,7 @@ Command and aliases | Description | Usage ### Searches 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` +`~weather` `~we` | Shows weather data for a specified city. You can also specify a country after a comma. | `~we Moscow, RU` `~youtube` `~yt` | Searches youtubes and shows the first result | `~yt query` `~imdb` `~omdb` | Queries omdb for movies or series, show first result. | `~imdb Batman vs Superman` `~randomcat` `~meow` | Shows a random cat image. | `~meow` diff --git a/src/NadekoBot/Migrations/20161224032833_logsettings.Designer.cs b/src/NadekoBot/Migrations/20161224032833_logsettings.Designer.cs new file mode 100644 index 00000000..a2691bdb --- /dev/null +++ b/src/NadekoBot/Migrations/20161224032833_logsettings.Designer.cs @@ -0,0 +1,855 @@ +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using NadekoBot.Services.Database; +using NadekoBot.Services.Database.Models; +using NadekoBot.Modules.Music.Classes; + +namespace NadekoBot.Migrations +{ + [DbContext(typeof(NadekoContext))] + [Migration("20161224032833_logsettings")] + partial class logsettings + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { + modelBuilder + .HasAnnotation("ProductVersion", "1.1.0-rtm-22752"); + + 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("AutoDeleteByeMessagesTimer"); + + b.Property("AutoDeleteGreetMessages"); + + b.Property("AutoDeleteGreetMessagesTimer"); + + b.Property("AutoDeleteSelfAssignedRoleMessages"); + + b.Property("ByeMessageChannelId"); + + b.Property("ChannelByeMessageText"); + + b.Property("ChannelGreetMessageText"); + + b.Property("CleverbotEnabled"); + + 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("MuteRoleName"); + + 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("ChannelCreatedId"); + + b.Property("ChannelDestroyed"); + + b.Property("ChannelDestroyedId"); + + b.Property("ChannelId"); + + b.Property("ChannelUpdated"); + + b.Property("ChannelUpdatedId"); + + b.Property("IsLogging"); + + b.Property("LogOtherId"); + + b.Property("LogUserPresence"); + + b.Property("LogUserPresenceId"); + + b.Property("LogVoicePresence"); + + b.Property("LogVoicePresenceId"); + + b.Property("LogVoicePresenceTTSId"); + + b.Property("MessageDeleted"); + + b.Property("MessageDeletedId"); + + b.Property("MessageUpdated"); + + b.Property("MessageUpdatedId"); + + b.Property("UserBanned"); + + b.Property("UserBannedId"); + + b.Property("UserJoined"); + + b.Property("UserJoinedId"); + + b.Property("UserLeft"); + + b.Property("UserLeftId"); + + b.Property("UserMutedId"); + + b.Property("UserPresenceChannelId"); + + b.Property("UserUnbanned"); + + b.Property("UserUnbannedId"); + + b.Property("UserUpdated"); + + b.Property("UserUpdatedId"); + + 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.MutedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("GuildConfigId"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("MutedUserId"); + }); + + 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.UserPokeTypes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("UserId"); + + b.Property("type"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("PokeGame"); + }); + + 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.MutedUserId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") + .WithMany("MutedUsers") + .HasForeignKey("GuildConfigId"); + }); + + 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/20161224032833_logsettings.cs b/src/NadekoBot/Migrations/20161224032833_logsettings.cs new file mode 100644 index 00000000..609e8d24 --- /dev/null +++ b/src/NadekoBot/Migrations/20161224032833_logsettings.cs @@ -0,0 +1,150 @@ +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace NadekoBot.Migrations +{ + public partial class logsettings : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "ChannelCreatedId", + table: "LogSettings", + nullable: true); + + migrationBuilder.AddColumn( + name: "ChannelDestroyedId", + table: "LogSettings", + nullable: true); + + migrationBuilder.AddColumn( + name: "ChannelUpdatedId", + table: "LogSettings", + nullable: true); + + migrationBuilder.AddColumn( + name: "LogOtherId", + table: "LogSettings", + nullable: true); + + migrationBuilder.AddColumn( + name: "LogUserPresenceId", + table: "LogSettings", + nullable: true); + + migrationBuilder.AddColumn( + name: "LogVoicePresenceId", + table: "LogSettings", + nullable: true); + + migrationBuilder.AddColumn( + name: "LogVoicePresenceTTSId", + table: "LogSettings", + nullable: true); + + migrationBuilder.AddColumn( + name: "MessageDeletedId", + table: "LogSettings", + nullable: true); + + migrationBuilder.AddColumn( + name: "MessageUpdatedId", + table: "LogSettings", + nullable: true); + + migrationBuilder.AddColumn( + name: "UserBannedId", + table: "LogSettings", + nullable: true); + + migrationBuilder.AddColumn( + name: "UserJoinedId", + table: "LogSettings", + nullable: true); + + migrationBuilder.AddColumn( + name: "UserLeftId", + table: "LogSettings", + nullable: true); + + migrationBuilder.AddColumn( + name: "UserMutedId", + table: "LogSettings", + nullable: true); + + migrationBuilder.AddColumn( + name: "UserUnbannedId", + table: "LogSettings", + nullable: true); + + migrationBuilder.AddColumn( + name: "UserUpdatedId", + table: "LogSettings", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "ChannelCreatedId", + table: "LogSettings"); + + migrationBuilder.DropColumn( + name: "ChannelDestroyedId", + table: "LogSettings"); + + migrationBuilder.DropColumn( + name: "ChannelUpdatedId", + table: "LogSettings"); + + migrationBuilder.DropColumn( + name: "LogOtherId", + table: "LogSettings"); + + migrationBuilder.DropColumn( + name: "LogUserPresenceId", + table: "LogSettings"); + + migrationBuilder.DropColumn( + name: "LogVoicePresenceId", + table: "LogSettings"); + + migrationBuilder.DropColumn( + name: "LogVoicePresenceTTSId", + table: "LogSettings"); + + migrationBuilder.DropColumn( + name: "MessageDeletedId", + table: "LogSettings"); + + migrationBuilder.DropColumn( + name: "MessageUpdatedId", + table: "LogSettings"); + + migrationBuilder.DropColumn( + name: "UserBannedId", + table: "LogSettings"); + + migrationBuilder.DropColumn( + name: "UserJoinedId", + table: "LogSettings"); + + migrationBuilder.DropColumn( + name: "UserLeftId", + table: "LogSettings"); + + migrationBuilder.DropColumn( + name: "UserMutedId", + table: "LogSettings"); + + migrationBuilder.DropColumn( + name: "UserUnbannedId", + table: "LogSettings"); + + migrationBuilder.DropColumn( + name: "UserUpdatedId", + table: "LogSettings"); + } + } +} diff --git a/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs b/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs index 6b7ef481..022480a4 100644 --- a/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs +++ b/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs @@ -423,34 +423,64 @@ namespace NadekoBot.Migrations b.Property("ChannelCreated"); + b.Property("ChannelCreatedId"); + b.Property("ChannelDestroyed"); + b.Property("ChannelDestroyedId"); + b.Property("ChannelId"); b.Property("ChannelUpdated"); + b.Property("ChannelUpdatedId"); + b.Property("IsLogging"); + b.Property("LogOtherId"); + b.Property("LogUserPresence"); + b.Property("LogUserPresenceId"); + b.Property("LogVoicePresence"); + b.Property("LogVoicePresenceId"); + + b.Property("LogVoicePresenceTTSId"); + b.Property("MessageDeleted"); + b.Property("MessageDeletedId"); + b.Property("MessageUpdated"); + b.Property("MessageUpdatedId"); + b.Property("UserBanned"); + b.Property("UserBannedId"); + b.Property("UserJoined"); + b.Property("UserJoinedId"); + b.Property("UserLeft"); + b.Property("UserLeftId"); + + b.Property("UserMutedId"); + b.Property("UserPresenceChannelId"); b.Property("UserUnbanned"); + b.Property("UserUnbannedId"); + b.Property("UserUpdated"); + b.Property("UserUpdatedId"); + b.Property("VoicePresenceChannelId"); b.HasKey("Id"); diff --git a/src/NadekoBot/Modules/Administration/Commands/LogCommand.cs b/src/NadekoBot/Modules/Administration/Commands/LogCommand.cs index 1a44e3b4..8e2d76b8 100644 --- a/src/NadekoBot/Modules/Administration/Commands/LogCommand.cs +++ b/src/NadekoBot/Modules/Administration/Commands/LogCommand.cs @@ -4,6 +4,7 @@ using Discord.WebSocket; using Microsoft.EntityFrameworkCore; using NadekoBot.Attributes; using NadekoBot.Extensions; +using NadekoBot.Modules.Permissions; using NadekoBot.Services; using NadekoBot.Services.Database.Models; using NLog; @@ -88,11 +89,11 @@ namespace NadekoBot.Modules.Administration { LogSetting logSetting; if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out logSetting) - || !logSetting.IsLogging) + || (logSetting.UserMutedId == null)) return Task.CompletedTask; ITextChannel logChannel; - if ((logChannel = TryGetLogChannel(usr.Guild, logSetting)) == null) + if ((logChannel = TryGetLogChannel(usr.Guild, logSetting, LogType.UserMuted)) == null) return Task.CompletedTask; var task = Task.Run(async () => @@ -120,11 +121,11 @@ namespace NadekoBot.Modules.Administration { LogSetting logSetting; if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out logSetting) - || !logSetting.IsLogging) + || (logSetting.UserMutedId == null)) return Task.CompletedTask; ITextChannel logChannel; - if ((logChannel = TryGetLogChannel(usr.Guild, logSetting)) == null) + if ((logChannel = TryGetLogChannel(usr.Guild, logSetting, LogType.UserMuted)) == null) return Task.CompletedTask; var task = Task.Run(async () => @@ -155,10 +156,10 @@ namespace NadekoBot.Modules.Administration LogSetting logSetting; if (!GuildLogSettings.TryGetValue(users.First().Guild.Id, out logSetting) - || !logSetting.IsLogging) + || (logSetting.LogOtherId == null)) return; ITextChannel logChannel; - if ((logChannel = TryGetLogChannel(users.First().Guild, logSetting)) == null) + if ((logChannel = TryGetLogChannel(users.First().Guild, logSetting, LogType.Other)) == null) return; var punishment = ""; @@ -177,7 +178,7 @@ namespace NadekoBot.Modules.Administration punishment = "⛔️ BANNED"; //punishment = "BANNED"; } - await logChannel.SendMessageAsync(String.Join("\n",users.Select(user=>$"‼️ {Format.Bold(user.ToString())} got **{punishment}** due to __**{protection}**__ protection on **{user.Guild.Name}** server."))) + await logChannel.SendMessageAsync(String.Join("\n", users.Select(user => $"‼️ {Format.Bold(user.ToString())} got **{punishment}** due to __**{protection}**__ protection on **{user.Guild.Name}** server."))) //await logChannel.SendMessageAsync(String.Join("\n",users.Select(user=>$"{Format.Bold(user.ToString())} was **{punishment}** due to `{protection}` protection on **{user.Guild.Name}** server."))) .ConfigureAwait(false); } @@ -186,12 +187,11 @@ namespace NadekoBot.Modules.Administration { LogSetting logSetting; if (!GuildLogSettings.TryGetValue(before.Guild.Id, out logSetting) - || !logSetting.IsLogging - || !logSetting.UserUpdated) + || (logSetting.UserUpdatedId == null)) return Task.CompletedTask; ITextChannel logChannel; - if ((logChannel = TryGetLogChannel(before.Guild, logSetting)) == null) + if ((logChannel = TryGetLogChannel(before.Guild, logSetting, LogType.UserUpdated)) == null) return Task.CompletedTask; var task = Task.Run(async () => @@ -204,7 +204,7 @@ namespace NadekoBot.Modules.Administration str += $"👤__**{before.Username}#{before.Discriminator}**__ **| Name Changed |** 🆔 `{before.Id}`\n\t\t`New:` **{after.ToString()}**"; else if (before.Nickname != after.Nickname) str += $"👤__**{before.Username}#{before.Discriminator}**__ **| Nickname Changed |** 🆔 `{before.Id}`\n\t\t`Old:` **{before.Nickname}#{before.Discriminator}**\n\t\t`New:` **{after.Nickname}#{after.Discriminator}**"; - //str += $"**Nickname Changed**`{before.Username}#{before.Discriminator}`\n\t\t`Old:` {before.Nickname}#{before.Discriminator}\n\t\t`New:` {after.Nickname}#{after.Discriminator}"; + //str += $"**Nickname Changed**`{before.Username}#{before.Discriminator}`\n\t\t`Old:` {before.Nickname}#{before.Discriminator}\n\t\t`New:` {after.Nickname}#{after.Discriminator}"; else if (before.AvatarUrl != after.AvatarUrl) //str += $"**Avatar Changed**👤`{before.Username}#{before.Discriminator}`\n\t {await _google.ShortenUrl(before.AvatarUrl)} `=>` {await _google.ShortenUrl(after.AvatarUrl)}"; str += $"👤__**{before.Username}#{before.Discriminator}**__ **| Avatar Changed |** 🆔 `{before.Id}`\n\t🖼 {await _google.ShortenUrl(before.AvatarUrl)} `=>` {await _google.ShortenUrl(after.AvatarUrl)}"; @@ -242,13 +242,12 @@ namespace NadekoBot.Modules.Administration LogSetting logSetting; if (!GuildLogSettings.TryGetValue(before.Guild.Id, out logSetting) - || !logSetting.IsLogging - || !logSetting.ChannelUpdated + || (logSetting.ChannelUpdatedId == null) || logSetting.IgnoredChannels.Any(ilc => ilc.ChannelId == after.Id)) return Task.CompletedTask; ITextChannel logChannel; - if ((logChannel = TryGetLogChannel(before.Guild, logSetting)) == null) + if ((logChannel = TryGetLogChannel(before.Guild, logSetting, LogType.ChannelUpdated)) == null) return Task.CompletedTask; var task = Task.Run(async () => @@ -280,13 +279,12 @@ namespace NadekoBot.Modules.Administration LogSetting logSetting; if (!GuildLogSettings.TryGetValue(ch.Guild.Id, out logSetting) - || !logSetting.IsLogging - || !logSetting.ChannelDestroyed - || logSetting.IgnoredChannels.Any(ilc=>ilc.ChannelId == ch.Id)) + || (logSetting.ChannelDestroyedId == null) + || logSetting.IgnoredChannels.Any(ilc => ilc.ChannelId == ch.Id)) return Task.CompletedTask; ITextChannel logChannel; - if ((logChannel = TryGetLogChannel(ch.Guild, logSetting)) == null) + if ((logChannel = TryGetLogChannel(ch.Guild, logSetting, LogType.ChannelDestroyed)) == null) return Task.CompletedTask; var task = Task.Run(async () => @@ -305,12 +303,11 @@ namespace NadekoBot.Modules.Administration LogSetting logSetting; if (!GuildLogSettings.TryGetValue(ch.Guild.Id, out logSetting) - || !logSetting.IsLogging - || !logSetting.ChannelCreated) + || (logSetting.ChannelCreatedId == null)) return Task.CompletedTask; ITextChannel logChannel; - if ((logChannel = TryGetLogChannel(ch.Guild, logSetting)) == null) + if ((logChannel = TryGetLogChannel(ch.Guild, logSetting, LogType.ChannelCreated)) == null) return Task.CompletedTask; var task = Task.Run(async () => @@ -335,28 +332,28 @@ namespace NadekoBot.Modules.Administration LogSetting logSetting; if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out logSetting) - || !logSetting.LogVoicePresence) + || (logSetting.LogVoicePresenceId == null)) return Task.CompletedTask; ITextChannel logChannel; - if ((logChannel = TryGetLogChannel(usr.Guild, logSetting, LogChannelType.Voice)) == null) + if ((logChannel = TryGetLogChannel(usr.Guild, logSetting, LogType.VoicePresence)) == null) return Task.CompletedTask; - string str = null; - if (beforeVch?.Guild == afterVch?.Guild) - { - str = $"🎙`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__ moved from **{beforeVch.Name}** to **{afterVch.Name}** voice channel."; - } - else if (beforeVch == null) - { - str = $"🎙`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__ has joined **{afterVch.Name}** voice channel."; - } - else if (afterVch == null) - { - str = $"🎙`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__ has left **{beforeVch.Name}** voice channel."; - } - if(str != null) - UserPresenceUpdates.AddOrUpdate(logChannel, new List() { str }, (id, list) => { list.Add(str); return list; }); + string str = null; + if (beforeVch?.Guild == afterVch?.Guild) + { + str = $"🎙`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__ moved from **{beforeVch.Name}** to **{afterVch.Name}** voice channel."; + } + else if (beforeVch == null) + { + str = $"🎙`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__ has joined **{afterVch.Name}** voice channel."; + } + else if (afterVch == null) + { + str = $"🎙`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__ has left **{beforeVch.Name}** voice channel."; + } + if (str != null) + UserPresenceUpdates.AddOrUpdate(logChannel, new List() { str }, (id, list) => { list.Add(str); return list; }); return Task.CompletedTask; } @@ -365,12 +362,12 @@ namespace NadekoBot.Modules.Administration { LogSetting logSetting; if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out logSetting) - || !logSetting.LogUserPresence + || (logSetting.LogUserPresenceId == null) || before.Status == after.Status) return Task.CompletedTask; ITextChannel logChannel; - if ((logChannel = TryGetLogChannel(usr.Guild, logSetting, LogChannelType.UserPresence)) == null) + if ((logChannel = TryGetLogChannel(usr.Guild, logSetting, LogType.UserPresence)) == null) return Task.CompletedTask; string str; if (before.Status != after.Status) @@ -387,12 +384,11 @@ namespace NadekoBot.Modules.Administration { LogSetting logSetting; if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out logSetting) - || !logSetting.IsLogging - || !logSetting.UserLeft) + || (logSetting.UserLeftId == null)) return Task.CompletedTask; ITextChannel logChannel; - if ((logChannel = TryGetLogChannel(usr.Guild, logSetting)) == null) + if ((logChannel = TryGetLogChannel(usr.Guild, logSetting, LogType.UserLeft)) == null) return Task.CompletedTask; var task = Task.Run(async () => @@ -407,12 +403,11 @@ namespace NadekoBot.Modules.Administration { LogSetting logSetting; if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out logSetting) - || !logSetting.IsLogging - || !logSetting.UserJoined) + || (logSetting.UserJoinedId == null)) return Task.CompletedTask; ITextChannel logChannel; - if ((logChannel = TryGetLogChannel(usr.Guild, logSetting)) == null) + if ((logChannel = TryGetLogChannel(usr.Guild, logSetting, LogType.UserJoined)) == null) return Task.CompletedTask; var task = Task.Run(async () => @@ -427,17 +422,16 @@ namespace NadekoBot.Modules.Administration { LogSetting logSetting; if (!GuildLogSettings.TryGetValue(guild.Id, out logSetting) - || !logSetting.IsLogging - || !logSetting.UserUnbanned) + || (logSetting.UserUnbannedId == null)) return Task.CompletedTask; ITextChannel logChannel; - if ((logChannel = TryGetLogChannel(guild, logSetting)) == null) + if ((logChannel = TryGetLogChannel(guild, logSetting, LogType.UserUnbanned)) == null) return Task.CompletedTask; var task = Task.Run(async () => { - try { await logChannel.SendMessageAsync($"❕🕘`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__♻️ **| USER UN-BANNED |** 🆔 `{usr.Id}`").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); } + try { await logChannel.SendMessageAsync($"❕🕘`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__♻️ **| USER UN-BANNED |** 🆔 `{usr.Id}`").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); } }); return Task.CompletedTask; @@ -447,12 +441,11 @@ namespace NadekoBot.Modules.Administration { LogSetting logSetting; if (!GuildLogSettings.TryGetValue(guild.Id, out logSetting) - || !logSetting.IsLogging - || !logSetting.UserBanned) + || (logSetting.UserBannedId == null)) return Task.CompletedTask; ITextChannel logChannel; - if ((logChannel = TryGetLogChannel(guild, logSetting)) == null) + if ((logChannel = TryGetLogChannel(guild, logSetting, LogType.UserBanned)) == null) return Task.CompletedTask; var task = Task.Run(async () => @@ -475,13 +468,12 @@ namespace NadekoBot.Modules.Administration LogSetting logSetting; if (!GuildLogSettings.TryGetValue(channel.Guild.Id, out logSetting) - || !logSetting.IsLogging - || !logSetting.MessageDeleted + || (logSetting.MessageDeletedId == null) || logSetting.IgnoredChannels.Any(ilc => ilc.ChannelId == channel.Id)) return Task.CompletedTask; ITextChannel logChannel; - if ((logChannel = TryGetLogChannel(channel.Guild, logSetting)) == null || logChannel.Id == msg.Id) + if ((logChannel = TryGetLogChannel(channel.Guild, logSetting, LogType.MessageDeleted)) == null || logChannel.Id == msg.Id) return Task.CompletedTask; var task = Task.Run(async () => @@ -519,19 +511,18 @@ namespace NadekoBot.Modules.Administration LogSetting logSetting; if (!GuildLogSettings.TryGetValue(channel.Guild.Id, out logSetting) - || !logSetting.IsLogging - || !logSetting.MessageUpdated + || (logSetting.MessageUpdatedId == null) || logSetting.IgnoredChannels.Any(ilc => ilc.ChannelId == channel.Id)) return Task.CompletedTask; ITextChannel logChannel; - if ((logChannel = TryGetLogChannel(channel.Guild, logSetting)) == null || logChannel.Id == after.Channel.Id) + if ((logChannel = TryGetLogChannel(channel.Guild, logSetting, LogType.MessageUpdated)) == null || logChannel.Id == after.Channel.Id) return Task.CompletedTask; var task = Task.Run(async () => { //try { await logChannel.SendMessageAsync($@"🕔`{prettyCurrentTime}` **Message** 📝 `#{channel.Name}` -//👤`{before.Author.Username}` + //👤`{before.Author.Username}` try { await logChannel.SendMessageAsync($@"🕔`{prettyCurrentTime}`👤__**{before.Author.Username}#{before.Author.Discriminator}**__ **| 📝 Edited Message |** 🆔 `{before.Author.Id}` #⃣ `{channel.Name}` `Old:` {before.Resolve(userHandling: UserMentionHandling.NameAndDiscriminator).SanitizeMentions()} **`New:`** {after.Resolve(userHandling: UserMentionHandling.NameAndDiscriminator).SanitizeMentions()}").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); } @@ -540,70 +531,177 @@ namespace NadekoBot.Modules.Administration return Task.CompletedTask; } - private enum LogChannelType { Text, Voice, UserPresence }; - private static ITextChannel TryGetLogChannel(IGuild guild, LogSetting logSetting, LogChannelType logChannelType = LogChannelType.Text) + public enum LogType { - ulong id = 0; + Other, + MessageUpdated, + MessageDeleted, + UserJoined, + UserLeft, + UserBanned, + UserUnbanned, + UserUpdated, + ChannelCreated, + ChannelDestroyed, + ChannelUpdated, + UserPresence, + VoicePresence, + VoicePresenceTTS, + UserMuted + }; + + private static ITextChannel TryGetLogChannel(IGuild guild, LogSetting logSetting, LogType logChannelType) + { + ulong? id = null; switch (logChannelType) { - case LogChannelType.Text: - id = logSetting.ChannelId; + case LogType.Other: + id = logSetting.LogOtherId; break; - case LogChannelType.Voice: - id = logSetting.VoicePresenceChannelId; + case LogType.MessageUpdated: + id = logSetting.MessageUpdatedId; break; - case LogChannelType.UserPresence: - id = logSetting.UserPresenceChannelId; + case LogType.MessageDeleted: + id = logSetting.MessageDeletedId; + break; + case LogType.UserJoined: + id = logSetting.UserJoinedId; + break; + case LogType.UserLeft: + id = logSetting.UserLeftId; + break; + case LogType.UserBanned: + id = logSetting.UserBannedId; + break; + case LogType.UserUnbanned: + id = logSetting.UserUnbannedId; + break; + case LogType.UserUpdated: + id = logSetting.UserUpdatedId; + break; + case LogType.ChannelCreated: + id = logSetting.ChannelCreatedId; + break; + case LogType.ChannelDestroyed: + id = logSetting.ChannelDestroyedId; + break; + case LogType.ChannelUpdated: + id = logSetting.ChannelUpdatedId; + break; + case LogType.UserPresence: + id = logSetting.LogUserPresenceId; + break; + case LogType.VoicePresence: + id = logSetting.LogVoicePresenceId; + break; + case LogType.VoicePresenceTTS: + id = logSetting.LogVoicePresenceTTSId; + break; + case LogType.UserMuted: + id = logSetting.UserMutedId; + break; + default: break; } - var channel = guild.GetTextChannel(id); + + if (!id.HasValue) + { + UnsetLogSetting(guild.Id, logChannelType); + return null; + } + var channel = guild.GetTextChannel(id.Value); if (channel == null) - using (var uow = DbHandler.UnitOfWork()) - { - var newLogSetting = uow.GuildConfigs.For(guild.Id).LogSetting; - switch (logChannelType) - { - case LogChannelType.Text: - logSetting.IsLogging = false; - break; - case LogChannelType.Voice: - logSetting.LogVoicePresence = false; - break; - case LogChannelType.UserPresence: - logSetting.LogUserPresence = false; - break; - } - GuildLogSettings.AddOrUpdate(guild.Id, newLogSetting, (gid, old) => newLogSetting); - uow.Complete(); - return null; - } + { + UnsetLogSetting(guild.Id, logChannelType); + return null; + } else return channel; } + private static void UnsetLogSetting(ulong guildId, LogType logChannelType) + { + using (var uow = DbHandler.UnitOfWork()) + { + var newLogSetting = uow.GuildConfigs.LogSettingsFor(guildId).LogSetting; + switch (logChannelType) + { + case LogType.Other: + break; + case LogType.MessageUpdated: + break; + case LogType.MessageDeleted: + break; + case LogType.UserJoined: + break; + case LogType.UserLeft: + break; + case LogType.UserBanned: + break; + case LogType.UserUnbanned: + break; + case LogType.UserUpdated: + break; + case LogType.ChannelCreated: + break; + case LogType.ChannelDestroyed: + break; + case LogType.ChannelUpdated: + break; + case LogType.UserPresence: + break; + case LogType.VoicePresence: + break; + case LogType.VoicePresenceTTS: + break; + default: + break; + } + GuildLogSettings.AddOrUpdate(guildId, newLogSetting, (gid, old) => newLogSetting); + uow.Complete(); + } + } + + public enum EnableDisable + { + Enable, + Disable + } + [NadekoCommand, Usage, Description, Aliases] [RequireContext(ContextType.Guild)] [RequirePermission(GuildPermission.Administrator)] [OwnerOnly] - public async Task LogServer(IUserMessage msg) + public async Task LogServer(IUserMessage msg, PermissionAction action) { var channel = (ITextChannel)msg.Channel; LogSetting logSetting; using (var uow = DbHandler.UnitOfWork()) { - logSetting = uow.GuildConfigs.For(channel.Guild.Id).LogSetting; + logSetting = uow.GuildConfigs.LogSettingsFor(channel.Guild.Id).LogSetting; GuildLogSettings.AddOrUpdate(channel.Guild.Id, (id) => logSetting, (id, old) => logSetting); - logSetting.IsLogging = !logSetting.IsLogging; - if (logSetting.IsLogging) - logSetting.ChannelId = channel.Id; - await uow.CompleteAsync(); - } + logSetting.LogOtherId = + logSetting.MessageUpdatedId = + logSetting.MessageDeletedId = + logSetting.UserJoinedId = + logSetting.UserLeftId = + logSetting.UserBannedId = + logSetting.UserUnbannedId = + logSetting.UserUpdatedId = + logSetting.ChannelCreatedId = + logSetting.ChannelDestroyedId = + logSetting.ChannelUpdatedId = + logSetting.LogUserPresenceId = + logSetting.LogVoicePresenceId = + logSetting.LogVoicePresenceTTSId = (action.Value ? channel.Id : (ulong?)null); - if (logSetting.IsLogging) - await channel.SendMessageAsync("✅ **Logging enabled.**").ConfigureAwait(false); + await uow.CompleteAsync().ConfigureAwait(false); + } + if (action.Value) + await channel.SendMessageAsync("✅ Logging all events on this channel.").ConfigureAwait(false); else - await channel.SendMessageAsync("ℹ️ **Logging disabled.**").ConfigureAwait(false); + await channel.SendMessageAsync("ℹ️ Logging disabled.").ConfigureAwait(false); } [NadekoCommand, Usage, Description, Aliases] @@ -616,7 +714,7 @@ namespace NadekoBot.Modules.Administration int removed; using (var uow = DbHandler.UnitOfWork()) { - var config = uow.GuildConfigs.For(channel.Guild.Id); + var config = uow.GuildConfigs.LogSettingsFor(channel.Guild.Id); LogSetting logSetting = GuildLogSettings.GetOrAdd(channel.Guild.Id, (id) => config.LogSetting); removed = logSetting.IgnoredChannels.RemoveWhere(ilc => ilc.ChannelId == channel.Id); config.LogSetting.IgnoredChannels.RemoveWhere(ilc => ilc.ChannelId == channel.Id); @@ -635,146 +733,84 @@ namespace NadekoBot.Modules.Administration await channel.SendMessageAsync($"ℹ️ Logging will **no longer ignore** #⃣ `{channel.Name} ({channel.Id})`").ConfigureAwait(false); } - //[LocalizedCommand, LocalizedRemarks, LocalizedSummary, LocalizedAlias] - //[RequireContext(ContextType.Guild)] - //[OwnerOnly] - //public async Task LogAdd(IUserMessage msg, [Remainder] string eventName) - //{ - // var channel = (ITextChannel)msg.Channel; - // //eventName = eventName?.Replace(" ","").ToLowerInvariant(); - - // switch (eventName.ToLowerInvariant()) - // { - // case "messageupdated": - // case "messagedeleted": - // case "userjoined": - // case "userleft": - // case "userbanned": - // case "userunbanned": - // case "channelcreated": - // case "channeldestroyed": - // case "channelupdated": - // using (var uow = DbHandler.UnitOfWork()) - // { - // var logSetting = uow.GuildConfigs.For(channel.Guild.Id).LogSetting; - // GuildLogSettings.AddOrUpdate(channel.Guild.Id, (id) => logSetting, (id, old) => logSetting); - // var prop = logSetting.GetType().GetProperty(eventName); - // prop.SetValue(logSetting, true); - // await uow.CompleteAsync().ConfigureAwait(false); - // } - // await channel.SendMessageAsync($"`Now logging {eventName} event.`").ConfigureAwait(false); - // break; - // default: - // await channel.SendMessageAsync($"`Event \"{eventName}\" not found.`").ConfigureAwait(false); - // break; - // } - //} - - //[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias] - //[RequireContext(ContextType.Guild)] - //public async Task LogRemove(IUserMessage msg, string eventName) - //{ - // var channel = (ITextChannel)msg.Channel; - // eventName = eventName.ToLowerInvariant(); - - // switch (eventName) - // { - // case "messagereceived": - // case "messageupdated": - // case "messagedeleted": - // case "userjoined": - // case "userleft": - // case "userbanned": - // case "userunbanned": - // case "channelcreated": - // case "channeldestroyed": - // case "channelupdated": - // using (var uow = DbHandler.UnitOfWork()) - // { - // var config = uow.GuildConfigs.For(channel.Guild.Id); - // LogSetting logSetting = GuildLogSettings.GetOrAdd(channel.Guild.Id, (id) => config.LogSetting); - // logSetting.GetType().GetProperty(eventName).SetValue(logSetting, false); - // config.LogSetting = logSetting; - // await uow.CompleteAsync().ConfigureAwait(false); - // } - // await channel.SendMessageAsync($"`No longer logging {eventName} event.`").ConfigureAwait(false); - // break; - // default: - // await channel.SendMessageAsync($"`Event \"{eventName}\" not found.`").ConfigureAwait(false); - // break; - // } - //} - [NadekoCommand, Usage, Description, Aliases] [RequireContext(ContextType.Guild)] [RequirePermission(GuildPermission.Administrator)] - public async Task UserPresence(IUserMessage imsg) + [OwnerOnly] + public async Task LogEvents(IUserMessage imsg) { - var channel = (ITextChannel)imsg.Channel; - bool enabled; - using (var uow = DbHandler.UnitOfWork()) - { - var logSetting = uow.GuildConfigs.For(channel.Guild.Id).LogSetting; - GuildLogSettings.AddOrUpdate(channel.Guild.Id, (id) => logSetting, (id, old) => logSetting); - enabled = logSetting.LogUserPresence = !logSetting.LogUserPresence; - if(enabled) - logSetting.UserPresenceChannelId = channel.Id; - await uow.CompleteAsync().ConfigureAwait(false); - } - - if (enabled) - await channel.SendMessageAsync($"✅ Logging **user presence** updates in #⃣ `{channel.Name} ({channel.Id})`").ConfigureAwait(false); - else - await channel.SendMessageAsync($"ℹ️ Stopped logging **user presence** updates.").ConfigureAwait(false); + await imsg.Channel.SendConfirmAsync("Log events you can subscribe to:", String.Join(", ", Enum.GetNames(typeof(LogType)).Cast())); } [NadekoCommand, Usage, Description, Aliases] [RequireContext(ContextType.Guild)] [RequirePermission(GuildPermission.Administrator)] - public async Task VoicePresence(IUserMessage imsg) + [OwnerOnly] + public async Task Log(IUserMessage imsg, LogType type) { var channel = (ITextChannel)imsg.Channel; - bool enabled; + ulong? channelId = null; using (var uow = DbHandler.UnitOfWork()) { - var logSetting = uow.GuildConfigs.For(channel.Guild.Id, set => set.Include(gc => gc.LogSetting) - .ThenInclude(ls => ls.IgnoredVoicePresenceChannelIds)) - .LogSetting; + var logSetting = uow.GuildConfigs.LogSettingsFor(channel.Guild.Id).LogSetting; GuildLogSettings.AddOrUpdate(channel.Guild.Id, (id) => logSetting, (id, old) => logSetting); - enabled = logSetting.LogVoicePresence = !logSetting.LogVoicePresence; - if (enabled) - logSetting.VoicePresenceChannelId = channel.Id; + switch (type) + { + case LogType.Other: + channelId = logSetting.LogOtherId = (logSetting.LogOtherId == null ? channel.Id : default(ulong?)); + break; + case LogType.MessageUpdated: + channelId = logSetting.MessageUpdatedId = (logSetting.MessageUpdatedId == null ? channel.Id : default(ulong?)); + break; + case LogType.MessageDeleted: + channelId = logSetting.MessageDeletedId = (logSetting.MessageDeletedId == null ? channel.Id : default(ulong?)); + break; + case LogType.UserJoined: + channelId = logSetting.UserJoinedId = (logSetting.UserJoinedId == null ? channel.Id : default(ulong?)); + break; + case LogType.UserLeft: + channelId = logSetting.UserLeftId = (logSetting.UserLeftId == null ? channel.Id : default(ulong?)); + break; + case LogType.UserBanned: + channelId = logSetting.UserBannedId = (logSetting.UserBannedId == null ? channel.Id : default(ulong?)); + break; + case LogType.UserUnbanned: + channelId = logSetting.UserUnbannedId = (logSetting.UserUnbannedId == null ? channel.Id : default(ulong?)); + break; + case LogType.UserUpdated: + channelId = logSetting.UserUpdatedId = (logSetting.UserUpdatedId == null ? channel.Id : default(ulong?)); + break; + case LogType.UserMuted: + channelId = logSetting.UserMutedId = (logSetting.UserMutedId == null ? channel.Id : default(ulong?)); + break; + case LogType.ChannelCreated: + channelId = logSetting.ChannelCreatedId = (logSetting.ChannelCreatedId == null ? channel.Id : default(ulong?)); + break; + case LogType.ChannelDestroyed: + channelId = logSetting.ChannelDestroyedId = (logSetting.ChannelDestroyedId == null ? channel.Id : default(ulong?)); + break; + case LogType.ChannelUpdated: + channelId = logSetting.ChannelUpdatedId = (logSetting.ChannelUpdatedId == null ? channel.Id : default(ulong?)); + break; + case LogType.UserPresence: + channelId = logSetting.LogUserPresenceId = (logSetting.LogUserPresenceId == null ? channel.Id : default(ulong?)); + break; + case LogType.VoicePresence: + channelId = logSetting.LogVoicePresenceId = (logSetting.LogVoicePresenceId == null ? channel.Id : default(ulong?)); + break; + case LogType.VoicePresenceTTS: + channelId = logSetting.LogVoicePresenceTTSId = (logSetting.LogVoicePresenceTTSId == null ? channel.Id : default(ulong?)); + break; + } + await uow.CompleteAsync().ConfigureAwait(false); } - if (enabled) - await channel.SendMessageAsync($"✅ Logging **voice presence** updates in #⃣ `{channel.Name} ({channel.Id})`").ConfigureAwait(false); + if (channelId != null) + await channel.SendMessageAsync($"✅ Logging `{type}` event in #⃣ `{channel.Name} ({channel.Id})`").ConfigureAwait(false); else - await channel.SendMessageAsync($"ℹ️ Stopped logging **voice presence** updates.").ConfigureAwait(false); + await channel.SendMessageAsync($"ℹ️ Stopped logging `{type}` event.").ConfigureAwait(false); } - - //[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias] - //[RequireContext(ContextType.Guild)] - //public async Task VoiPresIgnore(IUserMessage imsg, IVoiceChannel voiceChannel) - //{ - // var channel = (ITextChannel)imsg.Channel; - // int removed; - // using (var uow = DbHandler.UnitOfWork()) - // { - // var config = uow.GuildConfigs.For(channel.Guild.Id); - // LogSetting logSetting = GuildLogSettings.GetOrAdd(channel.Guild.Id, (id) => config.LogSetting); - // removed = logSetting.IgnoredVoicePresenceChannelIds.RemoveWhere(ivpc => ivpc.ChannelId == voiceChannel.Id); - // if (removed == 0) - // logSetting.IgnoredVoicePresenceChannelIds.Add(new IgnoredVoicePresenceChannel { ChannelId = voiceChannel.Id }); - // config.LogSetting = logSetting; - // await uow.CompleteAsync().ConfigureAwait(false); - // } - - // if (removed == 0) - // await channel.SendMessageAsync($"`Enabled logging voice presence updates for {voiceChannel.Name} ({voiceChannel.Id}) channel.`").ConfigureAwait(false); - // else - // await channel.SendMessageAsync($"`Disabled logging voice presence updates for {voiceChannel.Name} ({voiceChannel.Id}) channel.`").ConfigureAwait(false); - //} } } -} +} \ No newline at end of file diff --git a/src/NadekoBot/Modules/Administration/Commands/MessageRepeater.cs b/src/NadekoBot/Modules/Administration/Commands/MessageRepeater.cs index 583f0f05..2063a381 100644 --- a/src/NadekoBot/Modules/Administration/Commands/MessageRepeater.cs +++ b/src/NadekoBot/Modules/Administration/Commands/MessageRepeater.cs @@ -50,10 +50,16 @@ namespace NadekoBot.Modules.Administration { while (!token.IsCancellationRequested) { + var toSend = "🔄 " + Repeater.Message; await Task.Delay(Repeater.Interval, token).ConfigureAwait(false); + + var lastMsgInChannel = (await Channel.GetMessagesAsync(1)).FirstOrDefault(); + if (lastMsgInChannel.Id == oldMsg.Id) //don't send if it's the same message in the channel + continue; + if (oldMsg != null) try { await oldMsg.DeleteAsync(); } catch { } - try { oldMsg = await Channel.SendMessageAsync("🔄 " + Repeater.Message).ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); try { source.Cancel(); } catch { } } + try { oldMsg = await Channel.SendMessageAsync(toSend).ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); try { source.Cancel(); } catch { } } } } catch (OperationCanceledException) { } diff --git a/src/NadekoBot/Modules/Administration/Commands/Migration.cs b/src/NadekoBot/Modules/Administration/Commands/Migration.cs index 7027488a..9d323245 100644 --- a/src/NadekoBot/Modules/Administration/Commands/Migration.cs +++ b/src/NadekoBot/Modules/Administration/Commands/Migration.cs @@ -195,12 +195,9 @@ namespace NadekoBot.Modules.Administration guildConfig.GenerateCurrencyChannelIds = new HashSet(data.GenerateCurrencyChannels.Select(gc => new GCChannelId() { ChannelId = gc.Key })); selfAssRoles.AddRange(data.ListOfSelfAssignableRoles.Select(r => new SelfAssignedRole() { GuildId = guildConfig.GuildId, RoleId = r }).ToArray()); var logSetting = guildConfig.LogSetting; - guildConfig.LogSetting.IsLogging = data.LogChannel != null; - guildConfig.LogSetting.ChannelId = data.LogChannel ?? 0; guildConfig.LogSetting.IgnoredChannels = new HashSet(data.LogserverIgnoreChannels.Select(id => new IgnoredLogChannel() { ChannelId = id })); - guildConfig.LogSetting.LogUserPresence = data.LogPresenceChannel != null; - guildConfig.LogSetting.UserPresenceChannelId = data.LogPresenceChannel ?? 0; + guildConfig.LogSetting.LogUserPresenceId = data.LogPresenceChannel; guildConfig.FollowedStreams = new HashSet(data.ObservingStreams.Select(x => diff --git a/src/NadekoBot/Modules/Gambling/Commands/DiceRollCommand.cs b/src/NadekoBot/Modules/Gambling/Commands/DiceRollCommand.cs index 7b2c8118..f1c3252a 100644 --- a/src/NadekoBot/Modules/Gambling/Commands/DiceRollCommand.cs +++ b/src/NadekoBot/Modules/Gambling/Commands/DiceRollCommand.cs @@ -19,6 +19,9 @@ namespace NadekoBot.Modules.Gambling public class DriceRollCommands { private Regex dndRegex { get; } = new Regex(@"^(?\d+)d(?\d+)(?:\+(?\d+))?(?:\-(?\d+))?$", RegexOptions.Compiled); + private Regex fudgeRegex { get; } = new Regex(@"^(?\d+)d(?:F|f)$", RegexOptions.Compiled); + + private readonly char[] fateRolls = new[] { '-', ' ', '+' }; [NadekoCommand, Usage, Description, Aliases] [RequireContext(ContextType.Guild)] @@ -141,12 +144,29 @@ namespace NadekoBot.Modules.Gambling if (channel == null) return; - var rng = new NadekoRandom(); Match match; - if ((match = dndRegex.Match(arg)).Length != 0) + int n1; + int n2; + if ((match = fudgeRegex.Match(arg)).Length != 0 && + int.TryParse(match.Groups["n1"].ToString(), out n1) && + n1 > 0 && n1 < 500) { - int n1; - int n2; + var rng = new NadekoRandom(); + + var rolls = new List(); + + for (int i = 0; i < n1; i++) + { + rolls.Add(fateRolls[rng.Next(0, fateRolls.Length)]); + } + var embed = new EmbedBuilder().WithOkColor().WithDescription($"{umsg.Author.Mention} rolled {n1} fate {(n1 == 1 ? "die" : "dice")}.") + .AddField(efb => efb.WithName(Format.Bold("Result")) + .WithValue(string.Join(" ", rolls.Select(c => Format.Code($"[{c}]"))))); + await channel.EmbedAsync(embed.Build()).ConfigureAwait(false); + } + else if ((match = dndRegex.Match(arg)).Length != 0) + { + var rng = new NadekoRandom(); if (int.TryParse(match.Groups["n1"].ToString(), out n1) && int.TryParse(match.Groups["n2"].ToString(), out n2) && n1 <= 50 && n2 <= 100000 && n1 > 0 && n2 > 0) @@ -161,8 +181,11 @@ namespace NadekoBot.Modules.Gambling { arr[i] = rng.Next(1, n2 + 1) + add - sub; } - var elemCnt = 0; - await channel.SendConfirmAsync($"{umsg.Author.Mention} rolled {n1} {(n1 == 1 ? "die" : "dice")} `1 to {n2}` +`{add}` -`{sub}`.\n`Result:` " + string.Join(", ", (ordered ? arr.OrderBy(x => x).AsEnumerable() : arr).Select(x => elemCnt++ % 2 == 0 ? $"**{x}**" : x.ToString()))).ConfigureAwait(false); + + var embed = new EmbedBuilder().WithOkColor().WithDescription($"{umsg.Author.Mention} rolled {n1} {(n1 == 1 ? "die" : "dice")} `1 to {n2}` +`{add}` -`{sub}`") + .AddField(efb => efb.WithName(Format.Bold("Result")) + .WithValue(string.Join(" ", (ordered ? arr.OrderBy(x => x).AsEnumerable() : arr).Select(x => Format.Code(x.ToString()))))); + await channel.EmbedAsync(embed.Build()).ConfigureAwait(false); } } } diff --git a/src/NadekoBot/Modules/Gambling/Commands/FlipCoinCommand.cs b/src/NadekoBot/Modules/Gambling/Commands/FlipCoinCommand.cs index 110905cc..2c1b9245 100644 --- a/src/NadekoBot/Modules/Gambling/Commands/FlipCoinCommand.cs +++ b/src/NadekoBot/Modules/Gambling/Commands/FlipCoinCommand.cs @@ -67,6 +67,7 @@ namespace NadekoBot.Modules.Gambling if (!removed) { await channel.SendErrorAsync($"{guildUser.Mention} You don't have enough {Gambling.CurrencyPluralName}.").ConfigureAwait(false); + return; } //heads = true //tails = false diff --git a/src/NadekoBot/Modules/Games/Commands/Hangman/HangmanGame.cs b/src/NadekoBot/Modules/Games/Commands/Hangman/HangmanGame.cs index 048f51f3..d8bf3e7c 100644 --- a/src/NadekoBot/Modules/Games/Commands/Hangman/HangmanGame.cs +++ b/src/NadekoBot/Modules/Games/Commands/Hangman/HangmanGame.cs @@ -116,7 +116,8 @@ namespace NadekoBot.Modules.Games.Commands.Hangman var embed = new EmbedBuilder().WithTitle("Hangman Game") .WithDescription(toSend) .AddField(efb => efb.WithName("It was").WithValue(Term.Word)) - .WithImage(eib => eib.WithUrl(Term.ImageUrl)); + .WithImage(eib => eib.WithUrl(Term.ImageUrl)) + .WithFooter(efb => efb.WithText(string.Join(" ", Guesses))); if (Errors >= MaxErrors) await GameChannel.EmbedAsync(embed.WithErrorColor().Build()).ConfigureAwait(false); else @@ -134,7 +135,13 @@ namespace NadekoBot.Modules.Games.Commands.Hangman MessagesSinceLastPost = 0; Task.Run(async () => { - try { await GameChannel.SendConfirmAsync("Hangman Game", ScrambledWord + "\n" + GetHangman()).ConfigureAwait(false); } catch { } + try + { + await GameChannel.SendConfirmAsync("Hangman Game", + ScrambledWord + "\n" + GetHangman(), + footer: string.Join(" ", Guesses)).ConfigureAwait(false); + } + catch { } }); } return Task.CompletedTask; @@ -151,9 +158,11 @@ namespace NadekoBot.Modules.Games.Commands.Hangman { if (Guesses.Contains(guess)) { + MessagesSinceLastPost = 0; ++Errors; if (Errors < MaxErrors) - await GameChannel.SendErrorAsync("Hangman Game", $"{msg.Author.Mention} Letter `{guess}` has already been used.\n" + ScrambledWord + "\n" + GetHangman()).ConfigureAwait(false); + await GameChannel.SendErrorAsync("Hangman Game", $"{msg.Author.Mention} Letter `{guess}` has already been used.\n" + ScrambledWord + "\n" + GetHangman(), + footer: string.Join(" ", Guesses)).ConfigureAwait(false); else await End().ConfigureAwait(false); return; @@ -170,14 +179,18 @@ namespace NadekoBot.Modules.Games.Commands.Hangman await End().ConfigureAwait(false); return; } - try { await GameChannel.SendConfirmAsync("Hangman Game", $"{msg.Author.Mention} guessed a letter `{guess}`!\n" + ScrambledWord + "\n" + GetHangman()).ConfigureAwait(false); } catch { } + MessagesSinceLastPost = 0; + try { await GameChannel.SendConfirmAsync("Hangman Game", $"{msg.Author.Mention} guessed a letter `{guess}`!\n" + ScrambledWord + "\n" + GetHangman(), + footer: string.Join(" ", Guesses)).ConfigureAwait(false); } catch { } } else { + MessagesSinceLastPost = 0; ++Errors; if (Errors < MaxErrors) - await GameChannel.SendErrorAsync("Hangman Game", $"{msg.Author.Mention} Letter `{guess}` does not exist.\n" + ScrambledWord + "\n" + GetHangman()).ConfigureAwait(false); + await GameChannel.SendErrorAsync("Hangman Game", $"{msg.Author.Mention} Letter `{guess}` does not exist.\n" + ScrambledWord + "\n" + GetHangman(), + footer: string.Join(" ", Guesses)).ConfigureAwait(false); else await End().ConfigureAwait(false); } diff --git a/src/NadekoBot/Modules/Help/Help.cs b/src/NadekoBot/Modules/Help/Help.cs index 2f25f31a..f1f1ea0e 100644 --- a/src/NadekoBot/Modules/Help/Help.cs +++ b/src/NadekoBot/Modules/Help/Help.cs @@ -38,8 +38,10 @@ namespace NadekoBot.Modules.Help public async Task Modules(IUserMessage umsg) { - await umsg.Channel.SendMessageAsync("📜 **List of modules:** ```css\n• " + string.Join("\n• ", NadekoBot.CommandService.Modules.Select(m => m.Name)) + $"\n``` ℹ️ **Type** `-commands module_name` **to get a list of commands in that module.** ***e.g.*** `-commands games`") - .ConfigureAwait(false); + var embed = new EmbedBuilder().WithOkColor().WithFooter(efb => efb.WithText($" ℹ️ Type `-cmds ModuleName` to get a list of commands in that module. eg `-cmds games`")) + .WithTitle("📜 List Of Modules").WithDescription("\n• " + string.Join("\n• ", NadekoBot.CommandService.Modules.Select(m => m.Name).OrderBy(s=>s))) + .Build(); + await umsg.Channel.EmbedAsync(embed).ConfigureAwait(false); } [NadekoCommand, Usage, Description, Aliases] diff --git a/src/NadekoBot/Modules/Music/Music.cs b/src/NadekoBot/Modules/Music/Music.cs index 3b52abaa..7495af35 100644 --- a/src/NadekoBot/Modules/Music/Music.cs +++ b/src/NadekoBot/Modules/Music/Music.cs @@ -310,27 +310,31 @@ namespace NadekoBot.Modules.Music await channel.SendErrorAsync($"🎵 Failed to find any songs.").ConfigureAwait(false); return; } - var idArray = ids as string[] ?? ids.ToArray(); - var count = idArray.Length; + var count = ids.Count(); - var msg = - await channel.SendMessageAsync($"🎵 Attempting to queue **{count}** songs".SnPl(count) + "...").ConfigureAwait(false); + var msg = await channel.SendMessageAsync($"🎵 Attempting to queue **{count}** songs".SnPl(count) + "...").ConfigureAwait(false); var cancelSource = new CancellationTokenSource(); - var tasks = Task.WhenAll(idArray.Select(async id => - { - if (cancelSource.Token.IsCancellationRequested) - return; - try - { - await QueueSong(((IGuildUser)umsg.Author), channel, ((IGuildUser)umsg.Author).VoiceChannel, id, true).ConfigureAwait(false); - } - catch (SongNotFoundException) { } - catch { try { cancelSource.Cancel(); } catch { } } - })); + var gusr = (IGuildUser)umsg.Author; - await Task.WhenAny(tasks, Task.Delay(Timeout.Infinite, cancelSource.Token)); + while (ids.Any() && !cancelSource.IsCancellationRequested) + { + var tasks = Task.WhenAll(ids.Take(5).Select(async id => + { + if (cancelSource.Token.IsCancellationRequested) + return; + try + { + await QueueSong(gusr, channel, gusr.VoiceChannel, id, true).ConfigureAwait(false); + } + catch (SongNotFoundException) { } + catch { try { cancelSource.Cancel(); } catch { } } + })); + + await Task.WhenAny(tasks, Task.Delay(Timeout.Infinite, cancelSource.Token)); + ids = ids.Skip(5); + } await msg.ModifyAsync(m => m.Content = "✅ Playlist queue complete.").ConfigureAwait(false); } @@ -386,11 +390,12 @@ namespace NadekoBot.Modules.Music var dir = new DirectoryInfo(arg); var fileEnum = dir.GetFiles("*", SearchOption.AllDirectories) .Where(x => !x.Attributes.HasFlag(FileAttributes.Hidden | FileAttributes.System)); + var gusr = (IGuildUser)umsg.Author; foreach (var file in fileEnum) { try { - await QueueSong(((IGuildUser)umsg.Author), channel, ((IGuildUser)umsg.Author).VoiceChannel, file.FullName, true, MusicType.Local).ConfigureAwait(false); + await QueueSong(gusr, channel, gusr.VoiceChannel, file.FullName, true, MusicType.Local).ConfigureAwait(false); } catch (PlaylistFullException) { @@ -636,9 +641,10 @@ namespace NadekoBot.Modules.Music } IUserMessage msg = null; try { msg = await channel.SendMessageAsync($"🎶 Attempting to load **{mpl.Songs.Count}** songs...").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); } + + var usr = (IGuildUser)umsg.Author; foreach (var item in mpl.Songs) { - var usr = (IGuildUser)umsg.Author; try { await QueueSong(usr, channel, usr.VoiceChannel, item.Query, true, item.ProviderType).ConfigureAwait(false); diff --git a/src/NadekoBot/Modules/Permissions/Commands/FilterCommands.cs b/src/NadekoBot/Modules/Permissions/Commands/FilterCommands.cs index d6f22fb5..ab2558f5 100644 --- a/src/NadekoBot/Modules/Permissions/Commands/FilterCommands.cs +++ b/src/NadekoBot/Modules/Permissions/Commands/FilterCommands.cs @@ -2,6 +2,7 @@ using Discord.Commands; using Microsoft.EntityFrameworkCore; using NadekoBot.Attributes; +using NadekoBot.Extensions; using NadekoBot.Services; using System.Collections.Concurrent; using System.Linq; @@ -77,12 +78,12 @@ namespace NadekoBot.Modules.Permissions if (enabled) { InviteFilteringServers.Add(channel.Guild.Id); - await channel.SendMessageAsync("✅ `Invite filtering enabled on this server.`").ConfigureAwait(false); + await channel.SendConfirmAsync("Invite filtering enabled on this server.").ConfigureAwait(false); } else { InviteFilteringServers.TryRemove(channel.Guild.Id); - await channel.SendMessageAsync("ℹ️ `Invite filtering disabled on this server.`").ConfigureAwait(false); + await channel.SendConfirmAsync("Invite filtering disabled on this server.").ConfigureAwait(false); } } @@ -110,12 +111,12 @@ namespace NadekoBot.Modules.Permissions if (removed == 0) { InviteFilteringChannels.Add(channel.Id); - await channel.SendMessageAsync("✅ `Invite filtering enabled on this channel.`").ConfigureAwait(false); + await channel.SendConfirmAsync("Invite filtering enabled on this channel.").ConfigureAwait(false); } else { InviteFilteringChannels.TryRemove(channel.Id); - await channel.SendMessageAsync("ℹ️ `Invite filtering disabled on this channel.`").ConfigureAwait(false); + await channel.SendConfirmAsync("Invite filtering disabled on this channel.").ConfigureAwait(false); } } @@ -136,12 +137,12 @@ namespace NadekoBot.Modules.Permissions if (enabled) { WordFilteringServers.Add(channel.Guild.Id); - await channel.SendMessageAsync("✅ `Word filtering enabled on this server.`").ConfigureAwait(false); + await channel.SendConfirmAsync("Word filtering enabled on this server.").ConfigureAwait(false); } else { WordFilteringServers.TryRemove(channel.Guild.Id); - await channel.SendMessageAsync("ℹ️ `Word filtering disabled on this server.`").ConfigureAwait(false); + await channel.SendConfirmAsync("Word filtering disabled on this server.").ConfigureAwait(false); } } @@ -169,12 +170,12 @@ namespace NadekoBot.Modules.Permissions if (removed == 0) { WordFilteringChannels.Add(channel.Id); - await channel.SendMessageAsync("✅ `Word filtering enabled on this channel.`").ConfigureAwait(false); + await channel.SendConfirmAsync("Word filtering enabled on this channel.").ConfigureAwait(false); } else { WordFilteringChannels.TryRemove(channel.Id); - await channel.SendMessageAsync("ℹ️ `Word filtering disabled on this channel.`").ConfigureAwait(false); + await channel.SendConfirmAsync("Word filtering disabled on this channel.").ConfigureAwait(false); } } @@ -207,13 +208,13 @@ namespace NadekoBot.Modules.Permissions if (removed == 0) { filteredWords.Add(word); - await channel.SendMessageAsync($"✅ Word `{word}` successfully added to the list of filtered words.") + await channel.SendConfirmAsync($"Word `{word}` successfully added to the list of filtered words.") .ConfigureAwait(false); } else { filteredWords.TryRemove(word); - await channel.SendMessageAsync($"ℹ️ Word `{word}` removed from the list of filtered words.") + await channel.SendConfirmAsync($"Word `{word}` removed from the list of filtered words.") .ConfigureAwait(false); } } @@ -227,7 +228,7 @@ namespace NadekoBot.Modules.Permissions ConcurrentHashSet filteredWords; ServerFilteredWords.TryGetValue(channel.Guild.Id, out filteredWords); - await channel.SendMessageAsync($"ℹ️ `List of banned words:`\n" + string.Join(",\n", filteredWords)) + await channel.SendConfirmAsync($"List of filtered words", string.Join("\n", filteredWords)) .ConfigureAwait(false); } } diff --git a/src/NadekoBot/Modules/Searches/Commands/AnimeSearchCommands.cs b/src/NadekoBot/Modules/Searches/Commands/AnimeSearchCommands.cs index a21ea1f5..52f9fda0 100644 --- a/src/NadekoBot/Modules/Searches/Commands/AnimeSearchCommands.cs +++ b/src/NadekoBot/Modules/Searches/Commands/AnimeSearchCommands.cs @@ -46,7 +46,8 @@ namespace NadekoBot.Modules.Searches anilistToken = JObject.Parse(stringContent)["access_token"].ToString(); } } - catch (Exception ex) { + catch (Exception ex) + { _log.Error(ex); } }, null, TimeSpan.FromSeconds(0), TimeSpan.FromMinutes(29)); @@ -69,34 +70,16 @@ namespace NadekoBot.Modules.Searches return; } - var embed = new Discord.API.Embed() - { - Description = animeData.Synopsis, - Title = animeData.title_english, - Url = animeData.Link, - Image = new Discord.API.EmbedImage() { - Url = animeData.image_url_lge - }, - Fields = new[] { - new Discord.API.EmbedField() { - Inline = true, - Name = "Episodes", - Value = animeData.total_episodes.ToString() - }, - new Discord.API.EmbedField() { - Inline = true, - Name = "Status", - Value = animeData.AiringStatus.ToString() - }, - new Discord.API.EmbedField() { - Inline = true, - Name = "Genres", - Value = String.Join(", ", animeData.Genres) - } - }, - Color = NadekoBot.OkColor - }; - await channel.EmbedAsync(embed).ConfigureAwait(false); + var embed = new EmbedBuilder().WithColor(NadekoBot.OkColor) + .WithDescription(animeData.Synopsis.Replace("
", Environment.NewLine)) + .WithTitle(animeData.title_english) + .WithUrl(animeData.Link) + .WithImageUrl(animeData.image_url_lge) + .AddField(efb => efb.WithName("Episodes").WithValue(animeData.total_episodes.ToString()).WithIsInline(true)) + .AddField(efb => efb.WithName("Status").WithValue(animeData.AiringStatus.ToString()).WithIsInline(true)) + .AddField(efb => efb.WithName("Genres").WithValue(String.Join(", ", animeData.Genres)).WithIsInline(true)) + .WithFooter(efb => efb.WithText("Score: " + animeData.average_score + " / 100")); + await channel.EmbedAsync(embed.Build()).ConfigureAwait(false); } [NadekoCommand, Usage, Description, Aliases] @@ -116,36 +99,17 @@ namespace NadekoBot.Modules.Searches return; } - var embed = new Discord.API.Embed() - { - Description = mangaData.Synopsis, - Title = mangaData.title_english, - Url = mangaData.Link, - Image = new Discord.API.EmbedImage() - { - Url = mangaData.image_url_lge - }, - Fields = new[] { - new Discord.API.EmbedField() { - Inline = true, - Name = "Chapters", - Value = mangaData.total_chapters.ToString() - }, - new Discord.API.EmbedField() { - Inline = true, - Name = "Status", - Value = mangaData.publishing_status.ToString() - }, - new Discord.API.EmbedField() { - Inline = true, - Name = "Genres", - Value = String.Join(", ", mangaData.Genres) - } - }, - Color = NadekoBot.OkColor - }; + var embed = new EmbedBuilder().WithColor(NadekoBot.OkColor) + .WithDescription(mangaData.Synopsis.Replace("
", Environment.NewLine)) + .WithTitle(mangaData.title_english) + .WithUrl(mangaData.Link) + .WithImageUrl(mangaData.image_url_lge) + .AddField(efb => efb.WithName("Episodes").WithValue(mangaData.total_chapters.ToString()).WithIsInline(true)) + .AddField(efb => efb.WithName("Status").WithValue(mangaData.publishing_status.ToString()).WithIsInline(true)) + .AddField(efb => efb.WithName("Genres").WithValue(String.Join(", ", mangaData.Genres)).WithIsInline(true)) + .WithFooter(efb => efb.WithText("Score: " + mangaData.average_score + " / 100")); - await channel.EmbedAsync(embed).ConfigureAwait(false); + await channel.EmbedAsync(embed.Build()).ConfigureAwait(false); } private async Task GetAnimeData(string query) @@ -165,7 +129,8 @@ namespace NadekoBot.Modules.Searches return await Task.Run(() => { try { return JsonConvert.DeserializeObject(aniData); } catch { return null; } }).ConfigureAwait(false); } } - catch (Exception ex) { + catch (Exception ex) + { _log.Warn(ex, "Failed anime search for {0}", query); return null; } diff --git a/src/NadekoBot/Modules/Searches/Commands/Models/AnimeResult.cs b/src/NadekoBot/Modules/Searches/Commands/Models/AnimeResult.cs index 3d08da6e..e5d779c0 100644 --- a/src/NadekoBot/Modules/Searches/Commands/Models/AnimeResult.cs +++ b/src/NadekoBot/Modules/Searches/Commands/Models/AnimeResult.cs @@ -13,6 +13,8 @@ namespace NadekoBot.Modules.Searches.Models public string description; public string image_url_lge; public string[] Genres; + public string average_score; + public string Link => "http://anilist.co/anime/" + id; public string Synopsis => description?.Substring(0, description.Length > 500 ? 500 : description.Length) + "..."; } diff --git a/src/NadekoBot/Modules/Searches/Commands/Models/MangaResult.cs b/src/NadekoBot/Modules/Searches/Commands/Models/MangaResult.cs index 5e262209..a0d47962 100644 --- a/src/NadekoBot/Modules/Searches/Commands/Models/MangaResult.cs +++ b/src/NadekoBot/Modules/Searches/Commands/Models/MangaResult.cs @@ -10,6 +10,7 @@ namespace NadekoBot.Modules.Searches.Models public int total_volumes; public string description; public string[] Genres; + public string average_score; public string Link => "http://anilist.co/manga/" + id; public string Synopsis => description?.Substring(0, description.Length > 500 ? 500 : description.Length) + "..."; } diff --git a/src/NadekoBot/Modules/Searches/Commands/StreamNotificationCommands.cs b/src/NadekoBot/Modules/Searches/Commands/StreamNotificationCommands.cs index b81626f2..8a09497e 100644 --- a/src/NadekoBot/Modules/Searches/Commands/StreamNotificationCommands.cs +++ b/src/NadekoBot/Modules/Searches/Commands/StreamNotificationCommands.cs @@ -108,7 +108,13 @@ namespace NadekoBot.Modules.Searches var channel = server?.GetTextChannel(fs.ChannelId); if (channel == null) return; - try { await channel.EmbedAsync(fs.GetEmbed(newStatus).Build()).ConfigureAwait(false); } catch { } + try + { + var msg = await channel.EmbedAsync(fs.GetEmbed(newStatus).Build()).ConfigureAwait(false); + if (!newStatus.IsLive) + msg.DeleteAfter(60); + } + catch { } } } catch { } diff --git a/src/NadekoBot/Modules/Utility/Utility.cs b/src/NadekoBot/Modules/Utility/Utility.cs index e4e2fe31..5de70a5f 100644 --- a/src/NadekoBot/Modules/Utility/Utility.cs +++ b/src/NadekoBot/Modules/Utility/Utility.cs @@ -15,6 +15,7 @@ using Discord.API; using Embed = Discord.API.Embed; using EmbedAuthor = Discord.API.EmbedAuthor; using EmbedField = Discord.API.EmbedField; +using System.Net.Http; namespace NadekoBot.Modules.Utility { @@ -27,6 +28,27 @@ namespace NadekoBot.Modules.Utility } + [NadekoCommand, Usage, Description, Aliases] + [RequireContext(ContextType.Guild)] + public async Task TogetherTube(IUserMessage imsg) + { + var channel = (ITextChannel)imsg.Channel; + + Uri target; + using (var http = new HttpClient()) + { + var res = await http.GetAsync("https://togethertube.com/room/create").ConfigureAwait(false); + target = res.RequestMessage.RequestUri; + } + + await channel.EmbedAsync(new EmbedBuilder().WithOkColor() + .WithAuthor(eab => eab.WithIconUrl("https://togethertube.com/assets/img/favicons/favicon-32x32.png") + .WithName("Together Tube") + .WithUrl("https://togethertube.com/")) + .WithDescription($"{imsg.Author.Mention} Here is your room link:\n{target}") + .Build()); + } + [NadekoCommand, Usage, Description, Aliases] [RequireContext(ContextType.Guild)] public async Task WhosPlaying(IUserMessage umsg, [Remainder] string game = null) @@ -185,64 +207,23 @@ namespace NadekoBot.Modules.Utility var stats = NadekoBot.Stats; await channel.EmbedAsync( - new Embed() - { - Author = new EmbedAuthor() - { - Name = $"NadekoBot v{StatsService.BotVersion}", - Url = "http://nadekobot.readthedocs.io/en/latest/", - IconUrl = "https://cdn.discordapp.com/avatars/116275390695079945/b21045e778ef21c96d175400e779f0fb.jpg" - }, - Fields = new[] { - new EmbedField() { - Name = Format.Bold("Author"), - Value = stats.Author, - Inline = true - }, - new EmbedField() { - Name = Format.Bold("Library"), - Value = stats.Library, - Inline = true - }, - new EmbedField() { - Name = Format.Bold("Bot ID"), - Value = NadekoBot.Client.GetCurrentUser().Id.ToString(), - Inline = true - }, - new EmbedField() { - Name = Format.Bold("Commands Ran"), - Value = stats.CommandsRan.ToString(), - Inline = true - }, - new EmbedField() { - Name = Format.Bold("Messages"), - Value = $"{stats.MessageCounter} ({stats.MessagesPerSecond:F2}/sec)", - Inline = true - }, - new EmbedField() { - Name = Format.Bold("Memory"), - Value = $"{stats.Heap} MB", - Inline = true - }, - new EmbedField() { - Name = Format.Bold("Owner ID(s)"), - Value = stats.OwnerIds, - Inline = true - }, - new EmbedField() { - Name = Format.Bold("Uptime"), - Value = stats.GetUptimeString("\n"), - Inline = true - }, - new EmbedField() { - Name = Format.Bold("Presence"), - Value = $"{NadekoBot.Client.GetGuilds().Count} Servers\n{stats.TextChannels} Text Channels\n{stats.VoiceChannels} Voice Channels", - Inline = true - }, - - }, - Color = 0x00bbd6 - }); + new EmbedBuilder().WithOkColor() + .WithAuthor(eab => eab.WithName($"NadekoBot v{StatsService.BotVersion}") + .WithUrl("http://nadekobot.readthedocs.io/en/latest/") + .WithIconUrl("https://cdn.discordapp.com/avatars/116275390695079945/b21045e778ef21c96d175400e779f0fb.jpg")) + .AddField(efb => efb.WithName(Format.Bold("Author")).WithValue(stats.Author).WithIsInline(true)) + .AddField(efb => efb.WithName(Format.Bold("Library")).WithValue(stats.Library).WithIsInline(true)) + .AddField(efb => efb.WithName(Format.Bold("Bot ID")).WithValue(NadekoBot.Client.GetCurrentUser().Id.ToString()).WithIsInline(true)) + .AddField(efb => efb.WithName(Format.Bold("Commands Ran")).WithValue(stats.CommandsRan.ToString()).WithIsInline(true)) + .AddField(efb => efb.WithName(Format.Bold("Messages")).WithValue($"{stats.MessageCounter} ({stats.MessagesPerSecond:F2}/sec)").WithIsInline(true)) + .AddField(efb => efb.WithName(Format.Bold("Memory")).WithValue($"{stats.Heap} MB").WithIsInline(true)) + .AddField(efb => efb.WithName(Format.Bold("Owner ID(s)")).WithValue(stats.OwnerIds).WithIsInline(true)) + .AddField(efb => efb.WithName(Format.Bold("Uptime")).WithValue(stats.GetUptimeString("\n")).WithIsInline(true)) + .AddField(efb => efb.WithName(Format.Bold("Presence")).WithValue($"{NadekoBot.Client.GetGuilds().Count} Servers\n{stats.TextChannels} Text Channels\n{stats.VoiceChannels} Voice Channels").WithIsInline(true)) +#if !GLOBAL_NADEKO + .WithFooter(efb => efb.WithText($"Playing {Music.Music.MusicPlayers.Where(mp => mp.Value.CurrentSong != null).Count()} songs, {Music.Music.MusicPlayers.Sum(mp => mp.Value.Playlist.Count)} queued.")) +#endif + .Build()); } private Regex emojiFinder { get; } = new Regex(@"<:(?.+?):(?\d*)>", RegexOptions.Compiled); diff --git a/src/NadekoBot/Resources/CommandStrings.Designer.cs b/src/NadekoBot/Resources/CommandStrings.Designer.cs index df31964a..4193bdd7 100644 --- a/src/NadekoBot/Resources/CommandStrings.Designer.cs +++ b/src/NadekoBot/Resources/CommandStrings.Designer.cs @@ -3920,6 +3920,60 @@ namespace NadekoBot.Resources { } } + /// + /// Looks up a localized string similar to log. + /// + public static string log_cmd { + get { + return ResourceManager.GetString("log_cmd", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Toggles logging event. Disables it if it's active anywhere on the server. Enables if it's not active. Use `{0}logevents` to see a lit of all events you can subscribe to.. + /// + public static string log_desc { + get { + return ResourceManager.GetString("log_desc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to `{0}log userpresence` or `{0}log userbanned`. + /// + public static string log_usage { + get { + return ResourceManager.GetString("log_usage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to logevents. + /// + public static string logevents_cmd { + get { + return ResourceManager.GetString("logevents_cmd", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Shows a list of all events you can subscribe to with `{0}log`. + /// + public static string logevents_desc { + get { + return ResourceManager.GetString("logevents_desc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to `{0}logevents`. + /// + public static string logevents_usage { + get { + return ResourceManager.GetString("logevents_usage", resourceCulture); + } + } + /// /// Looks up a localized string similar to logignore. /// @@ -3957,7 +4011,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to Logs server activity in this channel.. + /// Looks up a localized string similar to Enables or Disables ALL log events. If enabled, all log events will log to this channel.. /// public static string logserver_desc { get { @@ -3966,7 +4020,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to `{0}logserver`. + /// Looks up a localized string similar to `{0}logserver enable` or `{0}logserver disable`. /// public static string logserver_usage { get { diff --git a/src/NadekoBot/Resources/CommandStrings.resx b/src/NadekoBot/Resources/CommandStrings.resx index 1b0f35cd..fb067b65 100644 --- a/src/NadekoBot/Resources/CommandStrings.resx +++ b/src/NadekoBot/Resources/CommandStrings.resx @@ -229,10 +229,10 @@ logserver - Logs server activity in this channel. + Enables or Disables ALL log events. If enabled, all log events will log to this channel. - `{0}logserver` + `{0}logserver enable` or `{0}logserver disable` logignore @@ -988,7 +988,7 @@ Sets a module's permission at the server level. - `{0}sm "module name" enable` + `{0}sm ModuleName enable` srvrcmd sc @@ -1006,7 +1006,7 @@ Sets a module's permission at the role level. - `{0}rm "module name" enable MyRole` + `{0}rm ModuleName enable MyRole` rolecmd rc @@ -1024,7 +1024,7 @@ Sets a module's permission at the channel level. - `{0}cm "module name" enable SomeChannel` + `{0}cm ModuleName enable SomeChannel` chnlcmd cc @@ -1042,7 +1042,7 @@ Sets a module's permission at the user level. - `{0}um "module name" enable SomeUsername` + `{0}um ModuleName enable SomeUsername` usrcmd uc @@ -1192,10 +1192,10 @@ 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. + 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. Y can be a letter 'F' if you want to roll fate dice instead of dnd. - `{0}roll` or `{0}roll 7` or `{0}roll 3d5` + `{0}roll` or `{0}roll 7` or `{0}roll 3d5` or `{0}roll 5dF` rolluo @@ -2799,4 +2799,22 @@ `{0}acro` or `{0}acro 30` + + logevents + + + Shows a list of all events you can subscribe to with `{0}log` + + + `{0}logevents` + + + log + + + Toggles logging event. Disables it if it's active anywhere on the server. Enables if it's not active. Use `{0}logevents` to see a lit of all events you can subscribe to. + + + `{0}log userpresence` or `{0}log userbanned` + \ No newline at end of file diff --git a/src/NadekoBot/Services/Database/Models/LogSetting.cs b/src/NadekoBot/Services/Database/Models/LogSetting.cs index b5e841fb..659df55c 100644 --- a/src/NadekoBot/Services/Database/Models/LogSetting.cs +++ b/src/NadekoBot/Services/Database/Models/LogSetting.cs @@ -2,33 +2,104 @@ namespace NadekoBot.Services.Database.Models { + public class LogSetting : DbEntity { - public bool IsLogging { get; set; } - public ulong ChannelId { get; set; } - public HashSet IgnoredChannels { get; set; } + public HashSet IgnoredChannels { get; set; } = new HashSet(); + public HashSet IgnoredVoicePresenceChannelIds { get; set; } = new HashSet(); - public bool MessageUpdated { get; set; } = true; - public bool MessageDeleted { get; set; } = true; + public ulong? LogOtherId { get; set; } = null; + public ulong? MessageUpdatedId { get; set; } = null; + public ulong? MessageDeletedId { get; set; } = null; - public bool UserJoined { get; set; } = true; - public bool UserLeft { get; set; } = true; - public bool UserBanned { get; set; } = true; - public bool UserUnbanned { get; set; } = true; - public bool UserUpdated { get; set; } = true; + public ulong? UserJoinedId { get; set; } = null; + public ulong? UserLeftId { get; set; } = null; + public ulong? UserBannedId { get; set; } = null; + public ulong? UserUnbannedId { get; set; } = null; + public ulong? UserUpdatedId { get; set; } = null; - public bool ChannelCreated { get; set; } = true; - public bool ChannelDestroyed { get; set; } = true; - public bool ChannelUpdated { get; set; } = true; + public ulong? ChannelCreatedId { get; set; } = null; + public ulong? ChannelDestroyedId { get; set; } = null; + public ulong? ChannelUpdatedId { get; set; } = null; + + public ulong? UserMutedId { get; set; } //userpresence - public bool LogUserPresence { get; set; } = false; - public ulong UserPresenceChannelId { get; set; } + public ulong? LogUserPresenceId { get; set; } = null; //voicepresence - public bool LogVoicePresence { get; set; } = false; - public ulong VoicePresenceChannelId { get; set; } - public HashSet IgnoredVoicePresenceChannelIds { get; set; } + public ulong? LogVoicePresenceId { get; set; } = null; + public ulong? LogVoicePresenceTTSId { get; set; } = null; + + + + //-------------------DO NOT USE---------------- + // these old fields are here because sqlite doesn't support drop column operation + // will be removed after bot moves to another database provider + /// + /// DON'T USE + /// + public bool IsLogging { get; set; } + /// + /// DON'T USE + /// + public ulong ChannelId { get; set; } + /// + /// DON'T USE + /// + public bool MessageUpdated { get; set; } = true; + /// + /// DON'T USE + /// + public bool MessageDeleted { get; set; } = true; + /// + /// DON'T USE + /// + public bool UserJoined { get; set; } = true; + /// + /// DON'T USE + /// + public bool UserLeft { get; set; } = true; + /// + /// DON'T USE + /// + public bool UserBanned { get; set; } = true; + /// + /// DON'T USE + /// + public bool UserUnbanned { get; set; } = true; + /// + /// DON'T USE + /// + public bool UserUpdated { get; set; } = true; + /// + /// DON'T USE + /// + public bool ChannelCreated { get; set; } = true; + /// + /// DON'T USE + /// + public bool ChannelDestroyed { get; set; } = true; + /// + /// DON'T USE + /// + public bool ChannelUpdated { get; set; } = true; + /// + /// DON'T USE + /// + public bool LogUserPresence { get; set; } = false; + /// + /// DON'T USE + /// + public ulong UserPresenceChannelId { get; set; } + /// + /// DON'T USE + /// + public bool LogVoicePresence { get; set; } = false; + /// + /// DON'T USE + /// + public ulong VoicePresenceChannelId { get; set; } } -} +} \ No newline at end of file diff --git a/src/NadekoBot/Services/Database/Repositories/IGuildConfigRepository.cs b/src/NadekoBot/Services/Database/Repositories/IGuildConfigRepository.cs index 1fc9015d..34f3f564 100644 --- a/src/NadekoBot/Services/Database/Repositories/IGuildConfigRepository.cs +++ b/src/NadekoBot/Services/Database/Repositories/IGuildConfigRepository.cs @@ -9,6 +9,7 @@ namespace NadekoBot.Services.Database.Repositories public interface IGuildConfigRepository : IRepository { GuildConfig For(ulong guildId, Func, IQueryable> includes = null); + GuildConfig LogSettingsFor(ulong guildId); GuildConfig PermissionsFor(ulong guildId); IEnumerable PermissionsForAll(); IEnumerable GetAllGuildConfigs(); diff --git a/src/NadekoBot/Services/Database/Repositories/Impl/GuildConfigRepository.cs b/src/NadekoBot/Services/Database/Repositories/Impl/GuildConfigRepository.cs index dc857b8b..0720e8ad 100644 --- a/src/NadekoBot/Services/Database/Repositories/Impl/GuildConfigRepository.cs +++ b/src/NadekoBot/Services/Database/Repositories/Impl/GuildConfigRepository.cs @@ -16,8 +16,6 @@ namespace NadekoBot.Services.Database.Repositories.Impl public IEnumerable GetAllGuildConfigs() => _set.Include(gc => gc.LogSetting) .ThenInclude(ls => ls.IgnoredChannels) - .Include(gc => gc.LogSetting) - .ThenInclude(ls => ls.IgnoredVoicePresenceChannelIds) .Include(gc => gc.RootPermission) .ThenInclude(gc => gc.Previous) .Include(gc => gc.RootPermission) @@ -43,10 +41,8 @@ namespace NadekoBot.Services.Database.Repositories.Impl { config = _set .Include(gc => gc.FollowedStreams) - .Include(gc => gc.LogSetting) - .ThenInclude(ls => ls.IgnoredChannels) .Include(gc => gc.LogSetting) - .ThenInclude(ls => ls.IgnoredVoicePresenceChannelIds) + .ThenInclude(ls => ls.IgnoredChannels) .Include(gc => gc.FilterInvitesChannelIds) .Include(gc => gc.FilterWordsChannelIds) .Include(gc => gc.FilteredWords) @@ -72,6 +68,13 @@ namespace NadekoBot.Services.Database.Repositories.Impl return config; } + public GuildConfig LogSettingsFor(ulong guildId) + { + return _set.Include(gc => gc.LogSetting) + .ThenInclude(gc => gc.IgnoredChannels) + .FirstOrDefault(); + } + public GuildConfig PermissionsFor(ulong guildId) { var query = _set.Include(gc => gc.RootPermission); diff --git a/src/NadekoBot/_Extensions/Extensions.cs b/src/NadekoBot/_Extensions/Extensions.cs index 4c98b5dd..439f8c1a 100644 --- a/src/NadekoBot/_Extensions/Extensions.cs +++ b/src/NadekoBot/_Extensions/Extensions.cs @@ -25,6 +25,9 @@ namespace NadekoBot.Extensions http.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); } + public static EmbedBuilder WithImageUrl(this EmbedBuilder eb, string url) => + eb.WithImage(eib => eib.WithUrl(url)); + public static EmbedBuilder WithOkColor(this EmbedBuilder eb) => eb.WithColor(NadekoBot.OkColor); @@ -114,14 +117,34 @@ namespace NadekoBot.Extensions public static Task EmbedAsync(this IMessageChannel ch, Discord.API.Embed embed, string msg = "") => ch.SendMessageAsync(msg, embed: embed); - public static Task SendErrorAsync(this IMessageChannel ch, string title, string error, string url = null) - => ch.SendMessageAsync("", embed: new Embed() { Description = error, Title = title, Url = url, Color = NadekoBot.ErrorColor }); + public static Task SendErrorAsync(this IMessageChannel ch, string title, string error, string url = null, string footer = null) + => ch.SendMessageAsync("", embed: new Embed() + { + Description = error, + Title = title, + Url = url, + Color = NadekoBot.ErrorColor, + Footer = new Discord.API.EmbedFooter() + { + Text = footer + } + }); public static Task SendErrorAsync(this IMessageChannel ch, string error) => ch.SendMessageAsync("", embed: new Embed() { Description = error, Color = NadekoBot.ErrorColor }); - public static Task SendConfirmAsync(this IMessageChannel ch, string title, string text, string url = null) - => ch.SendMessageAsync("", embed: new Embed() { Description = text, Title = title, Url = url, Color = NadekoBot.OkColor }); + public static Task SendConfirmAsync(this IMessageChannel ch, string title, string text, string url = null, string footer = null) + => ch.SendMessageAsync("", embed: new Embed() + { + Description = text, + Title = title, + Url = url, + Color = NadekoBot.OkColor, + Footer = new Discord.API.EmbedFooter() + { + Text = footer + } + }); public static Task SendConfirmAsync(this IMessageChannel ch, string text) => ch.SendMessageAsync("", embed: new Embed() { Description = text, Color = NadekoBot.OkColor }); diff --git a/src/NadekoBot/data/hangman.json b/src/NadekoBot/data/hangman.json index 40f1dd82..e13fd5ab 100644 --- a/src/NadekoBot/data/hangman.json +++ b/src/NadekoBot/data/hangman.json @@ -2579,7 +2579,7 @@ "ImageUrl": "https://www.randomlists.com/img/things/drill_press.jpg" }, { - "Word": "earser", + "Word": "eraser", "ImageUrl": "https://www.randomlists.com/img/things/earser.jpg" }, {