Esempio n. 1
0
        public async Task Status(CommandContext ctx)
        {
            await ctx.TriggerTypingAsync();

            string lang = Config.GetLang(ctx.Guild.Id.ToString());
            IReadOnlyList <DiscordChannel> channelList = await ctx.Guild.GetChannelsAsync();

            string[] list    = channelList.Cast <DiscordChannel>().Select(x => x.Id.ToString()).ToArray();
            JObject  streams = EventStreams.GetData(list);

            // Inform about streams if they exist on a server
            string streamingMsg = "";

            if (streams.Count > 0)
            {
                TimeSpan timestamp = DateTime.UtcNow - EventStreams.LatestTimestamp;
                streamingMsg = " " + Locale.GetMessage("configuring-status-streaming", lang, (int)timestamp.TotalMinutes, timestamp.Seconds);

                // Restart the stream if it is offline for five minutes
                if (timestamp.TotalMinutes > 5)
                {
                    Program.LogMessage("EventStreams restart was requested from !status command.", "EventStreams");
                    EventStreams.Init();
                }
            }

            // Respond to message
            await ctx.RespondAsync(Locale.GetMessage("configuring-status", lang) + streamingMsg);
        }
Esempio n. 2
0
        public async Task SetDomain(CommandContext ctx,
                                    [Description("configuring-help-domain-value"), RemainingText] string value)
        {
            string prevDomain = Config.GetDomain(ctx.Guild.Id.ToString());
            string lang       = Config.GetLang(ctx.Guild.Id.ToString());
            await ctx.TriggerTypingAsync();

            // Check for required parameters
            if (value.ToString() == "")
            {
                await ctx.RespondAsync(Locale.GetMessage("configuring-required-value", lang, ctx.Command.Name, Config.GetValue("prefix")));

                return;
            }

            // Check if matches Wikimedia project
            string[] projectList  = null;
            bool     notWmProject = (value != "-" && !EventStreams.CanBeUsed(value, out projectList));

            if (notWmProject)
            {
                await ctx.RespondAsync(Locale.GetMessage("configuring-badvalue-domain", lang, "`" + string.Join("`, `", projectList) + "`"));

                return;
            }

            // Do action and respond
            int succeeds = Config.SetOverride(ctx.Guild.Id.ToString(), "domain", value);

            if (succeeds == Config.RESULT_CHANGE)
            {
                await ctx.RespondAsync(Locale.GetMessage("configuring-changed-domain", lang, value));
            }
            await RespondOnErrors(succeeds, ctx, lang);
        }
Esempio n. 3
0
        public async Task CloseStream(CommandContext ctx,
                                      [Description("streaming-help-channel")] DiscordChannel channel,
                                      [RemainingText, Description("streaming-help-args")] string args = "")
        {
            await CommandChecks(ctx, channel, args, async(arguments, lang) =>
            {
                EventStreams.RemoveData(channel.Id.ToString(), arguments);
                string type = (arguments.ContainsKey("title") ? "title" : "namespace");
                string goal = GetGoalMessage(lang, type, arguments[type].ToString());

                await ctx.RespondAsync(Locale.GetMessage("streaming-closed", lang, goal, channel.Mention));
            });
        }
Esempio n. 4
0
        public async Task OpenStream(CommandContext ctx,
                                     [Description("streaming-help-channel")] DiscordChannel channel,
                                     [RemainingText, Description("streaming-help-args")] string args = "")
        {
            await CommandChecks(ctx, channel, args, async(arguments, lang) =>
            {
                Dictionary <string, dynamic> temp = EventStreams.SetData(channel.Id.ToString(), arguments);
                string type = (arguments.ContainsKey("title") ? "title" : "namespace");
                string goal = GetGoalMessage(lang, type, arguments[type].ToString());

                string desc = ListArguments(temp, lang);
                desc        = (desc.Length > 0 ? $":\n{desc}" : ".");
                await ctx.RespondAsync(Locale.GetMessage("streaming-opened", lang, goal, channel.Mention, desc));
            });
        }
