mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-12 02:08:27 -04:00
Restructured folders and project names, ci should be fixed
This commit is contained in:
149
src/NadekoBot/Modules/Games/Services/ChatterbotService.cs
Normal file
149
src/NadekoBot/Modules/Games/Services/ChatterbotService.cs
Normal file
@@ -0,0 +1,149 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Discord;
|
||||
using Discord.WebSocket;
|
||||
using NadekoBot.Common.ModuleBehaviors;
|
||||
using NadekoBot.Extensions;
|
||||
using NadekoBot.Modules.Permissions.Common;
|
||||
using NadekoBot.Modules.Permissions.Services;
|
||||
using NadekoBot.Core.Services;
|
||||
using NadekoBot.Modules.Games.Common.ChatterBot;
|
||||
using System.Net.Http;
|
||||
using Serilog;
|
||||
|
||||
namespace NadekoBot.Modules.Games.Services
|
||||
{
|
||||
public class ChatterBotService : IEarlyBehavior, INService
|
||||
{
|
||||
private readonly DiscordSocketClient _client;
|
||||
private readonly PermissionService _perms;
|
||||
private readonly CommandHandler _cmd;
|
||||
private readonly IBotStrings _strings;
|
||||
private readonly IBotCredentials _creds;
|
||||
private readonly IHttpClientFactory _httpFactory;
|
||||
|
||||
public ConcurrentDictionary<ulong, Lazy<IChatterBotSession>> ChatterBotGuilds { get; }
|
||||
|
||||
public int Priority => -1;
|
||||
public ModuleBehaviorType BehaviorType => ModuleBehaviorType.Executor;
|
||||
|
||||
public ChatterBotService(DiscordSocketClient client, PermissionService perms,
|
||||
NadekoBot bot, CommandHandler cmd, IBotStrings strings, IHttpClientFactory factory,
|
||||
IBotCredentials creds)
|
||||
{
|
||||
_client = client;
|
||||
_perms = perms;
|
||||
_cmd = cmd;
|
||||
_strings = strings;
|
||||
_creds = creds;
|
||||
_httpFactory = factory;
|
||||
|
||||
ChatterBotGuilds = new ConcurrentDictionary<ulong, Lazy<IChatterBotSession>>(
|
||||
bot.AllGuildConfigs
|
||||
.Where(gc => gc.CleverbotEnabled)
|
||||
.ToDictionary(gc => gc.GuildId, gc => new Lazy<IChatterBotSession>(() => CreateSession(), true)));
|
||||
}
|
||||
|
||||
public IChatterBotSession CreateSession()
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(_creds.CleverbotApiKey))
|
||||
return new OfficialCleverbotSession(_creds.CleverbotApiKey, _httpFactory);
|
||||
else
|
||||
return new CleverbotIOSession("GAh3wUfzDCpDpdpT", "RStKgqn7tcO9blbrv4KbXM8NDlb7H37C", _httpFactory);
|
||||
}
|
||||
|
||||
public string PrepareMessage(IUserMessage msg, out IChatterBotSession cleverbot)
|
||||
{
|
||||
var channel = msg.Channel as ITextChannel;
|
||||
cleverbot = null;
|
||||
|
||||
if (channel == null)
|
||||
return null;
|
||||
|
||||
if (!ChatterBotGuilds.TryGetValue(channel.Guild.Id, out Lazy<IChatterBotSession> lazyCleverbot))
|
||||
return null;
|
||||
|
||||
cleverbot = lazyCleverbot.Value;
|
||||
|
||||
var nadekoId = _client.CurrentUser.Id;
|
||||
var normalMention = $"<@{nadekoId}> ";
|
||||
var nickMention = $"<@!{nadekoId}> ";
|
||||
string message;
|
||||
if (msg.Content.StartsWith(normalMention, StringComparison.InvariantCulture))
|
||||
{
|
||||
message = msg.Content.Substring(normalMention.Length).Trim();
|
||||
}
|
||||
else if (msg.Content.StartsWith(nickMention, StringComparison.InvariantCulture))
|
||||
{
|
||||
message = msg.Content.Substring(nickMention.Length).Trim();
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
public static async Task<bool> TryAsk(IChatterBotSession cleverbot, ITextChannel channel, string message)
|
||||
{
|
||||
await channel.TriggerTypingAsync().ConfigureAwait(false);
|
||||
|
||||
var response = await cleverbot.Think(message).ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
await channel.SendConfirmAsync(response.SanitizeMentions(true)).ConfigureAwait(false);
|
||||
}
|
||||
catch
|
||||
{
|
||||
await channel.SendConfirmAsync(response.SanitizeMentions(true)).ConfigureAwait(false); // try twice :\
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<bool> RunBehavior(DiscordSocketClient client, IGuild guild, IUserMessage usrMsg)
|
||||
{
|
||||
if (!(guild is SocketGuild sg))
|
||||
return false;
|
||||
try
|
||||
{
|
||||
var message = PrepareMessage(usrMsg, out IChatterBotSession cbs);
|
||||
if (message == null || cbs == null)
|
||||
return false;
|
||||
|
||||
var pc = _perms.GetCacheFor(guild.Id);
|
||||
if (!pc.Permissions.CheckPermissions(usrMsg,
|
||||
"cleverbot",
|
||||
"Games".ToLowerInvariant(),
|
||||
out int index))
|
||||
{
|
||||
if (pc.Verbose)
|
||||
{
|
||||
var returnMsg = _strings.GetText("trigger", guild.Id, index + 1, Format.Bold(pc.Permissions[index].GetCommand(_cmd.GetPrefix(guild), (SocketGuild)guild)));
|
||||
try { await usrMsg.Channel.SendErrorAsync(returnMsg).ConfigureAwait(false); } catch { }
|
||||
Log.Information(returnMsg);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
var cleverbotExecuted = await TryAsk(cbs, (ITextChannel)usrMsg.Channel, message).ConfigureAwait(false);
|
||||
if (cleverbotExecuted)
|
||||
{
|
||||
Log.Information($@"CleverBot Executed
|
||||
Server: {guild.Name} [{guild.Id}]
|
||||
Channel: {usrMsg.Channel?.Name} [{usrMsg.Channel?.Id}]
|
||||
UserId: {usrMsg.Author} [{usrMsg.Author.Id}]
|
||||
Message: {usrMsg.Content}");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warning(ex,"Error in cleverbot");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
173
src/NadekoBot/Modules/Games/Services/GamesConfigService.cs
Normal file
173
src/NadekoBot/Modules/Games/Services/GamesConfigService.cs
Normal file
@@ -0,0 +1,173 @@
|
||||
using NadekoBot.Core.Common;
|
||||
using NadekoBot.Core.Common.Configs;
|
||||
using NadekoBot.Core.Services;
|
||||
using NadekoBot.Modules.Games.Common;
|
||||
|
||||
namespace NadekoBot.Modules.Games.Services
|
||||
{
|
||||
public sealed class GamesConfigService : ConfigServiceBase<GamesConfig>
|
||||
{
|
||||
public override string Name { get; } = "games";
|
||||
private const string FilePath = "data/games.yml";
|
||||
private static TypedKey<GamesConfig> changeKey = new TypedKey<GamesConfig>("config.games.updated");
|
||||
|
||||
public GamesConfigService(IConfigSeria serializer, IPubSub pubSub)
|
||||
: base(FilePath, serializer, pubSub, changeKey)
|
||||
{
|
||||
AddParsedProp("trivia.min_win_req", gs => gs.Trivia.MinimumWinReq, int.TryParse,
|
||||
ConfigPrinters.ToString, val => val > 0);
|
||||
AddParsedProp("trivia.currency_reward", gs => gs.Trivia.CurrencyReward, long.TryParse,
|
||||
ConfigPrinters.ToString, val => val >= 0);
|
||||
}
|
||||
}
|
||||
|
||||
// public sealed class GamesConfigMigrator : IConfigMigrator
|
||||
// {
|
||||
// // private readonly DbService _db;
|
||||
// private readonly GamesConfigService _gss;
|
||||
//
|
||||
// public GamesConfigMigrator(DbService dbService, GamesConfigService gss)
|
||||
// {
|
||||
// _log = LogManager.GetCurrentClassLogger();
|
||||
// _db = dbService;
|
||||
// _gss = gss;
|
||||
// }
|
||||
//
|
||||
// public void EnsureMigrated()
|
||||
// {
|
||||
// using var uow = _db.GetDbContext();
|
||||
// using var conn = uow._context.Database.GetDbConnection();
|
||||
// MigrateRaceAnimals(conn);
|
||||
// MigrateEightBall(conn);
|
||||
// }
|
||||
//
|
||||
// private void MigrateTrivia(DbConnection conn)
|
||||
// {
|
||||
// using (var checkTableCommand = conn.CreateCommand())
|
||||
// {
|
||||
// // make sure table still exists
|
||||
// checkTableCommand.CommandText =
|
||||
// "SELECT name FROM sqlite_master WHERE type='table' AND name='BotConfig';";
|
||||
// var checkReader = checkTableCommand.ExecuteReader();
|
||||
// if (!checkReader.HasRows)
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// Log.Information("Migrating trivia...");
|
||||
//
|
||||
// using var com = conn.CreateCommand();
|
||||
// com.CommandText = $@"SELECT MinimumTriviaWinReq, TriviaCurrencyReward FROM BotConfig";
|
||||
// using var reader = com.ExecuteReader();
|
||||
//
|
||||
// if (!reader.Read())
|
||||
// return;
|
||||
//
|
||||
// _gss.ModifyConfig(ModifyTriviaAction(reader));
|
||||
//
|
||||
// Log.Information("Trivia config migrated to data/games.yml");
|
||||
// }
|
||||
//
|
||||
// private static Action<GamesConfig> ModifyTriviaAction(DbDataReader reader)
|
||||
// => realConfig =>
|
||||
// {
|
||||
// var val = (int) (long) reader["MinimumTriviaWinReq"];
|
||||
// realConfig.Trivia.MinimumWinReq = val <= 0 ? 1 : val;
|
||||
// realConfig.Trivia.CurrencyReward = (long) reader["TriviaCurrencyReward"];
|
||||
// };
|
||||
//
|
||||
// private void MigrateEightBall(DbConnection conn)
|
||||
// {
|
||||
// using (var checkTableCommand = conn.CreateCommand())
|
||||
// {
|
||||
// // make sure table still exists
|
||||
// checkTableCommand.CommandText =
|
||||
// "SELECT name FROM sqlite_master WHERE type='table' AND name='EightBallResponses';";
|
||||
// var checkReader = checkTableCommand.ExecuteReader();
|
||||
// if (!checkReader.HasRows)
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// try
|
||||
// {
|
||||
// using (var com = conn.CreateCommand())
|
||||
// {
|
||||
// com.CommandText = $@"SELECT Text FROM EightBallResponses";
|
||||
// using var reader = com.ExecuteReader();
|
||||
//
|
||||
// if (!reader.Read())
|
||||
// return;
|
||||
//
|
||||
// Log.Information("Migrating eightball...");
|
||||
// _gss.ModifyConfig(Modify8ballAction(reader));
|
||||
// }
|
||||
//
|
||||
// Log.Information("Eightball migrated to data/games.yml");
|
||||
// MigrateTrivia(conn);
|
||||
// }
|
||||
// finally
|
||||
// {
|
||||
//
|
||||
// using var deleteEightBallCommand = conn.CreateCommand();
|
||||
// deleteEightBallCommand.CommandText = "DROP TABLE IF EXISTS EightBallResponses";
|
||||
// deleteEightBallCommand.ExecuteNonQuery();
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// private static Action<GamesConfig> Modify8ballAction(DbDataReader reader)
|
||||
// => realConfig =>
|
||||
// {
|
||||
// realConfig.EightBallResponses.Clear();
|
||||
// do
|
||||
// {
|
||||
// realConfig.EightBallResponses.Add((string) reader["Text"]);
|
||||
// } while (reader.Read());
|
||||
// };
|
||||
//
|
||||
// private void MigrateRaceAnimals(DbConnection conn)
|
||||
// {
|
||||
// using (var checkTableCommand = conn.CreateCommand())
|
||||
// {
|
||||
// // make sure table still exists
|
||||
// checkTableCommand.CommandText =
|
||||
// "SELECT name FROM sqlite_master WHERE type='table' AND name='RaceAnimals';";
|
||||
// var checkReader = checkTableCommand.ExecuteReader();
|
||||
// if (!checkReader.HasRows)
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// using (var com = conn.CreateCommand())
|
||||
// {
|
||||
// com.CommandText = $@"SELECT Name, Icon FROM RaceAnimals";
|
||||
// using var reader = com.ExecuteReader();
|
||||
//
|
||||
// if (!reader.Read())
|
||||
// return;
|
||||
//
|
||||
// Log.Information("Migrating race animals...");
|
||||
// _gss.ModifyConfig(ModifyRaceAnimalsAction(reader));
|
||||
// }
|
||||
//
|
||||
// Log.Information("Race animals migrated to data/games.yml");
|
||||
//
|
||||
// using var deleteRaceAnimalsCommand = conn.CreateCommand();
|
||||
// deleteRaceAnimalsCommand.CommandText = "DROP TABLE IF EXISTS RaceAnimals";
|
||||
// deleteRaceAnimalsCommand.ExecuteNonQuery();
|
||||
// }
|
||||
//
|
||||
// private static Action<GamesConfig> ModifyRaceAnimalsAction(DbDataReader reader)
|
||||
// => realConfig =>
|
||||
// {
|
||||
// realConfig.RaceAnimals.Clear();
|
||||
//
|
||||
// do
|
||||
// {
|
||||
// realConfig.RaceAnimals.Add(new RaceAnimal()
|
||||
// {
|
||||
// Icon = (string) reader["Icon"],
|
||||
// Name = (string) reader["Name"]
|
||||
// });
|
||||
// } while (reader.Read());
|
||||
// };
|
||||
// }
|
||||
}
|
159
src/NadekoBot/Modules/Games/Services/GamesService.cs
Normal file
159
src/NadekoBot/Modules/Games/Services/GamesService.cs
Normal file
@@ -0,0 +1,159 @@
|
||||
using Discord;
|
||||
using NadekoBot.Common;
|
||||
using NadekoBot.Core.Services;
|
||||
using NadekoBot.Extensions;
|
||||
using NadekoBot.Modules.Games.Common;
|
||||
using NadekoBot.Modules.Games.Common.Acrophobia;
|
||||
using NadekoBot.Modules.Games.Common.Hangman;
|
||||
using NadekoBot.Modules.Games.Common.Nunchi;
|
||||
using NadekoBot.Modules.Games.Common.Trivia;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Serilog;
|
||||
|
||||
namespace NadekoBot.Modules.Games.Services
|
||||
{
|
||||
public class GamesService : INService, IUnloadableService
|
||||
{
|
||||
private readonly GamesConfigService _gamesConfig;
|
||||
|
||||
public ConcurrentDictionary<ulong, GirlRating> GirlRatings { get; } = new ConcurrentDictionary<ulong, GirlRating>();
|
||||
|
||||
public IReadOnlyList<string> EightBallResponses => _gamesConfig.Data.EightBallResponses;
|
||||
|
||||
private readonly Timer _t;
|
||||
private readonly IHttpClientFactory _httpFactory;
|
||||
private readonly IMemoryCache _8BallCache;
|
||||
private readonly Random _rng;
|
||||
|
||||
private const string TypingArticlesPath = "data/typing_articles3.json";
|
||||
|
||||
public List<TypingArticle> TypingArticles { get; } = new List<TypingArticle>();
|
||||
|
||||
//channelId, game
|
||||
public ConcurrentDictionary<ulong, AcrophobiaGame> AcrophobiaGames { get; } = new ConcurrentDictionary<ulong, AcrophobiaGame>();
|
||||
|
||||
public ConcurrentDictionary<ulong, Hangman> HangmanGames { get; } = new ConcurrentDictionary<ulong, Hangman>();
|
||||
public TermPool TermPool { get; } = new TermPool();
|
||||
|
||||
public ConcurrentDictionary<ulong, TriviaGame> RunningTrivias { get; } = new ConcurrentDictionary<ulong, TriviaGame>();
|
||||
public Dictionary<ulong, TicTacToe> TicTacToeGames { get; } = new Dictionary<ulong, TicTacToe>();
|
||||
public ConcurrentDictionary<ulong, TypingGame> RunningContests { get; } = new ConcurrentDictionary<ulong, TypingGame>();
|
||||
public ConcurrentDictionary<ulong, NunchiGame> NunchiGames { get; } = new ConcurrentDictionary<ulong, NunchiGame>();
|
||||
|
||||
public AsyncLazy<RatingTexts> Ratings { get; }
|
||||
|
||||
public class RatingTexts
|
||||
{
|
||||
public string Nog { get; set; }
|
||||
public string Tra { get; set; }
|
||||
public string Fun { get; set; }
|
||||
public string Uni { get; set; }
|
||||
public string Wif { get; set; }
|
||||
public string Dat { get; set; }
|
||||
public string Dan { get; set; }
|
||||
}
|
||||
|
||||
public GamesService(GamesConfigService gamesConfig, IHttpClientFactory httpFactory)
|
||||
{
|
||||
_gamesConfig = gamesConfig;
|
||||
_httpFactory = httpFactory;
|
||||
_8BallCache = new MemoryCache(new MemoryCacheOptions()
|
||||
{
|
||||
SizeLimit = 500_000
|
||||
});
|
||||
|
||||
Ratings = new AsyncLazy<RatingTexts>(GetRatingTexts);
|
||||
_rng = new NadekoRandom();
|
||||
|
||||
//girl ratings
|
||||
_t = new Timer((_) =>
|
||||
{
|
||||
GirlRatings.Clear();
|
||||
|
||||
}, null, TimeSpan.FromDays(1), TimeSpan.FromDays(1));
|
||||
|
||||
try
|
||||
{
|
||||
TypingArticles = JsonConvert.DeserializeObject<List<TypingArticle>>(File.ReadAllText(TypingArticlesPath));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warning("Error while loading typing articles {0}", ex.ToString());
|
||||
TypingArticles = new List<TypingArticle>();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<RatingTexts> GetRatingTexts()
|
||||
{
|
||||
using (var http = _httpFactory.CreateClient())
|
||||
{
|
||||
var text = await http.GetStringAsync("https://nadeko-pictures.nyc3.digitaloceanspaces.com/other/rategirl/rates.json");
|
||||
return JsonConvert.DeserializeObject<RatingTexts>(text);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Unload()
|
||||
{
|
||||
_t.Change(Timeout.Infinite, Timeout.Infinite);
|
||||
|
||||
AcrophobiaGames.ForEach(x => x.Value.Dispose());
|
||||
AcrophobiaGames.Clear();
|
||||
HangmanGames.ForEach(x => x.Value.Dispose());
|
||||
HangmanGames.Clear();
|
||||
await Task.WhenAll(RunningTrivias.Select(x => x.Value.StopGame())).ConfigureAwait(false);
|
||||
RunningTrivias.Clear();
|
||||
|
||||
TicTacToeGames.Clear();
|
||||
|
||||
await Task.WhenAll(RunningContests.Select(x => x.Value.Stop()))
|
||||
.ConfigureAwait(false);
|
||||
RunningContests.Clear();
|
||||
NunchiGames.ForEach(x => x.Value.Dispose());
|
||||
NunchiGames.Clear();
|
||||
}
|
||||
|
||||
public void AddTypingArticle(IUser user, string text)
|
||||
{
|
||||
TypingArticles.Add(new TypingArticle
|
||||
{
|
||||
Source = user.ToString(),
|
||||
Extra = $"Text added on {DateTime.UtcNow} by {user}.",
|
||||
Text = text.SanitizeMentions(true),
|
||||
});
|
||||
|
||||
File.WriteAllText(TypingArticlesPath, JsonConvert.SerializeObject(TypingArticles));
|
||||
}
|
||||
|
||||
public string GetEightballResponse(ulong userId, string question)
|
||||
{
|
||||
return _8BallCache.GetOrCreate($"8ball:{userId}:{question}", e =>
|
||||
{
|
||||
e.Size = question.Length;
|
||||
e.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(12);
|
||||
return EightBallResponses[_rng.Next(0, EightBallResponses.Count)];;
|
||||
});
|
||||
}
|
||||
|
||||
public TypingArticle RemoveTypingArticle(int index)
|
||||
{
|
||||
var articles = TypingArticles;
|
||||
if (index < 0 || index >= articles.Count)
|
||||
return null;
|
||||
|
||||
var removed = articles[index];
|
||||
TypingArticles.RemoveAt(index);
|
||||
|
||||
File.WriteAllText(TypingArticlesPath, JsonConvert.SerializeObject(articles));
|
||||
return removed;
|
||||
}
|
||||
}
|
||||
}
|
127
src/NadekoBot/Modules/Games/Services/PollService.cs
Normal file
127
src/NadekoBot/Modules/Games/Services/PollService.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Discord;
|
||||
using Discord.WebSocket;
|
||||
using NadekoBot.Common.ModuleBehaviors;
|
||||
using NadekoBot.Modules.Games.Common;
|
||||
using NadekoBot.Core.Services;
|
||||
using NadekoBot.Core.Services.Database.Models;
|
||||
using NadekoBot.Common.Collections;
|
||||
using NadekoBot.Extensions;
|
||||
using Serilog;
|
||||
|
||||
namespace NadekoBot.Modules.Games.Services
|
||||
{
|
||||
public class PollService : IEarlyBehavior, INService
|
||||
{
|
||||
public ConcurrentDictionary<ulong, PollRunner> ActivePolls { get; } = new ConcurrentDictionary<ulong, PollRunner>();
|
||||
|
||||
public int Priority => -5;
|
||||
public ModuleBehaviorType BehaviorType => ModuleBehaviorType.Executor;
|
||||
|
||||
private readonly DbService _db;
|
||||
private readonly IBotStrings _strs;
|
||||
|
||||
public PollService(DbService db, IBotStrings strs)
|
||||
{
|
||||
_db = db;
|
||||
_strs = strs;
|
||||
|
||||
using (var uow = db.GetDbContext())
|
||||
{
|
||||
ActivePolls = uow.Polls.GetAllPolls()
|
||||
.ToDictionary(x => x.GuildId, x =>
|
||||
{
|
||||
var pr = new PollRunner(db, x);
|
||||
pr.OnVoted += Pr_OnVoted;
|
||||
return pr;
|
||||
})
|
||||
.ToConcurrent();
|
||||
}
|
||||
}
|
||||
|
||||
public Poll CreatePoll(ulong guildId, ulong channelId, string input)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(input) || !input.Contains(";"))
|
||||
return null;
|
||||
var data = input.Split(';');
|
||||
if (data.Length < 3)
|
||||
return null;
|
||||
|
||||
var col = new IndexedCollection<PollAnswer>(data.Skip(1)
|
||||
.Select(x => new PollAnswer() { Text = x }));
|
||||
|
||||
return new Poll()
|
||||
{
|
||||
Answers = col,
|
||||
Question = data[0],
|
||||
ChannelId = channelId,
|
||||
GuildId = guildId,
|
||||
Votes = new System.Collections.Generic.HashSet<PollVote>()
|
||||
};
|
||||
}
|
||||
|
||||
public bool StartPoll(Poll p)
|
||||
{
|
||||
var pr = new PollRunner(_db, p);
|
||||
if (ActivePolls.TryAdd(p.GuildId, pr))
|
||||
{
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
uow.Polls.Add(p);
|
||||
uow.SaveChanges();
|
||||
}
|
||||
|
||||
pr.OnVoted += Pr_OnVoted;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Poll StopPoll(ulong guildId)
|
||||
{
|
||||
if (ActivePolls.TryRemove(guildId, out var pr))
|
||||
{
|
||||
pr.OnVoted -= Pr_OnVoted;
|
||||
|
||||
using var uow = _db.GetDbContext();
|
||||
uow.Polls.RemovePoll(pr.Poll.Id);
|
||||
uow.SaveChanges();
|
||||
|
||||
return pr.Poll;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private async Task Pr_OnVoted(IUserMessage msg, IGuildUser usr)
|
||||
{
|
||||
var toDelete = await msg.Channel.SendConfirmAsync(_strs.GetText("poll_voted",
|
||||
usr.Guild.Id, Format.Bold(usr.ToString())))
|
||||
.ConfigureAwait(false);
|
||||
toDelete.DeleteAfter(5);
|
||||
try { await msg.DeleteAsync().ConfigureAwait(false); } catch { }
|
||||
}
|
||||
|
||||
public async Task<bool> RunBehavior(DiscordSocketClient client, IGuild guild, IUserMessage msg)
|
||||
{
|
||||
if (guild == null)
|
||||
return false;
|
||||
|
||||
if (!ActivePolls.TryGetValue(guild.Id, out var poll))
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
return await poll.TryVote(msg).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warning(ex, "Error voting");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user