Пример #1
0
        /// <summary>
        /// The _client_ reaction added.
        /// </summary>
        /// <param name="messageCacheable">
        /// The message Cache-able.
        /// </param>
        /// <param name="channel">
        /// The channel.
        /// </param>
        /// <param name="reaction">
        /// The reaction.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        internal async Task ReactionAddedAsync(Cacheable <IUserMessage, ulong> messageCacheable, ISocketMessageChannel channel, SocketReaction reaction)
        {
            if (prefixOverride)
            {
                return;
            }
            LogHandler.LogMessage("Reaction Detected", LogSeverity.Verbose);

            IUserMessage message = messageCacheable.Value ?? await channel.GetMessageAsync(reaction.MessageId) as IUserMessage;

            if (message == null)
            {
                return;
            }

            if (reaction.User.Value?.IsBot == true || (string.IsNullOrWhiteSpace(message.Content) && !message.Embeds.Any()))
            {
                return;
            }

            try
            {
                var translateAction = Task.Run(
                    async() =>
                {
                    var guildId          = (channel as SocketGuildChannel).Guild.Id;
                    var translationSetup = _Translate.GetSetup(guildId);
                    if (translationSetup == null)
                    {
                        translationSetup = Provider.GetRequiredService <DatabaseHandler>().Execute <GuildModel>(DatabaseHandler.Operation.LOAD, null, guildId.ToString())?.Settings.Translate;
                        if (translationSetup == null)
                        {
                            return;
                        }

                        await _Translate.UpdateSetupAsync(guildId, translationSetup);
                    }
                    if (!translationSetup.EasyTranslate)
                    {
                        return;
                    }

                    // Check custom matches first
                    var languageType = translationSetup.CustomPairs.FirstOrDefault(x => x.EmoteMatches.Any(val => val == reaction.Emote.Name));

                    if (languageType == null)
                    {
                        // If no custom matches, check default matches
                        languageType = LanguageMap.DefaultMap.FirstOrDefault(x => x.EmoteMatches.Any(val => val == reaction.Emote.Name));
                        if (languageType == null)
                        {
                            LogHandler.LogMessage("Ignored EasyTranslate Reaction, No Emote Configured", LogSeverity.Verbose);
                            return;
                        }
                    }
                    if (translated.Any(x => x.Key == reaction.MessageId && x.Value.Contains(languageType.Language)))
                    {
                        LogHandler.LogMessage("Ignored EasyTranslate Reaction", LogSeverity.Verbose);
                        return;
                    }
                    var embed = await TranslationMethods.TranslateFullMessageAsync(languageType.Language, message, channel as IGuildChannel, reaction);

                    if (translationSetup.DMTranslations)
                    {
                        try
                        {
                            await reaction.User.Value.SendMessageAsync(embed.Item1 ?? "", false, embed.Item2);
                        }
                        catch
                        {
                            await reaction.Channel.SendMessageAsync($"Unable to send DM Translation to {reaction.User.Value?.Mention}");
                        }
                    }
                    else
                    {
                        try
                        {
                            await channel.SendMessageAsync(embed.Item1 ?? "", false, embed.Item2);
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine(e.ToString());
                        }

                        var match = translated.FirstOrDefault(x => x.Key == reaction.MessageId);
                        if (match.Value == null)
                        {
                            translated.TryAdd(reaction.MessageId, new List <LanguageMap.LanguageCode> {
                                languageType.Language
                            });
                        }
                        else
                        {
                            match.Value.Add(languageType.Language);
                        }
                    }

                    if (embed.Item3)
                    {
                        LogHandler.LogMessage(guildId, reaction.Channel.Name, reaction.UserId, $"Translated Message to {languageType.Language}: {message.Content}");
                    }
                });
            }
            catch (Exception e)
            {
                LogHandler.LogMessage(e.ToString(), LogSeverity.Error);
            }
        }