Esempio n. 5
0
        public async Task CloseStream(CommandContext ctx,
                                      [Description("streaming-help-channel")] DiscordChannel channel,
                                      [Description("streaming-help-goal")] string goal        = "",
                                      [Description("streaming-help-minlength")] int minLength = -1)
        {
            string lang = Config.GetLang(ctx.Guild.Id.ToString());

            // Ensure that we are in private channel
            if (ctx.Channel.Name != "moderators")
            {
                await ctx.RespondAsync(Locale.GetMessage("denied", lang));

                return;
            }
            ;
            await ctx.TriggerTypingAsync();

            // Check for required parameters
            if (channel == null)
            {
                await ctx.RespondAsync(Locale.GetMessage("streaming-required-channel", lang, "help closeStream", Config.GetValue("prefix")));

                return;
            }

            if (goal == "")
            {
                await ctx.RespondAsync(Locale.GetMessage("streaming-required-goal", lang, "help closeStream", Config.GetValue("prefix")));

                return;
            }

            // Format the goal
            goal = goal.Replace("_", " ").Replace("\\", "");

            // Change JSON config
            string len = (minLength != -1 ? minLength.ToString() : "");

            EventStreams.RemoveData(goal, channel.Id.ToString(), len);

            await ctx.RespondAsync(Locale.GetMessage("streaming-removed", lang, goal, channel.Mention));
        }
Esempio n. 6
0
        public async Task EditStream(CommandContext ctx,
                                     [Description("streaming-help-channel")] DiscordChannel channel,
                                     [RemainingText, Description("streaming-help-args")] string args = "")
        {
            await CommandChecks(ctx, channel, args, async(arguments, lang) =>
            {
                Dictionary <string, dynamic> temp = EventStreams.SetData(channel.Id.ToString(), arguments, false);
                string type = (arguments.ContainsKey("title") ? "title" : "namespace");
                string goal = GetGoalMessage(lang, type, arguments[type].ToString());

                // Return a specific message if nothing was changed
                if (temp.Count == 0)
                {
                    await ctx.RespondAsync(Locale.GetMessage("streaming-edited-nothing", lang, goal, channel.Mention));
                    return;
                }

                string desc = ListArguments(temp, lang);
                await ctx.RespondAsync(Locale.GetMessage("streaming-edited", lang, goal, channel.Mention, desc));
            });
        }
Esempio n. 7
0
        private Task Client_GuildAvailable(GuildCreateEventArgs e)
        {
            // Log the name of the guild that just became available
            e.Client.DebugLogger.LogMessage(LogLevel.Info, "DiscordWikiBot", $"Guild available: {e.Guild.Name}", DateTime.Now);

            // Load custom values if needed
            string guild = e.Guild.Id.ToString();

            Linking.Init(guild);

            Locale.LoadCustomLocale(Config.GetLang(guild));

            if (Config.GetTWChannel() != null && Config.GetTWLang() != null)
            {
                TranslateWiki.Init(Config.GetTWChannel(guild), Config.GetTWLang(guild));
            }

            if (Config.GetDomain() != "")
            {
                EventStreams.Subscribe(Config.GetDomain(guild));
            }

            return(Task.FromResult(0));
        }
Esempio n. 8
0
        public async Task ListStreams(CommandContext ctx)
        {
            string lang = Config.GetLang(ctx.Guild.Id.ToString());
            await ctx.TriggerTypingAsync();

            IReadOnlyList <DiscordChannel> channelList = await ctx.Guild.GetChannelsAsync();

            string[] list   = channelList.Cast <DiscordChannel>().Select(x => x.Id.ToString()).ToArray();
            JObject  result = EventStreams.GetData(list);

            // Send a ping if there are no results
            if (result.Count == 0)
            {
                await ctx.RespondAsync(Locale.GetMessage("streaming-list-nothing", lang));

                return;
            }

            // Compile a list of streams
            List <string> msg = new List <string>();

            foreach (KeyValuePair <string, JToken> entry in result)
            {
                string output  = "";
                string goal    = entry.Key.Trim('<', '>');
                string goalMsg = GetGoalMessage(lang, (goal == entry.Key ? "title" : "namespace"), goal);
                output += Locale.GetMessage("streaming-list-stream", lang, goalMsg, entry.Value.Count()) + "\n";

                // List each stream with an editing command
                foreach (KeyValuePair <string, JToken> item in (JObject)entry.Value)
                {
                    ulong          id                 = ulong.Parse(item.Key);
                    DiscordChannel channel            = ctx.Guild.GetChannel(id);
                    Dictionary <string, dynamic> args = ((JObject)item.Value).ToObject <Dictionary <string, dynamic> >();

                    // Combine everything
                    string editGoal = (goal == entry.Key ? $" --title {goal}" : $" --namespace {goal}");
                    string argsMsg  = ListArguments(args, lang);
                    argsMsg = (argsMsg.Length > 0 ? $":\n{argsMsg}" : "");

                    output += $"{channel.Mention}{argsMsg}\n`!editStream #{channel.Name}{editGoal}`";
                }

                msg.Add(output);
            }

            string response = Locale.GetMessage("streaming-list", lang, result.Count, string.Join("\n", msg));

            if (response.Length <= 2000)
            {
                await ctx.RespondAsync(response);
            }
            else
            {
                // Split long lists of streams into multiple messages
                response = Locale.GetMessage("streaming-list", lang, result.Count, "");
                foreach (var stream in msg)
                {
                    string output = stream + "\n";
                    if (response.Length + output.Length <= 2000)
                    {
                        response += output;
                    }
                    else
                    {
                        await ctx.RespondAsync(response);

                        response = "";
                    }
                }

                if (response.Length > 0)
                {
                    await ctx.RespondAsync(response);
                }
            }
        }
