예제 #1
0
        private void LoadCommands()
        {
            _prefixes.Add(_config.Prefix);
            if (_config.AllowMentionPrefix)
            {
                _prefixes.Add($"<@{discordClient.CurrentUser.Id}>");
                _prefixes.Add($"<@!{discordClient.CurrentUser.Id}>");
            }

            _logger.LogInformation($"Using {_prefixes.Count} prefix{(_prefixes.Count > 1 ? "es" : "")}; {string.Join(", ", _prefixes)}.");

            _commands.AddTypeParser(new SocketUserParser <SocketUser>());
            _commands.AddTypeParser(new SocketUserParser <SocketGuildUser>());
            _commands.AddTypeParser(new SocketGuildChannelParser <SocketGuildChannel>());
            _commands.AddTypeParser(new SocketGuildChannelParser <SocketTextChannel>());
            _commands.AddTypeParser(new SocketGuildChannelParser <SocketCategoryChannel>());
            _commands.AddTypeParser(new SocketGuildChannelParser <SocketVoiceChannel>());
            _commands.AddTypeParser(new SocketRoleParser());
            _commands.AddTypeParser(new CaseParser());
            _commands.AddTypeParser(new TimeSpanParser());
            _commands.AddTypeParser(new BanParser());


            _commands.AddModules(Assembly.GetEntryAssembly(), action: m =>
            {
            });
        }
예제 #2
0
        public override async Task InitializeAsync()
        {
            _commandService.AddTypeParser(_guildUserParser);
            _commandService.AddTypeParser(_userParser);

            _commandService.ModuleBuilding  += ParseStringTokensAsync;
            _client.MessageUpdated          += HandleMessageUpdateAsync;
            _commandService.CommandErrored  += HandleCommandErrorAsync;
            _commandService.CommandExecuted += HandleCommandExecutedAsync;

            var modulesLoaded = await _commandService.AddModulesAsync(Assembly.GetEntryAssembly());

            _client.MessageReceived += HandleMessageAsync;

            _logger.LogInformation(
                $"{modulesLoaded.Count} total modules loaded | {modulesLoaded.Sum(a => a.Commands.Count)} total commands loaded | 2 type parsers loaded");
        }
예제 #3
0
        public void Initialize()
        {
            _commands.AddModules(Assembly.GetEntryAssembly());

            _client.MessageCreated += OnMessageReceivedAsync;

            _commands.CommandExecuted += OnCommandExecuted;
            _commands.CommandErrored  += OnCommandErrored;

            _commands.AddTypeParser(new DiscordMemberTypeParser());
            _commands.AddTypeParser(new DiscordGuildTypeParser());
            _commands.AddTypeParser(new DiscordUserTypeParser());
            _commands.AddTypeParser(new DiscordChannelTypeParser());
            _commands.AddTypeParser(new DiscordRoleTypeParser());
            _commands.AddTypeParser(new SkeletonUserTypeParser());
            _commands.AddTypeParser(new UriTypeParser());
            _commands.AddTypeParser(new TimeSpanTypeParser());
            _commands.AddTypeParser(new RegionTypeParser());
        }
예제 #4
0
 internal static void AddTypeParsers(this CommandService service)
 {
     service.AddTypeParser(new UserParser <SocketGuildUser>());
     service.AddTypeParser(new UserParser <SocketUser>());
     service.AddTypeParser(new RoleParser <SocketRole>());
     service.AddTypeParser(new ChannelParser <SocketTextChannel>());
     service.AddTypeParser(new EmoteParser());
     service.AddTypeParser(new BooleanParser(), true);
 }
예제 #5
0
 public void AddTypeParser <T>(TypeParser <T> typeParser)
 {
     _commands.AddTypeParser(typeParser);
     _logger.Info($"[ADD_TYPE_PARSER] {typeParser.GetType().Name}");
 }
예제 #6
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            // API/Website Config
            services.AddControllers();
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo
                {
                    Title       = "Faforever.Qai",
                    Version     = "v1",
                    Description = "The API for the Faforever.Qai and Dostya bots."
                });
            });

            // Bot Services Config
            DatabaseConfiguration dbConfig = new()
            {
                DataSource = $"Data Source={Configuration["Config:DataSource"]}"
            };

#if DEBUG
            // For use when the DB is Database/db-name.db
            if (!Directory.Exists("Database"))
            {
                Directory.CreateDirectory("Database");
            }