Пример #2
0
        /// <summary>
        /// This event is triggered every time the a user sends a Message in a channel, dm etc. that the bot has access to view.
        /// </summary>
        /// <param name="socketMessage">
        /// The socket Message.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        internal async Task MessageReceivedAsync(SocketMessage socketMessage)
        {
            if (!(socketMessage is SocketUserMessage Message) || Message.Channel is IDMChannel)
            {
                return;
            }

            if (string.IsNullOrWhiteSpace(Message.Content) || Message.Content.Length < 3)
            {
                return;
            }

            if (Message.Author.IsBot || Message.Author.IsWebhook)
            {
                // Filter out all bot messages from triggering commands.
                return;
            }

            // Ensure that blacklisted users/guilds are not allowed to run commands
            if (CheckBlacklist(Message.Author.Id, (Message.Channel as IGuildChannel).Guild.Id))
            {
                return;
            }

            await _ChannelHelper.DoMediaChannelAsync(Message);

            var argPos     = 0;
            var isPrefixed = true;

            if (prefixOverride)
            {
                var config = JsonConvert.DeserializeObject <DatabaseObject>(File.ReadAllText("setup/DBConfig.json"));
                if (config.PrefixOverride != null)
                {
                    if (!Message.HasStringPrefix(config.PrefixOverride, ref argPos))
                    {
                        isPrefixed = false;
                    }
                }
                else
                {
                    LogHandler.LogMessage("Message Handler is being returned as the bot is in prefix override mode and you haven't specified a custom prefix in DBConfig.json", LogSeverity.Warning);
                    isPrefixed = false;
                }
            }
            else
            {
                // Filter out all messages that don't start with our Bot PrefixSetup, bot mention or server specific PrefixSetup.
                if (!(Message.HasMentionPrefix(Client.CurrentUser, ref argPos) || Message.HasStringPrefix(PrefixService.GetPrefix((Message.Channel as IGuildChannel)?.Guild?.Id ?? 0), ref argPos)))
                {
                    isPrefixed = false;
                }
            }

            // run level check and auto-message channel check if the current message is not a command prefixed message
            if (!isPrefixed)
            {
                var messageTask = Task.Run(
                    async() =>
                {
                    LogHandler.LogMessage($"G: {(Message.Channel as IGuildChannel)?.Guild?.Id} | C: {Message.Channel?.Id} | U: {Message.Author?.Id.ToString()} | M: {Message?.Content.Left(100)}", LogSeverity.Verbose);
                    await _LevelHelper.DoLevelsAsync(Message);
                    await _ChannelHelper.DoAutoMessageAsync(Message);
                });

                await StatHelper.LogMessageAsync(Message);

                return;
            }

            // Here we attempt to execute a command based on the user Message
            var commandTask = Task.Run(async() =>
            {
                var context = new Context(Client, Message, Provider);
                var result  = await CommandService.ExecuteAsync(context, argPos, Provider, MultiMatchHandling.Best);

                // Generate an error Message for users if a command is unsuccessful
                if (!result.IsSuccess)
                {
                    await CmdErrorAsync(context, result, argPos);
                }
                else
                {
                    var search = CommandService.Search(context, argPos);
                    var cmd    = search.Commands.FirstOrDefault();
                    StatHelper.LogCommand(cmd.Command, Message);
                    if (Config.LogCommandUsages)
                    {
                        LogHandler.LogMessage(context);
                    }
                }
            });
        }
