using System; using System.Collections.Generic; using System.Data; using System.Linq; using Dapper; using MySql.Data.MySqlClient; namespace JetKarmaBot { public class Db { Dictionary m_Chats; public IReadOnlyDictionary Chats => m_Chats; public void AddChat(Chat chat) { lock (m_SyncRoot) if (!m_Chats.ContainsKey(chat.ChatId)) { Conn.Execute(@"INSERT INTO chat (chatid) VALUES (@ChatId)", chat); m_Chats.Add(chat.ChatId, chat); } } Dictionary m_Users; public IReadOnlyDictionary Users => m_Users; public void AddUser(User user) { lock (m_SyncRoot) if (!m_Users.ContainsKey(user.UserId)) { Conn.Execute(@"INSERT INTO user (userid) VALUES (@UserId)", user); m_Users.Add(user.UserId, user); } } Dictionary m_AwardTypes; public byte DefaultAwardTypeId { get; } = 1; public IReadOnlyDictionary AwardTypes => m_AwardTypes; public IReadOnlyDictionary AwardTypesByCommandName { get; private set; } public int CountAwards(long userId, byte awardTypeId) { return Conn.QuerySingle ( "SELECT SUM(amount) FROM award WHERE toid = @userId AND awardtypeid = @awardTypeId", new { userId, awardTypeId } ) ?? 0; } public byte GetAwardTypeId(string name) => AwardTypesByCommandName.GetOrDefault(name)?.AwardTypeId ?? DefaultAwardTypeId; public bool AddAward(byte awardTypeId, long fromId, long toId, long chatId) { AddChat(new Chat() { ChatId = chatId }); AddUser(new User() { UserId = fromId}); AddUser(new User() { UserId = toId }); int affected = Conn.ExecuteScalar( @"INSERT INTO award (chatid, fromid, toid, awardtypeid, amount) VALUES (@chatId, @fromId, @toId, @awardTypeId, 1)", new { awardTypeId, fromId, toId, chatId }); return affected == 1; } #region types public class Chat { public long ChatId { get; set; } } public class User { public long UserId { get; set; } } public class AwardType { public byte AwardTypeId { get; set; } public string CommandName { get; set; } public string Name { get; set; } public string Symbol { get; set; } public string Description { get; set; } } public class Award { public int AwardId { get; set; } public byte AwardTypeId { get; set; } public long FromId { get; set; } public long ToId { get; set; } public long ChatId { get; set; } public byte Amount { get; set; } } #endregion #region service public Db(Config cfg) { Log("Initializing..."); Conn = new MySqlConnection(cfg.ConnectionString); Conn.ExecuteScalar("select 1"); Load(); Log("Initialized!"); } object m_SyncRoot = new object(); IDbConnection Conn { get; } void Load() { Log("Populating cache..."); m_Chats = Conn.Query("SELECT * FROM chat").ToDictionary(u => u.ChatId); m_Users = Conn.Query("SELECT * FROM user").ToDictionary(s => s.UserId); m_AwardTypes = Conn.Query("SELECT * FROM awardtype").ToDictionary(c => c.AwardTypeId); AwardTypesByCommandName = m_AwardTypes.Values.ToDictionary(kvp => kvp.CommandName); Log("Cache populated!"); } #endregion void Log (string Message) => Console.WriteLine($"[{nameof(Db)}]: {Message}"); } }