#endif

            string json         = File.ReadAllText(Path.Join("Config", "games_config.json"));
            var    botFunConfig = JsonConvert.DeserializeObject <BotFunConfiguration>(json);

            json = File.ReadAllText(Path.Join("Config", "url_config.json"));
            var urlConfig = JsonConvert.DeserializeObject <UrlConfiguration>(json);

            TwitchClientConfig twitchCfg = new()
            {
                ClientId     = Configuration["Config:TwitchClientId"],
                ClientSecret = Environment.GetEnvironmentVariable("TWITCH_CLIENT_SECRET")
            };

            services.AddLogging(options => options.AddConsole())
            .AddDbContext <QAIDatabaseModel>(options =>
            {
                options.UseSqlite(dbConfig.DataSource);
            }, ServiceLifetime.Singleton, ServiceLifetime.Singleton)
            .AddSingleton <RelayService>()
            // Command Service Registration
            .AddSingleton((x) =>
            {
                var options = new CommandService(new CommandServiceConfiguration()
                {
                    // Additional configuration for the command service goes here.
                });

                // Command modules go here.
                options.AddModules(System.Reflection.Assembly.GetAssembly(typeof(CustomCommandContext)));
                // Argument converters go here.
                options.AddTypeParser(new DiscordChannelTypeConverter());
                options.AddTypeParser(new DiscordRoleTypeConverter());
                options.AddTypeParser(new BotUserCapsuleConverter());
                options.AddTypeParser(new DiscordMemberConverter());
                options.AddTypeParser(new DiscordUserConverter());
                return(options);
            })
            .AddSingleton <QCommandsHandler>()
            .AddSingleton(typeof(TwitchClientConfig), twitchCfg)
            // Operation Service Registration
            .AddSingleton <IBotFunService>(new BotFunService(botFunConfig))
            .AddSingleton <IUrlService>(new UrlService(urlConfig))
            .AddSingleton <DiscordEventHandler>()
            .AddSingleton <AccountLinkService>()
            .AddTransient <IFetchPlayerStatsOperation, ApiFetchPlayerStatsOperation>()
            .AddTransient <IFindPlayerOperation, ApiFindPlayerOperation>()
            .AddTransient <ISearchUnitDatabaseOperation, UnitDbSearchUnitDatabaseOpeartion>()
            .AddTransient <IPlayerService, OperationPlayerService>()
            .AddTransient <GameService>()
            .AddTransient <ISearchMapOperation, ApiSearchMapOperation>()
            .AddTransient <IFetchLadderPoolOperation, ApiFetchLadderPoolOperation>()
            .AddTransient <IFetchReplayOperation, ApiFetchReplayOperation>()
            .AddTransient <IFetchClanOperation, ApiFetchClanOperation>()
            .AddTransient <IFetchTwitchStreamsOperation, FetchTwitchStreamsOperation>()
            .AddTransient <FafApiClient>();



            // HTTP Client Mapping
            services.AddHttpClient <ApiHttpClient>(client =>
            {
                client.BaseAddress = ApiUri;
            });

            services.AddHttpClient <UnitClient>(client =>
            {
                client.BaseAddress = new Uri(UnitDbUtils.UnitApi);
            });

            services.AddHttpClient <TwitchClient>();
            // Discord Information Setup
            DiscordBotConfiguration discordConfig = new()
            {
                Prefix = Configuration["Config:BotPrefix"],
                Shards = 1,
                Token  = Environment.GetEnvironmentVariable("DISCORD_TOKEN")
            };

            var dcfg = new DiscordConfiguration
            {
                Token           = discordConfig.Token,
                TokenType       = TokenType.Bot,
                MinimumLogLevel = LogLevel.Debug,
                ShardCount      = discordConfig.Shards, // Default to 1 for automatic sharding.
                Intents         = DiscordIntents.Guilds | DiscordIntents.GuildMessages | DiscordIntents.DirectMessages,
            };

            services.AddSingleton(discordConfig)
            .AddSingleton <DiscordShardedClient>(x =>
            {
                return(new(dcfg));
            })
            .AddSingleton <DiscordRestClient>(x =>
            {
                return(new(dcfg));
            })
            .AddSingleton <DiscordBot>();

            // IRC Information Setup
            var user = Configuration["Config:Irc:User"];
            var pass = Environment.GetEnvironmentVariable("IRC_PASS");
            IrcConfiguration ircConfig = new()
            {
                Connection = Configuration["Config:Irc:Connection"],
                Channels   = Configuration["Config:Irc:Channels"].Split(',').Select(s => s.Trim()).ToArray(),
                UserName   = user,
                NickName   = user,
                RealName   = user,
                Password   = pass
            };

            var ircConnInfo = new IrcUserRegistrationInfo
            {
                NickName = ircConfig.NickName,
                RealName = ircConfig.RealName,
                Password = ircConfig.Password,
                UserName = ircConfig.UserName
            };

            services.AddSingleton(ircConfig)
            .AddSingleton(ircConnInfo as IrcRegistrationInfo)
            .AddSingleton <QaIrc>();

            // Setup the OAuth2 settings
            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultSignInScheme       = CookieAuthenticationDefaults.AuthenticationScheme;

                options.DefaultChallengeScheme = "FAF";
            })
            .AddCookie()
            .AddOAuth("FAF", options =>
            {
                options.AuthorizationEndpoint = $"{ApiUri}oauth/authorize";                // FAF API Endpoint.

                options.CallbackPath     = new PathString("/authorization-code/callback"); // local auth endpoint
                options.AccessDeniedPath = new PathString("/api/link/denied");

                // Other FAF OAtuh configuration settings
                options.ClientId      = Configuration["Config:Faf:ClientId"];
                options.ClientSecret  = Environment.GetEnvironmentVariable("FAF_CLIENT_SECRET");
                options.TokenEndpoint = $"{ApiUri}oauth/token";

                options.Scope.Add("public_profile");

                options.Events = new OAuthEvents
                {
                    OnCreatingTicket = async context =>
                    {
                        // Get the FAF user information
                        var req = new HttpRequestMessage(HttpMethod.Get, $"{ApiUri}me");

                        req.Headers.Authorization = new("Bearer", context.AccessToken);

                        var res = await context.Backchannel.SendAsync(req);

                        if (res.IsSuccessStatusCode)
                        {     // if the request is valid, get the JSON data from it
                            var rawJson = await res.Content.ReadAsStreamAsync();

                            var faf = await System.Text.Json.JsonSerializer.DeserializeAsync <FafUser>(rawJson);

                            if (context.Request.Cookies.TryGetValue("token", out var token))
                            {
                                var link = context.HttpContext.RequestServices.GetRequiredService <AccountLinkService>();

                                try
                                {     // bind the information to the link with the token from the cookies
                                    link.BindFafUser(token, faf.Data.Attributes.UserId, faf.Data.Attributes.UserName);
                                }
                                catch (Exception ex)
                                {
                                    context.Response.Cookies.Append("error", ex.Message);
                                }

                                context.Success();
                            }
                            else
                            {
                                context.Response.Cookies.Append("error", "No token found.");
                            }
                        }
                        else
                        {
                            context.Response.Cookies.Append("error", "Failed to get user information from access token");
                        }
                    },
                    OnRemoteFailure = context =>
                    {
                        // TODO remove token from cookies and delete server token cache.
                        Console.WriteLine(context.Failure.Message);

                        return(Task.CompletedTask);
                    }
                };
            })
            // OAuth2 setup for authenticating with Discord.
            .AddOAuth("DISCORD", options =>
            {
                options.AuthorizationEndpoint = $"{Configuration["Config:Discord:Api"]}/oauth2/authorize";

                options.CallbackPath     = new PathString("/authorization-code/discord-callback"); // local auth endpoint
                options.AccessDeniedPath = new PathString("/api/link/denied");

                options.ClientId      = Configuration["Config:Discord:ClientId"];
                options.ClientSecret  = Environment.GetEnvironmentVariable("DISCORD_CLIENT_SECRET");
                options.TokenEndpoint = $"{Configuration["Config:Discord:TokenEndpoint"]}";

                options.Scope.Add("identify");

                options.Events = new OAuthEvents
                {
                    OnCreatingTicket = async context =>
                    {
                        // get user data
                        var client = new DiscordRestClient(new()
                        {
                            Token     = context.AccessToken,
                            TokenType = TokenType.Bearer
                        });

                        var user = await client.GetCurrentUserAsync();

                        if (context.Request.Cookies.TryGetValue("token", out var token))
                        {
                            var link = context.HttpContext.RequestServices.GetRequiredService <AccountLinkService>();

                            try
                            {     // verify the user information grabbed matches the user info
                                  // saved from the inital command
                                if (!link.VerifyDiscord(token, user.Id))
                                {
                                    context.Response.Cookies.Append("error", "Discord ID used for sign in did not match Discord ID from the Discord Application.");
                                }
                            }
                            catch (Exception ex)
                            {
                                context.Response.Cookies.Append("error", ex.Message);
                            }

                            context.Success();
                        }
                        else
                        {
                            context.Response.Cookies.Append("error", "No token found.");
                        }
                    },
                    OnRemoteFailure = context =>
                    {
                        // TODO remove token from cookies and delete server token cache.

                        return(Task.CompletedTask);
                    }
                };
            });
        }
예제 #7
0
 private void InitializeTypeParsers()
 {
     CommandService.AddTypeParser(new UserParser());
     CommandService.AddTypeParser(new TextChannelParser());
     CommandService.AddTypeParser(new CommandParser());
 }