Пример #3
0
        /// <summary>
        /// Triggers when a shard is ready
        /// </summary>
        /// <param name="socketClient">
        /// The socketClient.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        internal async Task ShardReadyAsync(DiscordSocketClient socketClient)
        {
            await socketClient.SetActivityAsync(new Game($"Shard: {socketClient.ShardId}", ActivityType.Watching));

            if (guildCheck)
            {
                if (Client.Shards.All(x => x.Guilds.Any()))
                {
                    if (prefixOverride)
                    {
                        LogHandler.LogMessage($"Bot is in Prefix Override Mode! Current Prefix is: {DatabaseHandler.Settings.PrefixOverride}", LogSeverity.Warning);
                    }


                    if (await DBLApi.InitializeAsync())
                    {
                        LogHandler.LogMessage("Discord Bots List API Initialized.");
                    }
                    else
                    {
                        LogHandler.LogMessage("Discord Bots List API Not Initialized.", LogSeverity.Warning);
                    }

                    Provider.GetRequiredService <TimerService>().Restart();

                    _ = Task.Run(
                        () =>
                    {
                        Limits.Initialize();
                        Waits.Initialize();

                        var handler = Provider.GetRequiredService <DatabaseHandler>();

                        if (!DatabaseHandler.Settings.DenyConfigDeletion)
                        {
                            // Returns all stored guild models
                            var guildIds    = Client.Guilds.Select(g => g.Id).ToList();
                            var missingList = handler.Query <GuildModel>().Where(g => !g.Settings.Config.SaveGuildModel && g.ID != 0).Select(x => x.ID).Where(x => !guildIds.Contains(x)).ToList();

                            foreach (var id in missingList)
                            {
                                handler.Execute <GuildModel>(DatabaseHandler.Operation.DELETE, id: id.ToString());
                                handler.Execute <GuildModel>(DatabaseHandler.Operation.DELETE, id: $"{id}-Tags");
                                handler.Execute <GuildModel>(DatabaseHandler.Operation.DELETE, id: $"{id}-Channels");
                                handler.Execute <GuildModel>(DatabaseHandler.Operation.DELETE, id: $"{id}-Levels");
                            }

                            /*
                             * // Only to be used if migrating from older database where all items were stored in the same guildModel
                             * var convert = Provider.GetRequiredService<GuildModelToServices>();
                             * foreach (var guildId in guildIds)
                             * {
                             *  var model = handler.Execute<GuildModel>(DatabaseHandler.Operation.LOAD, null, guildId);
                             *  if (model != null)
                             *  {
                             *      convert.SplitModelAsync(model);
                             *  }
                             * }
                             */
                        }
                        else
                        {
                            LogHandler.LogMessage("Server configs for servers which do not contain the bot will be preserved!", LogSeverity.Warning);
                        }
                    });

                    // Ensure that this is only run once as the bot initially connects.
                    guildCheck = false;
                }
                else
                {
                    // This will check to ensure that all our servers are initialized, whilst also allowing the bot to continue starting
                    _ = Task.Run(
                        () =>
                    {
                        var handler = Provider.GetRequiredService <DatabaseHandler>();

                        // This will load all guild models and retrieve their IDs
                        var Servers = handler.Query <GuildModel>();
                        var ids     = Servers.Select(s => s.ID).ToList();

                        // Now if the bots server list contains a guild but 'Servers' does not, we create a new object for the guild
                        foreach (var Guild in socketClient.Guilds.Select(x => x.Id))
                        {
                            if (!ids.Contains(Guild))
                            {
                                handler.Execute <GuildModel>(DatabaseHandler.Operation.CREATE, new GuildModel(Guild), Guild);
                            }
                        }
                    });
                }
            }

            LogHandler.LogMessage($"Shard: {socketClient.ShardId} Ready");
            if (!hideInvite)
            {
                LogHandler.LogMessage($"Invite: https://discordapp.com/oauth2/authorize?client_id={Client.CurrentUser.Id}&scope=bot&permissions=2146958591");
                hideInvite = true;
            }
        }
Пример #4
0
 /// <summary>
 /// This logs discord messages to our LogHandler
 /// </summary>
 /// <param name="message">
 /// The Message.
 /// </param>
 /// <returns>
 /// The <see cref="Task"/>.
 /// </returns>
 internal Task LogAsync(LogMessage message)
 {
     return(Task.Run(() => LogHandler.LogMessage(message.Message, message.Severity)));
 }
