public static async Task SetDefaultRaidReactions(this DiscordClient client, DiscordMessage message, bool isLobby, bool deleteExisting = true) { if (client == null) { return; } if (deleteExisting) { try { await message?.DeleteAllReactionsAsync(); await Task.Delay(10); } catch (Exception ex) { _logger.Error(ex); } } await message.CreateReactionAsync(DiscordEmoji.FromName(client, ":arrow_right:")); await message.CreateReactionAsync(DiscordEmoji.FromName(client, ":white_check_mark:")); if (isLobby) { await message.CreateReactionAsync(DiscordEmoji.FromName(client, ":x:")); await message.CreateReactionAsync(DiscordEmoji.FromName(client, ":arrows_counterclockwise:")); } }
private async Task CheckFeedChannelStatus(ulong channelId) { var channel = await _client.GetChannel(channelId); if (channel == null) { _logger.Error($"Failed to find Discord channel with id {channelId}."); return; } var mostRecent = await channel.GetMessage(channel.LastMessageId); if (mostRecent == null) { _logger.Error($"Failed to retrieve last message for channel {channel.Name}."); return; } if (IsFeedUp(mostRecent.Timestamp.DateTime, FeedDownThreshold)) { return; } var owner = await _client.GetUser(_config.OwnerId); if (owner == null) { _logger.Error($"Failed to find owner with id {_config.OwnerId}."); return; } await _client.SendDirectMessage(owner, $"DISCORD FEED **{channel.Name}** IS DOWN!", null); await Utils.Wait(200); }
public static Location GetGoogleAddress(string city, double lat, double lng, string gmapsKey) { var apiKey = string.IsNullOrEmpty(gmapsKey) ? string.Empty : $"&key={gmapsKey}"; var url = $"https://maps.googleapis.com/maps/api/geocode/json?latlng={lat},{lng}&sensor=true{apiKey}"; var unknown = "Unknown"; try { var request = (HttpWebRequest)WebRequest.Create(url); var response = request.GetResponse(); using (var responseStream = response.GetResponseStream()) { var reader = new StreamReader(responseStream, Encoding.UTF8); var data = reader.ReadToEnd(); var parseJson = JObject.Parse(data); var status = Convert.ToString(parseJson["status"]); if (string.Compare(status, "OK", true) != 0) { return(null); } var result = parseJson["results"].FirstOrDefault(); var address = Convert.ToString(result["formatted_address"]); //var area = Convert.ToString(result["address_components"][2]["long_name"]); return(new Location(address, city ?? unknown, lat, lng)); } } catch (Exception ex) { _logger.Error(ex); } return(null); }
public SendEmailResponse SendEmail(SendEmailRequest sendEmailRequest) { try { var response = _client.SendEmail( sendEmailRequest.EmailAddress, sendEmailRequest.TemplateId, sendEmailRequest.Personalisation); return(response == null ? null : new SendEmailResponse { EmailId = response.id }); } catch (NotifyClientException e) { CustomLogger.Error( "EMAIL FAILURE: Error whilst sending email using Gov.UK Notify", new { NotifyEmail = sendEmailRequest, Personalisation = JsonConvert.SerializeObject(sendEmailRequest.Personalisation), ErrorMessageFromNotify = e.Message }); throw; } }
static void Main(string[] args) { // https://blog.magnusmontin.net/2018/11/05/platform-conditional-compilation-in-net-core/ //#if Linux // Console.WriteLine("Built on Linux!"); //#elif OSX // Console.WriteLine("Built on macOS!"); //#elif Windows // Console.WriteLine("Built in Windows!"); //#endif var config = Config.Load(Strings.ConfigFileName); if (config == null) { _logger.Error($"Failed to load config {Strings.ConfigFileName}."); return; } var allFound = ValidateCommandsExist(); if (!allFound) { _logger.Error($"Requirements not found on machine, exiting..."); return; } var bot = new Bot(config); bot.Start(); Process.GetCurrentProcess().WaitForExit(); }
private void AssignGuildMembersToRole(DiscordMessage message, List <string> roles, bool defaultCityFeed) { #pragma warning disable RECS0165 new System.Threading.Thread(async x => #pragma warning restore RECS0165 { var guild = message.Channel.Guild; var success = 0; var errors = 0; var failed = new List <string>(); await message.RespondAsync ( defaultCityFeed ? $"Starting default city feed assignment for all users of guild **{guild.Name}**." : $"Starting {string.Join(",", roles)} role(s) assignment to all users of guild **{guild.Name}**." ); foreach (var member in guild.Members) { try { foreach (var role in roles) { var discordRole = _client.GetRoleFromName(role); if (discordRole == null) { //Failed to find role. _logger.Error($"Failed to find city role {role}, please make sure it exists."); continue; } await member.GrantRoleAsync(discordRole, $"{discordRole.Name} role assignment."); _logger.Info($"Assigned {member.Username} to role {discordRole.Name}."); } success++; } catch (Exception ex) { errors++; failed.Add(member.Username); _logger.Error(ex); } } _logger.Info($"Finished assigning {string.Join(",", roles)} roles."); await message.RespondAsync ( $"{success}/{guild.MemberCount} members were assigned the " + (defaultCityFeed ? "default city feed" : string.Join(",", roles)) + $" roles and {errors} member's roles were not set." + (failed.Count == 0 ? "" : "\r\nList of users role assignment failed:\r\n" + string.Join(Environment.NewLine, failed)) ); }) { IsBackground = true }.Start(); }
private void LoadGeofences() { foreach (var(serverId, serverConfig) in _config.Instance.Servers) { serverConfig.Geofences.Clear(); var geofenceFiles = serverConfig.GeofenceFiles; var geofences = new List <GeofenceItem>(); if (geofenceFiles != null && geofenceFiles.Any()) { foreach (var file in geofenceFiles) { var filePath = Path.Combine(Strings.GeofenceFolder, file); try { var fileGeofences = GeofenceItem.FromFile(filePath); geofences.AddRange(fileGeofences); _logger.Info($"Successfully loaded {fileGeofences.Count} geofences from {file}"); } catch (Exception ex) { _logger.Error($"Could not load Geofence file {file} (for server {serverId}):"); _logger.Error(ex); } } } serverConfig.Geofences.AddRange(geofences); } }
public void ParseData(string data) { try { if (string.IsNullOrEmpty(data)) { return; } //File.AppendAllText("debug.txt", data + "\r\n"); var obj = JsonConvert.DeserializeObject <dynamic>(data); if (obj == null) { return; } foreach (dynamic part in obj) { string type = Convert.ToString(part["type"]); dynamic message = part["message"]; switch (type) { case "pokemon": ParsePokemon(message); break; //case "gym": // ParseGym(message); // break; //case "gym-info": //case "gym_details": // ParseGymInfo(message); // break; //case "egg": case "raid": ParseRaid(message); break; //case "tth": //case "scheduler": // ParseTth(message); // break; } } } catch (Exception ex) { Utils.LogError(ex); _logger.Error(ex); _logger.Info("{0}", Convert.ToString(data)); } }
private bool SwitchWorkerAccounts(string city, int amount) { //Check if workers supply file exists. var supplyWorkersFile = Path.Combine(_config.MapFolder, SupplyPath); if (!File.Exists(supplyWorkersFile)) { _logger.Error($"Failed to find workers supply file..."); return(false); } //Retrieve all workers in a list. var goodWorkers = new List <string>(File.ReadAllLines(supplyWorkersFile)); if (goodWorkers.Count == 0) { _logger.Error($"Failed to get list of workers, file is empty..."); return(false); } //Take an amount from the supply list. var count = Math.Min(amount, goodWorkers.Count); var newWorkers = goodWorkers.Take(count).ToList(); goodWorkers.RemoveAll(newWorkers.Contains); //Write new workers supply list. File.WriteAllLines(supplyWorkersFile, goodWorkers); //Check if the old workers file for the specified city exists. var cityWorkersFile = Path.Combine(_config.MapFolder, string.Format(AccountsFile, city)); if (!File.Exists(cityWorkersFile)) { _logger.Error($"Failed to get workers file at {cityWorkersFile}."); return(false); } //Check if there are any old workers that might be banned, if so write them out. var oldWorkers = new List <string>(File.ReadAllLines(cityWorkersFile)); if (oldWorkers.Count > 0) { //Write out banned/used workers. var bannedWorkersFile = Path.Combine(_config.MapFolder, $"{BannedPath}{DateTime.Now.ToString("yyyy-MM-dd")}.txt"); File.AppendAllLines(bannedWorkersFile, oldWorkers); } //Write out good workers. File.WriteAllLines(cityWorkersFile, newWorkers); return(true); }
public void UpdateOrganisationDetails(long organisationId) { _CustomLogger.Debug($"Loading organisation - OrganisationId({organisationId})"); var organisation = _DataRepository.Get <Organisation>(organisationId); _CustomLogger.Debug($"Updating LastCheckedAgainstCompaniesHouse - OrganisationId({organisationId})"); organisation.LastCheckedAgainstCompaniesHouse = VirtualDateTime.Now; _DataRepository.SaveChangesAsync().Wait(); try { _CustomLogger.Debug($"Calling CoHo API - OrganisationId({organisationId})"); var organisationFromCompaniesHouse = _CompaniesHouseAPI.GetCompanyAsync(organisation.CompanyNumber).Result; _CustomLogger.Debug($"Starting transaction - OrganisationId({organisationId})"); _DataRepository.BeginTransactionAsync( async() => { try { _CustomLogger.Debug($"Updating SIC codes - OrganisationId({organisationId})"); UpdateSicCode(organisation, organisationFromCompaniesHouse); _CustomLogger.Debug($"Updating Address - OrganisationId({organisationId})"); UpdateAddress(organisation, organisationFromCompaniesHouse); _CustomLogger.Debug($"Updating Name - OrganisationId({organisationId})"); UpdateName(organisation, organisationFromCompaniesHouse); _CustomLogger.Debug($"Saving - OrganisationId({organisationId})"); _DataRepository.SaveChangesAsync().Wait(); _DataRepository.CommitTransaction(); _CustomLogger.Debug($"Saved - OrganisationId({organisationId})"); } catch (Exception ex) { var message = $"Update from Companies House: Failed to update database, organisation id = {organisationId}"; _CustomLogger.Error(message, ex); _DataRepository.RollbackTransaction(); } }) .Wait(); } catch (Exception ex) { var message = $"Update from Companies House: Failed to get company data from companies house, organisation id = {organisationId}"; _CustomLogger.Error(message, ex); } }
public async Task SetReminder(DiscordMessage message, string reminder, string where = "", string seperator = "in") { try { var userId = message.Author.Id; var time = GetTimeInterval(reminder); if (Convert.ToInt32(time) == 0) { await message.RespondAsync($"{message.Author.Mention} you specified an invalid time format."); return; } if (!CheckTimeInterval(userId, time)) { await message.RespondAsync($"{message.Author.Mention}, you cannot have two reminders that are within 60 seconds of each other."); return; } ulong channelId = 0; if (!string.IsNullOrEmpty(where)) { channelId = message.ChannelId; } var reminders = new List <Reminder>(); if (_db.Reminders.ContainsKey(userId)) { _db.Reminders.TryGetValue(userId, out reminders); } reminder = SanitizeString(reminder); var msg = reminder.Substring(0, reminder.LastIndexOf(seperator, StringComparison.Ordinal)); var data = new Reminder { Time = DateTime.UtcNow.AddSeconds(time), Message = msg, Where = channelId }; reminders.Add(data); _db.Reminders.AddOrUpdate(userId, reminders, (key, oldValue) => reminders); ReminderSvc.ChangeToClosestInterval(); _db.Save(); await message.RespondAsync($"Successfully set reminder for {message.Author.Mention} to `{data.Message}` in `{reminder.Substring(reminder.LastIndexOf(seperator, StringComparison.Ordinal) + seperator.Length)}`!"); } catch (Exception ex) { _logger.Error(ex); } }
public override string Translate(string value) { try { return(base.Translate(value) ?? value); } catch (Exception ex) { _logger.Error($"Failed to find locale translation for key '{value}'"); _logger.Error(ex); } return(value); }
private AlarmList LoadAlarms(string alarmsFilePath) { _logger.Trace($"WebhookManager::LoadAlarms [AlarmsFilePath={alarmsFilePath}]"); if (!File.Exists(alarmsFilePath)) { _logger.Error($"Failed to load file alarms file '{alarmsFilePath}'..."); return(null); } var alarmData = File.ReadAllText(alarmsFilePath); if (string.IsNullOrEmpty(alarmData)) { _logger.Error($"Failed to load '{alarmsFilePath}', file is empty..."); return(null); } var alarms = JsonConvert.DeserializeObject <AlarmList>(alarmData); if (alarms == null) { _logger.Error($"Failed to deserialize the alarms file '{alarmsFilePath}', make sure you don't have any json syntax errors."); return(null); } _logger.Info($"Alarms file {alarmsFilePath} was loaded successfully."); alarms.Alarms.ForEach(x => { var geofences = x.LoadGeofence(); for (var i = 0; i < geofences.Count; i++) { var geofence = geofences[i]; if (!Geofences.ContainsKey(geofence.Name)) { Geofences.Add(geofence.Name, geofence); _logger.Debug($"Geofence file loaded for {x.Name}..."); } } _logger.Info($"Loading alerts file {x.AlertsFile}..."); x.LoadAlerts(); _logger.Info($"Loading filters file {x.FiltersFile}..."); x.LoadFilters(); }); return(alarms); }
public SubscriptionManager(WhConfig whConfig) { _logger.Trace($"SubscriptionManager::SubscriptionManager"); _whConfig = whConfig; if (_whConfig?.Database?.Main == null) { var err = "Main database is not configured in config.json file."; _logger.Error(err); throw new NullReferenceException(err); } if (_whConfig?.Database?.Scanner == null) { var err = "Scanner database is not configured in config.json file."; _logger.Error(err); throw new NullReferenceException(err); } _connFactory = new OrmLiteConnectionFactory(_whConfig.Database.Main.ToString(), MySqlDialect.Provider); //_scanConnFactory = new OrmLiteConnectionFactory(_whConfig.Database.Scanner.ToString(), MySqlDialect.Provider); if (!CreateDefaultTables()) { _logger.Error("FAiled to create default tables"); } // Reload subscriptions every 60 seconds to account for UI changes _reloadTimer = new Timer(_whConfig.ReloadSubscriptionChangesMinutes * 60 * 1000); _reloadTimer.Elapsed += OnReloadTimerElapsed; _reloadTimer.Start(); ReloadSubscriptions(); }
public string Translate(string value, params object[] args) { try { return(args.Length > 0 ? string.Format(base.Translate(value), args) : base.Translate(value)); } catch (Exception ex) { _logger.Error($"Failed to find locale translation for key '{value}' and arguments: '{string.Join(",", args)}'"); _logger.Error(ex); } return(value); }
public static string FormatText(this string text, params object[] args) { try { var msg = text; for (var i = 0; i < args.Length; i++) { if (string.IsNullOrEmpty(msg)) { continue; } if (args == null) { continue; } if (args[i] == null) { msg = msg.Replace("{" + i + "}", null); continue; } msg = msg.Replace("{" + i + "}", args[i].ToString()); } return(msg); } catch (Exception ex) { _logger.Error(ex); return(string.Format(text, args)); } }
private async Task <DiscordChannel> CreateLobbyChannel(Lobby lobby) { _logger.Trace($"RaidLobbyManager::CreateLobbyChannel [Lobby={lobby.ChannelName}]"); try { var lobbyCategory = await GetLobbyCategory(); var exists = lobbyCategory.Children.FirstOrDefault(x => string.Compare(x.Name, lobby.ChannelName, true) == 0); var lobbyChannel = exists ?? await lobbyCategory.Guild.CreateChannelAsync(lobby.ChannelName, ChannelType.Text, lobbyCategory); if (lobbyChannel == null) { _logger.Warn($"Could not create raid lobby channel with channel name {lobby.ChannelName}."); return(null); } return(lobbyChannel); } catch (Exception ex) { _logger.Error(ex); } return(null); }
public static string Execute(string cmd, string args, out int exitCode, bool includeErrorOutput = false) { var psi = new ProcessStartInfo { FileName = cmd, Arguments = args, CreateNoWindow = true, RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, WindowStyle = ProcessWindowStyle.Hidden }; var p = Process.Start(psi); var output = p.StandardOutput.ReadToEndAsync().GetAwaiter().GetResult(); if (includeErrorOutput) { output += '\n' + p.StandardError.ReadToEndAsync().GetAwaiter().GetResult(); } p.OutputDataReceived += (sender, e) => _logger.Debug($"[OUT] {e.Data}"); p.ErrorDataReceived += (sender, e) => _logger.Error($"[ERR] {e.Data}"); p.WaitForExit(); exitCode = p.ExitCode; return(output); }
private async Task StartFeeds(DiscordMessage message, List <string> feeds) { var msg = string.Empty; var started = new List <string>(); var failed = new List <string>(); try { foreach (var cityName in feeds) { if (TaskManager.StartTask("RM " + cityName)) { started.Add(cityName); } else { failed.Add(cityName); } } await message.RespondAsync ( (started.Count > 0 ? $"{message.Author.Mention} started feed(s) **{string.Join("**, **", started)}**." : string.Empty) + (failed.Count > 0 ? $"\r\n{message.Author.Mention} failed to start feed(s) **{string.Join("**, **", failed)}**." : string.Empty) ); } catch (Exception ex) { _logger.Error(ex); } }
public async Task Execute(DiscordMessage message, Command command) { if (!command.HasArgs) { return; } if (command.Args.Count != 2) { return; } await message.IsDirectMessageSupported(); var channelName = command.Args[0]; var channel = _client.GetChannelByName(channelName); if (channel == null) { await message.RespondAsync($"Failed to lookup channel {channelName}."); return; } try { var msg = command.Args[1]; await channel.SendMessageAsync(msg); } catch (Exception ex) { _logger.Error(ex); } }
private async Task ProcessPendingQueue() { try { T firstEvent = null; if (_queue.Count > 0) { firstEvent = _queue.Dequeue(); } if (firstEvent == null) { return; } var success = await ProcessEvent(firstEvent); if (!success) { return; } QueueLengthChanged(_queue.Count); } catch (Exception ex) { _logger.Error(ex); } }
public async Task Execute(DiscordMessage message, Command command) { if (!command.HasArgs) { await message.RespondAsync($"{message.Author.Mention} please specify a city e.g. `{_config.CommandsPrefix}{command.Name} Upland`"); return; } var city = command.Args[0]; if (!_config.CityRoles.Exists(x => string.Compare(x, city, true) == 0)) { await message.RespondAsync($"{message.Author.Mention} you may only check weather conditions of one of the following cities: **{string.Join("**, **", _config.CityRoles)}**."); return; } try { var weather = _weatherSvc.GetWeatherConditions(city); if (weather == null) { await message.RespondAsync($"{message.Author.Mention} failed to retrieve the weather conditions for {city}."); return; } var eb = new DiscordEmbedBuilder(); eb.WithTitle($"{city} Weather Conditions"); eb.AddField("Weather", weather.GameplayWeather.ToString().Replace("_", null), true); eb.AddField("Time", weather.WorldTime.ToString(), true); eb.AddField("Severity", weather.Severity.ToString(), true); eb.AddField("Warning Weather", weather.WarnWeather.ToString(), true); eb.AddField("Cloud Level", weather.CloudLevel.ToString(), true); eb.AddField("Rain Level", weather.RainLevel.ToString(), true); eb.AddField("Fog Level", weather.FogLevel.ToString(), true); eb.AddField("Snow Level", weather.SnowLevel.ToString(), true); eb.AddField("Wind Level", weather.WindLevel.ToString(), true); eb.AddField("Wind Direction", weather.WindDirection.ToString(), true); eb.AddField("Last Updated", weather.LastUpdated.ToLocalTime().ToString()); //eb.AddField("Weather", weather.WeatherText, true); //eb.AddField("Temperature", $"{weather.Temperature.Imperial.Value}°{weather.Temperature.Imperial.Unit}", true); //eb.WithImageUrl(string.Format(WeatherIconUrl, weather.WeatherIcon.ToString("D2"))); //eb.WithUrl(weather.Link); var embed = eb.Build(); if (embed == null) { return; } await message.RespondAsync(string.Empty, false, embed); } catch (Exception ex) { _logger.Error(ex); } }
public void LoadConfigs() { if (!Directory.Exists(TemplatesFolder)) { _logger.Error($"Templates folder for static maps does not exist: {TemplatesFolder}"); return; } }
private static int ParsePokemonId(string value) { var split = value.Split('_'); if (!int.TryParse(split[0], out var id)) { _logger.Error($"Failed to parse grunttype {split[0]}"); return(0); } return(id); }
public static bool MatchesIV(string iv, uint minimumIV, uint maximumIV) { var matchesIV = false; var missing = iv == "?" || string.IsNullOrEmpty(iv); if (!missing) { if (!double.TryParse(iv.Replace("%", ""), out double resultIV)) { _logger.Error($"Failed to parse pokemon IV value '{iv}', skipping filter check."); return(false); } matchesIV |= Math.Round(resultIV) >= minimumIV && Math.Round(resultIV) <= maximumIV; } matchesIV |= (missing && minimumIV == 0); return(matchesIV); }
public static List <GeofenceItem> LoadGeofences(string geofencesFolder) { var geofences = new List <GeofenceItem>(); foreach (var file in Directory.EnumerateFiles(geofencesFolder)) { try { var fileGeofences = GeofenceItem.FromFile(file); geofences.AddRange(fileGeofences); } catch (Exception ex) { _logger.Error($"Could not load Geofence file {file}:"); _logger.Error(ex); } } return(geofences); }
private async Task Client_GuildAvailable(GuildCreateEventArgs e) { // If guild is in configured servers list then attempt to create emojis needed if (_whConfig.Servers.ContainsKey(e.Guild.Id)) { await UpdateGuildStats(e.Guild); if (!(e.Client is DiscordClient client)) { _logger.Error($"DiscordClient is null, Unable to update status."); return; } // Set custom bot status if guild is in config server list if (_whConfig.Servers.ContainsKey(e.Guild.Id)) { var status = _whConfig.Servers[e.Guild.Id].Status; await client.UpdateStatusAsync(new DiscordGame(status ?? $"v{Strings.Version}"), UserStatus.Online); } } }
public SubscriptionManager(WhConfigHolder whConfig) { _logger.Trace($"SubscriptionManager::SubscriptionManager"); _whConfig = whConfig; if (_whConfig.Instance?.Database?.Main == null) { var err = "Main database is not configured in config.json file."; _logger.Error(err); throw new NullReferenceException(err); } if (_whConfig.Instance?.Database?.Scanner == null) { var err = "Scanner database is not configured in config.json file."; _logger.Error(err); throw new NullReferenceException(err); } if (_whConfig.Instance?.Database?.Nests == null) { _logger.Warn("Nest database is not configured in config.json file, nest alarms and commands will not work."); } _connFactory = new OrmLiteConnectionFactory(_whConfig.Instance.Database.Main.ToString(), MySqlDialect.Provider); // Reload subscriptions every minute x 60 seconds to account for UI changes _reloadTimer = new Timer(_whConfig.Instance.ReloadSubscriptionChangesMinutes * 60 * 1000); _reloadTimer.Elapsed += (sender, e) => ReloadSubscriptions(); _reloadTimer.Start(); ReloadSubscriptions(); }
private AlarmList LoadAlarms(string alarmsFilePath) { _logger.Trace($"WebhookManager::LoadAlarms [AlarmsFilePath={alarmsFilePath}]"); if (!File.Exists(alarmsFilePath)) { _logger.Error($"Failed to load file alarms file '{alarmsFilePath}'..."); return(null); } var alarmData = File.ReadAllText(alarmsFilePath); if (string.IsNullOrEmpty(alarmData)) { _logger.Error($"Failed to load '{alarmsFilePath}', file is empty..."); return(null); } var alarms = JsonConvert.DeserializeObject <AlarmList>(alarmData); if (alarms == null) { _logger.Error($"Failed to deserialize the alarms file '{alarmsFilePath}', make sure you don't have any json syntax errors."); return(null); } _logger.Info($"Alarms file {alarmsFilePath} was loaded successfully."); alarms.Alarms.ForEach(x => { if (x.Geofences != null) { foreach (var geofenceName in x.Geofences) { var geofences = Geofences.Where(g => g.Name.Equals(geofenceName, StringComparison.OrdinalIgnoreCase) || g.Filename.Equals(geofenceName, StringComparison.OrdinalIgnoreCase)).ToList(); if (geofences.Any()) { x.GeofenceItems.AddRange(geofences); } else { _logger.Warn($"No geofences were found matching the name or filename \"{geofenceName}\" (for alarm \"{x.Name}\")"); } } } x.LoadAlerts(); x.LoadFilters(); }); return(alarms); }
public async Task Execute(DiscordMessage message, Command command) { if (command.Args.Count == 0) { return; } var question = command.Args[0]; var answers = command.Args[1]; var channel = await _client.GetChannel(_config.VotingPollsChannelId); if (channel == null) { _logger.Error($"Failed to get voting poll channel with id {_config.VotingPollsChannelId}."); return; } var poll = new VotingPoll { Question = question, Answers = new List <string>(answers.Trim('\0', ' ').Split(',')), Enabled = true }; var eb = new DiscordEmbedBuilder { Title = poll.Question, Color = DiscordColor.Purple }; for (int i = 0; i < poll.Answers.Count; i++) { eb.Description += $"{_validVotingReactions[i]} {poll.Answers[i]}\r\n\r\n"; } eb.ImageUrl = VotingImage; var embed = eb.Build(); if (embed == null) { return; } var pollMessage = await channel.SendMessageAsync(command.Args.Count == 3?command.Args[2] : string.Empty, false, embed); poll.PollMessageId = pollMessage.Id; for (int i = 0; i < poll.Answers.Count; i++) { await pollMessage.CreateReactionAsync(DiscordEmoji.FromName(_client, ":regional_indicator_" + (i + 1).NumberToAlphabet() + ":")); } }