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); }
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); }
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)); }); }
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)); }); }
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)); }
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)); }); }
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)); }
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); } } }
/// <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(); }
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(); }
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); }