Пример #5
0
        /// <summary>
        /// Initializes the database for use
        /// </summary>
        /// <returns>
        /// The Document Store
        /// </returns>
        public Task <IDocumentStore> InitializeAsync()
        {
            // Ensure that the bots database settings are setup, if not prompt to enter details
            if (!File.Exists("setup/DBConfig.json"))
            {
                LogHandler.LogMessage("Please enter details about your bot and database configuration. NOTE: You can hit enter for a default value. ");
                LogHandler.LogMessage("Enter the database Name: (ie. MyRavenDatabase) DEFAULT: RavenBOT");
                var databaseName = Console.ReadLine();
                if (string.IsNullOrEmpty(databaseName))
                {
                    databaseName = "RavenBOT";
                }

                LogHandler.LogMessage("Enter the database URL: (typically http://127.0.0.1:8080 if hosting locally) DEFAULT: http://127.0.0.1:8080");
                var databaseUrl = Console.ReadLine();
                if (string.IsNullOrEmpty(databaseUrl))
                {
                    databaseUrl = "http://127.0.0.1:8080";
                }

                File.WriteAllText("setup/DBConfig.json", JsonConvert.SerializeObject(
                                      new DatabaseObject
                {
                    Name = databaseName,
                    Urls = new List <string> {
                        databaseUrl
                    }
                },
                                      Formatting.Indented),
                                  Encoding.UTF8);

                Settings = JsonConvert.DeserializeObject <DatabaseObject>(File.ReadAllText("setup/DBConfig.json"));
            }
            else
            {
                Settings = JsonConvert.DeserializeObject <DatabaseObject>(File.ReadAllText("setup/DBConfig.json"));
                LogHandler.LogMessage("Connecting to Server\n" + $"=> URL: \n{string.Join("\n", Settings.Urls)}\n" + $"=> Name: {Settings.Name}");
            }

            if (Settings.Urls.Count == 0)
            {
                throw new Exception("No database urls have been detected in config, please add one");
            }

            // This initializes the document store, and ensures that RavenDB is working properly
            Store = new Lazy <IDocumentStore>(() => new DocumentStore {
                Database = Settings.Name, Urls = Settings.Urls.ToArray()
            }.Initialize(), true).Value;
            if (Store == null)
            {
                LogHandler.LogMessage("Failed to build document store.", LogSeverity.Critical);
            }

            // This creates the database
            if (Store.Maintenance.Server.Send(new GetDatabaseNamesOperation(0, 20)).All(x => x != Settings.Name))
            {
                Store.Maintenance.Server.Send(new CreateDatabaseOperation(new DatabaseRecord(Settings.Name)));
                LogHandler.LogMessage($"Created Database => {Settings.Name}");
            }

            // To ensure the backup operation is functioning and backing up to our bots directory we update the backup operation on each boot of the bot
            try
            {
                var record = Store.Maintenance.ForDatabase(Settings.Name).Server.Send(new GetDatabaseRecordOperation(Settings.Name));
                var backup = record.PeriodicBackups.FirstOrDefault(x => x.Name == "Backup");

                if (backup == null)
                {
                    var newbackup = new PeriodicBackupConfiguration {
                        Name = "Backup", BackupType = BackupType.Backup, FullBackupFrequency = Settings.FullBackup, IncrementalBackupFrequency = Settings.IncrementalBackup, LocalSettings = new LocalSettings {
                            FolderPath = Settings.BackupFolder
                        }
                    };
                    Store.Maintenance.ForDatabase(Settings.Name).Send(new UpdatePeriodicBackupOperation(newbackup));
                }
                else
                {
                    // In the case that we already have a backup operation setup, ensure that we update the backup location accordingly
                    backup.LocalSettings = new LocalSettings {
                        FolderPath = Settings.BackupFolder
                    };
                    Store.Maintenance.ForDatabase(Settings.Name).Send(new UpdatePeriodicBackupOperation(backup));
                }
            }
            catch
            {
                LogHandler.LogMessage("RavenDB: Failed to set Backup operation. Backups may not be saved", LogSeverity.Warning);
            }

            // Prompt the user to set up the bots configuration.
            if (Settings.IsConfigCreated == false)
            {
                var configModel = new ConfigModel();
                LogHandler.LogMessage("Enter bots token: (You can get this from https://discordapp.com/developers/applications/me)");
                var token = Console.ReadLine();
                if (string.IsNullOrWhiteSpace(token))
                {
                    throw new Exception("You must supply a token for this bot to operate.");
                }

                LogHandler.LogMessage("Enter bots prefix: (This will be used to initiate a command, ie. +say or +help) DEFAULT: +");
                var prefix = Console.ReadLine();
                if (string.IsNullOrEmpty(prefix))
                {
                    prefix = "+";
                }

                configModel.Token  = token;
                configModel.Prefix = prefix;

                // This inserts the config object into the database and writes the DatabaseConfig to file.
                Execute <ConfigModel>(Operation.CREATE, configModel, "Config");
                Settings.IsConfigCreated = true;
                File.WriteAllText("setup/DBConfig.json", JsonConvert.SerializeObject(Settings, Formatting.Indented));
            }

            LogHandler.PrintApplicationInformation(Settings, Execute <ConfigModel>(Operation.LOAD, null, "Config"));

            // Note the logger has to be updated/re-set after we set the database up otherwise there will be a null reference when trying to log initially
            if (Settings.LogToDatabase)
            {
                LogHandler.Log = new LoggerConfiguration().MinimumLevel.Is(LogHandler.DiscordLogToEventLevel(Settings.LogSeverity)).WriteTo.Console().WriteTo.RavenDB(
                    Store,
                    defaultDatabase: Settings.Name,
                    expiration: TimeSpan.FromDays(2)).CreateLogger();
            }
            else
            {
                LogHandler.Log = new LoggerConfiguration().MinimumLevel.Is(LogHandler.DiscordLogToEventLevel(Settings.LogSeverity)).CreateLogger();
            }

            return(Task.FromResult(Store));
        }