Esempio n. 9
0
        /// <summary>
        /// Initialise the bot and keep it running
        /// </summary>
        public async Task Run()
        {
            // Set proper TLS settings
            ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

            // Check for a token
            string tokenPath = @"token.txt";

            if (!File.Exists(tokenPath))
            {
                Console.WriteLine("Please create a file called \"token.txt\" before running the bot!");
                Console.WriteLine("[Press any key to exit...]");
                Console.ReadKey();
                Environment.Exit(0);
            }
            Token = File.ReadAllText(tokenPath, Encoding.Default);

            // Get JSON config file
            Config.Init();

            // Initialise Discord client
            Client = new DiscordClient(new DiscordConfiguration()
            {
                AutoReconnect   = true,
                LargeThreshold  = 250,
                MinimumLogLevel = LogLevel.Information,
                Token           = Token,
                TokenType       = TokenType.Bot,
            });

            // Initialise events
            LogMessage($"DiscordWikiBot, version {Version}");

            // Get default locale
            Locale.Init();

            // Get site information and start linking bot
            LogMessage("Getting wiki site information");
            Linking.Init();

            // Methods for linking bot
            Client.MessageCreated += (s, e) =>
            {
                Task.Run(async() =>
                {
                    await Linking.Answer(s, e);
                });

                return(Task.CompletedTask);
            };
            Client.MessageUpdated += (s, e) =>
            {
                Task.Run(async() =>
                {
                    await Linking.Edit(s, e);
                });

                return(Task.CompletedTask);
            };
            Client.MessageDeleted      += Linking.Delete;
            Client.MessagesBulkDeleted += Linking.BulkDelete;

            // Start EventStreams
            if (Config.GetDomain() != null)
            {
                EventStreams.Init();
            }

            // Start Translatewiki fetches
            if (Config.GetTWChannel() != null && Config.GetTWLang() != null)
            {
                TranslateWiki.Init();
            }

            // Set some events for logging the information
            Client.Ready          += Client_Ready;
            Client.GuildAvailable += Client_GuildAvailable;
            Client.GuildCreated   += Client_GuildCreated;
            Client.GuildDeleted   += Client_GuildDeleted;
            Client.ClientErrored  += Client_ClientErrored;

            // Initialise commands
            LogMessage("Setting up commands");
            Commands = Client.UseCommandsNext(new CommandsNextConfiguration
            {
                StringPrefixes      = new[] { Config.GetValue("prefix") },
                EnableDms           = false,
                EnableMentionPrefix = true,
            });

            Commands.RegisterCommands <Pinging>();

            Commands.RegisterCommands <Configuring>();

            if (EventStreams.Enabled)
            {
                Commands.RegisterCommands <Streaming>();
            }

            // Set up custom formatter
            Commands.SetHelpFormatter <LocalisedHelpFormatter>();

            // Connect and start
            LogMessage("Connecting...");
            await Client.ConnectAsync();

            // Make sure not to close down automatically
            await CtrlC();
        }
