internal void RemoveEventHandler(IDiscordInterface e) { if (e is IDiscordAPIEvents a) { api.Remove(a); } if (e is IDiscordChannelEvents c) { channel.Remove(c); } if (e is IDiscordServerEvents s) { server.Remove(s); } if (e is IDiscordInviteEvents i) { invite.Remove(i); } if (e is IDiscordMessageEvents m) { message.Remove(m); } if (e is IDiscordStatusEvents st) { status.Remove(st); } if (e is IDiscordVoiceEvents v) { voice.Remove(v); } if (e is IDiscordWebhookEvents w) { webhook.Remove(w); } }
protected override async Task ExecuteAsync(CancellationToken stoppingToken) { foreach (var token in await _apiTokenData.GetAllKeys()) { _logger.Info($"Setting up discord client for Server {token.ServerName}"); _discordSocketClient = new DiscordSocketClient(new DiscordSocketConfig { MessageCacheSize = 0, ExclusiveBulkDelete = true, AlwaysDownloadUsers = true, GatewayIntents = GatewayIntents.Guilds | GatewayIntents.GuildMembers | GatewayIntents.GuildMessageReactions | GatewayIntents.GuildMessages | GatewayIntents.GuildVoiceStates }); _discordSocketClient.Log += message => { if (message.Exception != null) { _logger.Warn($"DiscordClient: {message.Message} - {message.Exception.Message}"); } else { _logger.Info($"DiscordClient: {message.Message}"); } return(Task.CompletedTask); }; _discordSocketClient.Ready += () => { _logger.Info($"Discord client for {token.ServerName} is ready"); return(Task.CompletedTask); }; _discordSocketClient.Disconnected += exception => { _logger.Error($"Discord Client disconnected: {exception.Message}"); return(Task.CompletedTask); }; //TODO handle disconnected event and try to reconnect await _discordSocketClient.LoginAsync(TokenType.Bot, token.ApiKey); await _discordSocketClient.StartAsync(); _discordInterface = new DiscordInterface(_discordSocketClient); _commandProcessingService = new CommandProcessingService(_discordInterface, _schedulerFactory, _activityMonitor); await _commandProcessingService.StartAsync(CancellationToken.None); //TODO when monitoring users in channels create that service here break; //TODO only use 1 server at a time for now } }
/// <summary> /// Constructor /// </summary> /// <param name="discordInterface">Interface to send and receive discord messages</param> /// <param name="schedulerFactory">Generator for Reactive Schedulers</param> /// <param name="activityMonitor">Allows the commands to log an event occuring</param> public CommandProcessingService(IDiscordInterface discordInterface, ISchedulerFactory schedulerFactory, IActivityMonitor activityMonitor) { _discordInterface = discordInterface; _schedulerFactory = schedulerFactory; _activityMonitor = activityMonitor; _scheduler = schedulerFactory.GenerateScheduler(); _commandDict = new Dictionary <string, BaseDiscordCommand>(); }
/// <summary> /// Runs a game of trivia with the provided trivia source. /// Expected args: /// 1. Trivia source name that matches a provider in _questionProviders /// 2. (Optional) The number of rounds to play, default is 10 /// </summary> /// <param name="discordInterface"></param> /// <param name="args"></param> /// <param name="rawMessage"></param> protected override async Task Execute(IDiscordInterface discordInterface, string[] args, SocketMessage rawMessage) { if (!TryExtractArgs(args, out var questionProvider, out var gameLength)) { // Command was used wrong, print usage info and exit await discordInterface.SendMessageAsync(rawMessage.Channel, FullHelpText); return; } Subject <DiscordMessage> subject = new Subject <DiscordMessage>(); discordInterface.MessageReceived.ObserveOn(_scheduler) .Where(message => message.Channel.Id == rawMessage.Channel.Id) .Subscribe(message => { subject.OnNext(new DiscordMessage(message.Channel, message.Author.Username, message.Content)); }); var gameResult = new GameResults(); // Start asking questions var questions = await questionProvider.GetQuestions(gameLength); //TODO this might need to be async for (int i = 0; i < questions.Count; i++) { await discordInterface.SendMessageAsync(rawMessage.Channel, $"Question {i + 1}:\n{questions[i].Question}"); var result = await questions[i].ExecuteQuestion(subject.AsObservable(), questionProvider.QuestionDuration); if (result.Scores.Count == 0) { // No one was correct await discordInterface.SendMessageAsync(rawMessage.Channel, $"No one was correct! Answer:\n{questions[i].Answer}"); } else { gameResult.CombineWith(result); //Someone was correct await discordInterface.SendMessageAsync(rawMessage.Channel, $"{String.Join(", ", result.Scores.Where(score => score.Value > 0).Select(score => score.Key))} was correct!\n" + $"{gameResult.PrintScores()}"); } } // Game is over, inform everyone of the winner await discordInterface.SendMessageAsync(rawMessage.Channel, $"Game over, winner was {gameResult.GetWinner()}\n" + $"{gameResult.PrintScores()}"); }
protected override async Task Execute(IDiscordInterface discordInterface, string[] args, SocketMessage rawMessage) { var response = new StringBuilder(); response.AppendLine("Test command:"); response.AppendLine($"From User: {rawMessage.Author.Username}"); response.AppendLine($"Channel: {rawMessage.Channel.Name}"); for (int i = 0; i < args.Length; i++) { response.AppendLine($"Arg{i}: {args[i]}"); } await discordInterface.SendMessageAsync(rawMessage.Channel, response.ToString()); }
public async Task ExecuteCommand(IDiscordInterface discordInterface, string[] args, SocketMessage rawMessage) { try { bool allowed = true; string reason = ""; // Check if we are allowed to do this command in this channel if (AllowedChannels.Length != 0 && !AllowedChannels.Contains(rawMessage.Channel.Name)) { allowed = false; reason += $"In channel {rawMessage.Channel.Name} but allowed channels are {String.Join(',', AllowedChannels)}\n"; } // Check if this user has a role that is in the whitelist if (AllowedRoles.Length != 0 && !rawMessage.Author.GetRolesAsString().ToList().Intersect(AllowedRoles).Any()) { allowed = false; reason += $"Allowed roles are {String.Join(',', AllowedRoles)} but user {rawMessage.Author.Username} " + $"only has roles {String.Join(',', rawMessage.Author.GetRolesAsString())}\n"; } // Check if this user has a role that is in the blacklist if (DisallowedRoles.Length != 0 && rawMessage.Author.GetRolesAsString().Intersect(DisallowedRoles).Any()) { allowed = false; reason += $"User {rawMessage.Author.Username} has blacklisted role/s " + $"{String.Join(',', rawMessage.Author.GetRolesAsString().Intersect(DisallowedRoles))}\n"; } if (allowed) { await Execute(discordInterface, args, rawMessage); } else { _logger.Warn($"User {rawMessage.Author.Username} tried to execute command {CommandString} but it failed because:\n{reason.Trim()}"); } } catch (Exception e) { _logger.Error(e, $"Unexpected error when attmpeting to exectue a command: {e.Message}"); } }
public static void UnregisterEventsHandler(IDiscordInterface e) => interfaces.RemoveEventHandler(e);
public static void RegisterEventsHandler(IDiscordInterface e) => interfaces.AddEventHandler(e);
/// <summary> /// Execute the discord command /// </summary> /// <param name="discordInterface"></param> /// <param name="args"></param> /// <param name="rawMessage"></param> /// <returns></returns> protected abstract Task Execute(IDiscordInterface discordInterface, string[] args, SocketMessage rawMessage);
protected override Task Execute(IDiscordInterface discordInterface, string[] args, SocketMessage rawMessage) { ExecuteCount++; return(Task.CompletedTask); }
protected override async Task Execute(IDiscordInterface discordInterface, string[] args, SocketMessage rawMessage) { // Get the current username. This can be either the current nickname, or the discord username, or the discord user id (if it is an integer) // Can also be surround in quotes f**k my life args = Utils.ArgumentParseUtils.ParseArgsWithQuotes(args); if (args.Length < 3) { await SendMessage("Read how to use this command you peppeg"); _logger.Debug($"Received invalid Rename user: {String.Join(',', args)}"); return; } var currentName = args[1]; var newName = args[2]; SocketGuildUser user = null; // Try with user ID if (long.TryParse(currentName, out long userId)) { try { user = discordInterface.RawClient.GetUser((ulong)userId) as SocketGuildUser; } catch (Exception e) { _logger.Error(e, $"Cannot find user with id {userId}: {e.Message}"); } } // Try with nickname or username if (user == null) { foreach (var guild in discordInterface.RawClient.Guilds) { user = guild.Users.FirstOrDefault(p => p.Username == currentName || p.Nickname == currentName); if (user != null) { break; } } } if (user != null) { try { await user?.ModifyAsync(x => x.Nickname = newName); await SendMessage($"Changed {currentName} to {newName}"); await ActivityMonitor.LogActivity(new Activity() { CommandName = CommandString, Author = rawMessage.Author.Username, Channel = rawMessage.Channel.Name, Succeeded = true, Result = $"Changed user {user.Username} nickname from {currentName} to {newName}" }); } catch (Exception e) { await SendMessage($"ERROR: {e.Message}"); await ActivityMonitor.LogActivity(new Activity() { CommandName = CommandString, Author = rawMessage.Author.Username, Channel = rawMessage.Channel.Name, Succeeded = false, Result = $"Failed to change username for user {user.Username}: {e.Message}" }); } } else { await SendMessage($"Cannot find user with name {currentName}"); await ActivityMonitor.LogActivity(new Activity() { CommandName = CommandString, Author = rawMessage.Author.Username, Channel = rawMessage.Channel.Name, Succeeded = false, Result = $"Cannot find user with name {currentName}" }); } async Task SendMessage(string message) => await discordInterface.SendMessageAsync(rawMessage.Channel, message); }