Merge remote-tracking branch 'refs/remotes/Kwoth/1.0' into unitconversion
# Conflicts: # src/NadekoBot/Services/Database/NadekoContext.cs
This commit is contained in:
		
							
								
								
									
										18
									
								
								src/NadekoBot/Attributes/LocalizedAlias.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/NadekoBot/Attributes/LocalizedAlias.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
using Discord.Commands;
 | 
			
		||||
using NadekoBot.Services;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Runtime.CompilerServices;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Attributes
 | 
			
		||||
{
 | 
			
		||||
    public class LocalizedAliasAttribute : AliasAttribute
 | 
			
		||||
    {
 | 
			
		||||
        public LocalizedAliasAttribute([CallerMemberName] string memberName = "") : base(Localization.LoadCommandString(memberName.ToLowerInvariant() + "_text").Split(' ').Skip(1).ToArray())
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,12 +1,13 @@
 | 
			
		||||
using Discord.Commands;
 | 
			
		||||
using NadekoBot.Services;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Runtime.CompilerServices;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Attributes
 | 
			
		||||
{
 | 
			
		||||
    public class LocalizedCommandAttribute : CommandAttribute
 | 
			
		||||
    {
 | 
			
		||||
        public LocalizedCommandAttribute([CallerMemberName] string memberName="") : base(Localization.LoadCommandString(memberName.ToLowerInvariant() + "_text"))
 | 
			
		||||
        public LocalizedCommandAttribute([CallerMemberName] string memberName="") : base(Localization.LoadCommandString(memberName.ToLowerInvariant() + "_text").Split(' ')[0])
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@ using NadekoBot.Services.Database.Impl;
 | 
			
		||||
namespace NadekoBot.Migrations
 | 
			
		||||
{
 | 
			
		||||
    [DbContext(typeof(NadekoSqliteContext))]
 | 
			
		||||
    [Migration("20160830011641_first")]
 | 
			
		||||
    [Migration("20160901001820_first")]
 | 
			
		||||
    partial class first
 | 
			
		||||
    {
 | 
			
		||||
        protected override void BuildTargetModel(ModelBuilder modelBuilder)
 | 
			
		||||
@@ -156,6 +156,30 @@ namespace NadekoBot.Migrations
 | 
			
		||||
                    b.ToTable("EightBallResponse");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.FollowedStream", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<int>("Id")
 | 
			
		||||
                        .ValueGeneratedOnAdd();
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("ChannelId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<int?>("GuildConfigId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("GuildId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<bool>("LastStatus");
 | 
			
		||||
 | 
			
		||||
                    b.Property<int>("Type");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("Username");
 | 
			
		||||
 | 
			
		||||
                    b.HasKey("Id");
 | 
			
		||||
 | 
			
		||||
                    b.HasIndex("GuildConfigId");
 | 
			
		||||
 | 
			
		||||
                    b.ToTable("FollowedStream");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<int>("Id")
 | 
			
		||||
@@ -195,6 +219,8 @@ namespace NadekoBot.Migrations
 | 
			
		||||
 | 
			
		||||
                    b.Property<bool>("SendDmGreetMessage");
 | 
			
		||||
 | 
			
		||||
                    b.Property<bool>("VoicePlusTextEnabled");
 | 
			
		||||
 | 
			
		||||
                    b.HasKey("Id");
 | 
			
		||||
 | 
			
		||||
                    b.HasIndex("GuildId")
 | 
			
		||||
@@ -360,6 +386,13 @@ namespace NadekoBot.Migrations
 | 
			
		||||
                        .HasForeignKey("BotConfigId");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            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.ModulePrefix", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
 | 
			
		||||
@@ -98,7 +98,8 @@ namespace NadekoBot.Migrations
 | 
			
		||||
                    GuildId = table.Column<ulong>(nullable: false),
 | 
			
		||||
                    SendChannelByeMessage = table.Column<bool>(nullable: false),
 | 
			
		||||
                    SendChannelGreetMessage = table.Column<bool>(nullable: false),
 | 
			
		||||
                    SendDmGreetMessage = table.Column<bool>(nullable: false)
 | 
			
		||||
                    SendDmGreetMessage = table.Column<bool>(nullable: false),
 | 
			
		||||
                    VoicePlusTextEnabled = table.Column<bool>(nullable: false)
 | 
			
		||||
                },
 | 
			
		||||
                constraints: table =>
 | 
			
		||||
                {
 | 
			
		||||
@@ -295,6 +296,30 @@ namespace NadekoBot.Migrations
 | 
			
		||||
                        onDelete: ReferentialAction.Cascade);
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            migrationBuilder.CreateTable(
 | 
			
		||||
                name: "FollowedStream",
 | 
			
		||||
                columns: table => new
 | 
			
		||||
                {
 | 
			
		||||
                    Id = table.Column<int>(nullable: false)
 | 
			
		||||
                        .Annotation("Autoincrement", true),
 | 
			
		||||
                    ChannelId = table.Column<ulong>(nullable: false),
 | 
			
		||||
                    GuildConfigId = table.Column<int>(nullable: true),
 | 
			
		||||
                    GuildId = table.Column<ulong>(nullable: false),
 | 
			
		||||
                    LastStatus = table.Column<bool>(nullable: false),
 | 
			
		||||
                    Type = table.Column<int>(nullable: false),
 | 
			
		||||
                    Username = table.Column<string>(nullable: true)
 | 
			
		||||
                },
 | 
			
		||||
                constraints: table =>
 | 
			
		||||
                {
 | 
			
		||||
                    table.PrimaryKey("PK_FollowedStream", x => x.Id);
 | 
			
		||||
                    table.ForeignKey(
 | 
			
		||||
                        name: "FK_FollowedStream_GuildConfigs_GuildConfigId",
 | 
			
		||||
                        column: x => x.GuildConfigId,
 | 
			
		||||
                        principalTable: "GuildConfigs",
 | 
			
		||||
                        principalColumn: "Id",
 | 
			
		||||
                        onDelete: ReferentialAction.Restrict);
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            migrationBuilder.CreateIndex(
 | 
			
		||||
                name: "IX_BlacklistItem_BotConfigId",
 | 
			
		||||
                table: "BlacklistItem",
 | 
			
		||||
@@ -322,6 +347,11 @@ namespace NadekoBot.Migrations
 | 
			
		||||
                table: "EightBallResponse",
 | 
			
		||||
                column: "BotConfigId");
 | 
			
		||||
 | 
			
		||||
            migrationBuilder.CreateIndex(
 | 
			
		||||
                name: "IX_FollowedStream_GuildConfigId",
 | 
			
		||||
                table: "FollowedStream",
 | 
			
		||||
                column: "GuildConfigId");
 | 
			
		||||
 | 
			
		||||
            migrationBuilder.CreateIndex(
 | 
			
		||||
                name: "IX_GuildConfigs_GuildId",
 | 
			
		||||
                table: "GuildConfigs",
 | 
			
		||||
@@ -374,7 +404,7 @@ namespace NadekoBot.Migrations
 | 
			
		||||
                name: "EightBallResponse");
 | 
			
		||||
 | 
			
		||||
            migrationBuilder.DropTable(
 | 
			
		||||
                name: "GuildConfigs");
 | 
			
		||||
                name: "FollowedStream");
 | 
			
		||||
 | 
			
		||||
            migrationBuilder.DropTable(
 | 
			
		||||
                name: "ModulePrefix");
 | 
			
		||||
@@ -400,6 +430,9 @@ namespace NadekoBot.Migrations
 | 
			
		||||
            migrationBuilder.DropTable(
 | 
			
		||||
                name: "ClashOfClans");
 | 
			
		||||
 | 
			
		||||
            migrationBuilder.DropTable(
 | 
			
		||||
                name: "GuildConfigs");
 | 
			
		||||
 | 
			
		||||
            migrationBuilder.DropTable(
 | 
			
		||||
                name: "BotConfig");
 | 
			
		||||
        }
 | 
			
		||||
							
								
								
									
										432
									
								
								src/NadekoBot/Migrations/20160901010812_second.Designer.cs
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										432
									
								
								src/NadekoBot/Migrations/20160901010812_second.Designer.cs
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,432 @@
 | 
			
		||||
using System;
 | 
			
		||||
using Microsoft.EntityFrameworkCore;
 | 
			
		||||
using Microsoft.EntityFrameworkCore.Infrastructure;
 | 
			
		||||
using Microsoft.EntityFrameworkCore.Metadata;
 | 
			
		||||
using Microsoft.EntityFrameworkCore.Migrations;
 | 
			
		||||
using NadekoBot.Services.Database.Impl;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Migrations
 | 
			
		||||
{
 | 
			
		||||
    [DbContext(typeof(NadekoSqliteContext))]
 | 
			
		||||
    [Migration("20160901010812_second")]
 | 
			
		||||
    partial class second
 | 
			
		||||
    {
 | 
			
		||||
        protected override void BuildTargetModel(ModelBuilder modelBuilder)
 | 
			
		||||
        {
 | 
			
		||||
            modelBuilder
 | 
			
		||||
                .HasAnnotation("ProductVersion", "1.0.0-rtm-21431");
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistItem", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<int>("Id")
 | 
			
		||||
                        .ValueGeneratedOnAdd();
 | 
			
		||||
 | 
			
		||||
                    b.Property<int?>("BotConfigId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("ItemId");
 | 
			
		||||
 | 
			
		||||
                    b.HasKey("Id");
 | 
			
		||||
 | 
			
		||||
                    b.HasIndex("BotConfigId");
 | 
			
		||||
 | 
			
		||||
                    b.ToTable("BlacklistItem");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.BotConfig", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<int>("Id")
 | 
			
		||||
                        .ValueGeneratedOnAdd();
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("BufferSize");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("CurrencyName");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("CurrencyPluralName");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("CurrencySign");
 | 
			
		||||
 | 
			
		||||
                    b.Property<bool>("DontJoinServers");
 | 
			
		||||
 | 
			
		||||
                    b.Property<bool>("ForwardMessages");
 | 
			
		||||
 | 
			
		||||
                    b.Property<bool>("ForwardToAllOwners");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("RemindMessageFormat");
 | 
			
		||||
 | 
			
		||||
                    b.Property<bool>("RotatingStatuses");
 | 
			
		||||
 | 
			
		||||
                    b.HasKey("Id");
 | 
			
		||||
 | 
			
		||||
                    b.ToTable("BotConfig");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashCaller", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<int>("Id")
 | 
			
		||||
                        .ValueGeneratedOnAdd();
 | 
			
		||||
 | 
			
		||||
                    b.Property<bool>("BaseDestroyed");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("CallUser");
 | 
			
		||||
 | 
			
		||||
                    b.Property<int>("ClashWarId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<int>("Stars");
 | 
			
		||||
 | 
			
		||||
                    b.Property<DateTime>("TimeAdded");
 | 
			
		||||
 | 
			
		||||
                    b.HasKey("Id");
 | 
			
		||||
 | 
			
		||||
                    b.HasIndex("ClashWarId");
 | 
			
		||||
 | 
			
		||||
                    b.ToTable("ClashCallers");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashWar", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<int>("Id")
 | 
			
		||||
                        .ValueGeneratedOnAdd();
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("ChannelId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("EnemyClan");
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("GuildId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<int>("Size");
 | 
			
		||||
 | 
			
		||||
                    b.Property<DateTime>("StartedAt");
 | 
			
		||||
 | 
			
		||||
                    b.Property<int>("WarState");
 | 
			
		||||
 | 
			
		||||
                    b.HasKey("Id");
 | 
			
		||||
 | 
			
		||||
                    b.ToTable("ClashOfClans");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.Currency", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<int>("Id")
 | 
			
		||||
                        .ValueGeneratedOnAdd();
 | 
			
		||||
 | 
			
		||||
                    b.Property<long>("Amount");
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("UserId");
 | 
			
		||||
 | 
			
		||||
                    b.HasKey("Id");
 | 
			
		||||
 | 
			
		||||
                    b.HasIndex("UserId")
 | 
			
		||||
                        .IsUnique();
 | 
			
		||||
 | 
			
		||||
                    b.ToTable("Currency");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.Donator", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<int>("Id")
 | 
			
		||||
                        .ValueGeneratedOnAdd();
 | 
			
		||||
 | 
			
		||||
                    b.Property<int>("Amount");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("Name");
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("UserId");
 | 
			
		||||
 | 
			
		||||
                    b.HasKey("Id");
 | 
			
		||||
 | 
			
		||||
                    b.HasIndex("UserId")
 | 
			
		||||
                        .IsUnique();
 | 
			
		||||
 | 
			
		||||
                    b.ToTable("Donators");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.EightBallResponse", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<int>("Id")
 | 
			
		||||
                        .ValueGeneratedOnAdd();
 | 
			
		||||
 | 
			
		||||
                    b.Property<int?>("BotConfigId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("Text");
 | 
			
		||||
 | 
			
		||||
                    b.HasKey("Id");
 | 
			
		||||
 | 
			
		||||
                    b.HasIndex("BotConfigId");
 | 
			
		||||
 | 
			
		||||
                    b.ToTable("EightBallResponse");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.FollowedStream", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<int>("Id")
 | 
			
		||||
                        .ValueGeneratedOnAdd();
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("ChannelId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<int?>("GuildConfigId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("GuildId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<bool>("LastStatus");
 | 
			
		||||
 | 
			
		||||
                    b.Property<int>("Type");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("Username");
 | 
			
		||||
 | 
			
		||||
                    b.HasKey("Id");
 | 
			
		||||
 | 
			
		||||
                    b.HasIndex("GuildConfigId");
 | 
			
		||||
 | 
			
		||||
                    b.ToTable("FollowedStream");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<int>("Id")
 | 
			
		||||
                        .ValueGeneratedOnAdd();
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("AutoAssignRoleId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<bool>("AutoDeleteByeMessages");
 | 
			
		||||
 | 
			
		||||
                    b.Property<bool>("AutoDeleteGreetMessages");
 | 
			
		||||
 | 
			
		||||
                    b.Property<int>("AutoDeleteGreetMessagesTimer");
 | 
			
		||||
 | 
			
		||||
                    b.Property<bool>("AutoDeleteSelfAssignedRoleMessages");
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("ByeMessageChannelId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("ChannelByeMessageText");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("ChannelGreetMessageText");
 | 
			
		||||
 | 
			
		||||
                    b.Property<float>("DefaultMusicVolume");
 | 
			
		||||
 | 
			
		||||
                    b.Property<bool>("DeleteMessageOnCommand");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("DmGreetMessageText");
 | 
			
		||||
 | 
			
		||||
                    b.Property<bool>("ExclusiveSelfAssignedRoles");
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("GreetMessageChannelId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("GuildId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<bool>("SendChannelByeMessage");
 | 
			
		||||
 | 
			
		||||
                    b.Property<bool>("SendChannelGreetMessage");
 | 
			
		||||
 | 
			
		||||
                    b.Property<bool>("SendDmGreetMessage");
 | 
			
		||||
 | 
			
		||||
                    b.Property<bool>("VoicePlusTextEnabled");
 | 
			
		||||
 | 
			
		||||
                    b.HasKey("Id");
 | 
			
		||||
 | 
			
		||||
                    b.HasIndex("GuildId")
 | 
			
		||||
                        .IsUnique();
 | 
			
		||||
 | 
			
		||||
                    b.ToTable("GuildConfigs");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.ModulePrefix", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<int>("Id")
 | 
			
		||||
                        .ValueGeneratedOnAdd();
 | 
			
		||||
 | 
			
		||||
                    b.Property<int?>("BotConfigId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("ModuleName");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("Prefix");
 | 
			
		||||
 | 
			
		||||
                    b.HasKey("Id");
 | 
			
		||||
 | 
			
		||||
                    b.HasIndex("BotConfigId");
 | 
			
		||||
 | 
			
		||||
                    b.ToTable("ModulePrefix");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<int>("Id")
 | 
			
		||||
                        .ValueGeneratedOnAdd();
 | 
			
		||||
 | 
			
		||||
                    b.Property<int?>("BotConfigId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("Status");
 | 
			
		||||
 | 
			
		||||
                    b.HasKey("Id");
 | 
			
		||||
 | 
			
		||||
                    b.HasIndex("BotConfigId");
 | 
			
		||||
 | 
			
		||||
                    b.ToTable("PlayingStatus");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.Quote", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<int>("Id")
 | 
			
		||||
                        .ValueGeneratedOnAdd();
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("AuthorId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("AuthorName")
 | 
			
		||||
                        .IsRequired();
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("GuildId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("Keyword")
 | 
			
		||||
                        .IsRequired();
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("Text")
 | 
			
		||||
                        .IsRequired();
 | 
			
		||||
 | 
			
		||||
                    b.HasKey("Id");
 | 
			
		||||
 | 
			
		||||
                    b.ToTable("Quotes");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.RaceAnimal", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<int>("Id")
 | 
			
		||||
                        .ValueGeneratedOnAdd();
 | 
			
		||||
 | 
			
		||||
                    b.Property<int?>("BotConfigId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("Icon");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("Name");
 | 
			
		||||
 | 
			
		||||
                    b.HasKey("Id");
 | 
			
		||||
 | 
			
		||||
                    b.HasIndex("BotConfigId");
 | 
			
		||||
 | 
			
		||||
                    b.ToTable("RaceAnimal");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.Reminder", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<int>("Id")
 | 
			
		||||
                        .ValueGeneratedOnAdd();
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("ChannelId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<bool>("IsPrivate");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("Message");
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("ServerId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("UserId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<DateTime>("When");
 | 
			
		||||
 | 
			
		||||
                    b.HasKey("Id");
 | 
			
		||||
 | 
			
		||||
                    b.ToTable("Reminders");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.Repeater", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<int>("Id")
 | 
			
		||||
                        .ValueGeneratedOnAdd();
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("ChannelId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("GuildId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<TimeSpan>("Interval");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("Message");
 | 
			
		||||
 | 
			
		||||
                    b.HasKey("Id");
 | 
			
		||||
 | 
			
		||||
                    b.HasIndex("ChannelId")
 | 
			
		||||
                        .IsUnique();
 | 
			
		||||
 | 
			
		||||
                    b.ToTable("Repeaters");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.SelfAssignedRole", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<int>("Id")
 | 
			
		||||
                        .ValueGeneratedOnAdd();
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("GuildId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("RoleId");
 | 
			
		||||
 | 
			
		||||
                    b.HasKey("Id");
 | 
			
		||||
 | 
			
		||||
                    b.HasIndex("GuildId", "RoleId")
 | 
			
		||||
                        .IsUnique();
 | 
			
		||||
 | 
			
		||||
                    b.ToTable("SelfAssignableRoles");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.TypingArticle", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<int>("Id")
 | 
			
		||||
                        .ValueGeneratedOnAdd();
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("Author");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("Text");
 | 
			
		||||
 | 
			
		||||
                    b.HasKey("Id");
 | 
			
		||||
 | 
			
		||||
                    b.ToTable("TypingArticles");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            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.EightBallResponse", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
 | 
			
		||||
                        .WithMany("EightBallResponses")
 | 
			
		||||
                        .HasForeignKey("BotConfigId");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            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.ModulePrefix", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
 | 
			
		||||
                        .WithMany("ModulePrefixes")
 | 
			
		||||
                        .HasForeignKey("BotConfigId");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            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.RaceAnimal", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
 | 
			
		||||
                        .WithMany("RaceAnimals")
 | 
			
		||||
                        .HasForeignKey("BotConfigId");
 | 
			
		||||
                });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										32
									
								
								src/NadekoBot/Migrations/20160901010812_second.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/NadekoBot/Migrations/20160901010812_second.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Microsoft.EntityFrameworkCore.Migrations;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Migrations
 | 
			
		||||
{
 | 
			
		||||
    public partial class second : Migration
 | 
			
		||||
    {
 | 
			
		||||
        protected override void Up(MigrationBuilder migrationBuilder)
 | 
			
		||||
        {
 | 
			
		||||
            migrationBuilder.CreateTable(
 | 
			
		||||
                name: "TypingArticles",
 | 
			
		||||
                columns: table => new
 | 
			
		||||
                {
 | 
			
		||||
                    Id = table.Column<int>(nullable: false)
 | 
			
		||||
                        .Annotation("Autoincrement", true),
 | 
			
		||||
                    Author = table.Column<string>(nullable: true),
 | 
			
		||||
                    Text = table.Column<string>(nullable: true)
 | 
			
		||||
                },
 | 
			
		||||
                constraints: table =>
 | 
			
		||||
                {
 | 
			
		||||
                    table.PrimaryKey("PK_TypingArticles", x => x.Id);
 | 
			
		||||
                });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected override void Down(MigrationBuilder migrationBuilder)
 | 
			
		||||
        {
 | 
			
		||||
            migrationBuilder.DropTable(
 | 
			
		||||
                name: "TypingArticles");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -155,6 +155,30 @@ namespace NadekoBot.Migrations
 | 
			
		||||
                    b.ToTable("EightBallResponse");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.FollowedStream", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<int>("Id")
 | 
			
		||||
                        .ValueGeneratedOnAdd();
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("ChannelId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<int?>("GuildConfigId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<ulong>("GuildId");
 | 
			
		||||
 | 
			
		||||
                    b.Property<bool>("LastStatus");
 | 
			
		||||
 | 
			
		||||
                    b.Property<int>("Type");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("Username");
 | 
			
		||||
 | 
			
		||||
                    b.HasKey("Id");
 | 
			
		||||
 | 
			
		||||
                    b.HasIndex("GuildConfigId");
 | 
			
		||||
 | 
			
		||||
                    b.ToTable("FollowedStream");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<int>("Id")
 | 
			
		||||
@@ -194,6 +218,8 @@ namespace NadekoBot.Migrations
 | 
			
		||||
 | 
			
		||||
                    b.Property<bool>("SendDmGreetMessage");
 | 
			
		||||
 | 
			
		||||
                    b.Property<bool>("VoicePlusTextEnabled");
 | 
			
		||||
 | 
			
		||||
                    b.HasKey("Id");
 | 
			
		||||
 | 
			
		||||
                    b.HasIndex("GuildId")
 | 
			
		||||
@@ -337,6 +363,20 @@ namespace NadekoBot.Migrations
 | 
			
		||||
                    b.ToTable("SelfAssignableRoles");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.TypingArticle", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.Property<int>("Id")
 | 
			
		||||
                        .ValueGeneratedOnAdd();
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("Author");
 | 
			
		||||
 | 
			
		||||
                    b.Property<string>("Text");
 | 
			
		||||
 | 
			
		||||
                    b.HasKey("Id");
 | 
			
		||||
 | 
			
		||||
                    b.ToTable("TypingArticles");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistItem", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
 | 
			
		||||
@@ -359,6 +399,13 @@ namespace NadekoBot.Migrations
 | 
			
		||||
                        .HasForeignKey("BotConfigId");
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            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.ModulePrefix", b =>
 | 
			
		||||
                {
 | 
			
		||||
                    b.HasOne("NadekoBot.Services.Database.Models.BotConfig")
 | 
			
		||||
 
 | 
			
		||||
@@ -48,7 +48,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ////todo owner only
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task Restart(IUserMessage umsg)
 | 
			
		||||
        //{
 | 
			
		||||
@@ -60,7 +60,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
        //    Environment.Exit(0);
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        [RequirePermission(GuildPermission.Administrator)]
 | 
			
		||||
        public async Task Delmsgoncmd(IUserMessage umsg)
 | 
			
		||||
@@ -80,7 +80,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                await channel.SendMessageAsync("❗`Stopped automatic deletion of successfull command invokations.`");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        [RequirePermission(GuildPermission.ManageRoles)]
 | 
			
		||||
        public async Task Setrole(IUserMessage umsg, IGuildUser usr, [Remainder] IRole role)
 | 
			
		||||
@@ -98,7 +98,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        [RequirePermission(GuildPermission.ManageRoles)]
 | 
			
		||||
        public async Task Removerole(IUserMessage umsg, IGuildUser usr, [Remainder] IRole role)
 | 
			
		||||
@@ -115,7 +115,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        [RequirePermission(GuildPermission.ManageRoles)]
 | 
			
		||||
        public async Task RenameRole(IUserMessage umsg, IRole roleToEdit, string newname)
 | 
			
		||||
@@ -137,7 +137,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        [RequirePermission(GuildPermission.ManageRoles)]
 | 
			
		||||
        public async Task RemoveAllRoles(IUserMessage umsg, [Remainder] IGuildUser user)
 | 
			
		||||
@@ -155,7 +155,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        [RequirePermission(GuildPermission.ManageRoles)]
 | 
			
		||||
        public async Task CreateRole(IUserMessage umsg, [Remainder] string roleName = null)
 | 
			
		||||
@@ -176,7 +176,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        [RequirePermission(GuildPermission.ManageRoles)]
 | 
			
		||||
        public async Task RoleColor(IUserMessage umsg, params string[] args)
 | 
			
		||||
@@ -214,7 +214,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        [RequirePermission(GuildPermission.BanMembers)]
 | 
			
		||||
        public async Task Ban(IUserMessage umsg, IGuildUser user)
 | 
			
		||||
@@ -241,7 +241,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        [RequirePermission(GuildPermission.BanMembers)]
 | 
			
		||||
        public async Task Softban(IUserMessage umsg, IGuildUser user, [Remainder] string msg = null)
 | 
			
		||||
@@ -267,7 +267,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Kick(IUserMessage umsg, IGuildUser user, [Remainder] string msg = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -295,7 +295,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        [RequirePermission(GuildPermission.MuteMembers)]
 | 
			
		||||
        public async Task Mute(IUserMessage umsg, params IGuildUser[] users)
 | 
			
		||||
@@ -318,7 +318,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        [RequirePermission(GuildPermission.MuteMembers)]
 | 
			
		||||
        public async Task Unmute(IUserMessage umsg, params IGuildUser[] users)
 | 
			
		||||
@@ -341,7 +341,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        [RequirePermission(GuildPermission.DeafenMembers)]
 | 
			
		||||
        public async Task Deafen(IUserMessage umsg, params IGuildUser[] users)
 | 
			
		||||
@@ -364,7 +364,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        [RequirePermission(GuildPermission.DeafenMembers)]
 | 
			
		||||
        public async Task UnDeafen(IUserMessage umsg, params IGuildUser[] users)
 | 
			
		||||
@@ -387,7 +387,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        [RequirePermission(GuildPermission.ManageChannels)]
 | 
			
		||||
        public async Task DelVoiChanl(IUserMessage umsg, [Remainder] IVoiceChannel voiceChannel)
 | 
			
		||||
@@ -396,7 +396,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            await umsg.Channel.SendMessageAsync($"Removed channel **{voiceChannel.Name}**.").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        [RequirePermission(GuildPermission.ManageChannels)]
 | 
			
		||||
        public async Task CreatVoiChanl(IUserMessage umsg, [Remainder] string channelName)
 | 
			
		||||
@@ -406,7 +406,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            await channel.SendMessageAsync($"Created voice channel **{ch.Name}**, id `{ch.Id}`.").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        [RequirePermission(GuildPermission.ManageChannels)]
 | 
			
		||||
        public async Task DelTxtChanl(IUserMessage umsg, [Remainder] ITextChannel channel)
 | 
			
		||||
@@ -415,7 +415,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            await channel.SendMessageAsync($"Removed text channel **{channel.Name}**, id `{channel.Id}`.").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        [RequirePermission(GuildPermission.ManageChannels)]
 | 
			
		||||
        public async Task CreaTxtChanl(IUserMessage umsg, [Remainder] string channelName)
 | 
			
		||||
@@ -425,7 +425,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            await channel.SendMessageAsync($"Added text channel **{txtCh.Name}**, id `{txtCh.Id}`.").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        [RequirePermission(GuildPermission.ManageChannels)]
 | 
			
		||||
        public async Task SetTopic(IUserMessage umsg, [Remainder] string topic = null)
 | 
			
		||||
@@ -436,7 +436,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            await channel.SendMessageAsync(":ok: **New channel topic set.**").ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        [RequirePermission(GuildPermission.ManageChannels)]
 | 
			
		||||
        public async Task SetChanlName(IUserMessage umsg, [Remainder] string name)
 | 
			
		||||
@@ -449,7 +449,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        //delets her own messages, no perm required
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Prune(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
@@ -462,7 +462,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // prune x
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        [RequirePermission(ChannelPermission.ManageMessages)]
 | 
			
		||||
        public async Task Prune(IUserMessage msg, int count)
 | 
			
		||||
@@ -481,7 +481,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //prune @user [x]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Prune(IUserMessage msg, IGuildUser user, int count = 100)
 | 
			
		||||
        {
 | 
			
		||||
@@ -491,7 +491,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            await msg.Channel.DeleteMessagesAsync(enumerable);
 | 
			
		||||
        }
 | 
			
		||||
        ////todo owner only
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task Die(IUserMessage umsg)
 | 
			
		||||
        //{
 | 
			
		||||
@@ -503,7 +503,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        ////todo owner only
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task Setname(IUserMessage umsg, [Remainder] string newName = null)
 | 
			
		||||
        //{
 | 
			
		||||
@@ -512,7 +512,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        ////todo owner only
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task NewAvatar(IUserMessage umsg, [Remainder] string img = null)
 | 
			
		||||
        //{
 | 
			
		||||
@@ -531,7 +531,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        ////todo owner only
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task SetGame(IUserMessage umsg, [Remainder] string game = null)
 | 
			
		||||
        //{
 | 
			
		||||
@@ -543,7 +543,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        ////todo owner only
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task Send(IUserMessage umsg, string where, [Remainder] string msg = null)
 | 
			
		||||
        //{
 | 
			
		||||
@@ -588,7 +588,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        ////todo owner only
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task Announce(IUserMessage umsg, [Remainder] string message)
 | 
			
		||||
        //{
 | 
			
		||||
@@ -603,7 +603,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        ////todo owner only
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task SaveChat(IUserMessage umsg, int cnt)
 | 
			
		||||
        //{
 | 
			
		||||
@@ -635,7 +635,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        [RequirePermission(GuildPermission.MentionEveryone)]
 | 
			
		||||
        public async Task MentionRole(IUserMessage umsg, params IRole[] roles)
 | 
			
		||||
@@ -660,7 +660,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            await channel.SendMessageAsync(send).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Donators(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
@@ -676,7 +676,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Donadd(IUserMessage umsg, IUser donator, int amount)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -38,7 +38,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            [RequirePermission(GuildPermission.ManageRoles)]
 | 
			
		||||
            public async Task AutoAssignRole(IUserMessage umsg, [Remainder] IRole role = null)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,111 +1,103 @@
 | 
			
		||||
//using Discord;
 | 
			
		||||
//using Discord.Commands;
 | 
			
		||||
//using NadekoBot.Classes;
 | 
			
		||||
//using NadekoBot.Modules.Permissions.Classes;
 | 
			
		||||
//using System;
 | 
			
		||||
//using System.Collections.Concurrent;
 | 
			
		||||
//using System.Collections.Generic;
 | 
			
		||||
//using System.Linq;
 | 
			
		||||
using Discord;
 | 
			
		||||
using Discord.Commands;
 | 
			
		||||
using Discord.WebSocket;
 | 
			
		||||
using NadekoBot.Attributes;
 | 
			
		||||
using NadekoBot.Extensions;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
////todo DB
 | 
			
		||||
//namespace NadekoBot.Modules.Administration
 | 
			
		||||
//{
 | 
			
		||||
//    class CrossServerTextChannel : DiscordCommand
 | 
			
		||||
//    {
 | 
			
		||||
//        public CrossServerTextChannel(DiscordModule module) : base(module)
 | 
			
		||||
//        {
 | 
			
		||||
//            NadekoBot.Client.MessageReceived += async (s, e) =>
 | 
			
		||||
//            {
 | 
			
		||||
//                try
 | 
			
		||||
//                {
 | 
			
		||||
//                    if (umsg.Author.Id == NadekoBot.Client.CurrentUser.Id) return;
 | 
			
		||||
//                    foreach (var subscriber in Subscribers)
 | 
			
		||||
//                    {
 | 
			
		||||
//                        var set = subscriber.Value;
 | 
			
		||||
//                        if (!set.Contains(e.Channel))
 | 
			
		||||
//                            continue;
 | 
			
		||||
//                        foreach (var chan in set.Except(new[] { e.Channel }))
 | 
			
		||||
//                        {
 | 
			
		||||
//                            await chan.SendMessageAsync(GetText(e.Server, e.Channel, umsg.Author, e.Message)).ConfigureAwait(false);
 | 
			
		||||
//                        }
 | 
			
		||||
//                    }
 | 
			
		||||
//                }
 | 
			
		||||
//                catch { }
 | 
			
		||||
//            };
 | 
			
		||||
//            NadekoBot.Client.MessageUpdated += async (s, e) =>
 | 
			
		||||
//            {
 | 
			
		||||
//                try
 | 
			
		||||
//                {
 | 
			
		||||
//                    if (e.After?.User?.Id == null || e.After.User.Id == NadekoBot.Client.CurrentUser.Id) return;
 | 
			
		||||
//                    foreach (var subscriber in Subscribers)
 | 
			
		||||
//                    {
 | 
			
		||||
//                        var set = subscriber.Value;
 | 
			
		||||
//                        if (!set.Contains(e.Channel))
 | 
			
		||||
//                            continue;
 | 
			
		||||
//                        foreach (var chan in set.Except(new[] { e.Channel }))
 | 
			
		||||
//                        {
 | 
			
		||||
//                            var msg = chan.Messages
 | 
			
		||||
//                                .FirstOrDefault(m =>
 | 
			
		||||
//                                    m.RawText == GetText(e.Server, e.Channel, umsg.Author, e.Before));
 | 
			
		||||
//                            if (msg != default(Message))
 | 
			
		||||
//                                await msg.Edit(GetText(e.Server, e.Channel, umsg.Author, e.After)).ConfigureAwait(false);
 | 
			
		||||
//                        }
 | 
			
		||||
//                    }
 | 
			
		||||
namespace NadekoBot.Modules.Administration
 | 
			
		||||
{
 | 
			
		||||
    public partial class Administration
 | 
			
		||||
    {
 | 
			
		||||
        [Group]
 | 
			
		||||
        public class CrossServerTextChannel
 | 
			
		||||
        {
 | 
			
		||||
            public CrossServerTextChannel()
 | 
			
		||||
            {
 | 
			
		||||
                NadekoBot.Client.MessageReceived += (imsg) =>
 | 
			
		||||
                {
 | 
			
		||||
                    var msg = imsg as IUserMessage;
 | 
			
		||||
                    if (msg == null)
 | 
			
		||||
                        return Task.CompletedTask;
 | 
			
		||||
 | 
			
		||||
//                }
 | 
			
		||||
//                catch { }
 | 
			
		||||
//            };
 | 
			
		||||
//        }
 | 
			
		||||
                    var channel = imsg.Channel as ITextChannel;
 | 
			
		||||
                    if (channel == null)
 | 
			
		||||
                        return Task.CompletedTask;
 | 
			
		||||
 | 
			
		||||
//        private string GetText(Server server, Channel channel, User user, Message message) =>
 | 
			
		||||
//            $"**{server.Name} | {channel.Name}** `{user.Name}`: " + message.RawText;
 | 
			
		||||
                    Task.Run(async () =>
 | 
			
		||||
                    {
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            if (msg.Author.Id == NadekoBot.Client.GetCurrentUser().Id) return;
 | 
			
		||||
                            foreach (var subscriber in Subscribers)
 | 
			
		||||
                            {
 | 
			
		||||
                                var set = subscriber.Value;
 | 
			
		||||
                                if (!set.Contains(msg.Channel))
 | 
			
		||||
                                    continue;
 | 
			
		||||
                                foreach (var chan in set.Except(new[] { channel }))
 | 
			
		||||
                                {
 | 
			
		||||
                                    await chan.SendMessageAsync(GetText(channel.Guild, channel, (IGuildUser)msg.Author, msg)).ConfigureAwait(false);
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        catch { }
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
//        public static readonly ConcurrentDictionary<int, HashSet<Channel>> Subscribers = new ConcurrentDictionary<int, HashSet<Channel>>();
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
//        internal override void Init(CommandGroupBuilder cgb)
 | 
			
		||||
//        {
 | 
			
		||||
//            cgb.CreateCommand(Module.Prefix + "scsc")
 | 
			
		||||
//                .Description("Starts an instance of cross server channel. You will get a token as a DM " +
 | 
			
		||||
//                             $"that other people will use to tune in to the same instance. **Bot Owner Only.** | `{Prefix}scsc`")
 | 
			
		||||
//                .AddCheck(SimpleCheckers.OwnerOnly())
 | 
			
		||||
//                .Do(async e =>
 | 
			
		||||
//                {
 | 
			
		||||
//                    var token = new Random().Next();
 | 
			
		||||
//                    var set = new HashSet<Channel>();
 | 
			
		||||
//                    if (Subscribers.TryAdd(token, set))
 | 
			
		||||
//                    {
 | 
			
		||||
//                        set.Add(e.Channel);
 | 
			
		||||
//                        await umsg.Author.SendMessageAsync("This is your CSC token:" + token.ToString()).ConfigureAwait(false);
 | 
			
		||||
//                    }
 | 
			
		||||
//                });
 | 
			
		||||
            private string GetText(IGuild server, ITextChannel channel, IGuildUser user, IUserMessage message) =>
 | 
			
		||||
                $"**{server.Name} | {channel.Name}** `{user.Username}`: " + message.Content;
 | 
			
		||||
 | 
			
		||||
//            cgb.CreateCommand(Module.Prefix + "jcsc")
 | 
			
		||||
//                .Description($"Joins current channel to an instance of cross server channel using the token. **Needs Manage Server Permissions.**| `{Prefix}jcsc`")
 | 
			
		||||
//                .Parameter("token")
 | 
			
		||||
//                .AddCheck(SimpleCheckers.ManageServer())
 | 
			
		||||
//                .Do(async e =>
 | 
			
		||||
//                {
 | 
			
		||||
//                    int token;
 | 
			
		||||
//                    if (!int.TryParse(token, out token))
 | 
			
		||||
//                        return;
 | 
			
		||||
//                    HashSet<Channel> set;
 | 
			
		||||
//                    if (!Subscribers.TryGetValue(token, out set))
 | 
			
		||||
//                        return;
 | 
			
		||||
//                    set.Add(e.Channel);
 | 
			
		||||
//                    await channel.SendMessageAsync(":ok:").ConfigureAwait(false);
 | 
			
		||||
//                });
 | 
			
		||||
            public static readonly ConcurrentDictionary<int, HashSet<ITextChannel>> Subscribers = new ConcurrentDictionary<int, HashSet<ITextChannel>>();
 | 
			
		||||
 | 
			
		||||
//            cgb.CreateCommand(Module.Prefix + "lcsc")
 | 
			
		||||
//                .Description($"Leaves Cross server channel instance from this channel. **Needs Manage Server Permissions.**| `{Prefix}lcsc`")
 | 
			
		||||
//                .AddCheck(SimpleCheckers.ManageServer())
 | 
			
		||||
//                .Do(async e =>
 | 
			
		||||
//                {
 | 
			
		||||
//                    foreach (var subscriber in Subscribers)
 | 
			
		||||
//                    {
 | 
			
		||||
//                        subscriber.Value.Remove(e.Channel);
 | 
			
		||||
//                    }
 | 
			
		||||
//                    await channel.SendMessageAsync(":ok:").ConfigureAwait(false);
 | 
			
		||||
//                });
 | 
			
		||||
//        }
 | 
			
		||||
//    }
 | 
			
		||||
//}
 | 
			
		||||
            ////todo owner only
 | 
			
		||||
            //[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            //[RequireContext(ContextType.Guild)]
 | 
			
		||||
            //public async Task Scsc(IUserMessage msg)
 | 
			
		||||
            //{
 | 
			
		||||
            //    var channel = (ITextChannel)msg.Channel;
 | 
			
		||||
            //    var token = new Random().Next();
 | 
			
		||||
            //    var set = new HashSet<ITextChannel>();
 | 
			
		||||
            //    if (Subscribers.TryAdd(token, set))
 | 
			
		||||
            //    {
 | 
			
		||||
            //        set.Add(channel);
 | 
			
		||||
            //        await ((IGuildUser)msg.Author).SendMessageAsync("This is your CSC token:" + token.ToString()).ConfigureAwait(false);
 | 
			
		||||
            //    }
 | 
			
		||||
            //}
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            [RequirePermission(GuildPermission.ManageGuild)]
 | 
			
		||||
            public async Task Jcsc(IUserMessage imsg, int token)
 | 
			
		||||
            {
 | 
			
		||||
                var channel = (ITextChannel)imsg.Channel;
 | 
			
		||||
 | 
			
		||||
                HashSet<ITextChannel> set;
 | 
			
		||||
                if (!Subscribers.TryGetValue(token, out set))
 | 
			
		||||
                    return;
 | 
			
		||||
                set.Add(channel);
 | 
			
		||||
                await channel.SendMessageAsync(":ok:").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            [RequirePermission(GuildPermission.ManageGuild)]
 | 
			
		||||
            public async Task Lcsc(IUserMessage imsg)
 | 
			
		||||
            {
 | 
			
		||||
                var channel = (ITextChannel)imsg.Channel;
 | 
			
		||||
 | 
			
		||||
                foreach (var subscriber in Subscribers)
 | 
			
		||||
                {
 | 
			
		||||
                    subscriber.Value.Remove(channel);
 | 
			
		||||
                }
 | 
			
		||||
                await channel.SendMessageAsync(":ok:").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,33 @@
 | 
			
		||||
using Discord;
 | 
			
		||||
using Discord.Commands;
 | 
			
		||||
using Discord.WebSocket;
 | 
			
		||||
using NadekoBot.Extensions;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.Administration
 | 
			
		||||
{
 | 
			
		||||
    public partial class Administration {
 | 
			
		||||
        [Group]
 | 
			
		||||
        public class LogCommands
 | 
			
		||||
        {
 | 
			
		||||
            private DiscordSocketClient _client;
 | 
			
		||||
 | 
			
		||||
            private string prettyCurrentTime => $"【{DateTime.Now:HH:mm:ss}】";
 | 
			
		||||
 | 
			
		||||
            public LogCommands(DiscordSocketClient client)
 | 
			
		||||
            {
 | 
			
		||||
                _client = client;
 | 
			
		||||
                _client.MessageReceived += _client_MessageReceived;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            private Task _client_MessageReceived(IMessage arg)
 | 
			
		||||
            {
 | 
			
		||||
                throw new NotImplementedException();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -13,7 +13,7 @@
 | 
			
		||||
////todo Add flags for every event
 | 
			
		||||
//namespace NadekoBot.Modules.Administration
 | 
			
		||||
//{
 | 
			
		||||
//    internal class LogCommand : DiscordCommand
 | 
			
		||||
//    public class LogCommand : DiscordCommand
 | 
			
		||||
//    {
 | 
			
		||||
//        private string prettyCurrentTime => $"【{DateTime.Now:HH:mm:ss}】";
 | 
			
		||||
 | 
			
		||||
@@ -373,7 +373,7 @@
 | 
			
		||||
//            catch { }
 | 
			
		||||
//        }
 | 
			
		||||
 | 
			
		||||
//        internal override void Init(CommandGroupBuilder cgb)
 | 
			
		||||
//        public override void Init(CommandGroupBuilder cgb)
 | 
			
		||||
//        {
 | 
			
		||||
 | 
			
		||||
//            cgb.CreateCommand(Module.Prefix + "spmom")
 | 
			
		||||
 
 | 
			
		||||
@@ -73,7 +73,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            [RequirePermission(GuildPermission.ManageMessages)]
 | 
			
		||||
            public async Task RepeatInvoke(IUserMessage imsg)
 | 
			
		||||
@@ -90,7 +90,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                await channel.SendMessageAsync("🔄 " + rep.Repeater.Message).ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task Repeat(IUserMessage imsg)
 | 
			
		||||
            {
 | 
			
		||||
@@ -110,7 +110,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                    await channel.SendMessageAsync("`No message is repeating.`").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task Repeat(IUserMessage imsg, int minutes, [Remainder] string message)
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -86,7 +86,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                    {"%queued%", () => Music.Music.MusicPlayers.Sum(kvp => kvp.Value.Playlist.Count).ToString()}
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task RotatePlaying(IUserMessage umsg)
 | 
			
		||||
            {
 | 
			
		||||
@@ -106,7 +106,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                    await channel.SendMessageAsync("`Rotating playing status disabled.`");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task AddPlaying(IUserMessage umsg, [Remainder] string status)
 | 
			
		||||
            {
 | 
			
		||||
@@ -122,7 +122,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                await channel.SendMessageAsync("`Added.`").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task ListPlaying(IUserMessage umsg)
 | 
			
		||||
            {
 | 
			
		||||
@@ -144,7 +144,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task RemovePlaying(IUserMessage umsg, int index)
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -5,9 +5,9 @@ using NadekoBot.Attributes;
 | 
			
		||||
using NadekoBot.Extensions;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
//todo rewrite to accept msg/sec (for example 1/5 - 1 message every 5 seconds)
 | 
			
		||||
namespace NadekoBot.Modules.Administration
 | 
			
		||||
{
 | 
			
		||||
    public partial class Administration
 | 
			
		||||
@@ -15,58 +15,103 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
        [Group]
 | 
			
		||||
        public class RatelimitCommand
 | 
			
		||||
        {
 | 
			
		||||
            public static ConcurrentDictionary<ulong, ConcurrentDictionary<ulong, DateTime>> RatelimitingChannels = new ConcurrentDictionary<ulong, ConcurrentDictionary<ulong, DateTime>>();
 | 
			
		||||
            public static ConcurrentDictionary<ulong, Ratelimiter> RatelimitingChannels = new ConcurrentDictionary<ulong, Ratelimiter>();
 | 
			
		||||
 | 
			
		||||
            private static readonly TimeSpan ratelimitTime = new TimeSpan(0, 0, 0, 5);
 | 
			
		||||
            private DiscordSocketClient _client { get; }
 | 
			
		||||
 | 
			
		||||
            public class Ratelimiter
 | 
			
		||||
            {
 | 
			
		||||
                public class RatelimitedUser
 | 
			
		||||
                {
 | 
			
		||||
                    public ulong UserId { get; set; }
 | 
			
		||||
                    public int MessageCount { get; set; } = 0;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                public ulong ChannelId { get; set; }
 | 
			
		||||
 | 
			
		||||
                public int MaxMessages { get; set; }
 | 
			
		||||
                public int PerSeconds { get; set; }
 | 
			
		||||
 | 
			
		||||
                public CancellationTokenSource cancelSource { get; set; } = new CancellationTokenSource();
 | 
			
		||||
 | 
			
		||||
                public ConcurrentDictionary<ulong, RatelimitedUser> Users { get; set; } = new ConcurrentDictionary<ulong, RatelimitedUser>();
 | 
			
		||||
 | 
			
		||||
                public bool CheckUserRatelimit(ulong id)
 | 
			
		||||
                {
 | 
			
		||||
                    RatelimitedUser usr = Users.GetOrAdd(id, (key) => new RatelimitedUser() { UserId = id });
 | 
			
		||||
                    if (usr.MessageCount == MaxMessages)
 | 
			
		||||
                    {
 | 
			
		||||
                        return true;
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        usr.MessageCount++;
 | 
			
		||||
                        var t = Task.Run(async () => {
 | 
			
		||||
                            try
 | 
			
		||||
                            {
 | 
			
		||||
                                await Task.Delay(PerSeconds * 1000, cancelSource.Token);
 | 
			
		||||
                            }
 | 
			
		||||
                            catch (OperationCanceledException) { }
 | 
			
		||||
                            usr.MessageCount--;
 | 
			
		||||
                        });
 | 
			
		||||
                        return false;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            public RatelimitCommand()
 | 
			
		||||
            {
 | 
			
		||||
 | 
			
		||||
                this._client = NadekoBot.Client;
 | 
			
		||||
 | 
			
		||||
               _client.MessageReceived += async (umsg) =>
 | 
			
		||||
               _client.MessageReceived += (umsg) =>
 | 
			
		||||
                {
 | 
			
		||||
                    var usrMsg = umsg as IUserMessage;
 | 
			
		||||
                    var channel = usrMsg.Channel as ITextChannel;
 | 
			
		||||
 | 
			
		||||
                    if (channel == null || await usrMsg.IsAuthor())
 | 
			
		||||
                        return;
 | 
			
		||||
                    ConcurrentDictionary<ulong, DateTime> userTimePair;
 | 
			
		||||
                    if (!RatelimitingChannels.TryGetValue(channel.Id, out userTimePair)) return;
 | 
			
		||||
                    DateTime lastMessageTime;
 | 
			
		||||
                    if (userTimePair.TryGetValue(usrMsg.Author.Id, out lastMessageTime))
 | 
			
		||||
                    var t = Task.Run(async () =>
 | 
			
		||||
                    {
 | 
			
		||||
                        if (DateTime.Now - lastMessageTime < ratelimitTime)
 | 
			
		||||
                        {
 | 
			
		||||
                            try
 | 
			
		||||
                            {
 | 
			
		||||
                                await usrMsg.DeleteAsync().ConfigureAwait(false);
 | 
			
		||||
                            }
 | 
			
		||||
                            catch { }
 | 
			
		||||
                        var usrMsg = umsg as IUserMessage;
 | 
			
		||||
                        var channel = usrMsg.Channel as ITextChannel;
 | 
			
		||||
 | 
			
		||||
                        if (channel == null || await usrMsg.IsAuthor())
 | 
			
		||||
                            return;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    userTimePair.AddOrUpdate(usrMsg.Author.Id, id => DateTime.Now, (id, dt) => DateTime.Now);
 | 
			
		||||
                        Ratelimiter limiter;
 | 
			
		||||
                        if (!RatelimitingChannels.TryGetValue(channel.Id, out limiter))
 | 
			
		||||
                            return;
 | 
			
		||||
 | 
			
		||||
                        if (limiter.CheckUserRatelimit(usrMsg.Author.Id))
 | 
			
		||||
                            await usrMsg.DeleteAsync();
 | 
			
		||||
                    });
 | 
			
		||||
                    return Task.CompletedTask;
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task Slowmode(IUserMessage umsg)
 | 
			
		||||
            public async Task Slowmode(IUserMessage umsg, int msg = 1, int perSec = 5)
 | 
			
		||||
            {
 | 
			
		||||
                var channel = (ITextChannel)umsg.Channel;
 | 
			
		||||
 | 
			
		||||
                ConcurrentDictionary<ulong, DateTime> throwaway;
 | 
			
		||||
                Ratelimiter throwaway;
 | 
			
		||||
                if (RatelimitingChannels.TryRemove(channel.Id, out throwaway))
 | 
			
		||||
                {
 | 
			
		||||
                    await channel.SendMessageAsync("Slow mode disabled.").ConfigureAwait(false);
 | 
			
		||||
                    throwaway.cancelSource.Cancel();
 | 
			
		||||
                    await channel.SendMessageAsync("`Slow mode disabled.`").ConfigureAwait(false);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                if (RatelimitingChannels.TryAdd(channel.Id, new ConcurrentDictionary<ulong, DateTime>()))
 | 
			
		||||
 | 
			
		||||
                if (msg < 1 || perSec < 1)
 | 
			
		||||
                {
 | 
			
		||||
                    await channel.SendMessageAsync("Slow mode initiated. " +
 | 
			
		||||
                                                "Users can't send more than 1 message every 5 seconds.")
 | 
			
		||||
                    await channel.SendMessageAsync("`Invalid parameters.`");
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (RatelimitingChannels.TryAdd(channel.Id,throwaway = new Ratelimiter() {
 | 
			
		||||
                    ChannelId = channel.Id,
 | 
			
		||||
                    MaxMessages = msg,
 | 
			
		||||
                    PerSeconds = perSec,
 | 
			
		||||
                }))
 | 
			
		||||
                {
 | 
			
		||||
                    await channel.SendMessageAsync("`Slow mode initiated.` " +
 | 
			
		||||
                                                $"Users can't send more than {throwaway.MaxMessages} message(s) every {throwaway.PerSeconds} second(s).")
 | 
			
		||||
                                                .ConfigureAwait(false);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
        public class SelfAssignedRolesCommands
 | 
			
		||||
        {
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            [RequirePermission(GuildPermission.ManageRoles)]
 | 
			
		||||
            public async Task Asar(IUserMessage umsg, [Remainder] IRole role)
 | 
			
		||||
@@ -49,7 +49,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                await channel.SendMessageAsync(msg.ToString()).ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            [RequirePermission(GuildPermission.ManageRoles)]
 | 
			
		||||
            public async Task Rsar(IUserMessage umsg, [Remainder] IRole role)
 | 
			
		||||
@@ -70,7 +70,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                await channel.SendMessageAsync($":ok:**{role.Name}** has been removed from the list of self-assignable roles").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task Lsar(IUserMessage umsg)
 | 
			
		||||
            {
 | 
			
		||||
@@ -105,7 +105,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                await channel.SendMessageAsync(msg.ToString() + "\n\n" + removeMsg.ToString()).ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            [RequirePermission(GuildPermission.ManageRoles)]
 | 
			
		||||
            public async Task Tesar(IUserMessage umsg)
 | 
			
		||||
@@ -124,7 +124,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                await channel.SendMessageAsync("Self assigned roles are now " + exl);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task Iam(IUserMessage umsg, [Remainder] IRole role)
 | 
			
		||||
            {
 | 
			
		||||
@@ -182,7 +182,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task Iamnot(IUserMessage umsg, [Remainder] IRole role)
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@
 | 
			
		||||
//                this._client = client;
 | 
			
		||||
//            }
 | 
			
		||||
 | 
			
		||||
//            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
//            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
//            [RequireContext(ContextType.Guild)]
 | 
			
		||||
//            public async Task Leave(IUserMessage umsg, [Remainder] string guildStr)
 | 
			
		||||
//            {
 | 
			
		||||
 
 | 
			
		||||
@@ -106,7 +106,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            [RequirePermission(GuildPermission.ManageGuild)]
 | 
			
		||||
            public async Task GreetDel(IUserMessage umsg)
 | 
			
		||||
@@ -128,7 +128,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                    await channel.SendMessageAsync("`Automatic deletion of greet messages has been disabled.`").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            [RequirePermission(GuildPermission.ManageGuild)]
 | 
			
		||||
            public async Task Greet(IUserMessage umsg)
 | 
			
		||||
@@ -151,7 +151,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                    await channel.SendMessageAsync("Greet announcements disabled.").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            [RequirePermission(GuildPermission.ManageGuild)]
 | 
			
		||||
            public async Task GreetMsg(IUserMessage umsg, [Remainder] string text)
 | 
			
		||||
@@ -180,7 +180,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                    await channel.SendMessageAsync("Enable greet messsages by typing `.greet`").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            [RequirePermission(GuildPermission.ManageGuild)]
 | 
			
		||||
            public async Task GreetDm(IUserMessage umsg)
 | 
			
		||||
@@ -202,7 +202,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                    await channel.SendMessageAsync("Greet announcements disabled.").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            [RequirePermission(GuildPermission.ManageGuild)]
 | 
			
		||||
            public async Task GreetDmMsg(IUserMessage umsg, [Remainder] string text)
 | 
			
		||||
@@ -231,7 +231,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                    await channel.SendMessageAsync("Enable DM greet messsages by typing `.greetdm`").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            [RequirePermission(GuildPermission.ManageGuild)]
 | 
			
		||||
            public async Task Bye(IUserMessage umsg)
 | 
			
		||||
@@ -254,7 +254,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                    await channel.SendMessageAsync("Bye announcements disabled.").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            [RequirePermission(GuildPermission.ManageGuild)]
 | 
			
		||||
            public async Task ByeMsg(IUserMessage umsg, [Remainder] string text)
 | 
			
		||||
@@ -283,7 +283,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
                    await channel.SendMessageAsync("Enable bye messsages by typing `.bye`").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            [RequirePermission(GuildPermission.ManageGuild)]
 | 
			
		||||
            public async Task ByeDel(IUserMessage umsg)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,166 +0,0 @@
 | 
			
		||||
//using Discord;
 | 
			
		||||
//using Discord.Commands;
 | 
			
		||||
//using NadekoBot.Classes;
 | 
			
		||||
//using NadekoBot.Extensions;
 | 
			
		||||
//using NadekoBot.Modules.Permissions.Classes;
 | 
			
		||||
//using System;
 | 
			
		||||
//using System.Linq;
 | 
			
		||||
//using System.Text.RegularExpressions;
 | 
			
		||||
//using System.Threading.Tasks;
 | 
			
		||||
//using ChPermOverride = Discord.ChannelPermissionOverrides;
 | 
			
		||||
 | 
			
		||||
////todo DB
 | 
			
		||||
////todo rewrite
 | 
			
		||||
//namespace NadekoBot.Modules.Administration
 | 
			
		||||
//{
 | 
			
		||||
//    internal class VoicePlusTextCommand : DiscordCommand
 | 
			
		||||
//    {
 | 
			
		||||
//        Regex channelNameRegex = new Regex(@"[^a-zA-Z0-9 -]", RegexOptions.Compiled);
 | 
			
		||||
//        public VoicePlusTextCommand(DiscordModule module) : base(module)
 | 
			
		||||
//        {
 | 
			
		||||
//            // changing servers may cause bugs
 | 
			
		||||
//            NadekoBot.Client.UserUpdated += async (sender, e) =>
 | 
			
		||||
//            {
 | 
			
		||||
//                try
 | 
			
		||||
//                {
 | 
			
		||||
//                    if (e.Server == null)
 | 
			
		||||
//                        return;
 | 
			
		||||
//                    var config = SpecificConfigurations.Default.Of(e.Server.Id);
 | 
			
		||||
//                    if (e.Before.VoiceChannel == e.After.VoiceChannel) return;
 | 
			
		||||
//                    if (!config.VoicePlusTextEnabled)
 | 
			
		||||
//                        return;
 | 
			
		||||
//                    var serverPerms = e.Server.GetUser(NadekoBot.Client.CurrentUser.Id)?.ServerPermissions;
 | 
			
		||||
//                    if (serverPerms == null)
 | 
			
		||||
//                        return;
 | 
			
		||||
//                    if (!serverPerms.Value.ManageChannels || !serverPerms.Value.ManageRoles)
 | 
			
		||||
//                    {
 | 
			
		||||
 | 
			
		||||
//                        try
 | 
			
		||||
//                        {
 | 
			
		||||
//                            await e.Server.Owner.SendMessageAsync(
 | 
			
		||||
//                                "I don't have manage server and/or Manage Channels permission," +
 | 
			
		||||
//                                $" so I cannot run voice+text on **{e.Server.Name}** server.").ConfigureAwait(false);
 | 
			
		||||
//                        }
 | 
			
		||||
//                        catch { } // meh
 | 
			
		||||
//                        config.VoicePlusTextEnabled = false;
 | 
			
		||||
//                        return;
 | 
			
		||||
//                    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//                    var beforeVch = e.Before.VoiceChannel;
 | 
			
		||||
//                    if (beforeVch != null)
 | 
			
		||||
//                    {
 | 
			
		||||
//                        var textChannel =
 | 
			
		||||
//                            e.Server.FindChannels(GetChannelName(beforeVch.Name), ChannelType.Text).FirstOrDefault();
 | 
			
		||||
//                        if (textChannel != null)
 | 
			
		||||
//                            await textChannel.AddPermissionsRule(e.Before,
 | 
			
		||||
//                                new ChPermOverride(readMessages: PermValue.Deny,
 | 
			
		||||
//                                                   sendMessages: PermValue.Deny)).ConfigureAwait(false);
 | 
			
		||||
//                    }
 | 
			
		||||
//                    var afterVch = e.After.VoiceChannel;
 | 
			
		||||
//                    if (afterVch != null && e.Server.AFKChannel != afterVch)
 | 
			
		||||
//                    {
 | 
			
		||||
//                        var textChannel = e.Server.FindChannels(
 | 
			
		||||
//                                                    GetChannelName(afterVch.Name),
 | 
			
		||||
//                                                    ChannelType.Text)
 | 
			
		||||
//                                                    .FirstOrDefault();
 | 
			
		||||
//                        if (textChannel == null)
 | 
			
		||||
//                        {
 | 
			
		||||
//                            textChannel = (await e.Server.CreateChannel(GetChannelName(afterVch.Name), ChannelType.Text).ConfigureAwait(false));
 | 
			
		||||
//                            await textChannel.AddPermissionsRule(e.Server.EveryoneRole,
 | 
			
		||||
//                                new ChPermOverride(readMessages: PermValue.Deny,
 | 
			
		||||
//                                                   sendMessages: PermValue.Deny)).ConfigureAwait(false);
 | 
			
		||||
//                        }
 | 
			
		||||
//                        await textChannel.AddPermissionsRule(e.After,
 | 
			
		||||
//                            new ChPermOverride(readMessages: PermValue.Allow,
 | 
			
		||||
//                                               sendMessages: PermValue.Allow)).ConfigureAwait(false);
 | 
			
		||||
//                    }
 | 
			
		||||
//                }
 | 
			
		||||
//                catch (Exception ex)
 | 
			
		||||
//                {
 | 
			
		||||
//                    Console.WriteLine(ex);
 | 
			
		||||
//                }
 | 
			
		||||
//            };
 | 
			
		||||
//        }
 | 
			
		||||
 | 
			
		||||
//        private string GetChannelName(string voiceName) =>
 | 
			
		||||
//            channelNameRegex.Replace(voiceName, "").Trim().Replace(" ", "-").TrimTo(90, true) + "-voice";
 | 
			
		||||
 | 
			
		||||
//        internal override void Init(CommandGroupBuilder cgb)
 | 
			
		||||
//        {
 | 
			
		||||
//            cgb.CreateCommand(Module.Prefix + "cleanv+t")
 | 
			
		||||
//                .Alias(Module.Prefix + "cv+t")
 | 
			
		||||
//                .Description($"Deletes all text channels ending in `-voice` for which voicechannels are not found. **Use at your own risk.\nNeeds Manage Roles and Manage Channels Permissions.** | `{Prefix}cleanv+t`")
 | 
			
		||||
//                .AddCheck(SimpleCheckers.CanManageRoles)
 | 
			
		||||
//                .AddCheck(SimpleCheckers.ManageChannels())
 | 
			
		||||
//                .Do(async e =>
 | 
			
		||||
//                {
 | 
			
		||||
//                    if (!e.Server.CurrentUser.ServerPermissions.ManageChannels)
 | 
			
		||||
//                    {
 | 
			
		||||
//                        await channel.SendMessageAsync("`I have insufficient permission to do that.`");
 | 
			
		||||
//                        return;
 | 
			
		||||
//                    }
 | 
			
		||||
 | 
			
		||||
//                    var allTxtChannels = e.Server.TextChannels.Where(c => c.Name.EndsWith("-voice"));
 | 
			
		||||
//                    var validTxtChannelNames = e.Server.VoiceChannels.Select(c => GetChannelName(c.Name));
 | 
			
		||||
 | 
			
		||||
//                    var invalidTxtChannels = allTxtChannels.Where(c => !validTxtChannelNames.Contains(c.Name));
 | 
			
		||||
 | 
			
		||||
//                    foreach (var c in invalidTxtChannels)
 | 
			
		||||
//                    {
 | 
			
		||||
//                        try
 | 
			
		||||
//                        {
 | 
			
		||||
//                            await c.Delete();
 | 
			
		||||
//                        }
 | 
			
		||||
//                        catch { }
 | 
			
		||||
//                        await Task.Delay(500);
 | 
			
		||||
//                    }
 | 
			
		||||
 | 
			
		||||
//                    await channel.SendMessageAsync("`Done.`");
 | 
			
		||||
//                });
 | 
			
		||||
 | 
			
		||||
//            cgb.CreateCommand(Module.Prefix + "voice+text")
 | 
			
		||||
//                .Alias(Module.Prefix + "v+t")
 | 
			
		||||
//                .Description("Creates a text channel for each voice channel only users in that voice channel can see." +
 | 
			
		||||
//                             $"If you are server owner, keep in mind you will see them all the time regardless. **Needs Manage Roles and Manage Channels Permissions.**| `{Prefix}voice+text`")
 | 
			
		||||
//                .AddCheck(SimpleCheckers.ManageChannels())
 | 
			
		||||
//                .AddCheck(SimpleCheckers.CanManageRoles)
 | 
			
		||||
//                .Do(async e =>
 | 
			
		||||
//                {
 | 
			
		||||
//                    try
 | 
			
		||||
//                    {
 | 
			
		||||
//                        var config = SpecificConfigurations.Default.Of(e.Server.Id);
 | 
			
		||||
//                        if (config.VoicePlusTextEnabled == true)
 | 
			
		||||
//                        {
 | 
			
		||||
//                            config.VoicePlusTextEnabled = false;
 | 
			
		||||
//                            foreach (var textChannel in e.Server.TextChannels.Where(c => c.Name.EndsWith("-voice")))
 | 
			
		||||
//                            {
 | 
			
		||||
//                                try
 | 
			
		||||
//                                {
 | 
			
		||||
//                                    await textChannel.Delete().ConfigureAwait(false);
 | 
			
		||||
//                                }
 | 
			
		||||
//                                catch
 | 
			
		||||
//                                {
 | 
			
		||||
//                                    await channel.SendMessageAsync(
 | 
			
		||||
//                                            ":anger: Error: Most likely i don't have permissions to do this.")
 | 
			
		||||
//                                                .ConfigureAwait(false);
 | 
			
		||||
//                                    return;
 | 
			
		||||
//                                }
 | 
			
		||||
//                            }
 | 
			
		||||
//                            await channel.SendMessageAsync("Successfuly removed voice + text feature.").ConfigureAwait(false);
 | 
			
		||||
//                            return;
 | 
			
		||||
//                        }
 | 
			
		||||
//                        config.VoicePlusTextEnabled = true;
 | 
			
		||||
//                        await channel.SendMessageAsync("Successfuly enabled voice + text feature. " +
 | 
			
		||||
//                                                    "**Make sure the bot has manage roles and manage channels permissions**")
 | 
			
		||||
//                                                    .ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
//                    }
 | 
			
		||||
//                    catch (Exception ex)
 | 
			
		||||
//                    {
 | 
			
		||||
//                        await channel.SendMessageAsync(ex.ToString()).ConfigureAwait(false);
 | 
			
		||||
//                    }
 | 
			
		||||
//                });
 | 
			
		||||
//        }
 | 
			
		||||
//    }
 | 
			
		||||
//}
 | 
			
		||||
@@ -0,0 +1,170 @@
 | 
			
		||||
using Discord;
 | 
			
		||||
using Discord.Commands;
 | 
			
		||||
using Discord.WebSocket;
 | 
			
		||||
using NadekoBot.Attributes;
 | 
			
		||||
using NadekoBot.Extensions;
 | 
			
		||||
using NadekoBot.Services;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text.RegularExpressions;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.Administration
 | 
			
		||||
{
 | 
			
		||||
    public partial class Administration
 | 
			
		||||
    {
 | 
			
		||||
        [Group]
 | 
			
		||||
        public class VoicePlusTextCommands
 | 
			
		||||
        {
 | 
			
		||||
            Regex channelNameRegex = new Regex(@"[^a-zA-Z0-9 -]", RegexOptions.Compiled);
 | 
			
		||||
            //guildid/voiceplustextenabled
 | 
			
		||||
            private ConcurrentDictionary<ulong, bool> voicePlusTextCache;
 | 
			
		||||
            public VoicePlusTextCommands()
 | 
			
		||||
            {
 | 
			
		||||
                NadekoBot.Client.UserUpdated += UserUpdatedEventHandler;
 | 
			
		||||
                voicePlusTextCache = new ConcurrentDictionary<ulong, bool>();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            private Task UserUpdatedEventHandler(IGuildUser before, IGuildUser after)
 | 
			
		||||
            {
 | 
			
		||||
                Task.Run(async () =>
 | 
			
		||||
                {
 | 
			
		||||
                    var guild = before.Guild ?? after.Guild;
 | 
			
		||||
                    var botUserPerms = guild.GetCurrentUser().GuildPermissions;
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        if (before.VoiceChannel == after.VoiceChannel) return;
 | 
			
		||||
 | 
			
		||||
                        bool isEnabled;
 | 
			
		||||
                        voicePlusTextCache.TryGetValue(guild.Id, out isEnabled);
 | 
			
		||||
                        if (!isEnabled)
 | 
			
		||||
                            return;
 | 
			
		||||
 | 
			
		||||
                        if (!botUserPerms.ManageChannels || !botUserPerms.ManageRoles)
 | 
			
		||||
                        {
 | 
			
		||||
                            try
 | 
			
		||||
                            {
 | 
			
		||||
                                await (await guild.GetOwnerAsync()).SendMessageAsync(
 | 
			
		||||
                                    "I don't have manage server and/or Manage Channels permission," +
 | 
			
		||||
                                    $" so I cannot run voice+text on **{guild.Name}** server.").ConfigureAwait(false);
 | 
			
		||||
                            }
 | 
			
		||||
                            catch { }
 | 
			
		||||
                            using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
                            {
 | 
			
		||||
                                uow.GuildConfigs.For(before.Guild.Id).VoicePlusTextEnabled = false;
 | 
			
		||||
                                voicePlusTextCache.TryUpdate(guild.Id, false, true);
 | 
			
		||||
                            }
 | 
			
		||||
                            return;
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                        var beforeVch = before.VoiceChannel;
 | 
			
		||||
                        if (beforeVch != null)
 | 
			
		||||
                        {
 | 
			
		||||
                            var textChannel = guild.GetTextChannels().Where(t => t.Name == GetChannelName(beforeVch.Name)).FirstOrDefault();
 | 
			
		||||
                            if (textChannel != null)
 | 
			
		||||
                                await textChannel.AddPermissionOverwriteAsync(before,
 | 
			
		||||
                                    new OverwritePermissions(readMessages: PermValue.Deny,
 | 
			
		||||
                                                       sendMessages: PermValue.Deny)).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        var afterVch = after.VoiceChannel;
 | 
			
		||||
                        if (afterVch != null && guild.AFKChannelId != afterVch.Id)
 | 
			
		||||
                        {
 | 
			
		||||
                            var textChannel = guild.GetTextChannels()
 | 
			
		||||
                                                        .Where(t => t.Name ==  GetChannelName(afterVch.Name))
 | 
			
		||||
                                                        .FirstOrDefault();
 | 
			
		||||
                            if (textChannel == null)
 | 
			
		||||
                            {
 | 
			
		||||
                                textChannel = (await guild.CreateTextChannelAsync(GetChannelName(afterVch.Name)).ConfigureAwait(false));
 | 
			
		||||
                                await textChannel.AddPermissionOverwriteAsync(guild.EveryoneRole,
 | 
			
		||||
                                    new OverwritePermissions(readMessages: PermValue.Deny,
 | 
			
		||||
                                                       sendMessages: PermValue.Deny)).ConfigureAwait(false);
 | 
			
		||||
                            }
 | 
			
		||||
                            await textChannel.AddPermissionOverwriteAsync(after,
 | 
			
		||||
                                new OverwritePermissions(readMessages: PermValue.Allow,
 | 
			
		||||
                                                        sendMessages: PermValue.Allow)).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    catch (Exception ex)
 | 
			
		||||
                    {
 | 
			
		||||
                        Console.WriteLine(ex);
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
                return Task.CompletedTask;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            private string GetChannelName(string voiceName) =>
 | 
			
		||||
                channelNameRegex.Replace(voiceName, "").Trim().Replace(" ", "-").TrimTo(90, true) + "-voice";
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            [RequirePermission(GuildPermission.ManageRoles)]
 | 
			
		||||
            [RequirePermission(GuildPermission.ManageChannels)]
 | 
			
		||||
            public async Task VoicePlusText(IUserMessage msg, [Remainder] string arg)
 | 
			
		||||
            {
 | 
			
		||||
                var channel = (ITextChannel)msg.Channel;
 | 
			
		||||
                var guild = channel.Guild;
 | 
			
		||||
 | 
			
		||||
                var botUser = guild.GetCurrentUser();
 | 
			
		||||
                if (!botUser.GuildPermissions.ManageRoles || !botUser.GuildPermissions.ManageChannels)
 | 
			
		||||
                {
 | 
			
		||||
                    await channel.SendMessageAsync(":anger: `I require manage roles and manage channels permissions to enable this feature.`");
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    bool isEnabled;
 | 
			
		||||
                    using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
                    {
 | 
			
		||||
                        var conf = uow.GuildConfigs.For(guild.Id);
 | 
			
		||||
                        isEnabled = conf.VoicePlusTextEnabled = !conf.VoicePlusTextEnabled;
 | 
			
		||||
                    }
 | 
			
		||||
                    voicePlusTextCache.AddOrUpdate(guild.Id, isEnabled, (id, val) => isEnabled);
 | 
			
		||||
                    if (isEnabled)
 | 
			
		||||
                    {
 | 
			
		||||
                        foreach (var textChannel in guild.GetTextChannels().Where(c => c.Name.EndsWith("-voice")))
 | 
			
		||||
                        {
 | 
			
		||||
                            try { await textChannel.DeleteAsync().ConfigureAwait(false); } catch { }
 | 
			
		||||
                        }
 | 
			
		||||
                        await channel.SendMessageAsync("Successfuly removed voice + text feature.").ConfigureAwait(false);
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
                    await channel.SendMessageAsync("Successfuly enabled voice + text feature.").ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
                }
 | 
			
		||||
                catch (Exception ex)
 | 
			
		||||
                {
 | 
			
		||||
                    await channel.SendMessageAsync(ex.ToString()).ConfigureAwait(false);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            [RequirePermission(GuildPermission.ManageChannels)]
 | 
			
		||||
            [RequirePermission(GuildPermission.ManageRoles)]
 | 
			
		||||
            public async Task CleanVPlusT(IUserMessage msg, [Remainder] string arg)
 | 
			
		||||
            {
 | 
			
		||||
                var channel = (ITextChannel)msg.Channel;
 | 
			
		||||
                var guild = channel.Guild;
 | 
			
		||||
                if (!guild.GetCurrentUser().GuildPermissions.ManageChannels)
 | 
			
		||||
                {
 | 
			
		||||
                    await channel.SendMessageAsync("`I have insufficient permission to do that.`");
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                var allTxtChannels = guild.GetTextChannels().Where(c => c.Name.EndsWith("-voice"));
 | 
			
		||||
                var validTxtChannelNames = guild.GetVoiceChannels().Select(c => GetChannelName(c.Name));
 | 
			
		||||
 | 
			
		||||
                var invalidTxtChannels = allTxtChannels.Where(c => !validTxtChannelNames.Contains(c.Name));
 | 
			
		||||
 | 
			
		||||
                foreach (var c in invalidTxtChannels)
 | 
			
		||||
                {
 | 
			
		||||
                    try { await c.DeleteAsync().ConfigureAwait(false); } catch { }
 | 
			
		||||
                    await Task.Delay(500);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                await channel.SendMessageAsync("`Done.`");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -54,7 +54,7 @@ namespace NadekoBot.Modules.ClashOfClans
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task CreateWar(IUserMessage umsg, int size, [Remainder] string enemyClan = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -87,7 +87,7 @@ namespace NadekoBot.Modules.ClashOfClans
 | 
			
		||||
            await channel.SendMessageAsync($"❗🔰**CREATED CLAN WAR AGAINST {cw.ShortPrint()}**").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task StartWar(IUserMessage umsg, [Remainder] string number = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -115,7 +115,7 @@ namespace NadekoBot.Modules.ClashOfClans
 | 
			
		||||
            SaveWar(war);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task ListWar(IUserMessage umsg, [Remainder] string number = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -158,7 +158,7 @@ namespace NadekoBot.Modules.ClashOfClans
 | 
			
		||||
            await channel.SendMessageAsync(warsInfo.Item1[warsInfo.Item2].ToPrettyString()).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Claim(IUserMessage umsg, int number, int baseNumber, [Remainder] string other_name = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -186,7 +186,7 @@ namespace NadekoBot.Modules.ClashOfClans
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task ClaimFinish1(IUserMessage umsg, int number, int baseNumber, [Remainder] string other_name = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -194,7 +194,7 @@ namespace NadekoBot.Modules.ClashOfClans
 | 
			
		||||
            await FinishClaim(umsg, number, baseNumber, other_name, 1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task ClaimFinish2(IUserMessage umsg, int number, int baseNumber, [Remainder] string other_name = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -202,7 +202,7 @@ namespace NadekoBot.Modules.ClashOfClans
 | 
			
		||||
            await FinishClaim(umsg, number, baseNumber, other_name, 2);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task ClaimFinish(IUserMessage umsg, int number, int baseNumber, [Remainder] string other_name = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -210,7 +210,7 @@ namespace NadekoBot.Modules.ClashOfClans
 | 
			
		||||
            await FinishClaim(umsg, number, baseNumber, other_name);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task EndWar(IUserMessage umsg, int number)
 | 
			
		||||
        {
 | 
			
		||||
@@ -231,7 +231,7 @@ namespace NadekoBot.Modules.ClashOfClans
 | 
			
		||||
            warsInfo.Item1.RemoveAt(warsInfo.Item2);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Unclaim(IUserMessage umsg, int number, [Remainder] string otherName = null)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
        {
 | 
			
		||||
            public static ConcurrentDictionary<ulong, AnimalRace> AnimalRaces = new ConcurrentDictionary<ulong, AnimalRace>();
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task Race(IUserMessage umsg)
 | 
			
		||||
            {
 | 
			
		||||
@@ -32,7 +32,7 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
                    await channel.SendMessageAsync("🏁 `Failed starting a race. Another race is probably running.`");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task JoinRace(IUserMessage umsg, int amount = 0)
 | 
			
		||||
            {
 | 
			
		||||
@@ -60,7 +60,7 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
 | 
			
		||||
                private ConcurrentQueue<string> animals { get; }
 | 
			
		||||
 | 
			
		||||
                public bool Fail { get; internal set; }
 | 
			
		||||
                public bool Fail { get; set; }
 | 
			
		||||
 | 
			
		||||
                public List<Participant> participants = new List<Participant>();
 | 
			
		||||
                private ulong serverId;
 | 
			
		||||
 
 | 
			
		||||
@@ -14,17 +14,17 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
    {
 | 
			
		||||
        private Regex dndRegex { get; } = new Regex(@"(?<n1>\d+)d(?<n2>\d+)", RegexOptions.Compiled);
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public Task Roll(IUserMessage umsg, [Remainder] string arg = null) =>
 | 
			
		||||
            InternalRoll(umsg, arg, true);
 | 
			
		||||
            publicRoll(umsg, arg, true);
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public Task Rolluo(IUserMessage umsg, [Remainder] string arg = null) =>
 | 
			
		||||
            InternalRoll(umsg, arg, false);
 | 
			
		||||
            publicRoll(umsg, arg, false);
 | 
			
		||||
        //todo drawing
 | 
			
		||||
        private async Task InternalRoll(IUserMessage umsg, string arg, bool ordered)
 | 
			
		||||
        private async Task publicRoll(IUserMessage umsg, string arg, bool ordered)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = (ITextChannel)umsg.Channel;
 | 
			
		||||
            var r = new Random();
 | 
			
		||||
@@ -106,7 +106,7 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
            //}
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task NRoll(IUserMessage umsg, [Remainder] string range)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -11,11 +11,11 @@
 | 
			
		||||
////todo drawing
 | 
			
		||||
//namespace NadekoBot.Modules.Gambling
 | 
			
		||||
//{
 | 
			
		||||
//    internal class DrawCommand : DiscordCommand
 | 
			
		||||
//    public class DrawCommand : DiscordCommand
 | 
			
		||||
//    {
 | 
			
		||||
//        public DrawCommand(DiscordModule module) : base(module) { }
 | 
			
		||||
 | 
			
		||||
//        internal override void Init(CommandGroupBuilder cgb)
 | 
			
		||||
//        public override void Init(CommandGroupBuilder cgb)
 | 
			
		||||
//        {
 | 
			
		||||
//            cgb.CreateCommand(Module.Prefix + "draw")
 | 
			
		||||
//                .Description($"Draws a card from the deck.If you supply number [x], she draws up to 5 cards from the deck. | `{Prefix}draw [x]`")
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        ////todo drawing
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task Flip(IUserMessage imsg, int count = 0)
 | 
			
		||||
        //{
 | 
			
		||||
@@ -39,7 +39,7 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
        //    await channel.SendMessageAsync("Invalid number").ConfigureAwait(false);
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task Betflip(IUserMessage umsg, int amount, string guess)
 | 
			
		||||
        //{
 | 
			
		||||
 
 | 
			
		||||
@@ -34,7 +34,7 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
            
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Raffle(IUserMessage umsg, [Remainder] IRole role = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -48,7 +48,7 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
            await channel.SendMessageAsync($"**Raffled user:** {usr.Username} (id: {usr.Id})").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        [LocalizedCommand("$$$"), LocalizedDescription("$$$"), LocalizedSummary("$$$")]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Cash(IUserMessage umsg, [Remainder] IUser user = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -66,7 +66,7 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
            await channel.SendMessageAsync($"{user.Username} has {amount} {config.CurrencySign}").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Give(IUserMessage umsg, long amount, [Remainder] IUser receiver)
 | 
			
		||||
        {
 | 
			
		||||
@@ -92,12 +92,12 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ////todo owner only
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public Task Award(IUserMessage umsg, long amount, [Remainder] IGuildUser usr) =>
 | 
			
		||||
        //    Award(umsg, amount, usr.Id);
 | 
			
		||||
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task Award(IUserMessage umsg, long amount, [Remainder] ulong usrId)
 | 
			
		||||
        //{
 | 
			
		||||
@@ -112,13 +112,13 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        ////todo owner only
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public Task Take(IUserMessage umsg, long amount, [Remainder] IGuildUser user) =>
 | 
			
		||||
        //    Take(umsg, amount, user.Id);
 | 
			
		||||
 | 
			
		||||
        //todo owner only
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task Take(IUserMessage umsg, long amount, [Remainder] ulong usrId)
 | 
			
		||||
        //{
 | 
			
		||||
@@ -131,7 +131,7 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
        //    await channel.SendMessageAsync($"{umsg.Author.Mention} successfully took {amount} {Gambling.CurrencyName}s from <@{usrId}>!").ConfigureAwait(false);
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task BetRoll(IUserMessage umsg, long amount)
 | 
			
		||||
        {
 | 
			
		||||
@@ -181,7 +181,7 @@ namespace NadekoBot.Modules.Gambling
 | 
			
		||||
            await channel.SendMessageAsync(str).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Leaderboard(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@ namespace NadekoBot.Modules.Games
 | 
			
		||||
{
 | 
			
		||||
    public partial class GamesModule
 | 
			
		||||
    {
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Leet(IUserMessage umsg, int level, [Remainder] string text = null)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -63,7 +63,7 @@
 | 
			
		||||
 | 
			
		||||
//        private SemaphoreSlim locker = new SemaphoreSlim(1,1);
 | 
			
		||||
 | 
			
		||||
//        internal override void Init(CommandGroupBuilder cgb)
 | 
			
		||||
//        public override void Init(CommandGroupBuilder cgb)
 | 
			
		||||
//        {
 | 
			
		||||
//            cgb.CreateCommand(Module.Prefix + "pick")
 | 
			
		||||
//                .Description($"Picks a flower planted in this channel. | `{Prefix}pick`")
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@ namespace NadekoBot.Modules.Games
 | 
			
		||||
    {
 | 
			
		||||
        public static ConcurrentDictionary<IGuild, Poll> ActivePolls = new ConcurrentDictionary<IGuild, Poll>();
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Poll(IUserMessage umsg, [Remainder] string arg = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -35,7 +35,7 @@ namespace NadekoBot.Modules.Games
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Pollend(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,196 +1,190 @@
 | 
			
		||||
//using Discord;
 | 
			
		||||
//using Discord.Commands;
 | 
			
		||||
//using NadekoBot.Classes;
 | 
			
		||||
//using NadekoBot.DataModels;
 | 
			
		||||
//using NadekoBot.Extensions;
 | 
			
		||||
//using System;
 | 
			
		||||
//using System.Collections.Concurrent;
 | 
			
		||||
//using System.Collections.Generic;
 | 
			
		||||
//using System.Diagnostics;
 | 
			
		||||
//using System.Linq;
 | 
			
		||||
//using System.Threading.Tasks;
 | 
			
		||||
using Discord;
 | 
			
		||||
using Discord.Commands;
 | 
			
		||||
using Discord.WebSocket;
 | 
			
		||||
using NadekoBot.Attributes;
 | 
			
		||||
using NadekoBot.Extensions;
 | 
			
		||||
using NadekoBot.Services;
 | 
			
		||||
using NadekoBot.Services.Database;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
////todo DB
 | 
			
		||||
////todo Rewrite?
 | 
			
		||||
//namespace NadekoBot.Modules.Games
 | 
			
		||||
//{
 | 
			
		||||
//    public static class SentencesProvider
 | 
			
		||||
//    {
 | 
			
		||||
//        internal static string GetRandomSentence()
 | 
			
		||||
//        {
 | 
			
		||||
//            var data = DbHandler.Instance.GetAllRows<TypingArticle>();
 | 
			
		||||
//            try
 | 
			
		||||
//            {
 | 
			
		||||
//                return data.ToList()[new Random().Next(0, data.Count())].Text;
 | 
			
		||||
//            }
 | 
			
		||||
//            catch
 | 
			
		||||
//            {
 | 
			
		||||
//                return "Failed retrieving data from parse. Owner didn't add any articles to type using `typeadd`.";
 | 
			
		||||
//            }
 | 
			
		||||
//        }
 | 
			
		||||
//    }
 | 
			
		||||
namespace NadekoBot.Modules.Games
 | 
			
		||||
{
 | 
			
		||||
    public class TypingGame
 | 
			
		||||
    {
 | 
			
		||||
        public const float WORD_VALUE = 4.5f;
 | 
			
		||||
        private readonly ITextChannel channel;
 | 
			
		||||
        public string CurrentSentence;
 | 
			
		||||
        public bool IsActive;
 | 
			
		||||
        private readonly Stopwatch sw;
 | 
			
		||||
        private readonly List<ulong> finishedUserIds;
 | 
			
		||||
 | 
			
		||||
//    public class TypingGame
 | 
			
		||||
//    {
 | 
			
		||||
//        public const float WORD_VALUE = 4.5f;
 | 
			
		||||
//        private readonly Channel channel;
 | 
			
		||||
//        public string CurrentSentence;
 | 
			
		||||
//        public bool IsActive;
 | 
			
		||||
//        private readonly Stopwatch sw;
 | 
			
		||||
//        private readonly List<ulong> finishedUserIds;
 | 
			
		||||
        public TypingGame(ITextChannel channel)
 | 
			
		||||
        {
 | 
			
		||||
            this.channel = channel;
 | 
			
		||||
            IsActive = false;
 | 
			
		||||
            sw = new Stopwatch();
 | 
			
		||||
            finishedUserIds = new List<ulong>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
//        public TypingGame(Channel channel)
 | 
			
		||||
//        {
 | 
			
		||||
//            this.channel = channel;
 | 
			
		||||
//            IsActive = false;
 | 
			
		||||
//            sw = new Stopwatch();
 | 
			
		||||
//            finishedUserIds = new List<ulong>();
 | 
			
		||||
//        }
 | 
			
		||||
        public ITextChannel Channel { get; set; }
 | 
			
		||||
 | 
			
		||||
//        public Channel Channell { get; internal set; }
 | 
			
		||||
        public async Task<bool> Stop()
 | 
			
		||||
        {
 | 
			
		||||
            if (!IsActive) return false;
 | 
			
		||||
            NadekoBot.Client.MessageReceived -= AnswerReceived;
 | 
			
		||||
            finishedUserIds.Clear();
 | 
			
		||||
            IsActive = false;
 | 
			
		||||
            sw.Stop();
 | 
			
		||||
            sw.Reset();
 | 
			
		||||
            await channel.SendMessageAsync("Typing contest stopped").ConfigureAwait(false);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
//        internal async Task<bool> Stop()
 | 
			
		||||
//        {
 | 
			
		||||
//            if (!IsActive) return false;
 | 
			
		||||
//            NadekoBot.Client.MessageReceived -= AnswerReceived;
 | 
			
		||||
//            finishedUserIds.Clear();
 | 
			
		||||
//            IsActive = false;
 | 
			
		||||
//            sw.Stop();
 | 
			
		||||
//            sw.Reset();
 | 
			
		||||
//            await channel.Send("Typing contest stopped").ConfigureAwait(false);
 | 
			
		||||
//            return true;
 | 
			
		||||
//        }
 | 
			
		||||
 | 
			
		||||
//        internal async Task Start()
 | 
			
		||||
//        {
 | 
			
		||||
//            while (true)
 | 
			
		||||
//            {
 | 
			
		||||
//                if (IsActive) return; // can't start running game
 | 
			
		||||
//                IsActive = true;
 | 
			
		||||
//                CurrentSentence = SentencesProvider.GetRandomSentence();
 | 
			
		||||
//                var i = (int)(CurrentSentence.Length / WORD_VALUE * 1.7f);
 | 
			
		||||
//                await channel.SendMessageAsync($":clock2: Next contest will last for {i} seconds. Type the bolded text as fast as you can.").ConfigureAwait(false);
 | 
			
		||||
        public async Task Start()
 | 
			
		||||
        {
 | 
			
		||||
            while (true)
 | 
			
		||||
            {
 | 
			
		||||
                if (IsActive) return; // can't start running game
 | 
			
		||||
                IsActive = true;
 | 
			
		||||
                CurrentSentence = GetRandomSentence();
 | 
			
		||||
                var i = (int)(CurrentSentence.Length / WORD_VALUE * 1.7f);
 | 
			
		||||
                await channel.SendMessageAsync($":clock2: Next contest will last for {i} seconds. Type the bolded text as fast as you can.").ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//                var msg = await channel.SendMessageAsync("Starting new typing contest in **3**...").ConfigureAwait(false);
 | 
			
		||||
//                await Task.Delay(1000).ConfigureAwait(false);
 | 
			
		||||
//                await msg.Edit("Starting new typing contest in **2**...").ConfigureAwait(false);
 | 
			
		||||
//                await Task.Delay(1000).ConfigureAwait(false);
 | 
			
		||||
//                await msg.Edit("Starting new typing contest in **1**...").ConfigureAwait(false);
 | 
			
		||||
//                await Task.Delay(1000).ConfigureAwait(false);
 | 
			
		||||
//                await msg.Edit($":book:**{CurrentSentence.Replace(" ", " \x200B")}**:book:").ConfigureAwait(false);
 | 
			
		||||
//                sw.Start();
 | 
			
		||||
//                HandleAnswers();
 | 
			
		||||
                var msg = await channel.SendMessageAsync("Starting new typing contest in **3**...").ConfigureAwait(false);
 | 
			
		||||
                await Task.Delay(1000).ConfigureAwait(false);
 | 
			
		||||
                await msg.ModifyAsync(m => m.Content = "Starting new typing contest in **2**...").ConfigureAwait(false);
 | 
			
		||||
                await Task.Delay(1000).ConfigureAwait(false);
 | 
			
		||||
                await msg.ModifyAsync(m => m.Content = "Starting new typing contest in **1**...").ConfigureAwait(false);
 | 
			
		||||
                await Task.Delay(1000).ConfigureAwait(false);
 | 
			
		||||
                await msg.ModifyAsync(m => m.Content = $":book:**{CurrentSentence.Replace(" ", " \x200B")}**:book:").ConfigureAwait(false);
 | 
			
		||||
                sw.Start();
 | 
			
		||||
                HandleAnswers();
 | 
			
		||||
 | 
			
		||||
//                while (i > 0)
 | 
			
		||||
//                {
 | 
			
		||||
//                    await Task.Delay(1000).ConfigureAwait(false);
 | 
			
		||||
//                    i--;
 | 
			
		||||
//                    if (!IsActive)
 | 
			
		||||
//                        return;
 | 
			
		||||
//                }
 | 
			
		||||
                while (i > 0)
 | 
			
		||||
                {
 | 
			
		||||
                    await Task.Delay(1000).ConfigureAwait(false);
 | 
			
		||||
                    i--;
 | 
			
		||||
                    if (!IsActive)
 | 
			
		||||
                        return;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
//                await Stop().ConfigureAwait(false);
 | 
			
		||||
//            }
 | 
			
		||||
//        }
 | 
			
		||||
                await Stop().ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
//        private void HandleAnswers()
 | 
			
		||||
//        {
 | 
			
		||||
//            NadekoBot.Client.MessageReceived += AnswerReceived;
 | 
			
		||||
//        }
 | 
			
		||||
        public string GetRandomSentence()
 | 
			
		||||
        {
 | 
			
		||||
            using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
            {
 | 
			
		||||
                return uow.TypingArticles.GetRandom()?.Text ?? "No typing articles found. Use `>typeadd` command to add a new article for typing.";
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
//        private async void AnswerReceived(object sender, MessageEventArgs e)
 | 
			
		||||
//        {
 | 
			
		||||
//            try
 | 
			
		||||
//            {
 | 
			
		||||
//                if (e.Channel == null || e.Channel.Id != channel.Id || umsg.Author.Id == NadekoBot.Client.CurrentUser.Id) return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
//                var guess = e.Message.RawText;
 | 
			
		||||
        private void HandleAnswers()
 | 
			
		||||
        {
 | 
			
		||||
            NadekoBot.Client.MessageReceived += AnswerReceived;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
//                var distance = CurrentSentence.LevenshteinDistance(guess);
 | 
			
		||||
//                var decision = Judge(distance, guess.Length);
 | 
			
		||||
//                if (decision && !finishedUserIds.Contains(umsg.Author.Id))
 | 
			
		||||
//                {
 | 
			
		||||
//                    finishedUserIds.Add(umsg.Author.Id);
 | 
			
		||||
//                    await channel.Send($"{umsg.Author.Mention} finished in **{sw.Elapsed.Seconds}** seconds with { distance } errors, **{ CurrentSentence.Length / WORD_VALUE / sw.Elapsed.Seconds * 60 }** WPM!").ConfigureAwait(false);
 | 
			
		||||
//                    if (finishedUserIds.Count % 2 == 0)
 | 
			
		||||
//                    {
 | 
			
		||||
//                        await channel.SendMessageAsync($":exclamation: `A lot of people finished, here is the text for those still typing:`\n\n:book:**{CurrentSentence}**:book:").ConfigureAwait(false);
 | 
			
		||||
//                    }
 | 
			
		||||
//                }
 | 
			
		||||
//            }
 | 
			
		||||
//            catch { }
 | 
			
		||||
//        }
 | 
			
		||||
        private async Task AnswerReceived(IMessage imsg)
 | 
			
		||||
        {
 | 
			
		||||
            var msg = imsg as IUserMessage;
 | 
			
		||||
            if (msg == null)
 | 
			
		||||
                return;
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                if (channel== null || channel.Id != channel.Id || msg.Author.Id == NadekoBot.Client.GetCurrentUser().Id) return;
 | 
			
		||||
 | 
			
		||||
//        private bool Judge(int errors, int textLength) => errors <= textLength / 25;
 | 
			
		||||
                var guess = msg.Content;
 | 
			
		||||
 | 
			
		||||
//    }
 | 
			
		||||
                var distance = CurrentSentence.LevenshteinDistance(guess);
 | 
			
		||||
                var decision = Judge(distance, guess.Length);
 | 
			
		||||
                if (decision && !finishedUserIds.Contains(msg.Author.Id))
 | 
			
		||||
                {
 | 
			
		||||
                    finishedUserIds.Add(msg.Author.Id);
 | 
			
		||||
                    await channel.SendMessageAsync($"{msg.Author.Mention} finished in **{sw.Elapsed.Seconds}** seconds with { distance } errors, **{ CurrentSentence.Length / WORD_VALUE / sw.Elapsed.Seconds * 60 }** WPM!").ConfigureAwait(false);
 | 
			
		||||
                    if (finishedUserIds.Count % 2 == 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        await channel.SendMessageAsync($":exclamation: `A lot of people finished, here is the text for those still typing:`\n\n:book:**{CurrentSentence}**:book:").ConfigureAwait(false);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch { }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
//    internal class SpeedTyping : DiscordCommand
 | 
			
		||||
//    {
 | 
			
		||||
        private bool Judge(int errors, int textLength) => errors <= textLength / 25;
 | 
			
		||||
 | 
			
		||||
//        public static ConcurrentDictionary<ulong, TypingGame> RunningContests;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
//        public SpeedTyping(DiscordModule module) : base(module)
 | 
			
		||||
//        {
 | 
			
		||||
//            RunningContests = new ConcurrentDictionary<ulong, TypingGame>();
 | 
			
		||||
//        }
 | 
			
		||||
    [Group]
 | 
			
		||||
    public class SpeedTypingCommands
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
//        public Func<CommandEventArgs, Task> DoFunc() =>
 | 
			
		||||
//            async e =>
 | 
			
		||||
//            {
 | 
			
		||||
//                var game = RunningContests.GetOrAdd(umsg.Author.Server.Id, id => new TypingGame(e.Channel));
 | 
			
		||||
        public static ConcurrentDictionary<ulong, TypingGame> RunningContests;
 | 
			
		||||
 | 
			
		||||
//                if (game.IsActive)
 | 
			
		||||
//                {
 | 
			
		||||
//                    await channel.SendMessageAsync(
 | 
			
		||||
//                            $"Contest already running in " +
 | 
			
		||||
//                            $"{game.Channell.Mention} channel.")
 | 
			
		||||
//                                .ConfigureAwait(false);
 | 
			
		||||
//                }
 | 
			
		||||
//                else
 | 
			
		||||
//                {
 | 
			
		||||
//                    await game.Start().ConfigureAwait(false);
 | 
			
		||||
//                }
 | 
			
		||||
//            };
 | 
			
		||||
        public SpeedTypingCommands()
 | 
			
		||||
        {
 | 
			
		||||
            RunningContests = new ConcurrentDictionary<ulong, TypingGame>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
//        private Func<CommandEventArgs, Task> QuitFunc() =>
 | 
			
		||||
//            async e =>
 | 
			
		||||
//            {
 | 
			
		||||
//                TypingGame game;
 | 
			
		||||
//                if (RunningContests.TryRemove(umsg.Author.Server.Id, out game))
 | 
			
		||||
//                {
 | 
			
		||||
//                    await game.Stop().ConfigureAwait(false);
 | 
			
		||||
//                    return;
 | 
			
		||||
//                }
 | 
			
		||||
//                await channel.SendMessageAsync("No contest to stop on this channel.").ConfigureAwait(false);
 | 
			
		||||
//            };
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task TypeStart(IUserMessage msg)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = (ITextChannel)msg.Channel;
 | 
			
		||||
 | 
			
		||||
//        internal override void Init(CommandGroupBuilder cgb)
 | 
			
		||||
//        {
 | 
			
		||||
//            cgb.CreateCommand(Module.Prefix + "typestart")
 | 
			
		||||
//                .Description($"Starts a typing contest. | `{Prefix}typestart`")
 | 
			
		||||
//                .Do(DoFunc());
 | 
			
		||||
            var game = RunningContests.GetOrAdd(channel.Guild.Id, id => new TypingGame(channel));
 | 
			
		||||
 | 
			
		||||
//            cgb.CreateCommand(Module.Prefix + "typestop")
 | 
			
		||||
//                .Description($"Stops a typing contest on the current channel. | `{Prefix}typestop`")
 | 
			
		||||
//                .Do(QuitFunc());
 | 
			
		||||
            if (game.IsActive)
 | 
			
		||||
            {
 | 
			
		||||
                await channel.SendMessageAsync(
 | 
			
		||||
                        $"Contest already running in " +
 | 
			
		||||
                        $"{game.Channel.Mention} channel.")
 | 
			
		||||
                            .ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                await game.Start().ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
//            cgb.CreateCommand(Module.Prefix + "typeadd")
 | 
			
		||||
//                .Description($"Adds a new article to the typing contest. Owner only. | `{Prefix}typeadd wordswords`")
 | 
			
		||||
//                .Parameter("text", ParameterType.Unparsed)
 | 
			
		||||
//                .Do(async e =>
 | 
			
		||||
//                {
 | 
			
		||||
//                    if (!NadekoBot.IsOwner(umsg.Author.Id) || string.IsNullOrWhiteSpace(text)) return;
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task TypeStop(IUserMessage imsg)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = (ITextChannel)imsg.Channel;
 | 
			
		||||
            TypingGame game;
 | 
			
		||||
            if (RunningContests.TryRemove(channel.Guild.Id, out game))
 | 
			
		||||
            {
 | 
			
		||||
                await game.Stop().ConfigureAwait(false);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            await channel.SendMessageAsync("No contest to stop on this channel.").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
//                    DbHandler.Instance.Connection.Insert(new TypingArticle
 | 
			
		||||
//                    {
 | 
			
		||||
//                        Text = text,
 | 
			
		||||
//                        DateAdded = DateTime.Now
 | 
			
		||||
//                    });
 | 
			
		||||
        ////todo owner only
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task Typeadd(IUserMessage imsg, [Remainder] string text)
 | 
			
		||||
        //{
 | 
			
		||||
        //    var channel = (ITextChannel)imsg.Channel;
 | 
			
		||||
 | 
			
		||||
//                    await channel.SendMessageAsync("Added new article for typing game.").ConfigureAwait(false);
 | 
			
		||||
//                });
 | 
			
		||||
//        }
 | 
			
		||||
//    }
 | 
			
		||||
//}
 | 
			
		||||
        //    using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
        //    {
 | 
			
		||||
        //        uow.TypingArticles.Add(new Services.Database.Models.TypingArticle
 | 
			
		||||
        //        {
 | 
			
		||||
        //            Author = imsg.Author.Username,
 | 
			
		||||
        //            Text = text
 | 
			
		||||
        //        });
 | 
			
		||||
        //    }
 | 
			
		||||
 | 
			
		||||
        //    await channel.SendMessageAsync("Added new article for typing game.").ConfigureAwait(false);
 | 
			
		||||
        //}
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,6 @@ using System.Text;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
// todo rewrite
 | 
			
		||||
namespace NadekoBot.Modules.Games.Trivia
 | 
			
		||||
{
 | 
			
		||||
    public class TriviaGame
 | 
			
		||||
 
 | 
			
		||||
@@ -27,7 +27,7 @@ namespace NadekoBot.Modules.Games.Trivia
 | 
			
		||||
            return list[rand];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal void Reload()
 | 
			
		||||
        public void Reload()
 | 
			
		||||
        {
 | 
			
		||||
            var arr = JArray.Parse(File.ReadAllText("data/triviaquestions.json"));
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,7 @@ namespace NadekoBot.Modules.Games
 | 
			
		||||
        {
 | 
			
		||||
            public static ConcurrentDictionary<ulong, TriviaGame> RunningTrivias = new ConcurrentDictionary<ulong, TriviaGame>();
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task Trivia(IUserMessage umsg, string[] args)
 | 
			
		||||
            {
 | 
			
		||||
@@ -44,7 +44,7 @@ namespace NadekoBot.Modules.Games
 | 
			
		||||
                    await channel.SendMessageAsync("Trivia game is already running on this server.\n" + trivia.CurrentQuestion).ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task Tl(IUserMessage umsg)
 | 
			
		||||
            {
 | 
			
		||||
@@ -57,7 +57,7 @@ namespace NadekoBot.Modules.Games
 | 
			
		||||
                    await channel.SendMessageAsync("No trivia is running on this server.").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task Tq(IUserMessage umsg)
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -27,7 +27,7 @@ namespace NadekoBot.Modules.Games
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Choose(IUserMessage umsg, [Remainder] string list = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -41,7 +41,7 @@ namespace NadekoBot.Modules.Games
 | 
			
		||||
            await channel.SendMessageAsync(listArr[rng.Next(0, listArr.Length)]).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task _8Ball(IUserMessage umsg, [Remainder] string question = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -54,7 +54,7 @@ namespace NadekoBot.Modules.Games
 | 
			
		||||
🎱 `8Ball Answers` __**{_8BallResponses.Shuffle().FirstOrDefault()}**__").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Rps(IUserMessage umsg, string input)
 | 
			
		||||
        {
 | 
			
		||||
@@ -104,7 +104,7 @@ namespace NadekoBot.Modules.Games
 | 
			
		||||
            await channel.SendMessageAsync(msg).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Linux(IUserMessage umsg, string guhnoo, string loonix)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ namespace NadekoBot.Modules.Help
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Modules(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
@@ -35,7 +35,7 @@ namespace NadekoBot.Modules.Help
 | 
			
		||||
                                       .ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Commands(IUserMessage umsg, [Remainder] string module = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -44,7 +44,7 @@ namespace NadekoBot.Modules.Help
 | 
			
		||||
            module = module?.Trim().ToUpperInvariant();
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(module))
 | 
			
		||||
                return;
 | 
			
		||||
            var cmds = _commands.Commands.Where(c => c.Module.Name.ToUpperInvariant() == module)
 | 
			
		||||
            var cmds = _commands.Commands.Where(c => c.Module.Name.ToUpperInvariant().StartsWith(module))
 | 
			
		||||
                                                  .OrderBy(c => c.Text)
 | 
			
		||||
                                                  .AsEnumerable();
 | 
			
		||||
            var cmdsArray = cmds as Command[] ?? cmds.ToArray();
 | 
			
		||||
@@ -55,8 +55,7 @@ namespace NadekoBot.Modules.Help
 | 
			
		||||
            }
 | 
			
		||||
            if (module != "customreactions" && module != "conversations")
 | 
			
		||||
            {
 | 
			
		||||
                //todo aliases
 | 
			
		||||
                await channel.SendTableAsync("`List Of Commands:`\n", cmdsArray, el => $"{el.Text,-15}").ConfigureAwait(false);
 | 
			
		||||
                await channel.SendTableAsync("`List Of Commands:`\n", cmdsArray, el => $"{el.Text,-15} {"["+el.Aliases.Skip(1).FirstOrDefault()+"]",-8}").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
@@ -65,7 +64,7 @@ namespace NadekoBot.Modules.Help
 | 
			
		||||
            await channel.SendMessageAsync($"`You can type \"-h command_name\" to see the help about that specific command.`").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task H(IUserMessage umsg, [Remainder] string comToFind = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -77,16 +76,23 @@ namespace NadekoBot.Modules.Help
 | 
			
		||||
                await (await (umsg.Author as IGuildUser).CreateDMChannelAsync()).SendMessageAsync(HelpString).ConfigureAwait(false);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            var com = _commands.Commands.FirstOrDefault(c => c.Text.ToLowerInvariant() == comToFind);
 | 
			
		||||
            var com = _commands.Commands.FirstOrDefault(c => c.Text.ToLowerInvariant() == comToFind || c.Aliases.Select(a=>a.ToLowerInvariant()).Contains(comToFind));
 | 
			
		||||
 | 
			
		||||
            //todo aliases
 | 
			
		||||
            if (com == null)
 | 
			
		||||
            {
 | 
			
		||||
                await channel.SendMessageAsync("`No command found.`");
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            var str = $"**__Help for:__ `{com.Text}`**";
 | 
			
		||||
            var alias = com.Aliases.Skip(1).FirstOrDefault();
 | 
			
		||||
            if (alias != null)
 | 
			
		||||
                str += $" / `{ alias }`";
 | 
			
		||||
            if (com != null)
 | 
			
		||||
                await channel.SendMessageAsync($@"**__Help for:__ `{com.Text}`**
 | 
			
		||||
**Desc:** {com.Description}
 | 
			
		||||
                await channel.SendMessageAsync(str + $@"{Environment.NewLine}**Desc:** {com.Description}
 | 
			
		||||
**Usage:** {com.Summary}").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Hgit(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
@@ -102,8 +108,7 @@ namespace NadekoBot.Modules.Help
 | 
			
		||||
                    helpstr.AppendLine("----------------|--------------|-------");
 | 
			
		||||
                    lastModule = com.Module.Name;
 | 
			
		||||
                }
 | 
			
		||||
                //todo aliases
 | 
			
		||||
                helpstr.AppendLine($"`{com.Text}` | {com.Description} | {com.Summary}");
 | 
			
		||||
                helpstr.AppendLine($"`{com.Text}` {string.Join(" ", com.Aliases.Skip(1).Select(a=>"`"+a+"`"))} | {com.Description} | {com.Summary}");
 | 
			
		||||
            }
 | 
			
		||||
            helpstr = helpstr.Replace((await NadekoBot.Client.GetCurrentUserAsync()).Username , "@BotName");
 | 
			
		||||
#if DEBUG
 | 
			
		||||
@@ -113,7 +118,7 @@ namespace NadekoBot.Modules.Help
 | 
			
		||||
#endif
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Guide(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
@@ -124,7 +129,7 @@ namespace NadekoBot.Modules.Help
 | 
			
		||||
**Hosting Guides and docs can be found here**: <http://nadekobot.rtfd.io>").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Donate(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -234,7 +234,7 @@ namespace NadekoBot.Modules.Music.Classes
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal void ClearQueue()
 | 
			
		||||
        public void ClearQueue()
 | 
			
		||||
        {
 | 
			
		||||
            actionQueue.Enqueue(() =>
 | 
			
		||||
            {
 | 
			
		||||
@@ -256,7 +256,7 @@ namespace NadekoBot.Modules.Music.Classes
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal Task MoveToVoiceChannel(IVoiceChannel voiceChannel)
 | 
			
		||||
        public Task MoveToVoiceChannel(IVoiceChannel voiceChannel)
 | 
			
		||||
        {
 | 
			
		||||
            if (audioClient?.ConnectionState != ConnectionState.Connected)
 | 
			
		||||
                throw new InvalidOperationException("Can't move while bot is not connected to voice channel.");
 | 
			
		||||
@@ -264,13 +264,13 @@ namespace NadekoBot.Modules.Music.Classes
 | 
			
		||||
            return PlaybackVoiceChannel.ConnectAsync();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal bool ToggleRepeatSong() => this.RepeatSong = !this.RepeatSong;
 | 
			
		||||
        public bool ToggleRepeatSong() => this.RepeatSong = !this.RepeatSong;
 | 
			
		||||
 | 
			
		||||
        internal bool ToggleRepeatPlaylist() => this.RepeatPlaylist = !this.RepeatPlaylist;
 | 
			
		||||
        public bool ToggleRepeatPlaylist() => this.RepeatPlaylist = !this.RepeatPlaylist;
 | 
			
		||||
 | 
			
		||||
        internal bool ToggleAutoplay() => this.Autoplay = !this.Autoplay;
 | 
			
		||||
        public bool ToggleAutoplay() => this.Autoplay = !this.Autoplay;
 | 
			
		||||
 | 
			
		||||
        internal void ThrowIfQueueFull()
 | 
			
		||||
        public void ThrowIfQueueFull()
 | 
			
		||||
        {
 | 
			
		||||
            if (MaxQueueSize == 0)
 | 
			
		||||
                return;
 | 
			
		||||
 
 | 
			
		||||
@@ -16,18 +16,18 @@ namespace NadekoBot.Modules.Music.Classes
 | 
			
		||||
{
 | 
			
		||||
    public class SongInfo
 | 
			
		||||
    {
 | 
			
		||||
        public string Provider { get; internal set; }
 | 
			
		||||
        public MusicType ProviderType { get; internal set; }
 | 
			
		||||
        public string Provider { get; set; }
 | 
			
		||||
        public MusicType ProviderType { get; set; }
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Will be set only if the providertype is normal
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public string Query { get; internal set; }
 | 
			
		||||
        public string Title { get; internal set; }
 | 
			
		||||
        public string Uri { get; internal set; }
 | 
			
		||||
        public string Query { get; set; }
 | 
			
		||||
        public string Title { get; set; }
 | 
			
		||||
        public string Uri { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
    public class Song
 | 
			
		||||
    {
 | 
			
		||||
        public StreamState State { get; internal set; }
 | 
			
		||||
        public StreamState State { get; set; }
 | 
			
		||||
        public string PrettyName =>
 | 
			
		||||
            $"**【 {SongInfo.Title.TrimTo(55)} 】**`{(SongInfo.Provider ?? "-")}` `by {QueuerName}`";
 | 
			
		||||
        public SongInfo SongInfo { get; }
 | 
			
		||||
@@ -80,7 +80,7 @@ namespace NadekoBot.Modules.Music.Classes
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal async Task Play(IAudioClient voiceClient, CancellationToken cancelToken)
 | 
			
		||||
        public async Task Play(IAudioClient voiceClient, CancellationToken cancelToken)
 | 
			
		||||
        {
 | 
			
		||||
            var filename = Path.Combine(Music.MusicDataPath, DateTime.Now.UnixTimestamp().ToString());
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -40,7 +40,7 @@ namespace NadekoBot.Modules.Music.Classes
 | 
			
		||||
        public bool IsSoundCloudLink(string url) =>
 | 
			
		||||
            System.Text.RegularExpressions.Regex.IsMatch(url, "(.*)(soundcloud.com|snd.sc)(.*)");
 | 
			
		||||
 | 
			
		||||
        internal async Task<SoundCloudVideo> GetVideoByQueryAsync(string query)
 | 
			
		||||
        public async Task<SoundCloudVideo> GetVideoByQueryAsync(string query)
 | 
			
		||||
        {
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(query))
 | 
			
		||||
                throw new ArgumentNullException(nameof(query));
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
            _google = google;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Next(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
@@ -47,7 +47,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
                musicPlayer.Next();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Stop(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
@@ -62,7 +62,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Destroy(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
@@ -74,7 +74,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
                musicPlayer.Destroy();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Pause(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
@@ -91,7 +91,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
                await channel.SendMessageAsync("🎵`Music Player unpaused.`").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Queue(IUserMessage umsg, [Remainder] string query)
 | 
			
		||||
        {
 | 
			
		||||
@@ -105,7 +105,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task SoundCloudQueue(IUserMessage umsg, [Remainder] string query)
 | 
			
		||||
        {
 | 
			
		||||
@@ -119,7 +119,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task ListQueue(IUserMessage umsg, int page = 1)
 | 
			
		||||
        {
 | 
			
		||||
@@ -152,7 +152,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
            await channel.SendMessageAsync(toSend + string.Join("\n", musicPlayer.Playlist.Skip(startAt).Take(15).Select(v => $"`{number++}.` {v.PrettyName}"))).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task NowPlaying(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
@@ -167,7 +167,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
                                        $"{currentSong.PrettyCurrentTime()}").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Volume(IUserMessage umsg, int val)
 | 
			
		||||
        {
 | 
			
		||||
@@ -183,7 +183,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
            await channel.SendMessageAsync($"🎵 `Volume set to {volume}%`").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Defvol(IUserMessage umsg, [Remainder] int val)
 | 
			
		||||
        {
 | 
			
		||||
@@ -202,7 +202,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
            await channel.SendMessageAsync($"🎵 `Default volume set to {val}%`").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Mute(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
@@ -215,7 +215,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
            musicPlayer.SetVolume(0);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Max(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
@@ -228,7 +228,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
            musicPlayer.SetVolume(100);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Shuffle(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
@@ -248,7 +248,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
            await channel.SendMessageAsync("🎵 `Songs shuffled.`").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Playlist(IUserMessage umsg, [Remainder] string playlist)
 | 
			
		||||
        {
 | 
			
		||||
@@ -290,7 +290,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
            await msg.ModifyAsync(m => m.Content = "🎵 `Playlist queue complete.`").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task SoundCloudPl(IUserMessage umsg, [Remainder] string pl)
 | 
			
		||||
        {
 | 
			
		||||
@@ -327,7 +327,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task LocalPl(IUserMessage umsg, [Remainder] string directory)
 | 
			
		||||
        {
 | 
			
		||||
@@ -356,7 +356,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
            catch { }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Radio(IUserMessage umsg, string radio_link)
 | 
			
		||||
        {
 | 
			
		||||
@@ -374,7 +374,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Local(IUserMessage umsg, [Remainder] string path)
 | 
			
		||||
        {
 | 
			
		||||
@@ -386,7 +386,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Move(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
@@ -398,7 +398,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
            musicPlayer.MoveToVoiceChannel(voiceChannel);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Remove(IUserMessage umsg, int num)
 | 
			
		||||
        {
 | 
			
		||||
@@ -417,8 +417,8 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
            musicPlayer.RemoveSongAt(num - 1);
 | 
			
		||||
            await channel.SendMessageAsync($"🎵**Track {song.PrettyName} at position `#{num}` has been removed.**").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
        //todo fix
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Remove(IUserMessage umsg, string all)
 | 
			
		||||
        {
 | 
			
		||||
@@ -433,7 +433,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task MoveSong(IUserMessage umsg, [Remainder] string fromto)
 | 
			
		||||
        {
 | 
			
		||||
@@ -469,7 +469,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task SetMaxQueue(IUserMessage umsg, uint size)
 | 
			
		||||
        {
 | 
			
		||||
@@ -483,7 +483,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
            await channel.SendMessageAsync($"🎵 `Max queue set to {(size == 0 ? ("unlimited") : size + " tracks")}`");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task ReptCurSong(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
@@ -501,7 +501,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
                                            .ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task RepeatPl(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
@@ -514,7 +514,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ///
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task Save(IUserMessage umsg, [Remainder] string name)
 | 
			
		||||
        //{
 | 
			
		||||
@@ -522,7 +522,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task Load(IUserMessage umsg, [Remainder] string name)
 | 
			
		||||
        //{
 | 
			
		||||
@@ -530,7 +530,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task Playlists(IUserMessage umsg, [Remainder] string num)
 | 
			
		||||
        //{
 | 
			
		||||
@@ -538,7 +538,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task DeletePlaylist(IUserMessage umsg, [Remainder] string pl)
 | 
			
		||||
        //{
 | 
			
		||||
@@ -546,7 +546,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Goto(IUserMessage umsg, int time)
 | 
			
		||||
        {
 | 
			
		||||
@@ -583,7 +583,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
            await channel.SendMessageAsync($"`Skipped to {minutes}:{seconds}`").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task GetLink(IUserMessage umsg, int index = 0)
 | 
			
		||||
        {
 | 
			
		||||
@@ -618,7 +618,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Autoplay(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,7 @@ namespace NadekoBot.Modules.NSFW
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Hentai(IUserMessage umsg, [Remainder] string tag = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -41,7 +41,7 @@ namespace NadekoBot.Modules.NSFW
 | 
			
		||||
            await channel.SendMessageAsync(String.Join("\n\n", links)).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Danbooru(IUserMessage umsg, [Remainder] string tag = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -55,7 +55,7 @@ namespace NadekoBot.Modules.NSFW
 | 
			
		||||
                await channel.SendMessageAsync(link).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Gelbooru(IUserMessage umsg, [Remainder] string tag = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -69,7 +69,7 @@ namespace NadekoBot.Modules.NSFW
 | 
			
		||||
                await channel.SendMessageAsync(link).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Rule34(IUserMessage umsg, [Remainder] string tag = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -83,7 +83,7 @@ namespace NadekoBot.Modules.NSFW
 | 
			
		||||
                await channel.SendMessageAsync(link).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task E621(IUserMessage umsg, [Remainder] string tag = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -97,7 +97,7 @@ namespace NadekoBot.Modules.NSFW
 | 
			
		||||
                await channel.SendMessageAsync(link).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Cp(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
@@ -106,7 +106,7 @@ namespace NadekoBot.Modules.NSFW
 | 
			
		||||
            await channel.SendMessageAsync("http://i.imgur.com/MZkY1md.jpg").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Boobs(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
@@ -126,7 +126,7 @@ namespace NadekoBot.Modules.NSFW
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Butts(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
@@ -204,7 +204,7 @@ namespace NadekoBot.Modules.NSFW
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        internal static async Task<string> GetE621ImageLink(string tags)
 | 
			
		||||
        public static async Task<string> GetE621ImageLink(string tags)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@ namespace NadekoBot.Modules.Games
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //todo Dragon should PR this in
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Poke(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,99 +1,132 @@
 | 
			
		||||
//using Discord;
 | 
			
		||||
//using Discord.Commands;
 | 
			
		||||
//using NadekoBot.Attributes;
 | 
			
		||||
//using System;
 | 
			
		||||
//using System.Collections.Generic;
 | 
			
		||||
//using System.Linq;
 | 
			
		||||
//using System.Threading.Tasks;
 | 
			
		||||
using Discord;
 | 
			
		||||
using Discord.Commands;
 | 
			
		||||
using NadekoBot.Attributes;
 | 
			
		||||
using NadekoBot.Extensions;
 | 
			
		||||
using NadekoBot.Modules.Searches.Models;
 | 
			
		||||
using Newtonsoft.Json;
 | 
			
		||||
using Newtonsoft.Json.Linq;
 | 
			
		||||
using NLog;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
//// todo RestSharp
 | 
			
		||||
//namespace NadekoBot.Modules.Searches
 | 
			
		||||
//{
 | 
			
		||||
//    public partial class SearchesModule
 | 
			
		||||
//    {
 | 
			
		||||
//        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
//        [RequireContext(ContextType.Guild)]
 | 
			
		||||
//        public async Task Anime(IUserMessage umsg, [Remainder] string query = null)
 | 
			
		||||
//        {
 | 
			
		||||
//            var channel = (ITextChannel)umsg.Channel;
 | 
			
		||||
namespace NadekoBot.Modules.Searches
 | 
			
		||||
{
 | 
			
		||||
    public partial class Searches
 | 
			
		||||
    {
 | 
			
		||||
        [Group]
 | 
			
		||||
        public class AnimeSearchCommands
 | 
			
		||||
        {
 | 
			
		||||
            private Logger _log;
 | 
			
		||||
 | 
			
		||||
//            if (!(await ValidateQuery(umsg.Channel as ITextChannel, query).ConfigureAwait(false))) return;
 | 
			
		||||
//            string result;
 | 
			
		||||
//            try
 | 
			
		||||
//            {
 | 
			
		||||
//                result = (await GetAnimeData(query).ConfigureAwait(false)).ToString();
 | 
			
		||||
//            }
 | 
			
		||||
//            catch
 | 
			
		||||
//            {
 | 
			
		||||
//                await channel.SendMessageAsync("Failed to find that anime.").ConfigureAwait(false);
 | 
			
		||||
//                return;
 | 
			
		||||
//            }
 | 
			
		||||
            private string anilistToken { get; set; }
 | 
			
		||||
            private DateTime lastRefresh { get; set; }
 | 
			
		||||
 | 
			
		||||
//            await channel.SendMessageAsync(result.ToString()).ConfigureAwait(false);
 | 
			
		||||
//        }
 | 
			
		||||
            public AnimeSearchCommands()
 | 
			
		||||
            {
 | 
			
		||||
                _log = LogManager.GetCurrentClassLogger();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
//        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
//        [RequireContext(ContextType.Guild)]
 | 
			
		||||
//        public async Task Manga(IUserMessage umsg, [Remainder] string query = null)
 | 
			
		||||
//        {
 | 
			
		||||
//            var channel = (ITextChannel)umsg.Channel;
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task Anime(IUserMessage umsg, [Remainder] string query)
 | 
			
		||||
            {
 | 
			
		||||
                var channel = (ITextChannel)umsg.Channel;
 | 
			
		||||
 | 
			
		||||
//            if (!(await ValidateQuery(umsg.Channel as ITextChannel, query).ConfigureAwait(false))) return;
 | 
			
		||||
//            string result;
 | 
			
		||||
//            try
 | 
			
		||||
//            {
 | 
			
		||||
//                result = (await GetMangaData(query).ConfigureAwait(false)).ToString();
 | 
			
		||||
//            }
 | 
			
		||||
//            catch
 | 
			
		||||
//            {
 | 
			
		||||
//                await channel.SendMessageAsync("Failed to find that manga.").ConfigureAwait(false);
 | 
			
		||||
//                return;
 | 
			
		||||
//            }
 | 
			
		||||
//            await channel.SendMessageAsync(result).ConfigureAwait(false);
 | 
			
		||||
//        }
 | 
			
		||||
                if (string.IsNullOrWhiteSpace(query))
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
//        public static async Task<AnimeResult> GetAnimeData(string query)
 | 
			
		||||
//        {
 | 
			
		||||
//            if (string.IsNullOrWhiteSpace(query))
 | 
			
		||||
//                throw new ArgumentNullException(nameof(query));
 | 
			
		||||
                var result = await GetAnimeData(query).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
//            await RefreshAnilistToken().ConfigureAwait(false);
 | 
			
		||||
                await channel.SendMessageAsync(result.ToString() ?? "`No anime found.`").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
//            var link = "http://anilist.co/api/anime/search/" + Uri.EscapeUriString(query);
 | 
			
		||||
//            var smallContent = "";
 | 
			
		||||
//            var cl = new RestSharp.RestClient("http://anilist.co/api");
 | 
			
		||||
//            var rq = new RestSharp.RestRequest("/anime/search/" + Uri.EscapeUriString(query));
 | 
			
		||||
//            rq.AddParameter("access_token", token);
 | 
			
		||||
//            smallContent = cl.Execute(rq).Content;
 | 
			
		||||
//            var smallObj = JArray.Parse(smallContent)[0];
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task Manga(IUserMessage umsg, [Remainder] string query)
 | 
			
		||||
            {
 | 
			
		||||
                var channel = (ITextChannel)umsg.Channel;
 | 
			
		||||
 | 
			
		||||
//            rq = new RestSharp.RestRequest("/anime/" + smallObj["id"]);
 | 
			
		||||
//            rq.AddParameter("access_token", token);
 | 
			
		||||
//            var content = cl.Execute(rq).Content;
 | 
			
		||||
                if (string.IsNullOrWhiteSpace(query))
 | 
			
		||||
                    return;
 | 
			
		||||
 | 
			
		||||
//            return await Task.Run(() => JsonConvert.DeserializeObject<AnimeResult>(content)).ConfigureAwait(false);
 | 
			
		||||
//        }
 | 
			
		||||
                var result = await GetMangaData(query).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
//        public static async Task<MangaResult> GetMangaData(string query)
 | 
			
		||||
//        {
 | 
			
		||||
//            if (string.IsNullOrWhiteSpace(query))
 | 
			
		||||
//                throw new ArgumentNullException(nameof(query));
 | 
			
		||||
                await channel.SendMessageAsync(result.ToString() ?? "`No manga found.`").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
//            await RefreshAnilistToken().ConfigureAwait(false);
 | 
			
		||||
            private async Task<AnimeResult> GetAnimeData(string query)
 | 
			
		||||
            {
 | 
			
		||||
                if (string.IsNullOrWhiteSpace(query))
 | 
			
		||||
                    throw new ArgumentNullException(nameof(query));
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    await RefreshAnilistToken().ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
//            var link = "http://anilist.co/api/anime/search/" + Uri.EscapeUriString(query);
 | 
			
		||||
//            var smallContent = "";
 | 
			
		||||
//            var cl = new RestSharp.RestClient("http://anilist.co/api");
 | 
			
		||||
//            var rq = new RestSharp.RestRequest("/manga/search/" + Uri.EscapeUriString(query));
 | 
			
		||||
//            rq.AddParameter("access_token", token);
 | 
			
		||||
//            smallContent = cl.Execute(rq).Content;
 | 
			
		||||
//            var smallObj = JArray.Parse(smallContent)[0];
 | 
			
		||||
                    var link = "http://anilist.co/api/anime/search/" + Uri.EscapeUriString(query);
 | 
			
		||||
                    using (var http = new HttpClient())
 | 
			
		||||
                    {
 | 
			
		||||
                        var res = await http.GetStringAsync("http://anilist.co/api/anime/search/" + Uri.EscapeUriString(query) + $"?access_token={anilistToken}").ConfigureAwait(false);
 | 
			
		||||
                        var smallObj = JArray.Parse(res)[0];
 | 
			
		||||
                        var aniData = await http.GetStringAsync("http://anilist.co/api/anime/" + smallObj["id"] + $"?access_token={anilistToken}").ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
//            rq = new RestSharp.RestRequest("/manga/" + smallObj["id"]);
 | 
			
		||||
//            rq.AddParameter("access_token", token);
 | 
			
		||||
//            var content = cl.Execute(rq).Content;
 | 
			
		||||
                        return await Task.Run(() => JsonConvert.DeserializeObject<AnimeResult>(aniData)).ConfigureAwait(false);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                catch (Exception ex) {
 | 
			
		||||
                    _log.Warn(ex, "Failed anime search for {0}", query);
 | 
			
		||||
                    return null;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
//            return await Task.Run(() => JsonConvert.DeserializeObject<MangaResult>(content)).ConfigureAwait(false);
 | 
			
		||||
//        }
 | 
			
		||||
//    }
 | 
			
		||||
//}
 | 
			
		||||
            private async Task RefreshAnilistToken()
 | 
			
		||||
            {
 | 
			
		||||
                if (DateTime.Now - lastRefresh > TimeSpan.FromMinutes(29))
 | 
			
		||||
                    lastRefresh = DateTime.Now;
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                var headers = new Dictionary<string, string> {
 | 
			
		||||
                    {"grant_type", "client_credentials"},
 | 
			
		||||
                    {"client_id", "kwoth-w0ki9"},
 | 
			
		||||
                    {"client_secret", "Qd6j4FIAi1ZK6Pc7N7V4Z"},
 | 
			
		||||
                };
 | 
			
		||||
                using (var http = new HttpClient())
 | 
			
		||||
                {
 | 
			
		||||
                    http.AddFakeHeaders();
 | 
			
		||||
                    var formContent = new FormUrlEncodedContent(headers);
 | 
			
		||||
                    var response = await http.PostAsync("http://anilist.co/api/auth/access_token", formContent).ConfigureAwait(false);
 | 
			
		||||
                    var stringContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
 | 
			
		||||
                    anilistToken = JObject.Parse(stringContent)["access_token"].ToString();
 | 
			
		||||
                }
 | 
			
		||||
                
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            private async Task<MangaResult> GetMangaData(string query)
 | 
			
		||||
            {
 | 
			
		||||
                if (string.IsNullOrWhiteSpace(query))
 | 
			
		||||
                    throw new ArgumentNullException(nameof(query));
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    await RefreshAnilistToken().ConfigureAwait(false);
 | 
			
		||||
                    using (var http = new HttpClient())
 | 
			
		||||
                    {
 | 
			
		||||
                        var res = await http.GetStringAsync("http://anilist.co/api/manga/search/" + Uri.EscapeUriString(query) + $"?access_token={anilistToken}").ConfigureAwait(false);
 | 
			
		||||
                        var smallObj = JArray.Parse(res)[0];
 | 
			
		||||
                        var aniData = await http.GetStringAsync("http://anilist.co/api/manga/" + smallObj["id"] + $"?access_token={anilistToken}").ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
                        return await Task.Run(() => JsonConvert.DeserializeObject<MangaResult>(aniData)).ConfigureAwait(false);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                catch (Exception ex)
 | 
			
		||||
                {
 | 
			
		||||
                    _log.Warn(ex, "Failed anime search for {0}", query);
 | 
			
		||||
                    return null;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -14,7 +14,7 @@ namespace NadekoBot.Modules.Searches
 | 
			
		||||
    [Group]
 | 
			
		||||
    public partial class Searches
 | 
			
		||||
    {
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public static async Task Calculate(IUserMessage msg, [Remainder] string expression)
 | 
			
		||||
        {
 | 
			
		||||
@@ -41,7 +41,7 @@ namespace NadekoBot.Modules.Searches
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task CalcOps(IUserMessage msg)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,7 @@
 | 
			
		||||
//        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//        internal override void Init(CommandGroupBuilder cgb)
 | 
			
		||||
//        public override void Init(CommandGroupBuilder cgb)
 | 
			
		||||
//        {
 | 
			
		||||
//            cgb.CreateCommand(Module.Prefix + "convert")
 | 
			
		||||
//                .Description($"Convert quantities from>to. | `{Prefix}convert m>km 1000`")
 | 
			
		||||
 
 | 
			
		||||
@@ -41,7 +41,7 @@ namespace NadekoBot.Modules.Searches
 | 
			
		||||
                    _log.Warn("data/magicitems.json is missing. Magic items are not loaded.");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task Yomama(IUserMessage umsg)
 | 
			
		||||
            {
 | 
			
		||||
@@ -53,7 +53,7 @@ namespace NadekoBot.Modules.Searches
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task Randjoke(IUserMessage umsg)
 | 
			
		||||
            {
 | 
			
		||||
@@ -65,7 +65,7 @@ namespace NadekoBot.Modules.Searches
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task ChuckNorris(IUserMessage umsg)
 | 
			
		||||
            {
 | 
			
		||||
@@ -77,7 +77,7 @@ namespace NadekoBot.Modules.Searches
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task WowJoke(IUserMessage umsg)
 | 
			
		||||
            {
 | 
			
		||||
@@ -89,7 +89,7 @@ namespace NadekoBot.Modules.Searches
 | 
			
		||||
                await channel.SendMessageAsync(wowJokes[new Random().Next(0, wowJokes.Count)].ToString());
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task MagicItem(IUserMessage umsg)
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -31,7 +31,7 @@ namespace NadekoBot.Modules.Searches
 | 
			
		||||
                                                "Doesn't matter what you ban really. Enemy will ban your main and you will lose." };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Lolban(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
@@ -113,7 +113,7 @@ namespace NadekoBot.Modules.Searches
 | 
			
		||||
//            public float StatScore { get; set; }
 | 
			
		||||
//        }
 | 
			
		||||
 | 
			
		||||
//        internal override void Init(CommandGroupBuilder cgb)
 | 
			
		||||
//        public override void Init(CommandGroupBuilder cgb)
 | 
			
		||||
//        {
 | 
			
		||||
//            cgb.CreateCommand(Module.Prefix + "lolchamp")
 | 
			
		||||
//                  .Description($"Shows League Of Legends champion statistics. If there are spaces/apostrophes or in the name - omit them. Optional second parameter is a role. |`{Prefix}lolchamp Riven` or `{Prefix}lolchamp Annie sup`")
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@ namespace NadekoBot.Modules.Searches
 | 
			
		||||
{
 | 
			
		||||
    public partial class Searches
 | 
			
		||||
    {
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Memelist(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
@@ -29,7 +29,7 @@ namespace NadekoBot.Modules.Searches
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Memegen(IUserMessage umsg, string meme, string topText, string botText)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
namespace NadekoBot.Classes.JSONModels
 | 
			
		||||
namespace NadekoBot.Modules.Searches.Models
 | 
			
		||||
{
 | 
			
		||||
    public class AnimeResult
 | 
			
		||||
    {
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
namespace NadekoBot.Classes.JSONModels
 | 
			
		||||
namespace NadekoBot.Modules.Searches.Models
 | 
			
		||||
{
 | 
			
		||||
    public class MangaResult
 | 
			
		||||
    {
 | 
			
		||||
@@ -25,7 +25,7 @@ namespace NadekoBot.Modules.Searches
 | 
			
		||||
            {
 | 
			
		||||
                _log = LogManager.GetCurrentClassLogger();
 | 
			
		||||
            }
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task Osu(IUserMessage umsg, string usr, string mode)
 | 
			
		||||
            {
 | 
			
		||||
@@ -58,7 +58,7 @@ namespace NadekoBot.Modules.Searches
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task Osub(IUserMessage umsg, [Remainder] string map)
 | 
			
		||||
            {
 | 
			
		||||
@@ -95,7 +95,7 @@ namespace NadekoBot.Modules.Searches
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task Osu5(IUserMessage umsg, string user, [Remainder] string mode)
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -38,7 +38,7 @@ namespace NadekoBot.Modules.Searches
 | 
			
		||||
                    _log.Warn(PokemonAbilitiesFile + " is missing. Pokemon abilities not loaded.");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task Pokemon(IUserMessage umsg, [Remainder] string pokemon = null)
 | 
			
		||||
            {
 | 
			
		||||
@@ -59,7 +59,7 @@ namespace NadekoBot.Modules.Searches
 | 
			
		||||
                await channel.SendMessageAsync("`No pokemon found.`");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task PokemonAbility(IUserMessage umsg, [Remainder] string ability = null)
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,348 +1,288 @@
 | 
			
		||||
//using Discord.Commands;
 | 
			
		||||
//using NadekoBot.Classes;
 | 
			
		||||
//using Newtonsoft.Json.Linq;
 | 
			
		||||
//using System;
 | 
			
		||||
//using System.Collections.Concurrent;
 | 
			
		||||
//using System.Linq;
 | 
			
		||||
//using System.Threading.Tasks;
 | 
			
		||||
//using Discord;
 | 
			
		||||
//using NadekoBot.Services;
 | 
			
		||||
//using System.Threading;
 | 
			
		||||
using Discord.Commands;
 | 
			
		||||
using Newtonsoft.Json.Linq;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Discord;
 | 
			
		||||
using NadekoBot.Services;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using NadekoBot.Services.Database;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using NadekoBot.Services.Database.Models;
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
using Discord.WebSocket;
 | 
			
		||||
using NadekoBot.Attributes;
 | 
			
		||||
 | 
			
		||||
//todo DB
 | 
			
		||||
//namespace NadekoBot.Modules.Searches
 | 
			
		||||
//{
 | 
			
		||||
//    public partial class Searches
 | 
			
		||||
//    {
 | 
			
		||||
//        [Group]
 | 
			
		||||
//        public class StreamNotificationCommands
 | 
			
		||||
//        {
 | 
			
		||||
//            private readonly Timer checkTimer;
 | 
			
		||||
//            private ConcurrentDictionary<string, Tuple<bool, string>> cachedStatuses = new ConcurrentDictionary<string, Tuple<bool, string>>();
 | 
			
		||||
//            private bool FirstPass { get; set; } = true; 
 | 
			
		||||
namespace NadekoBot.Modules.Searches
 | 
			
		||||
{
 | 
			
		||||
    public partial class Searches
 | 
			
		||||
    {
 | 
			
		||||
        [Group]
 | 
			
		||||
        public class StreamNotificationCommands
 | 
			
		||||
        {
 | 
			
		||||
            private Timer checkTimer { get; }
 | 
			
		||||
            private ConcurrentDictionary<string, Tuple<bool, string>> cachedStatuses = new ConcurrentDictionary<string, Tuple<bool, string>>();
 | 
			
		||||
            private bool FirstPass { get; set; } = true;
 | 
			
		||||
 | 
			
		||||
//            public StreamNotifications(DiscordModule module)
 | 
			
		||||
//            {
 | 
			
		||||
//                checkTimer = new Timer(async (state) =>
 | 
			
		||||
//                {
 | 
			
		||||
//                    cachedStatuses.Clear();
 | 
			
		||||
//                    try
 | 
			
		||||
//                    {
 | 
			
		||||
//                        var streams = SpecificConfigurations.Default.AllConfigs.SelectMany(c => c.ObservingStreams);
 | 
			
		||||
//                        if (!streams.Any()) return;
 | 
			
		||||
//                        foreach (var stream in streams)
 | 
			
		||||
//                        {
 | 
			
		||||
//                            Tuple<bool, string> data;
 | 
			
		||||
//                            try
 | 
			
		||||
//                            {
 | 
			
		||||
//                                data = await GetStreamStatus(stream).ConfigureAwait(false);
 | 
			
		||||
//                            }
 | 
			
		||||
//                            catch
 | 
			
		||||
//                            {
 | 
			
		||||
//                                continue;
 | 
			
		||||
//                            }
 | 
			
		||||
            public StreamNotificationCommands()
 | 
			
		||||
            {
 | 
			
		||||
                checkTimer = new Timer(async (state) =>
 | 
			
		||||
                {
 | 
			
		||||
                    cachedStatuses.Clear();
 | 
			
		||||
                    try
 | 
			
		||||
                    {
 | 
			
		||||
                        IEnumerable<FollowedStream> streams;
 | 
			
		||||
                        using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
                        {
 | 
			
		||||
                            streams = uow.GuildConfigs.GetAllFollowedStreams();
 | 
			
		||||
                        }
 | 
			
		||||
                        foreach (var stream in streams)
 | 
			
		||||
                        {
 | 
			
		||||
                            Tuple<bool, string> data;
 | 
			
		||||
                            try
 | 
			
		||||
                            {
 | 
			
		||||
                                data = await GetStreamStatus(stream).ConfigureAwait(false);
 | 
			
		||||
                            }
 | 
			
		||||
                            catch
 | 
			
		||||
                            {
 | 
			
		||||
                                continue;
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
//                            if (data.Item1 != stream.LastStatus)
 | 
			
		||||
//                            {
 | 
			
		||||
//                                stream.LastStatus = data.Item1;
 | 
			
		||||
//                                if (FirstPass)
 | 
			
		||||
//                                    continue;
 | 
			
		||||
//                                var server = NadekoBot.Client.GetServer(stream.ServerId);
 | 
			
		||||
//                                var channel = server?.GetChannel(stream.ChannelId);
 | 
			
		||||
//                                if (channel == null)
 | 
			
		||||
//                                    continue;
 | 
			
		||||
//                                var msg = $"`{stream.Username}`'s stream is now " +
 | 
			
		||||
//                                          $"**{(data.Item1 ? "ONLINE" : "OFFLINE")}** with " +
 | 
			
		||||
//                                          $"**{data.Item2}** viewers.";
 | 
			
		||||
//                                if (stream.LastStatus)
 | 
			
		||||
//                                    if (stream.Type == StreamNotificationConfig.StreamType.Hitbox)
 | 
			
		||||
//                                        msg += $"\n`Here is the Link:`【 http://www.hitbox.tv/{stream.Username}/ 】";
 | 
			
		||||
//                                    else if (stream.Type == StreamNotificationConfig.StreamType.Twitch)
 | 
			
		||||
//                                        msg += $"\n`Here is the Link:`【 http://www.twitch.tv/{stream.Username}/ 】";
 | 
			
		||||
//                                    else if (stream.Type == StreamNotificationConfig.StreamType.Beam)
 | 
			
		||||
//                                        msg += $"\n`Here is the Link:`【 http://www.beam.pro/{stream.Username}/ 】";
 | 
			
		||||
//                                    else if (stream.Type == StreamNotificationConfig.StreamType.YoutubeGaming)
 | 
			
		||||
//                                        msg += $"\n`Here is the Link:`【 not implemented yet - {stream.Username} 】";
 | 
			
		||||
//                                await channel.SendMessageAsync(msg).ConfigureAwait(false);
 | 
			
		||||
//                            }
 | 
			
		||||
//                        }
 | 
			
		||||
//                        FirstPass = false;
 | 
			
		||||
//                    }
 | 
			
		||||
//                    catch { }
 | 
			
		||||
//                }, null, TimeSpan.Zero, TimeSpan.FromSeconds(15));
 | 
			
		||||
//            }
 | 
			
		||||
                            if (data.Item1 != stream.LastStatus)
 | 
			
		||||
                            {
 | 
			
		||||
                                stream.LastStatus = data.Item1;
 | 
			
		||||
                                if (FirstPass)
 | 
			
		||||
                                    continue;
 | 
			
		||||
                                var server = NadekoBot.Client.GetGuild(stream.GuildId);
 | 
			
		||||
                                var channel = server?.GetTextChannel(stream.ChannelId);
 | 
			
		||||
                                if (channel == null)
 | 
			
		||||
                                    continue;
 | 
			
		||||
                                var msg = $"`{stream.Username}`'s stream is now " +
 | 
			
		||||
                                          $"**{(data.Item1 ? "ONLINE" : "OFFLINE")}** with " +
 | 
			
		||||
                                          $"**{data.Item2}** viewers.";
 | 
			
		||||
                                if (stream.LastStatus)
 | 
			
		||||
                                    if (stream.Type == FollowedStream.FollowedStreamType.Hitbox)
 | 
			
		||||
                                        msg += $"\n`Here is the Link:`【 http://www.hitbox.tv/{stream.Username}/ 】";
 | 
			
		||||
                                    else if (stream.Type == FollowedStream.FollowedStreamType.Twitch)
 | 
			
		||||
                                        msg += $"\n`Here is the Link:`【 http://www.twitch.tv/{stream.Username}/ 】";
 | 
			
		||||
                                    else if (stream.Type == FollowedStream.FollowedStreamType.Beam)
 | 
			
		||||
                                        msg += $"\n`Here is the Link:`【 http://www.beam.pro/{stream.Username}/ 】";
 | 
			
		||||
                                    //else if (stream.Type == FollowedStream.FollowedStreamType.YoutubeGaming)
 | 
			
		||||
                                    //    msg += $"\n`Here is the Link:`【 not implemented yet - {stream.Username} 】";
 | 
			
		||||
                                await channel.SendMessageAsync(msg).ConfigureAwait(false);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        FirstPass = false;
 | 
			
		||||
                    }
 | 
			
		||||
                    catch { }
 | 
			
		||||
                }, null, TimeSpan.Zero, TimeSpan.FromSeconds(15));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
//            public StreamNotifications(ILocalization loc, CommandService cmds, IBotConfiguration config, DiscordSocketClient client) : base(loc, cmds, config, client)
 | 
			
		||||
//            {
 | 
			
		||||
//            }
 | 
			
		||||
            private async Task<Tuple<bool, string>> GetStreamStatus(FollowedStream stream, bool checkCache = true)
 | 
			
		||||
            {
 | 
			
		||||
                bool isLive;
 | 
			
		||||
                string response;
 | 
			
		||||
                JObject data;
 | 
			
		||||
                Tuple<bool, string> result;
 | 
			
		||||
                switch (stream.Type)
 | 
			
		||||
                {
 | 
			
		||||
                    case FollowedStream.FollowedStreamType.Hitbox:
 | 
			
		||||
                        var hitboxUrl = $"https://api.hitbox.tv/media/status/{stream.Username}";
 | 
			
		||||
                        if (checkCache && cachedStatuses.TryGetValue(hitboxUrl, out result))
 | 
			
		||||
                            return result;
 | 
			
		||||
                        using (var http = new HttpClient())
 | 
			
		||||
                        {
 | 
			
		||||
                            response = await http.GetStringAsync(hitboxUrl).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        data = JObject.Parse(response);
 | 
			
		||||
                        isLive = data["media_is_live"].ToString() == "1";
 | 
			
		||||
                        result = new Tuple<bool, string>(isLive, data["media_views"].ToString());
 | 
			
		||||
                        cachedStatuses.TryAdd(hitboxUrl, result);
 | 
			
		||||
                        return result;
 | 
			
		||||
                    case FollowedStream.FollowedStreamType.Twitch:
 | 
			
		||||
                        var twitchUrl = $"https://api.twitch.tv/kraken/streams/{Uri.EscapeUriString(stream.Username)}";
 | 
			
		||||
                        if (checkCache && cachedStatuses.TryGetValue(twitchUrl, out result))
 | 
			
		||||
                            return result;
 | 
			
		||||
                        using (var http = new HttpClient())
 | 
			
		||||
                        {
 | 
			
		||||
                            response = await http.GetStringAsync(twitchUrl).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        data = JObject.Parse(response);
 | 
			
		||||
                        isLive = !string.IsNullOrWhiteSpace(data["stream"].ToString());
 | 
			
		||||
                        result = new Tuple<bool, string>(isLive, isLive ? data["stream"]["viewers"].ToString() : "0");
 | 
			
		||||
                        cachedStatuses.TryAdd(twitchUrl, result);
 | 
			
		||||
                        return result;
 | 
			
		||||
                    case FollowedStream.FollowedStreamType.Beam:
 | 
			
		||||
                        var beamUrl = $"https://beam.pro/api/v1/channels/{stream.Username}";
 | 
			
		||||
                        if (checkCache && cachedStatuses.TryGetValue(beamUrl, out result))
 | 
			
		||||
                            return result;
 | 
			
		||||
                        using (var http = new HttpClient())
 | 
			
		||||
                        {
 | 
			
		||||
                            response = await http.GetStringAsync(beamUrl).ConfigureAwait(false);
 | 
			
		||||
                        }
 | 
			
		||||
                        data = JObject.Parse(response);
 | 
			
		||||
                        isLive = data["online"].ToObject<bool>() == true;
 | 
			
		||||
                        result = new Tuple<bool, string>(isLive, data["viewersCurrent"].ToString());
 | 
			
		||||
                        cachedStatuses.TryAdd(beamUrl, result);
 | 
			
		||||
                        return result;
 | 
			
		||||
                    default:
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
                return new Tuple<bool, string>(false, "0");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
//            private async Task<Tuple<bool, string>> GetStreamStatus(StreamNotificationConfig stream, bool checkCache = true)
 | 
			
		||||
//            {
 | 
			
		||||
//                bool isLive;
 | 
			
		||||
//                string response;
 | 
			
		||||
//                JObject data;
 | 
			
		||||
//                Tuple<bool, string> result;
 | 
			
		||||
//                switch (stream.Type)
 | 
			
		||||
//                {
 | 
			
		||||
//                    case StreamNotificationConfig.StreamType.Hitbox:
 | 
			
		||||
//                        var hitboxUrl = $"https://api.hitbox.tv/media/status/{stream.Username}";
 | 
			
		||||
//                        if (checkCache && cachedStatuses.TryGetValue(hitboxUrl, out result))
 | 
			
		||||
//                            return result;
 | 
			
		||||
//                        response = await http.GetStringAsync(hitboxUrl).ConfigureAwait(false);
 | 
			
		||||
//                        data = JObject.Parse(response);
 | 
			
		||||
//                        isLive = data["media_is_live"].ToString() == "1";
 | 
			
		||||
//                        result = new Tuple<bool, string>(isLive, data["media_views"].ToString());
 | 
			
		||||
//                        cachedStatuses.TryAdd(hitboxUrl, result);
 | 
			
		||||
//                        return result;
 | 
			
		||||
//                    case StreamNotificationConfig.StreamType.Twitch:
 | 
			
		||||
//                        var twitchUrl = $"https://api.twitch.tv/kraken/streams/{Uri.EscapeUriString(stream.Username)}";
 | 
			
		||||
//                        if (checkCache && cachedStatuses.TryGetValue(twitchUrl, out result))
 | 
			
		||||
//                            return result;
 | 
			
		||||
//                        response = await http.GetStringAsync(twitchUrl).ConfigureAwait(false);
 | 
			
		||||
//                        data = JObject.Parse(response);
 | 
			
		||||
//                        isLive = !string.IsNullOrWhiteSpace(data["stream"].ToString());
 | 
			
		||||
//                        result = new Tuple<bool, string>(isLive, isLive ? data["stream"]["viewers"].ToString() : "0");
 | 
			
		||||
//                        cachedStatuses.TryAdd(twitchUrl, result);
 | 
			
		||||
//                        return result;
 | 
			
		||||
//                    case StreamNotificationConfig.StreamType.Beam:
 | 
			
		||||
//                        var beamUrl = $"https://beam.pro/api/v1/channels/{stream.Username}";
 | 
			
		||||
//                        if (checkCache && cachedStatuses.TryGetValue(beamUrl, out result))
 | 
			
		||||
//                            return result;
 | 
			
		||||
//                        response = await http.GetStringAsync(beamUrl).ConfigureAwait(false);
 | 
			
		||||
//                        data = JObject.Parse(response);
 | 
			
		||||
//                        isLive = data["online"].ToObject<bool>() == true;
 | 
			
		||||
//                        result = new Tuple<bool, string>(isLive, data["viewersCurrent"].ToString());
 | 
			
		||||
//                        cachedStatuses.TryAdd(beamUrl, result);
 | 
			
		||||
//                        return result;
 | 
			
		||||
//                    default:
 | 
			
		||||
//                        break;
 | 
			
		||||
//                }
 | 
			
		||||
//                return new Tuple<bool, string>(false, "0");
 | 
			
		||||
//            }
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            [RequirePermission(GuildPermission.ManageMessages)]
 | 
			
		||||
            public async Task Hitbox(IUserMessage msg, [Remainder] string username) =>
 | 
			
		||||
                await TrackStream((ITextChannel)msg.Channel, username, FollowedStream.FollowedStreamType.Hitbox)
 | 
			
		||||
                    .ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
//            internal override void Init(CommandGroupBuilder cgb)
 | 
			
		||||
//            {
 | 
			
		||||
//                cgb.CreateCommand(Module.Prefix + "hitbox")
 | 
			
		||||
//                    .Alias(Module.Prefix + "hb")
 | 
			
		||||
//                    .Description("Notifies this channel when a certain user starts streaming." +
 | 
			
		||||
//                                 $" | `{Prefix}hitbox SomeStreamer`")
 | 
			
		||||
//                    .Parameter("username", ParameterType.Unparsed)
 | 
			
		||||
//                    .AddCheck(SimpleCheckers.ManageServer())
 | 
			
		||||
//                    .Do(TrackStream(StreamNotificationConfig.StreamType.Hitbox));
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            [RequirePermission(GuildPermission.ManageMessages)]
 | 
			
		||||
            public async Task Twitch(IUserMessage msg, [Remainder] string username) =>
 | 
			
		||||
                await TrackStream((ITextChannel)msg.Channel, username, FollowedStream.FollowedStreamType.Twitch)
 | 
			
		||||
                    .ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
//                cgb.CreateCommand(Module.Prefix + "twitch")
 | 
			
		||||
//                    .Alias(Module.Prefix + "tw")
 | 
			
		||||
//                    .Description("Notifies this channel when a certain user starts streaming." +
 | 
			
		||||
//                                 $" | `{Prefix}twitch SomeStreamer`")
 | 
			
		||||
//                    .AddCheck(SimpleCheckers.ManageServer())
 | 
			
		||||
//                    .Parameter("username", ParameterType.Unparsed)
 | 
			
		||||
//                    .Do(TrackStream(StreamNotificationConfig.StreamType.Twitch));
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            [RequirePermission(GuildPermission.ManageMessages)]
 | 
			
		||||
            public async Task Beam(IUserMessage msg, [Remainder] string username) =>
 | 
			
		||||
                await TrackStream((ITextChannel)msg.Channel, username, FollowedStream.FollowedStreamType.Beam)
 | 
			
		||||
                    .ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
//                cgb.CreateCommand(Module.Prefix + "beam")
 | 
			
		||||
//                    .Alias(Module.Prefix + "bm")
 | 
			
		||||
//                    .Description("Notifies this channel when a certain user starts streaming." +
 | 
			
		||||
//                                 $" | `{Prefix}beam SomeStreamer`")
 | 
			
		||||
//                    .AddCheck(SimpleCheckers.ManageServer())
 | 
			
		||||
//                    .Parameter("username", ParameterType.Unparsed)
 | 
			
		||||
//                    .Do(TrackStream(StreamNotificationConfig.StreamType.Beam));
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task ListStreams(IUserMessage imsg)
 | 
			
		||||
            {
 | 
			
		||||
                var channel = (ITextChannel)imsg.Channel;
 | 
			
		||||
 | 
			
		||||
//                cgb.CreateCommand(Module.Prefix + "checkhitbox")
 | 
			
		||||
//                    .Alias(Module.Prefix + "chhb")
 | 
			
		||||
//                    .Description("Checks if a certain user is streaming on the hitbox platform." +
 | 
			
		||||
//                                 $" | `{Prefix}chhb SomeStreamer`")
 | 
			
		||||
//                    .Parameter("username", ParameterType.Unparsed)
 | 
			
		||||
//                    .AddCheck(SimpleCheckers.ManageServer())
 | 
			
		||||
//                    .Do(async e =>
 | 
			
		||||
//                    {
 | 
			
		||||
//                        var stream = username?.Trim();
 | 
			
		||||
//                        if (string.IsNullOrWhiteSpace(stream))
 | 
			
		||||
//                            return;
 | 
			
		||||
//                        try
 | 
			
		||||
//                        {
 | 
			
		||||
//                            var streamStatus = (await GetStreamStatus(new StreamNotificationConfig
 | 
			
		||||
//                            {
 | 
			
		||||
//                                Username = stream,
 | 
			
		||||
//                                Type = StreamNotificationConfig.StreamType.Hitbox
 | 
			
		||||
//                            }));
 | 
			
		||||
//                            if (streamStatus.Item1)
 | 
			
		||||
//                            {
 | 
			
		||||
//                                await channel.SendMessageAsync($"`Streamer {streamStatus.Item2} is online.`");
 | 
			
		||||
//                            }
 | 
			
		||||
//                        }
 | 
			
		||||
//                        catch
 | 
			
		||||
//                        {
 | 
			
		||||
//                            await channel.SendMessageAsync("No channel found.");
 | 
			
		||||
//                        }
 | 
			
		||||
//                    });
 | 
			
		||||
                IEnumerable<FollowedStream> streams;
 | 
			
		||||
                using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
                {
 | 
			
		||||
                    streams = uow.GuildConfigs.For(channel.Guild.Id).FollowedStreams;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
//                cgb.CreateCommand(Module.Prefix + "checktwitch")
 | 
			
		||||
//                    .Alias(Module.Prefix + "chtw")
 | 
			
		||||
//                    .Description("Checks if a certain user is streaming on the twitch platform." +
 | 
			
		||||
//                                 $" | `{Prefix}chtw SomeStreamer`")
 | 
			
		||||
//                    .AddCheck(SimpleCheckers.ManageServer())
 | 
			
		||||
//                    .Parameter("username", ParameterType.Unparsed)
 | 
			
		||||
//                    .Do(async e =>
 | 
			
		||||
//                    {
 | 
			
		||||
//                        var stream = username?.Trim();
 | 
			
		||||
//                        if (string.IsNullOrWhiteSpace(stream))
 | 
			
		||||
//                            return;
 | 
			
		||||
//                        try
 | 
			
		||||
//                        {
 | 
			
		||||
//                            var streamStatus = (await GetStreamStatus(new StreamNotificationConfig
 | 
			
		||||
//                            {
 | 
			
		||||
//                                Username = stream,
 | 
			
		||||
//                                Type = StreamNotificationConfig.StreamType.Twitch
 | 
			
		||||
//                            }));
 | 
			
		||||
//                            if (streamStatus.Item1)
 | 
			
		||||
//                            {
 | 
			
		||||
//                                await channel.SendMessageAsync($"`Streamer {streamStatus.Item2} is online.`");
 | 
			
		||||
//                            }
 | 
			
		||||
//                        }
 | 
			
		||||
//                        catch
 | 
			
		||||
//                        {
 | 
			
		||||
//                            await channel.SendMessageAsync("No channel found.");
 | 
			
		||||
//                        }
 | 
			
		||||
//                    });
 | 
			
		||||
                if (!streams.Any())
 | 
			
		||||
                {
 | 
			
		||||
                    await channel.SendMessageAsync("You are not following any streams on this server.").ConfigureAwait(false);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
//                cgb.CreateCommand(Module.Prefix + "checkbeam")
 | 
			
		||||
//                    .Alias(Module.Prefix + "chbm")
 | 
			
		||||
//                    .Description("Checks if a certain user is streaming on the beam platform." +
 | 
			
		||||
//                                 $" | `{Prefix}chbm SomeStreamer`")
 | 
			
		||||
//                    .AddCheck(SimpleCheckers.ManageServer())
 | 
			
		||||
//                    .Parameter("username", ParameterType.Unparsed)
 | 
			
		||||
//                    .Do(async e =>
 | 
			
		||||
//                    {
 | 
			
		||||
//                        var stream = username?.Trim();
 | 
			
		||||
//                        if (string.IsNullOrWhiteSpace(stream))
 | 
			
		||||
//                            return;
 | 
			
		||||
//                        try
 | 
			
		||||
//                        {
 | 
			
		||||
//                            var streamStatus = (await GetStreamStatus(new StreamNotificationConfig
 | 
			
		||||
//                            {
 | 
			
		||||
//                                Username = stream,
 | 
			
		||||
//                                Type = StreamNotificationConfig.StreamType.Beam
 | 
			
		||||
//                            }));
 | 
			
		||||
//                            if (streamStatus.Item1)
 | 
			
		||||
//                            {
 | 
			
		||||
//                                await channel.SendMessageAsync($"`Streamer {streamStatus.Item2} is online.`");
 | 
			
		||||
//                            }
 | 
			
		||||
//                        }
 | 
			
		||||
//                        catch
 | 
			
		||||
//                        {
 | 
			
		||||
//                            await channel.SendMessageAsync("No channel found.");
 | 
			
		||||
//                        }
 | 
			
		||||
//                    });
 | 
			
		||||
                var text = string.Join("\n", streams.Select(snc =>
 | 
			
		||||
                {
 | 
			
		||||
                    return $"`{snc.Username}`'s stream on **{channel.Guild.GetTextChannel(snc.ChannelId)?.Name}** channel. 【`{snc.Type.ToString()}`】";
 | 
			
		||||
                }));
 | 
			
		||||
 | 
			
		||||
//                cgb.CreateCommand(Module.Prefix + "removestream")
 | 
			
		||||
//                    .Alias(Module.Prefix + "rms")
 | 
			
		||||
//                    .Description("Removes notifications of a certain streamer on this channel." +
 | 
			
		||||
//                                 $" | `{Prefix}rms SomeGuy`")
 | 
			
		||||
//                    .AddCheck(SimpleCheckers.ManageServer())
 | 
			
		||||
//                    .Parameter("username", ParameterType.Unparsed)
 | 
			
		||||
//                    .Do(async e =>
 | 
			
		||||
//                    {
 | 
			
		||||
//                        var username = username?.ToLower().Trim();
 | 
			
		||||
//                        if (string.IsNullOrWhiteSpace(username))
 | 
			
		||||
//                            return;
 | 
			
		||||
                await channel.SendMessageAsync($"You are following **{streams.Count()}** streams on this server.\n\n" + text).ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
//                        var config = SpecificConfigurations.Default.Of(e.Server.Id);
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task RemoveStream(IUserMessage msg, [Remainder] string username)
 | 
			
		||||
            {
 | 
			
		||||
                var channel = (ITextChannel)msg.Channel;
 | 
			
		||||
 | 
			
		||||
//                        var toRemove = config.ObservingStreams
 | 
			
		||||
//                            .FirstOrDefault(snc => snc.ChannelId == e.Channel.Id &&
 | 
			
		||||
//                                            snc.Username.ToLower().Trim() == username);
 | 
			
		||||
//                        if (toRemove == null)
 | 
			
		||||
//                        {
 | 
			
		||||
//                            await channel.SendMessageAsync(":anger: No such stream.").ConfigureAwait(false);
 | 
			
		||||
//                            return;
 | 
			
		||||
//                        }
 | 
			
		||||
                username = username.ToUpperInvariant().Trim();
 | 
			
		||||
 | 
			
		||||
//                        config.ObservingStreams.Remove(toRemove);
 | 
			
		||||
//                        await ConfigHandler.SaveConfig().ConfigureAwait(false);
 | 
			
		||||
//                        await channel.SendMessageAsync($":ok: Removed `{toRemovumsg.Authorname}`'s stream from notifications.").ConfigureAwait(false);
 | 
			
		||||
//                    });
 | 
			
		||||
                FollowedStream toRemove;
 | 
			
		||||
                using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
                {
 | 
			
		||||
                    var config = uow.GuildConfigs.For(channel.Guild.Id);
 | 
			
		||||
                    var streams = config.FollowedStreams;
 | 
			
		||||
                    toRemove = streams.Where(fs => fs.ChannelId == channel.Id && fs.Username.ToUpperInvariant() == username).FirstOrDefault();
 | 
			
		||||
                    if (toRemove != null)
 | 
			
		||||
                    {
 | 
			
		||||
                        config.FollowedStreams = streams.Except(new[] { toRemove }).ToList();
 | 
			
		||||
                        await uow.CompleteAsync();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                if (toRemove == null)
 | 
			
		||||
                {
 | 
			
		||||
                    await channel.SendMessageAsync(":anger: No such stream.").ConfigureAwait(false);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                await channel.SendMessageAsync($":ok: Removed `{toRemove.Username}`'s stream ({toRemove.Type}) from notifications.").ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
//                cgb.CreateCommand(Module.Prefix + "liststreams")
 | 
			
		||||
//                    .Alias(Module.Prefix + "ls")
 | 
			
		||||
//                    .Description("Lists all streams you are following on this server." +
 | 
			
		||||
//                                 $" | `{Prefix}ls`")
 | 
			
		||||
//                    .Do(async e =>
 | 
			
		||||
//                    {
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task CheckStream(IUserMessage imsg, FollowedStream.FollowedStreamType platform, [Remainder] string username)
 | 
			
		||||
            {
 | 
			
		||||
                var channel = (ITextChannel)imsg.Channel;
 | 
			
		||||
 | 
			
		||||
//                        var config = SpecificConfigurations.Default.Of(e.Server.Id);
 | 
			
		||||
                var stream = username?.Trim();
 | 
			
		||||
                if (string.IsNullOrWhiteSpace(stream))
 | 
			
		||||
                    return;
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    var streamStatus = (await GetStreamStatus(new FollowedStream
 | 
			
		||||
                    {
 | 
			
		||||
                        Username = stream,
 | 
			
		||||
                        Type = platform
 | 
			
		||||
                    }));
 | 
			
		||||
                    if (streamStatus.Item1)
 | 
			
		||||
                    {
 | 
			
		||||
                        await channel.SendMessageAsync($"`Streamer {streamStatus.Item2} is online.`");
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                catch
 | 
			
		||||
                {
 | 
			
		||||
                    await channel.SendMessageAsync("No channel found.");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
//                        var streams = config.ObservingStreams.Where(snc =>
 | 
			
		||||
//                            snc.ServerId == e.Server.Id);
 | 
			
		||||
 | 
			
		||||
//                        var streamsArray = streams as StreamNotificationConfig[] ?? streams.ToArray();
 | 
			
		||||
 | 
			
		||||
//                        if (streamsArray.Length == 0)
 | 
			
		||||
//                        {
 | 
			
		||||
//                            await channel.SendMessageAsync("You are not following any streams on this server.").ConfigureAwait(false);
 | 
			
		||||
//                            return;
 | 
			
		||||
//                        }
 | 
			
		||||
 | 
			
		||||
//                        var text = string.Join("\n", streamsArray.Select(snc =>
 | 
			
		||||
//                        {
 | 
			
		||||
//                            try
 | 
			
		||||
//                            {
 | 
			
		||||
//                                return $"`{snc.Username}`'s stream on **{e.Server.GetChannel(e.Channel.Id).Name}** channel. 【`{snc.Type.ToString()}`】";
 | 
			
		||||
//                            }
 | 
			
		||||
//                            catch { }
 | 
			
		||||
//                            return "";
 | 
			
		||||
//                        }));
 | 
			
		||||
 | 
			
		||||
//                        await channel.SendMessageAsync($"You are following **{streamsArray.Length}** streams on this server.\n\n" + text).ConfigureAwait(false);
 | 
			
		||||
//                    });
 | 
			
		||||
//            }
 | 
			
		||||
 | 
			
		||||
//            private Func<CommandEventArgs, Task> TrackStream(StreamNotificationConfig.StreamType type) =>
 | 
			
		||||
//                async e =>
 | 
			
		||||
//                {
 | 
			
		||||
//                    var username = username?.ToLowerInvariant();
 | 
			
		||||
//                    if (string.IsNullOrWhiteSpace(username))
 | 
			
		||||
//                        return;
 | 
			
		||||
 | 
			
		||||
//                    var config = SpecificConfigurations.Default.Of(e.Server.Id);
 | 
			
		||||
 | 
			
		||||
//                    var stream = new StreamNotificationConfig
 | 
			
		||||
//                    {
 | 
			
		||||
//                        ServerId = e.Server.Id,
 | 
			
		||||
//                        ChannelId = e.Channel.Id,
 | 
			
		||||
//                        Username = username,
 | 
			
		||||
//                        Type = type,
 | 
			
		||||
//                    };
 | 
			
		||||
//                    var exists = config.ObservingStreams.Contains(stream);
 | 
			
		||||
//                    if (exists)
 | 
			
		||||
//                    {
 | 
			
		||||
//                        await channel.SendMessageAsync(":anger: I am already notifying that stream on this channel.").ConfigureAwait(false);
 | 
			
		||||
//                        return;
 | 
			
		||||
//                    }
 | 
			
		||||
//                    Tuple<bool, string> data;
 | 
			
		||||
//                    try
 | 
			
		||||
//                    {
 | 
			
		||||
//                        data = await GetStreamStatus(stream).ConfigureAwait(false);
 | 
			
		||||
//                    }
 | 
			
		||||
//                    catch
 | 
			
		||||
//                    {
 | 
			
		||||
//                        await channel.SendMessageAsync(":anger: Stream probably doesn't exist.").ConfigureAwait(false);
 | 
			
		||||
//                        return;
 | 
			
		||||
//                    }
 | 
			
		||||
//                    var msg = $"Stream is currently **{(data.Item1 ? "ONLINE" : "OFFLINE")}** with **{data.Item2}** viewers";
 | 
			
		||||
//                    if (data.Item1)
 | 
			
		||||
//                        if (type == StreamNotificationConfig.StreamType.Hitbox)
 | 
			
		||||
//                            msg += $"\n`Here is the Link:`【 http://www.hitbox.tv/{stream.Username}/ 】";
 | 
			
		||||
//                        else if (type == StreamNotificationConfig.StreamType.Twitch)
 | 
			
		||||
//                            msg += $"\n`Here is the Link:`【 http://www.twitch.tv/{stream.Username}/ 】";
 | 
			
		||||
//                        else if (type == StreamNotificationConfig.StreamType.Beam)
 | 
			
		||||
//                            msg += $"\n`Here is the Link:`【 https://beam.pro/{stream.Username}/ 】";
 | 
			
		||||
//                        else if (type == StreamNotificationConfig.StreamType.YoutubeGaming)
 | 
			
		||||
//                            msg += $"\n`Here is the Link:` not implemented yet - {stream.Username}";
 | 
			
		||||
//                    stream.LastStatus = data.Item1;
 | 
			
		||||
//                    if (!exists)
 | 
			
		||||
//                        msg = $":ok: I will notify this channel when status changes.\n{msg}";
 | 
			
		||||
//                    await channel.SendMessageAsync(msg).ConfigureAwait(false);
 | 
			
		||||
//                    config.ObservingStreams.Add(stream);
 | 
			
		||||
//                };
 | 
			
		||||
//        }
 | 
			
		||||
//    }
 | 
			
		||||
//}
 | 
			
		||||
            private async Task TrackStream(ITextChannel channel, string username, FollowedStream.FollowedStreamType type)
 | 
			
		||||
            {
 | 
			
		||||
                username = username.ToUpperInvariant().Trim();
 | 
			
		||||
                var stream = new FollowedStream
 | 
			
		||||
                {
 | 
			
		||||
                    GuildId = channel.Guild.Id,
 | 
			
		||||
                    ChannelId = channel.Id,
 | 
			
		||||
                    Username = username,
 | 
			
		||||
                    Type = type,
 | 
			
		||||
                };
 | 
			
		||||
                bool exists;
 | 
			
		||||
                using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
                {
 | 
			
		||||
                    exists = uow.GuildConfigs.For(channel.Guild.Id).FollowedStreams.Where(fs => fs.ChannelId == channel.Id && fs.Username.ToUpperInvariant().Trim()  == username).Any();
 | 
			
		||||
                }
 | 
			
		||||
                if (exists)
 | 
			
		||||
                {
 | 
			
		||||
                    await channel.SendMessageAsync($":anger: I am already following `{username}` ({type}) stream on this channel.").ConfigureAwait(false);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                Tuple<bool, string> data;
 | 
			
		||||
                try
 | 
			
		||||
                {
 | 
			
		||||
                    data = await GetStreamStatus(stream).ConfigureAwait(false);
 | 
			
		||||
                }
 | 
			
		||||
                catch
 | 
			
		||||
                {
 | 
			
		||||
                    await channel.SendMessageAsync(":anger: Stream probably doesn't exist.").ConfigureAwait(false);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                var msg = $"Stream is currently **{(data.Item1 ? "ONLINE" : "OFFLINE")}** with **{data.Item2}** viewers";
 | 
			
		||||
                if (data.Item1)
 | 
			
		||||
                    if (type == FollowedStream.FollowedStreamType.Hitbox)
 | 
			
		||||
                        msg += $"\n`Here is the Link:`【 http://www.hitbox.tv/{stream.Username}/ 】";
 | 
			
		||||
                    else if (type == FollowedStream.FollowedStreamType.Twitch)
 | 
			
		||||
                        msg += $"\n`Here is the Link:`【 http://www.twitch.tv/{stream.Username}/ 】";
 | 
			
		||||
                    else if (type == FollowedStream.FollowedStreamType.Beam)
 | 
			
		||||
                        msg += $"\n`Here is the Link:`【 https://beam.pro/{stream.Username}/ 】";
 | 
			
		||||
                //else if (type == FollowedStream.FollowedStreamType.YoutubeGaming)
 | 
			
		||||
                //    msg += $"\n`Here is the Link:` not implemented yet - {stream.Username}";
 | 
			
		||||
                stream.LastStatus = data.Item1;
 | 
			
		||||
                using (var uow = DbHandler.UnitOfWork())
 | 
			
		||||
                {
 | 
			
		||||
                    uow.GuildConfigs.For(channel.Guild.Id).FollowedStreams.Add(stream);
 | 
			
		||||
                    await uow.CompleteAsync();
 | 
			
		||||
                }
 | 
			
		||||
                msg = $":ok: I will notify this channel when status changes.\n{msg}";
 | 
			
		||||
                await channel.SendMessageAsync(msg).ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -26,7 +26,7 @@ namespace NadekoBot.Modules.Searches
 | 
			
		||||
            _google = youtube;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Weather(IUserMessage umsg, string city, string country)
 | 
			
		||||
        {
 | 
			
		||||
@@ -47,7 +47,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
 | 
			
		||||
🌄 **Sunrise:** {obj["sunrise"]} 🌇 **Sunset:** {obj["sunset"]}").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Youtube(IUserMessage umsg, [Remainder] string query = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -62,7 +62,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
 | 
			
		||||
            await channel.SendMessageAsync(result).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Imdb(IUserMessage umsg, [Remainder] string query = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -86,7 +86,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
 | 
			
		||||
            await channel.SendMessageAsync(result.ToString()).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task RandomCat(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
@@ -99,7 +99,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task RandomDog(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
@@ -110,7 +110,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task I(IUserMessage umsg, [Remainder] string query = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -140,7 +140,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Ir(IUserMessage umsg, [Remainder] string query = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -172,7 +172,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Lmgtfy(IUserMessage umsg, [Remainder] string ffs = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -186,7 +186,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
 | 
			
		||||
                           .ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Google(IUserMessage umsg, [Remainder] string terms = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -200,7 +200,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
 | 
			
		||||
                           .ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
        ////todo drawing
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task Hearthstone(IUserMessage umsg, [Remainder] string name = null)
 | 
			
		||||
        //{
 | 
			
		||||
@@ -245,7 +245,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
 | 
			
		||||
        //    }
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Ud(IUserMessage umsg, [Remainder] string query = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -279,7 +279,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Hashtag(IUserMessage umsg, [Remainder] string query = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -314,7 +314,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Catfact(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
@@ -328,7 +328,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Revav(IUserMessage umsg, [Remainder] string arg = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -345,7 +345,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
 | 
			
		||||
            await channel.SendMessageAsync($"https://images.google.com/searchbyimage?image_url={usr.AvatarUrl}").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Revimg(IUserMessage umsg, [Remainder] string imageLink = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -357,7 +357,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
 | 
			
		||||
            await channel.SendMessageAsync($"https://images.google.com/searchbyimage?image_url={imageLink}").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Safebooru(IUserMessage umsg, [Remainder] string tag = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -371,7 +371,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
 | 
			
		||||
                await channel.SendMessageAsync(link).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Wiki(IUserMessage umsg, [Remainder] string query = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -392,7 +392,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ////todo drawing
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        //[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task Clr(IUserMessage umsg, [Remainder] string color = null)
 | 
			
		||||
        //{
 | 
			
		||||
@@ -417,7 +417,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
 | 
			
		||||
        //    await channel.SendFileAsync("arg1.png", img.ToStream());
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Videocall(IUserMessage umsg, [Remainder] string arg = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -440,7 +440,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Avatar(IUserMessage umsg, [Remainder] string mention = null)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@ namespace NadekoBot.Modules.Translator
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Translate(IUserMessage umsg, string langs, [Remainder] string text = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -44,7 +44,7 @@ namespace NadekoBot.Modules.Translator
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Translangs(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
////todo rewrite
 | 
			
		||||
//namespace NadekoBot.Modules.Trello
 | 
			
		||||
//{
 | 
			
		||||
//    internal class Trello : DiscordModule
 | 
			
		||||
//    public class Trello : DiscordModule
 | 
			
		||||
//    {
 | 
			
		||||
//        private readonly Timer t = new Timer { Interval = 2000 };
 | 
			
		||||
//        public override string Prefix { get; } = NadekoBot.Config.CommandPrefixes.Trello;
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@ namespace NadekoBot.Modules.Utility
 | 
			
		||||
{
 | 
			
		||||
    partial class Utility : DiscordModule
 | 
			
		||||
    {
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task ServerInfo(IUserMessage msg, string guild = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -47,7 +47,7 @@ namespace NadekoBot.Modules.Utility
 | 
			
		||||
            await msg.Reply(sb.ToString()).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task ChannelInfo(IUserMessage msg, ITextChannel channel = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -63,7 +63,7 @@ namespace NadekoBot.Modules.Utility
 | 
			
		||||
            await msg.Reply(toReturn).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task UserInfo(IUserMessage msg, IGuildUser usr = null)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@ namespace NadekoBot.Modules.Utility
 | 
			
		||||
{
 | 
			
		||||
    public partial class Utility
 | 
			
		||||
    {
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task ShowQuote(IUserMessage umsg, string keyword)
 | 
			
		||||
        {
 | 
			
		||||
@@ -37,7 +37,7 @@ namespace NadekoBot.Modules.Utility
 | 
			
		||||
            await channel.SendMessageAsync("📣 " + quote.Text);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task AddQuote(IUserMessage umsg, string keyword, [Remainder] string text)
 | 
			
		||||
        {
 | 
			
		||||
@@ -63,7 +63,7 @@ namespace NadekoBot.Modules.Utility
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task DeleteQuote(IUserMessage umsg, string keyword)
 | 
			
		||||
        {
 | 
			
		||||
@@ -90,7 +90,7 @@ namespace NadekoBot.Modules.Utility
 | 
			
		||||
            await channel.SendMessageAsync("`Deleted a random quote.`");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task DelAllQuotes(IUserMessage umsg, string keyword)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -92,7 +92,7 @@ namespace NadekoBot.Modules.Utility
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            [RequireContext(ContextType.Guild)]
 | 
			
		||||
            public async Task Remind(IUserMessage umsg, string meorchannel, string timeStr, [Remainder] string message)
 | 
			
		||||
            {
 | 
			
		||||
@@ -185,7 +185,7 @@ namespace NadekoBot.Modules.Utility
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            ////todo owner only
 | 
			
		||||
            //[LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
            //[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
            //[RequireContext(ContextType.Guild)]
 | 
			
		||||
            //public async Task RemindTemplate(IUserMessage umsg, [Remainder] string arg)
 | 
			
		||||
            //{
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@ namespace NadekoBot.Modules.Utility
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task WhosPlaying(IUserMessage umsg, [Remainder] string game = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -43,7 +43,7 @@ namespace NadekoBot.Modules.Utility
 | 
			
		||||
                await channel.SendMessageAsync("```xl\n" + string.Join("\n", arr.GroupBy(item => (i++) / 3).Select(ig => string.Concat(ig.Select(el => $"• {el,-35}")))) + "\n```").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task InRole(IUserMessage umsg, [Remainder] string roles = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -76,7 +76,7 @@ namespace NadekoBot.Modules.Utility
 | 
			
		||||
            await channel.SendMessageAsync(send).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task CheckMyPerms(IUserMessage msg)
 | 
			
		||||
        {
 | 
			
		||||
@@ -93,7 +93,7 @@ namespace NadekoBot.Modules.Utility
 | 
			
		||||
            await msg.Reply(builder.ToString());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task UserId(IUserMessage msg, IGuildUser target = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -101,20 +101,20 @@ namespace NadekoBot.Modules.Utility
 | 
			
		||||
            await msg.Reply($"Id of the user { usr.Username } is { usr.Id })").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        public async Task ChannelId(IUserMessage msg)
 | 
			
		||||
        {
 | 
			
		||||
            await msg.Reply($"This Channel's ID is {msg.Channel.Id}").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task ServerId(IUserMessage msg)
 | 
			
		||||
        {
 | 
			
		||||
            await msg.Reply($"This server's ID is {(msg.Channel as ITextChannel).Guild.Id}").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Roles(IUserMessage msg, IGuildUser target = null)
 | 
			
		||||
        {
 | 
			
		||||
@@ -129,7 +129,7 @@ namespace NadekoBot.Modules.Utility
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task ChannelTopic(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
@@ -142,7 +142,7 @@ namespace NadekoBot.Modules.Utility
 | 
			
		||||
                await channel.SendMessageAsync("`Topic:` " + topic);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary]
 | 
			
		||||
        [LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Stats(IUserMessage umsg)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										424
									
								
								src/NadekoBot/Resources/CommandStrings.Designer.cs
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										424
									
								
								src/NadekoBot/Resources/CommandStrings.Designer.cs
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -28,7 +28,7 @@ namespace NadekoBot.Resources {
 | 
			
		||||
        
 | 
			
		||||
        private static global::System.Globalization.CultureInfo resourceCulture;
 | 
			
		||||
        
 | 
			
		||||
        internal ResponseStrings() {
 | 
			
		||||
        public ResponseStrings() {
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        /// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,7 @@ namespace NadekoBot.Services.Database.Models
 | 
			
		||||
        public ulong ChannelId { get; set; }
 | 
			
		||||
 | 
			
		||||
        [NotMapped]
 | 
			
		||||
        public ITextChannel Channel { get; internal set; }
 | 
			
		||||
        public ITextChannel Channel { get; set; }
 | 
			
		||||
 | 
			
		||||
        public List<ClashCaller> Bases { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										22
									
								
								src/NadekoBot/Services/Database/Models/FollowedStream.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/NadekoBot/Services/Database/Models/FollowedStream.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Services.Database.Models
 | 
			
		||||
{
 | 
			
		||||
    public class FollowedStream : DbEntity
 | 
			
		||||
    {
 | 
			
		||||
        public ulong ChannelId { get; set; }
 | 
			
		||||
        public string Username { get; set; }
 | 
			
		||||
        public FollowedStreamType Type { get; set; }
 | 
			
		||||
        public bool LastStatus { get; set; }
 | 
			
		||||
        public ulong GuildId { get; set; }
 | 
			
		||||
 | 
			
		||||
        public enum FollowedStreamType
 | 
			
		||||
        {
 | 
			
		||||
            Twitch, Hitbox, Beam
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -31,6 +31,11 @@ namespace NadekoBot.Services.Database.Models
 | 
			
		||||
        //self assignable roles
 | 
			
		||||
        public bool ExclusiveSelfAssignedRoles { get; set; }
 | 
			
		||||
        public bool AutoDeleteSelfAssignedRoleMessages { get; set; }
 | 
			
		||||
        public float DefaultMusicVolume { get; set; }
 | 
			
		||||
        public float DefaultMusicVolume { get; set; } = 1.0f;
 | 
			
		||||
        public bool VoicePlusTextEnabled { get; set; }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        //stream notifications
 | 
			
		||||
        public List<FollowedStream> FollowedStreams { get; set; } = new List<FollowedStream>();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								src/NadekoBot/Services/Database/Models/TypingArticle.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/NadekoBot/Services/Database/Models/TypingArticle.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Services.Database.Models
 | 
			
		||||
{
 | 
			
		||||
    public class TypingArticle : DbEntity
 | 
			
		||||
    {
 | 
			
		||||
        public string Author { get; set; }
 | 
			
		||||
        public string Text { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -21,6 +21,7 @@ namespace NadekoBot.Services.Database
 | 
			
		||||
        public DbSet<Repeater> Repeaters { get; set; }
 | 
			
		||||
        public DbSet<Currency> Currency { get; set; }
 | 
			
		||||
        public DbSet<ConvertUnit> ConversionUnits { get; set; }
 | 
			
		||||
        public DbSet<TypingArticle> TypingArticles { get; set; }
 | 
			
		||||
 | 
			
		||||
        protected override void OnModelCreating(ModelBuilder modelBuilder)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -11,5 +11,6 @@ namespace NadekoBot.Services.Database.Repositories
 | 
			
		||||
    public interface IGuildConfigRepository : IRepository<GuildConfig>
 | 
			
		||||
    {
 | 
			
		||||
        GuildConfig For(ulong guildId);
 | 
			
		||||
        IEnumerable<FollowedStream> GetAllFollowedStreams();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,14 @@
 | 
			
		||||
using NadekoBot.Services.Database.Models;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Services.Database.Repositories
 | 
			
		||||
{
 | 
			
		||||
    public interface ITypingArticlesRepository : IRepository <TypingArticle>
 | 
			
		||||
    {
 | 
			
		||||
        TypingArticle GetRandom();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -20,7 +20,8 @@ namespace NadekoBot.Services.Database.Repositories.Impl
 | 
			
		||||
        /// <returns></returns>
 | 
			
		||||
        public GuildConfig For(ulong guildId)
 | 
			
		||||
        {
 | 
			
		||||
            var config = _set.FirstOrDefault(c => c.GuildId == guildId);
 | 
			
		||||
            var config = _set.Include(gc=>gc.FollowedStreams)
 | 
			
		||||
                             .FirstOrDefault(c => c.GuildId == guildId);
 | 
			
		||||
 | 
			
		||||
            if (config == null)
 | 
			
		||||
            {
 | 
			
		||||
@@ -32,5 +33,10 @@ namespace NadekoBot.Services.Database.Repositories.Impl
 | 
			
		||||
            }
 | 
			
		||||
            return config;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public IEnumerable<FollowedStream> GetAllFollowedStreams() =>
 | 
			
		||||
            _set.Include(gc => gc.FollowedStreams)
 | 
			
		||||
                .SelectMany(gc => gc.FollowedStreams)
 | 
			
		||||
                .ToList();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,25 @@
 | 
			
		||||
using NadekoBot.Services.Database.Models;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using Microsoft.EntityFrameworkCore;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Services.Database.Repositories.Impl
 | 
			
		||||
{
 | 
			
		||||
    public class TypingArticlesRepository : Repository<TypingArticle>, ITypingArticlesRepository
 | 
			
		||||
    {
 | 
			
		||||
        private Random _rand = null;
 | 
			
		||||
        private Random rand => _rand ?? (_rand = new Random());
 | 
			
		||||
        public TypingArticlesRepository(DbContext context) : base(context)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public TypingArticle GetRandom()
 | 
			
		||||
        {
 | 
			
		||||
            var skip = (int)(rand.NextDouble() * _set.Count());
 | 
			
		||||
            return _set.Skip(skip).FirstOrDefault();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -41,6 +41,9 @@ namespace NadekoBot.Services.Database
 | 
			
		||||
        private IUnitConverterRepository _conUnits;
 | 
			
		||||
        public IUnitConverterRepository ConverterUnits => _conUnits ?? (_conUnits = new UnitConverterRepository(_context));
 | 
			
		||||
 | 
			
		||||
        private ITypingArticlesRepository _typingArticles;
 | 
			
		||||
        public ITypingArticlesRepository TypingArticles => _typingArticles ?? (_typingArticles = new TypingArticlesRepository(_context));
 | 
			
		||||
 | 
			
		||||
        public UnitOfWork(NadekoContext context)
 | 
			
		||||
        {
 | 
			
		||||
            _context = context;
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@ using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Classes
 | 
			
		||||
{
 | 
			
		||||
    internal class SpecificConfigurations
 | 
			
		||||
    public class SpecificConfigurations
 | 
			
		||||
    {
 | 
			
		||||
        public static SpecificConfigurations Default { get; } = new SpecificConfigurations();
 | 
			
		||||
        public static bool Instantiated { get; private set; }
 | 
			
		||||
@@ -73,7 +73,7 @@ namespace NadekoBot.Classes
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    internal class ServerSpecificConfig : INotifyPropertyChanged
 | 
			
		||||
    public class ServerSpecificConfig : INotifyPropertyChanged
 | 
			
		||||
    {
 | 
			
		||||
        [JsonProperty("VoicePlusTextEnabled")]
 | 
			
		||||
        private bool voicePlusTextEnabled;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,20 +0,0 @@
 | 
			
		||||
using Newtonsoft.Json;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.DataModels
 | 
			
		||||
{
 | 
			
		||||
    internal class Announcement : IDataModel
 | 
			
		||||
    {
 | 
			
		||||
        public long ServerId { get; set; } = 0;
 | 
			
		||||
        public bool Greet { get; set; } = false;
 | 
			
		||||
        public bool GreetPM { get; set; } = false;
 | 
			
		||||
        [JsonProperty("greetChannel")]
 | 
			
		||||
        public long GreetChannelId { get; set; } = 0;
 | 
			
		||||
        public string GreetText { get; set; } = "Welcome %user%!";
 | 
			
		||||
        public bool Bye { get; set; } = false;
 | 
			
		||||
        public bool ByePM { get; set; } = false;
 | 
			
		||||
        [JsonProperty("byeChannel")]
 | 
			
		||||
        public long ByeChannelId { get; set; } = 0;
 | 
			
		||||
        public string ByeText { get; set; } = "%user% has left the server.";
 | 
			
		||||
        public bool DeleteGreetMessages { get; set; } = true;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,11 +0,0 @@
 | 
			
		||||
namespace NadekoBot.DataModels {
 | 
			
		||||
    internal class Command : IDataModel {
 | 
			
		||||
        public long UserId { get; set; }
 | 
			
		||||
        public string UserName { get; set; }
 | 
			
		||||
        public long ServerId { get; set; }
 | 
			
		||||
        public string ServerName { get; set; }
 | 
			
		||||
        public long ChannelId { get; set; }
 | 
			
		||||
        public string ChannelName { get; set; }
 | 
			
		||||
        public string CommandName { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,7 +0,0 @@
 | 
			
		||||
namespace NadekoBot.DataModels {
 | 
			
		||||
    internal class CurrencyState : IDataModel {
 | 
			
		||||
        public long Value { get; set; }
 | 
			
		||||
        [SQLite.Unique]
 | 
			
		||||
        public long UserId { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,7 +0,0 @@
 | 
			
		||||
namespace NadekoBot.DataModels {
 | 
			
		||||
    internal class CurrencyTransaction : IDataModel {
 | 
			
		||||
        public string Reason { get; set; }
 | 
			
		||||
        public int Value { get; set; }
 | 
			
		||||
        public long UserId { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,7 +0,0 @@
 | 
			
		||||
namespace NadekoBot.DataModels {
 | 
			
		||||
    internal class Donator : IDataModel {
 | 
			
		||||
        public long UserId { get; set; }
 | 
			
		||||
        public string UserName { get; set; }
 | 
			
		||||
        public int Amount { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,14 +0,0 @@
 | 
			
		||||
using SQLite;
 | 
			
		||||
using System;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.DataModels
 | 
			
		||||
{
 | 
			
		||||
    internal abstract class IDataModel
 | 
			
		||||
    {
 | 
			
		||||
        [PrimaryKey, AutoIncrement]
 | 
			
		||||
        public int? Id { get; set; }
 | 
			
		||||
        [Newtonsoft.Json.JsonProperty("createdAt")]
 | 
			
		||||
        public DateTime DateAdded { get; set; } = DateTime.Now;
 | 
			
		||||
        public IDataModel() { }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,10 +0,0 @@
 | 
			
		||||
namespace NadekoBot.DataModels
 | 
			
		||||
{
 | 
			
		||||
    class Incident : IDataModel
 | 
			
		||||
    {
 | 
			
		||||
        public long ServerId { get; set; }
 | 
			
		||||
        public long ChannelId { get; set; }
 | 
			
		||||
        public string Text { get; set; }
 | 
			
		||||
        public bool Read { get; set; } = false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +0,0 @@
 | 
			
		||||
namespace NadekoBot.DataModels
 | 
			
		||||
{
 | 
			
		||||
    internal class MusicPlaylist : IDataModel
 | 
			
		||||
    {
 | 
			
		||||
        public string Name { get; set; }
 | 
			
		||||
        public long CreatorId { get; set; }
 | 
			
		||||
        public string CreatorName { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,8 +0,0 @@
 | 
			
		||||
namespace NadekoBot.DataModels
 | 
			
		||||
{
 | 
			
		||||
    internal class PlaylistSongInfo : IDataModel
 | 
			
		||||
    {
 | 
			
		||||
        public int PlaylistId { get; set; }
 | 
			
		||||
        public int SongInfoId { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,14 +0,0 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.DataModels
 | 
			
		||||
{
 | 
			
		||||
    class UserPokeTypes : IDataModel
 | 
			
		||||
    {
 | 
			
		||||
        public long UserId { get; set; }
 | 
			
		||||
        public string type { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,10 +0,0 @@
 | 
			
		||||
namespace NadekoBot.DataModels {
 | 
			
		||||
    internal class Request : IDataModel {
 | 
			
		||||
        public string UserName { get; set; }
 | 
			
		||||
        public long UserId { get; set; }
 | 
			
		||||
        public string ServerName { get; set; }
 | 
			
		||||
        public long ServerId { get; set; }
 | 
			
		||||
        [Newtonsoft.Json.JsonProperty("Request")]
 | 
			
		||||
        public string RequestText { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,14 +0,0 @@
 | 
			
		||||
using SQLite;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.DataModels
 | 
			
		||||
{
 | 
			
		||||
    internal class SongInfo : IDataModel
 | 
			
		||||
    {
 | 
			
		||||
        public string Provider { get; internal set; }
 | 
			
		||||
        public int ProviderType { get; internal set; }
 | 
			
		||||
        public string Title { get; internal set; }
 | 
			
		||||
        public string Uri { get; internal set; }
 | 
			
		||||
        [Unique]
 | 
			
		||||
        public string Query { get; internal set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,10 +0,0 @@
 | 
			
		||||
using System;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.DataModels {
 | 
			
		||||
    internal class Stats : IDataModel {
 | 
			
		||||
        public int ConnectedServers { get; set; }
 | 
			
		||||
        public int OnlineUsers { get; set; }
 | 
			
		||||
        public TimeSpan Uptime { get; set; }
 | 
			
		||||
        public int RealOnlineUsers { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,8 +0,0 @@
 | 
			
		||||
namespace NadekoBot.DataModels
 | 
			
		||||
{
 | 
			
		||||
    internal class TestDataModel : IDataModel
 | 
			
		||||
    {
 | 
			
		||||
        public long TestNumber { get; set; }
 | 
			
		||||
        public string TestString { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,5 +0,0 @@
 | 
			
		||||
namespace NadekoBot.DataModels {
 | 
			
		||||
    internal class TypingArticle : IDataModel {
 | 
			
		||||
        public string Text { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,7 +0,0 @@
 | 
			
		||||
namespace NadekoBot.DataModels {
 | 
			
		||||
    internal class UserQuote : IDataModel {
 | 
			
		||||
        public string UserName { get; set; }
 | 
			
		||||
        public string Keyword { get; set; }
 | 
			
		||||
        public string Text { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,246 +0,0 @@
 | 
			
		||||
using Discord;
 | 
			
		||||
using NadekoBot.Extensions;
 | 
			
		||||
using Newtonsoft.Json;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Runtime.Serialization;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Classes.JSONModels
 | 
			
		||||
{
 | 
			
		||||
    public class Configuration
 | 
			
		||||
    {
 | 
			
		||||
        [JsonIgnore]
 | 
			
		||||
        public static readonly Dictionary<string, List<string>> DefaultCustomReactions = new Dictionary<string, List<string>>
 | 
			
		||||
        {
 | 
			
		||||
            {@"\o\", new List<string>()
 | 
			
		||||
            { "/o/" } },
 | 
			
		||||
            {"/o/", new List<string>()
 | 
			
		||||
            { @"\o\" } },
 | 
			
		||||
            {"moveto", new List<string>() {
 | 
			
		||||
                @"(👉 ͡° ͜ʖ ͡°)👉 %target%" } },
 | 
			
		||||
            {"comeatmebro", new List<string>() {
 | 
			
		||||
                "%target% (ง’̀-‘́)ง" } },
 | 
			
		||||
            {"e", new List<string>() {
 | 
			
		||||
                "%user% did it 😒 🔫",
 | 
			
		||||
                "%target% did it 😒 🔫" } },
 | 
			
		||||
            {"%mention% insult", new List<string>() {
 | 
			
		||||
                "%target% You are a poop.",
 | 
			
		||||
                "%target% You're a jerk.",
 | 
			
		||||
                "%target% I will eat you when I get my powers back."
 | 
			
		||||
                 } },
 | 
			
		||||
            {"%mention% praise", new List<string>()
 | 
			
		||||
            {
 | 
			
		||||
                "%target% You are cool.",
 | 
			
		||||
                "%target% You are nice!",
 | 
			
		||||
                "%target% You did a good job.",
 | 
			
		||||
                "%target% You did something nice.",
 | 
			
		||||
                "%target% is awesome!",
 | 
			
		||||
                "%target% Wow."
 | 
			
		||||
            } },
 | 
			
		||||
            {"%mention% pat", new List<string>() {
 | 
			
		||||
                "http://i.imgur.com/IiQwK12.gif",
 | 
			
		||||
                "http://i.imgur.com/JCXj8yD.gif",
 | 
			
		||||
                "http://i.imgur.com/qqBl2bm.gif",
 | 
			
		||||
                "http://i.imgur.com/eOJlnwP.gif",
 | 
			
		||||
                "https://45.media.tumblr.com/229ec0458891c4dcd847545c81e760a5/tumblr_mpfy232F4j1rxrpjzo1_r2_500.gif",
 | 
			
		||||
                "https://media.giphy.com/media/KZQlfylo73AMU/giphy.gif",
 | 
			
		||||
                "https://media.giphy.com/media/12hvLuZ7uzvCvK/giphy.gif",
 | 
			
		||||
                "http://gallery1.anivide.com/_full/65030_1382582341.gif",
 | 
			
		||||
                "https://49.media.tumblr.com/8e8a099c4eba22abd3ec0f70fd087cce/tumblr_nxovj9oY861ur1mffo1_500.gif ",
 | 
			
		||||
            } },
 | 
			
		||||
            {"%mention% cry", new List<string>()
 | 
			
		||||
            {
 | 
			
		||||
                "http://i.imgur.com/Xg3i1Qy.gif",
 | 
			
		||||
                "http://i.imgur.com/3K8DRrU.gif",
 | 
			
		||||
                "http://i.imgur.com/k58BcAv.gif",
 | 
			
		||||
                "http://i.imgur.com/I2fLXwo.gif"
 | 
			
		||||
            } },
 | 
			
		||||
            {"%mention% are you real?", new List<string>()
 | 
			
		||||
            {
 | 
			
		||||
                "%user%, I will be soon."
 | 
			
		||||
            } },
 | 
			
		||||
            {"%mention% are you there?", new List<string>()
 | 
			
		||||
            {
 | 
			
		||||
                "Yes. :)"
 | 
			
		||||
            } },
 | 
			
		||||
            {"%mention% draw", new List<string>() {
 | 
			
		||||
                "Sorry, I don't gamble, type $draw for that function."
 | 
			
		||||
            } },
 | 
			
		||||
            {"%mention% bb", new List<string>()
 | 
			
		||||
            {
 | 
			
		||||
                "Bye %target%"
 | 
			
		||||
            } },
 | 
			
		||||
            {"%mention% call", new List<string>() {
 | 
			
		||||
                "Calling %target%"
 | 
			
		||||
            } },
 | 
			
		||||
            {"%mention% disguise", new List<string>() {
 | 
			
		||||
                "https://cdn.discordapp.com/attachments/140007341880901632/156721710458994690/Cc5mixjUYAADgBs.jpg",
 | 
			
		||||
                "https://cdn.discordapp.com/attachments/140007341880901632/156721715831898113/hqdefault.jpg",
 | 
			
		||||
                "https://cdn.discordapp.com/attachments/140007341880901632/156721724430352385/okawari_01_haruka_weird_mask.jpg",
 | 
			
		||||
                "https://cdn.discordapp.com/attachments/140007341880901632/156721728763068417/mustache-best-girl.png"
 | 
			
		||||
 | 
			
		||||
            } },
 | 
			
		||||
            {"%mention% inv", new List<string>() {
 | 
			
		||||
                "To invite your bot, click on this link -> <https://discordapp.com/oauth2/authorize?client_id=%target%&scope=bot&permissions=66186303>"
 | 
			
		||||
            } },
 | 
			
		||||
            { "%mention% threaten", new List<string>() {
 | 
			
		||||
                "You wanna die, %target%?"
 | 
			
		||||
            } },
 | 
			
		||||
            { "%mention% archer", new List<string>() {
 | 
			
		||||
                "http://i.imgur.com/Bha9NhL.jpg"
 | 
			
		||||
            } }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        public bool DontJoinServers { get; set; } = false;
 | 
			
		||||
        public bool ForwardMessages { get; set; } = true;
 | 
			
		||||
        public bool ForwardToAllOwners { get; set; } = false;
 | 
			
		||||
        public bool IsRotatingStatus { get; set; } = false;
 | 
			
		||||
        public int BufferSize { get; set; } = 4.MiB();
 | 
			
		||||
 | 
			
		||||
        public string[] RaceAnimals { get; internal set; } = {
 | 
			
		||||
                "🐼",
 | 
			
		||||
                "🐻",
 | 
			
		||||
                "🐧",
 | 
			
		||||
                "🐨",
 | 
			
		||||
                "🐬",
 | 
			
		||||
                "🐞",
 | 
			
		||||
                "🦀",
 | 
			
		||||
                "🦄" };
 | 
			
		||||
 | 
			
		||||
        [JsonIgnore]
 | 
			
		||||
        public List<Quote> Quotes { get; set; } = new List<Quote>();
 | 
			
		||||
 | 
			
		||||
        [JsonIgnore]
 | 
			
		||||
        public List<PokemonType> PokemonTypes { get; set; } = new List<PokemonType>();
 | 
			
		||||
 | 
			
		||||
        public string RemindMessageFormat { get; set; } = "❗⏰**I've been told to remind you to '%message%' now by %user%.**⏰❗";
 | 
			
		||||
 | 
			
		||||
        [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
 | 
			
		||||
        public Dictionary<string, List<string>> CustomReactions { get; set; }
 | 
			
		||||
 | 
			
		||||
        public List<string> RotatingStatuses { get; set; } = new List<string>();
 | 
			
		||||
        public CommandPrefixesModel CommandPrefixes { get; set; } = new CommandPrefixesModel();
 | 
			
		||||
        public HashSet<ulong> ServerBlacklist { get; set; } = new HashSet<ulong>();
 | 
			
		||||
        public HashSet<ulong> ChannelBlacklist { get; set; } = new HashSet<ulong>();
 | 
			
		||||
 | 
			
		||||
        public HashSet<ulong> UserBlacklist { get; set; } = new HashSet<ulong>() {
 | 
			
		||||
            105309315895693312,
 | 
			
		||||
            119174277298782216,
 | 
			
		||||
            143515953525817344
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        [OnDeserialized]
 | 
			
		||||
        internal void OnDeserialized(StreamingContext context)
 | 
			
		||||
        {
 | 
			
		||||
            if (CustomReactions == null)
 | 
			
		||||
            {
 | 
			
		||||
                CustomReactions = DefaultCustomReactions;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        [OnSerializing]
 | 
			
		||||
        internal void OnSerializing(StreamingContext context)
 | 
			
		||||
        {
 | 
			
		||||
            if (CustomReactions == null)
 | 
			
		||||
            {
 | 
			
		||||
                CustomReactions = DefaultCustomReactions;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string[] _8BallResponses { get; set; } =
 | 
			
		||||
            {
 | 
			
		||||
                "Most definitely yes",
 | 
			
		||||
                "For sure",
 | 
			
		||||
                "As I see it, yes",
 | 
			
		||||
                "My sources say yes",
 | 
			
		||||
                "Yes",
 | 
			
		||||
                "Most likely",
 | 
			
		||||
                "Perhaps",
 | 
			
		||||
                "Maybe",
 | 
			
		||||
                "Not sure",
 | 
			
		||||
                "It is uncertain",
 | 
			
		||||
                "Ask me again later",
 | 
			
		||||
                "Don't count on it",
 | 
			
		||||
                "Probably not",
 | 
			
		||||
                "Very doubtful",
 | 
			
		||||
                "Most likely no",
 | 
			
		||||
                "Nope",
 | 
			
		||||
                "No",
 | 
			
		||||
                "My sources say no",
 | 
			
		||||
                "Dont even think about it",
 | 
			
		||||
                "Definitely no",
 | 
			
		||||
                "NO - It may cause disease contraction"
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
        public string CurrencySign { get; set; } = "🌸";
 | 
			
		||||
        public string CurrencyName { get; set; } = "NadekoFlower";
 | 
			
		||||
        public string DMHelpString { get; set; } = "Type `-h` for help.";
 | 
			
		||||
        public string HelpString { get; set; } = @"You can use `{0}modules` command to see a list of all modules.
 | 
			
		||||
You can use `{0}commands ModuleName`
 | 
			
		||||
(for example `{0}commands Administration`) to see a list of all of the commands in that module.
 | 
			
		||||
For a specific command help, use `{0}h ""Command name""` (for example `-h ""!m q""`)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
**LIST OF COMMANDS CAN BE FOUND ON THIS LINK**
 | 
			
		||||
<https://github.com/Kwoth/NadekoBot/blob/master/commandlist.md>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Nadeko Support Server: <https://discord.gg/0ehQwTK2RBjAxzEY>";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public class CommandPrefixesModel
 | 
			
		||||
    {
 | 
			
		||||
        public string Administration { get; set; } = ".";
 | 
			
		||||
        public string Searches { get; set; } = "~";
 | 
			
		||||
        public string NSFW { get; set; } = "~";
 | 
			
		||||
        public string Conversations { get; set; } = "<@{0}>";
 | 
			
		||||
        public string ClashOfClans { get; set; } = ",";
 | 
			
		||||
        public string Help { get; set; } = "-";
 | 
			
		||||
        public string Music { get; set; } = "!!";
 | 
			
		||||
        public string Trello { get; set; } = "trello ";
 | 
			
		||||
        public string Games { get; set; } = ">";
 | 
			
		||||
        public string Gambling { get; set; } = "$";
 | 
			
		||||
        public string Permissions { get; set; } = ";";
 | 
			
		||||
        public string Programming { get; set; } = "%";
 | 
			
		||||
        public string Pokemon { get; set; } = ">";
 | 
			
		||||
        public string Utility { get; set; } = ".";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static class ConfigHandler
 | 
			
		||||
    {
 | 
			
		||||
        private static readonly SemaphoreSlim configLock = new SemaphoreSlim(1, 1);
 | 
			
		||||
        public static async Task SaveConfig()
 | 
			
		||||
        {
 | 
			
		||||
            await configLock.WaitAsync();
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                File.WriteAllText("data/config.json", JsonConvert.SerializeObject(NadekoBot.Config, Formatting.Indented));
 | 
			
		||||
            }
 | 
			
		||||
            finally
 | 
			
		||||
            {
 | 
			
		||||
                configLock.Release();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static bool IsBlackListed(MessageEventArgs evArgs) => IsUserBlacklisted(evArgs.User.Id) ||
 | 
			
		||||
                                                                      (!evArgs.Channel.IsPrivate &&
 | 
			
		||||
                                                                       (IsChannelBlacklisted(evArgs.Channel.Id) || IsServerBlacklisted(evArgs.Server.Id)));
 | 
			
		||||
 | 
			
		||||
        public static bool IsServerBlacklisted(ulong id) => NadekoBot.Config.ServerBlacklist.Contains(id);
 | 
			
		||||
 | 
			
		||||
        public static bool IsChannelBlacklisted(ulong id) => NadekoBot.Config.ChannelBlacklist.Contains(id);
 | 
			
		||||
 | 
			
		||||
        public static bool IsUserBlacklisted(ulong id) => NadekoBot.Config.UserBlacklist.Contains(id);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public class Quote
 | 
			
		||||
    {
 | 
			
		||||
        public string Author { get; set; }
 | 
			
		||||
        public string Text { get; set; }
 | 
			
		||||
 | 
			
		||||
        public override string ToString() =>
 | 
			
		||||
            $"{Text}\n\t*-{Author}*";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -1,50 +0,0 @@
 | 
			
		||||
using System.IO;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Classes.JSONModels {
 | 
			
		||||
    public class LocalizedStrings {
 | 
			
		||||
        public string[] Insults { get; set; } = {
 | 
			
		||||
            " You are a poop.", " You're a jerk.",
 | 
			
		||||
            " I will eat you when I get my powers back."
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        public string[] Praises { get; set; } = {
 | 
			
		||||
            " You are cool.",
 | 
			
		||||
            " You are nice!",
 | 
			
		||||
            " You did a good job.",
 | 
			
		||||
            " You did something nice.",
 | 
			
		||||
            " is awesome!",
 | 
			
		||||
            " Wow."
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        public static string[] GetAvailableLocales() {
 | 
			
		||||
            Directory.CreateDirectory("data/locales");
 | 
			
		||||
            return Directory.GetFiles("data/locales");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //public static void HandleLocalization() {
 | 
			
		||||
        //    var locales = LocalizedStrings.GetAvailableLocales();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        //    Console.WriteLine("Pick a language:\n" +
 | 
			
		||||
        //                      "1. English");
 | 
			
		||||
        //    for (var i = 0; i < locales.Length; i++) {
 | 
			
		||||
        //        Console.WriteLine((i + 2) + ". " + Path.GetFileNameWithoutExtension(locales[i]));
 | 
			
		||||
        //    }
 | 
			
		||||
        //    File.WriteAllText("data/locales/english.json", JsonConvert.SerializeObject(new LocalizedStrings(), Formatting.Indented));
 | 
			
		||||
        //    try {
 | 
			
		||||
        //        Console.WriteLine($"Type in a number from {1} to {locales.Length + 1}\n");
 | 
			
		||||
        //        var input = Console.ReadLine();
 | 
			
		||||
        //        if (input != "1")
 | 
			
		||||
        //            Locale = LocalizedStrings.LoadLocale(locales[int.Parse(input) - 2]);
 | 
			
		||||
        //    } catch (Exception ex) {
 | 
			
		||||
        //        Console.ForegroundColor = ConsoleColor.Red;
 | 
			
		||||
        //        Console.WriteLine(ex);
 | 
			
		||||
        //        Console.ReadKey();
 | 
			
		||||
        //        return;
 | 
			
		||||
        //    }
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        public static LocalizedStrings LoadLocale(string localeFile) =>
 | 
			
		||||
            Newtonsoft.Json.JsonConvert.DeserializeObject<LocalizedStrings>(File.ReadAllText(localeFile));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,16 +0,0 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Classes.JSONModels
 | 
			
		||||
{
 | 
			
		||||
    class MagicItem
 | 
			
		||||
    {
 | 
			
		||||
        public string Name { get; set; }
 | 
			
		||||
        public string Description { get; set; }
 | 
			
		||||
        public override string ToString() =>
 | 
			
		||||
            $"✨`{Name}`\n\t*{Description}*";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,33 +0,0 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Classes.JSONModels
 | 
			
		||||
{
 | 
			
		||||
    public class PokemonType
 | 
			
		||||
    {
 | 
			
		||||
        public PokemonType(string n, string i, string[] m, List<PokemonMultiplier> multi)
 | 
			
		||||
        {
 | 
			
		||||
            Name = n;
 | 
			
		||||
            Icon = i;
 | 
			
		||||
            Moves = m;
 | 
			
		||||
            Multipliers = multi;
 | 
			
		||||
        }
 | 
			
		||||
        public string Name { get; set; }
 | 
			
		||||
        public List<PokemonMultiplier> Multipliers { get; set; }
 | 
			
		||||
        public string Icon { get; set; }
 | 
			
		||||
        public string[] Moves { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
    public class PokemonMultiplier
 | 
			
		||||
    {
 | 
			
		||||
        public PokemonMultiplier(string t, double m)
 | 
			
		||||
        {
 | 
			
		||||
            Type = t;
 | 
			
		||||
            Multiplication = m;
 | 
			
		||||
        }
 | 
			
		||||
        public string Type { get; set; }
 | 
			
		||||
        public double Multiplication { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,155 +0,0 @@
 | 
			
		||||
// ReSharper disable InconsistentNaming
 | 
			
		||||
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Classes.JSONModels
 | 
			
		||||
{
 | 
			
		||||
    public class Credentials
 | 
			
		||||
    {
 | 
			
		||||
        public string Token { get; set; } = "";
 | 
			
		||||
        public string ClientId { get; set; } = "170254782546575360";
 | 
			
		||||
        public ulong BotId { get; set; } = 1231231231231;
 | 
			
		||||
        public ulong[] OwnerIds { get; set; } = { 123123123123, 5675675679845 };
 | 
			
		||||
        public string GoogleAPIKey { get; set; } = "";
 | 
			
		||||
        public string SoundCloudClientID { get; set; } = "";
 | 
			
		||||
        public string MashapeKey { get; set; } = "";
 | 
			
		||||
        public string LOLAPIKey { get; set; } = "";
 | 
			
		||||
        public string TrelloAppKey { get; set; } = "";
 | 
			
		||||
        public string CarbonKey { get; set; } = "";
 | 
			
		||||
        public string OsuAPIKey { get; set; } = "";
 | 
			
		||||
    }
 | 
			
		||||
    [DebuggerDisplay("{items[0].id.playlistId}")]
 | 
			
		||||
    public class YoutubePlaylistSearch
 | 
			
		||||
    {
 | 
			
		||||
        public YtPlaylistItem[] items { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
    public class YtPlaylistItem
 | 
			
		||||
    {
 | 
			
		||||
        public YtPlaylistId id { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
    public class YtPlaylistId
 | 
			
		||||
    {
 | 
			
		||||
        public string kind { get; set; }
 | 
			
		||||
        public string playlistId { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
    [DebuggerDisplay("{items[0].id.videoId}")]
 | 
			
		||||
    public class YoutubeVideoSearch
 | 
			
		||||
    {
 | 
			
		||||
        public YtVideoItem[] items { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
    public class YtVideoItem
 | 
			
		||||
    {
 | 
			
		||||
        public YtVideoId id { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
    public class YtVideoId
 | 
			
		||||
    {
 | 
			
		||||
        public string kind { get; set; }
 | 
			
		||||
        public string videoId { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
    public class PlaylistItemsSearch
 | 
			
		||||
    {
 | 
			
		||||
        public string nextPageToken { get; set; }
 | 
			
		||||
        public PlaylistItem[] items { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
    public class PlaylistItem
 | 
			
		||||
    {
 | 
			
		||||
        public YtVideoId contentDetails { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #region wikpedia example
 | 
			
		||||
    //    {
 | 
			
		||||
    //    "batchcomplete": true,
 | 
			
		||||
    //    "query": {
 | 
			
		||||
    //        "normalized": [
 | 
			
		||||
    //            {
 | 
			
		||||
    //                "from": "u3fn92fb32f9yb329f32",
 | 
			
		||||
    //                "to": "U3fn92fb32f9yb329f32"
 | 
			
		||||
    //            }
 | 
			
		||||
    //        ],
 | 
			
		||||
    //        "pages": [
 | 
			
		||||
    //            {
 | 
			
		||||
    //                "ns": 0,
 | 
			
		||||
    //                "title": "U3fn92fb32f9yb329f32",
 | 
			
		||||
    //                "missing": true,
 | 
			
		||||
    //                "contentmodel": "wikitext",
 | 
			
		||||
    //                "pagelanguage": "en",
 | 
			
		||||
    //                "pagelanguagehtmlcode": "en",
 | 
			
		||||
    //                "pagelanguagedir": "ltr",
 | 
			
		||||
    //                "fullurl": "https://en.wikipedia.org/wiki/U3fn92fb32f9yb329f32",
 | 
			
		||||
    //                "editurl": "https://en.wikipedia.org/w/index.php?title=U3fn92fb32f9yb329f32&action=edit",
 | 
			
		||||
    //                "canonicalurl": "https://en.wikipedia.org/wiki/U3fn92fb32f9yb329f32"
 | 
			
		||||
    //            }
 | 
			
		||||
    //        ]
 | 
			
		||||
    //    }
 | 
			
		||||
    //}
 | 
			
		||||
    #endregion
 | 
			
		||||
 | 
			
		||||
    public class WikipediaApiModel
 | 
			
		||||
    {
 | 
			
		||||
        public WikipediaQuery Query { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public class WikipediaQuery
 | 
			
		||||
    {
 | 
			
		||||
        public WikipediaPage[] Pages { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public class WikipediaPage
 | 
			
		||||
    {
 | 
			
		||||
        public bool Missing { get; set; } = false;
 | 
			
		||||
        public string FullUrl { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public class WoWJoke
 | 
			
		||||
    {
 | 
			
		||||
        public string Question { get; set; }
 | 
			
		||||
        public string Answer { get; set; }
 | 
			
		||||
        public override string ToString() => $"`{Question}`\n\n**{Answer}**";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//{
 | 
			
		||||
// "kind": "youtube#searchListResponse",
 | 
			
		||||
// "etag": "\"kiOs9cZLH2FUp6r6KJ8eyq_LIOk/hCJTmyH_v57mh_MvnUFSTHfjzBs\"",
 | 
			
		||||
// "nextPageToken": "CAEQAA",
 | 
			
		||||
// "regionCode": "RS",
 | 
			
		||||
// "pageInfo": {
 | 
			
		||||
//  "totalResults": 4603,
 | 
			
		||||
//  "resultsPerPage": 1
 | 
			
		||||
// },
 | 
			
		||||
// "items": [
 | 
			
		||||
//  {
 | 
			
		||||
//   "kind": "youtube#searchResult",
 | 
			
		||||
//   "etag": "\"kiOs9cZLH2FUp6r6KJ8eyq_LIOk/iD1S35mk0xOfwTB_8lpPZ9u-Vzc\"",
 | 
			
		||||
//   "id": {
 | 
			
		||||
//    "kind": "youtube#playlist",
 | 
			
		||||
//    "playlistId": "PLs_KC2CCxJVMfOBnIyW5Kbu_GciNiYNAI"
 | 
			
		||||
//   },
 | 
			
		||||
//   "snippet": {
 | 
			
		||||
//    "publishedAt": "2016-04-14T11:35:29.000Z",
 | 
			
		||||
//    "channelId": "UCMLwm18Qa20L2L-HGpgC3jQ",
 | 
			
		||||
//    "title": "Popular Videos - Otorimonogatari & mousou express",
 | 
			
		||||
//    "description": "",
 | 
			
		||||
//    "thumbnails": {
 | 
			
		||||
//     "default": {
 | 
			
		||||
//      "url": "https://i.ytimg.com/vi/2FeptLky2mU/default.jpg",
 | 
			
		||||
//      "width": 120,
 | 
			
		||||
//      "height": 90
 | 
			
		||||
//     },
 | 
			
		||||
//     "medium": {
 | 
			
		||||
//      "url": "https://i.ytimg.com/vi/2FeptLky2mU/mqdefault.jpg",
 | 
			
		||||
//      "width": 320,
 | 
			
		||||
//      "height": 180
 | 
			
		||||
//     },
 | 
			
		||||
//     "high": {
 | 
			
		||||
//      "url": "https://i.ytimg.com/vi/2FeptLky2mU/hqdefault.jpg",
 | 
			
		||||
//      "width": 480,
 | 
			
		||||
//      "height": 360
 | 
			
		||||
//     }
 | 
			
		||||
//    },
 | 
			
		||||
//    "channelTitle": "Otorimonogatari - Topic",
 | 
			
		||||
//    "liveBroadcastContent": "none"
 | 
			
		||||
//   }
 | 
			
		||||
//  }
 | 
			
		||||
// ]
 | 
			
		||||
//}
 | 
			
		||||
@@ -9,7 +9,7 @@ using System.Text.RegularExpressions;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.CustomReactions
 | 
			
		||||
{
 | 
			
		||||
    internal class CustomReactionsModule : DiscordModule
 | 
			
		||||
    public class CustomReactionsModule : DiscordModule
 | 
			
		||||
    {
 | 
			
		||||
        public override string Prefix { get; } = "";
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -34,6 +34,6 @@ namespace NadekoBot.Classes
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Initializes the CommandBuilder with values using CommandGroupBuilder
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        internal abstract void Init(CommandGroupBuilder cgb);
 | 
			
		||||
        public abstract void Init(CommandGroupBuilder cgb);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@ using System.Threading.Tasks;
 | 
			
		||||
namespace NadekoBot.Modules.Permissions.Classes
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    internal class PermissionChecker : IPermissionChecker
 | 
			
		||||
    public class PermissionChecker : IPermissionChecker
 | 
			
		||||
    {
 | 
			
		||||
        public static PermissionChecker Instance { get; } = new PermissionChecker();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@ using System.Linq;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.Permissions.Classes
 | 
			
		||||
{
 | 
			
		||||
    internal static class PermissionHelper
 | 
			
		||||
    public static class PermissionHelper
 | 
			
		||||
    {
 | 
			
		||||
        public static bool ValidateBool(string passedArg)
 | 
			
		||||
        {
 | 
			
		||||
@@ -37,7 +37,7 @@ namespace NadekoBot.Modules.Permissions.Classes
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal static string ValidateModule(string mod)
 | 
			
		||||
        public static string ValidateModule(string mod)
 | 
			
		||||
        {
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(mod))
 | 
			
		||||
                throw new ArgumentNullException(nameof(mod));
 | 
			
		||||
@@ -50,7 +50,7 @@ namespace NadekoBot.Modules.Permissions.Classes
 | 
			
		||||
            throw new ArgumentException("That module does not exist.");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal static string ValidateCommand(string commandText)
 | 
			
		||||
        public static string ValidateCommand(string commandText)
 | 
			
		||||
        {
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(commandText))
 | 
			
		||||
                throw new ArgumentNullException(nameof(commandText));
 | 
			
		||||
@@ -65,7 +65,7 @@ namespace NadekoBot.Modules.Permissions.Classes
 | 
			
		||||
            throw new NullReferenceException("That command does not exist.");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal static Role ValidateRole(Server server, string roleName)
 | 
			
		||||
        public static Role ValidateRole(Server server, string roleName)
 | 
			
		||||
        {
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(roleName))
 | 
			
		||||
                throw new ArgumentNullException(nameof(roleName));
 | 
			
		||||
@@ -78,7 +78,7 @@ namespace NadekoBot.Modules.Permissions.Classes
 | 
			
		||||
            return role;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal static Channel ValidateChannel(Server server, string channelName)
 | 
			
		||||
        public static Channel ValidateChannel(Server server, string channelName)
 | 
			
		||||
        {
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(channelName))
 | 
			
		||||
                throw new ArgumentNullException(nameof(channelName));
 | 
			
		||||
@@ -88,7 +88,7 @@ namespace NadekoBot.Modules.Permissions.Classes
 | 
			
		||||
            return channel;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal static User ValidateUser(Server server, string userName)
 | 
			
		||||
        public static User ValidateUser(Server server, string userName)
 | 
			
		||||
        {
 | 
			
		||||
            if (string.IsNullOrWhiteSpace(userName))
 | 
			
		||||
                throw new ArgumentNullException(nameof(userName));
 | 
			
		||||
 
 | 
			
		||||
@@ -41,7 +41,7 @@ namespace NadekoBot.Modules.Permissions.Classes
 | 
			
		||||
            Console.WriteLine("Permission initialization complete.");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal static Permissions GetRolePermissionsById(Server server, ulong id)
 | 
			
		||||
        public static Permissions GetRolePermissionsById(Server server, ulong id)
 | 
			
		||||
        {
 | 
			
		||||
            ServerPermissions serverPerms;
 | 
			
		||||
            if (!PermissionsDict.TryGetValue(server.Id, out serverPerms))
 | 
			
		||||
@@ -52,7 +52,7 @@ namespace NadekoBot.Modules.Permissions.Classes
 | 
			
		||||
            return toReturn;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal static Permissions GetUserPermissionsById(Server server, ulong id)
 | 
			
		||||
        public static Permissions GetUserPermissionsById(Server server, ulong id)
 | 
			
		||||
        {
 | 
			
		||||
            ServerPermissions serverPerms;
 | 
			
		||||
            if (!PermissionsDict.TryGetValue(server.Id, out serverPerms))
 | 
			
		||||
@@ -63,7 +63,7 @@ namespace NadekoBot.Modules.Permissions.Classes
 | 
			
		||||
            return toReturn;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal static Permissions GetChannelPermissionsById(Server server, ulong id)
 | 
			
		||||
        public static Permissions GetChannelPermissionsById(Server server, ulong id)
 | 
			
		||||
        {
 | 
			
		||||
            ServerPermissions serverPerms;
 | 
			
		||||
            if (!PermissionsDict.TryGetValue(server.Id, out serverPerms))
 | 
			
		||||
@@ -74,13 +74,13 @@ namespace NadekoBot.Modules.Permissions.Classes
 | 
			
		||||
            return toReturn;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal static Permissions GetServerPermissions(Server server)
 | 
			
		||||
        public static Permissions GetServerPermissions(Server server)
 | 
			
		||||
        {
 | 
			
		||||
            ServerPermissions serverPerms;
 | 
			
		||||
            return !PermissionsDict.TryGetValue(server.Id, out serverPerms) ? null : serverPerms.Permissions;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal static PermissionBanType GetPermissionBanType(Command command, User user, Channel channel)
 | 
			
		||||
        public static PermissionBanType GetPermissionBanType(Command command, User user, Channel channel)
 | 
			
		||||
        {
 | 
			
		||||
            var server = user.Server;
 | 
			
		||||
            ServerPermissions serverPerms = PermissionsDict.GetOrAdd(server.Id, id => new ServerPermissions(id, server.Name));
 | 
			
		||||
@@ -174,7 +174,7 @@ namespace NadekoBot.Modules.Permissions.Classes
 | 
			
		||||
            return serverPerms.PermissionsControllerRole;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal static async Task SetPermissionsRole(Server server, string roleName)
 | 
			
		||||
        public static async Task SetPermissionsRole(Server server, string roleName)
 | 
			
		||||
        {
 | 
			
		||||
            var serverPerms = PermissionsDict.GetOrAdd(server.Id,
 | 
			
		||||
                new ServerPermissions(server.Id, server.Name));
 | 
			
		||||
@@ -183,7 +183,7 @@ namespace NadekoBot.Modules.Permissions.Classes
 | 
			
		||||
            await WriteServerToJson(serverPerms).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal static async Task SetVerbosity(Server server, bool val)
 | 
			
		||||
        public static async Task SetVerbosity(Server server, bool val)
 | 
			
		||||
        {
 | 
			
		||||
            var serverPerms = PermissionsDict.GetOrAdd(server.Id,
 | 
			
		||||
                new ServerPermissions(server.Id, server.Name));
 | 
			
		||||
@@ -192,7 +192,7 @@ namespace NadekoBot.Modules.Permissions.Classes
 | 
			
		||||
            await WriteServerToJson(serverPerms).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal static async Task CopyRolePermissions(Role fromRole, Role toRole)
 | 
			
		||||
        public static async Task CopyRolePermissions(Role fromRole, Role toRole)
 | 
			
		||||
        {
 | 
			
		||||
            var server = fromRole.Server;
 | 
			
		||||
            var serverPerms = PermissionsDict.GetOrAdd(server.Id,
 | 
			
		||||
@@ -210,7 +210,7 @@ namespace NadekoBot.Modules.Permissions.Classes
 | 
			
		||||
            await WriteServerToJson(serverPerms).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal static async Task CopyChannelPermissions(Channel fromChannel, Channel toChannel)
 | 
			
		||||
        public static async Task CopyChannelPermissions(Channel fromChannel, Channel toChannel)
 | 
			
		||||
        {
 | 
			
		||||
            var server = fromChannel.Server;
 | 
			
		||||
            var serverPerms = PermissionsDict.GetOrAdd(server.Id,
 | 
			
		||||
@@ -228,7 +228,7 @@ namespace NadekoBot.Modules.Permissions.Classes
 | 
			
		||||
            await WriteServerToJson(serverPerms).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal static async Task CopyUserPermissions(User fromUser, User toUser)
 | 
			
		||||
        public static async Task CopyUserPermissions(User fromUser, User toUser)
 | 
			
		||||
        {
 | 
			
		||||
            var server = fromUser.Server;
 | 
			
		||||
            var serverPerms = PermissionsDict.GetOrAdd(server.Id,
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@ using System.Text.RegularExpressions;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.Permissions
 | 
			
		||||
{
 | 
			
		||||
    internal class FilterInvitesCommand : DiscordCommand
 | 
			
		||||
    public class FilterInvitesCommand : DiscordCommand
 | 
			
		||||
    {
 | 
			
		||||
        private readonly Regex filterRegex = new Regex(@"(?:discord(?:\.gg|app\.com\/invite)\/(?<id>([\w]{16}|(?:[\w]+-?){3})))");
 | 
			
		||||
 | 
			
		||||
@@ -49,7 +49,7 @@ namespace NadekoBot.Modules.Permissions
 | 
			
		||||
            return serverPerms.ChannelPermissions.TryGetValue(channel.Id, out perms) && perms.FilterInvites;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        internal override void Init(CommandGroupBuilder cgb)
 | 
			
		||||
        public override void Init(CommandGroupBuilder cgb)
 | 
			
		||||
        {
 | 
			
		||||
            cgb.CreateCommand(Module.Prefix + "chnlfilterinv")
 | 
			
		||||
                .Alias(Module.Prefix + "cfi")
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user