Esempio n. 10
0
        public async Task Run()
        {
            // Set proper TLS settings
            ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

            // Check for a token
            string tokenPath = @"token.txt";

            if (!File.Exists(tokenPath))
            {
                Console.WriteLine("Please create a file called \"token.txt\" before running the bot!");
                Console.WriteLine("[Press any key to exit...]");
                Console.ReadKey();
                Environment.Exit(0);
            }
            Token = File.ReadAllText(tokenPath);

            // Get JSON config file
            Config.Init();

            // Initialise Discord client
            Client = new DiscordClient(new DiscordConfiguration()
            {
                AutoReconnect         = true,
                LargeThreshold        = 250,
                LogLevel              = LogLevel.Info,
                Token                 = Token,
                TokenType             = TokenType.Bot,
                UseInternalLogHandler = true,
            });

            // Initialise events
            Client.DebugLogger.LogMessage(LogLevel.Info, "DiscordWikiBot", "Initialising events", DateTime.Now);

            // Get locale
            Client.DebugLogger.LogMessage(LogLevel.Info, "DiscordWikiBot", string.Format("Loading {0} locale", Config.GetLang().ToUpper()), DateTime.Now);
            Locale.Init();

            // Get site information and start linking bot
            Client.DebugLogger.LogMessage(LogLevel.Info, "DiscordWikiBot", "Getting wiki site information", DateTime.Now);
            Linking.Init();

            // Methods for linking bot
            Client.MessageCreated += Linking.Answer;
            Client.MessageUpdated += Linking.Edit;
            Client.MessageDeleted += Linking.Delete;

            // Start EventStreams
            if (Config.GetDomain() != "")
            {
                EventStreams.Init();
            }

            // Start Translatewiki fetches
            if (Config.GetTWChannel() != null && Config.GetTWLang() != null)
            {
                Client.DebugLogger.LogMessage(LogLevel.Info, "DiscordWikiBot", $"Turning on Translatewiki ({Config.GetTWLang()})", DateTime.Now);
                TranslateWiki.Init();
            }

            // Set some events for logging the information
            Client.Ready          += Client_Ready;
            Client.GuildAvailable += Client_GuildAvailable;
            Client.ClientErrored  += Client_ClientErrored;

            // Initialise commands
            Client.DebugLogger.LogMessage(LogLevel.Info, "DiscordWikiBot", "Setting up commands", DateTime.Now);
            Commands = Client.UseCommandsNext(new CommandsNextConfiguration
            {
                StringPrefix        = Config.GetValue("prefix"),
                EnableDms           = false,
                EnableMentionPrefix = true,
            });

            Commands.RegisterCommands <Configuring>();

            Commands.RegisterCommands <Streaming>();

            // Set up custom formatter
            Commands.SetHelpFormatter <LocalisedHelpFormatter>();

            // Connect and start
            Client.DebugLogger.LogMessage(LogLevel.Info, "DiscordWikiBot", "Connecting...", DateTime.Now);
            await Client.ConnectAsync();

            // Make sure not to close down automatically
            await CtrlC();
        }
Esempio n. 11
0
        public async Task SetDomain(CommandContext ctx,
                                    [Description("configuring-help-domain-value"), RemainingText] string value)
        {
            string prevDomain = Config.GetDomain(ctx.Guild.Id.ToString());
            string lang       = Config.GetLang(ctx.Guild.Id.ToString());

            // List of Wikimedia projects
            string[] wmfProjects =
            {
                ".wikipedia.org",
                ".wiktionary.org",
                ".wikibooks.org",
                ".wikinews.org",
                ".wikiquote.org",
                ".wikisource.org",
                ".wikiversity.org",
                ".wikivoyage.org",
                ".wikimedia.org",
                "www.mediawiki.org",
                "www.wikidata.org"
            };

            // Ensure that we are in private channel
            if (ctx.Channel.Name != "moderators")
            {
                await ctx.RespondAsync(Locale.GetMessage("denied", lang));

                return;
            }
            ;
            await ctx.TriggerTypingAsync();

            // Check for required parameters
            if (value.ToString() == "")
            {
                await ctx.RespondAsync(Locale.GetMessage("configuring-required-value", lang, "help guildDomain", Config.GetValue("prefix")));

                return;
            }

            // Check if matches Wikimedia project
            bool isWmfProject = false;

            if (value != "-" && wmfProjects.Any(value.Contains))
            {
                isWmfProject = true;
            }

            if (!isWmfProject)
            {
                await ctx.RespondAsync(Locale.GetMessage("configuring-badvalue-domain", lang, "`" + string.Join("`, `", wmfProjects) + "`"));

                return;
            }

            // Check for return to default
            if (value == "-")
            {
                value = Config.GetDomain();
            }

            // Do action and respond
            int succeeds = Config.SetOverride(ctx.Guild.Id.ToString(), "domain", value);

            if (succeeds == Config.RESULT_CHANGE)
            {
                EventStreams.Subscribe(value);
                await ctx.RespondAsync(Locale.GetMessage("configuring-changed-domain", lang, value));
            }
            if (succeeds == Config.RESULT_RESET)
            {
                // Unsubscribe if this domain is not being used elsewhere
                if (value != prevDomain && !Config.IsValuePresent("domain", prevDomain))
                {
                    EventStreams.Unsubscribe(value);
                }
            }
            await RespondOnErrors(succeeds, ctx, lang);
        }