Browse Source

MTB-28 leave from rooms
bug fix with user specific symbols (markdown v2 triggers)

Tigran 4 years ago
parent
commit
c6d9024a04

+ 37 - 10
MafiaTelegramBot/Controllers/RoomController.cs

@@ -9,18 +9,45 @@ namespace MafiaTelegramBot.Controllers
     public static class RoomController
     {
         private static readonly Dictionary<string, GameRoom> OpenedGames = new();
-        
-        public static async Task<int> CreateNewGame(User owner, string roomName, string password = null)
+
+        public static async Task<int> CreateNewGame(User owner, string roomName, string secretPhrase = null)
         {
             var gameExists = await Task.Run(() => OpenedGames.ContainsKey(roomName));
-            if (gameExists) return Constants.GAME_EXISTS;
-            if (!owner.SetCurrentGame(roomName)) return Constants.USER_ALREADY_IN_GAME;
-            var room = new GameRoom {Creator = owner, RoomName = roomName, Password = password};
-            room.Players.Add(owner.Username, owner);
-            OpenedGames.Add(roomName, room);
-            return Constants.CODE_OK;
+            return await Task.Run(async () =>
+            {
+                if (gameExists) return Constants.GAME_EXISTS;
+                if (! await owner.SetCurrentGame(secretPhrase ?? roomName)) return Constants.USER_ALREADY_IN_GAME;
+                var room = secretPhrase == null
+                    ? new GameRoom {Creator = owner, RoomName = roomName}
+                    : new PrivateGameRoom {Creator = owner, RoomName = roomName};
+                OpenedGames.Add(secretPhrase ?? roomName, room);
+                room.Players.Add(owner.Username, owner);
+                return Constants.CODE_OK;
+            });
+        }
+
+        public static async Task<int> ConnectToGame(User player, string roomKey)
+        {
+            return await Task.Run(async () =>
+            {
+                if (OpenedGames[roomKey].IsFilled()) return Constants.ROOM_IS_FILLED;
+                if (! await player.SetCurrentGame(roomKey)) return Constants.USER_ALREADY_IN_GAME;
+                OpenedGames[roomKey].Players.Add(player.Username, player);
+                return Constants.CODE_OK;
+            });
+        }
+
+        public static async Task<int> LeaveFromGame(User player)
+        {
+            return await Task.Run(async () =>
+            {
+                var current = player.GetCurrentGame();
+                if (current == "") return Constants.USER_NOT_IN_GAME;
+                await player.RemoveGame();
+                OpenedGames[current].Players.Remove(player.Username);
+                if (OpenedGames[current].Players.Count == 0) OpenedGames.Remove(current);
+                return Constants.CODE_OK;
+            });
         }
-        
-        
     }
 }

+ 15 - 4
MafiaTelegramBot/DataBase/User.cs

@@ -1,6 +1,8 @@
 #nullable enable
+using System;
 using System.Collections.Generic;
 using System.Threading.Tasks;
+using MafiaTelegramBot.Resources;
 
 namespace MafiaTelegramBot.DataBase
 {
@@ -14,7 +16,7 @@ namespace MafiaTelegramBot.DataBase
         public Dictionary<string, int> RoleGames = new();
         public Dictionary<string, int> RoleWins = new();
 
-        private string? _currentGame;
+        private string _currentGame = "";
 
         public async Task UpdateName(string name)
         {
@@ -22,15 +24,24 @@ namespace MafiaTelegramBot.DataBase
             await UserDao.Update(this);
         }
 
-        public string? GetCurrentGame()
+        public string GetCurrentGame()
         {
             return _currentGame;
         }
 
-        public bool SetCurrentGame(string roomName)
+        public async Task<bool> SetCurrentGame(string roomName)
         {
-            if (_currentGame != null) return false;
+            if (_currentGame != "") return false;
             _currentGame = roomName;
+            await UserDao.Update(this);
+            return true;
+        }
+        
+        public async Task<bool> RemoveGame()
+        {
+            if (_currentGame == "") return false;
+            _currentGame = "";
+            await UserDao.Update(this);
             return true;
         }
     }

+ 2 - 2
MafiaTelegramBot/DataBase/UserDao.cs

@@ -1,4 +1,5 @@
 #nullable enable
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
@@ -22,8 +23,7 @@ namespace MafiaTelegramBot.DataBase
         
         public static async Task Update(User user)
         {
-            var updateIndex = 0;
-            await Task.Run(() => updateIndex = DataBase.FindIndex(user1 => user1.Id == user.Id));
+            var updateIndex = await Task.Run(() => DataBase.FindIndex(user1 => user1.Id == user.Id));
             if (updateIndex != -1) DataBase[updateIndex] = user;
             else DataBase.Add(user);
         }

+ 16 - 16
MafiaTelegramBot/Game/GameRoom.cs

@@ -1,4 +1,3 @@
-#nullable enable
 using System.Collections.Generic;
 using MafiaTelegramBot.DataBase;
 using MafiaTelegramBot.Resources;
@@ -7,27 +6,28 @@ namespace MafiaTelegramBot.Game
 {
     public class GameRoom
     {
-        public string? Password { get; init; }
-        private bool _isRunned;
-        public string? RoomName { get; init; }
+        private bool _isRunning;
+        private int _maxPlayers = Constants.PLAYER_LIMITS_MAX;
+        private int _minPlayers = Constants.PLAYER_LIMITS_MIN;
+        public virtual bool IsPrivate { get; protected set; } = false;
+        public string RoomName { get; init; } = "NoNameRoom";
         public User Creator { get; init; } = new();
         public readonly Dictionary<string, User> Players = new();
         public readonly Dictionary<string, string> Settings = new();
 
         public int Start()
         {
-            switch (Players.Count)
-            {
-                case < Constants.PLAYER_LIMITS_MIN: return Constants.TOO_FEW_PLAYERS;
-                case > Constants.PLAYER_LIMITS_MAX: return Constants.TOO_MANY_PLAYERS;
-                default:
-                {
-                    if (_isRunned) return Constants.GAME_ALREADY_RUNNING;
-                    _isRunned = true;
-                    //TODO game start logic
-                    return Constants.CODE_OK;
-                }
-            }
+            if (Players.Count < _minPlayers) return Constants.TOO_FEW_PLAYERS;
+            if (Players.Count > _maxPlayers) return Constants.TOO_MANY_PLAYERS;
+            if (_isRunning) return Constants.GAME_ALREADY_RUNNING;
+            _isRunning = true;
+            //TODO game start logic
+            return Constants.CODE_OK;
+        }
+
+        public bool IsFilled()
+        {
+            return Players.Count == _maxPlayers;
         }
     }
 }

+ 7 - 0
MafiaTelegramBot/Game/PrivateGameRoom.cs

@@ -0,0 +1,7 @@
+namespace MafiaTelegramBot.Game
+{
+    public class PrivateGameRoom : GameRoom
+    {
+        public override bool IsPrivate { get; protected set; } = true;
+    }
+}

+ 12 - 5
MafiaTelegramBot/Models/Bot.cs

@@ -62,10 +62,12 @@ namespace MafiaTelegramBot.Models
             {
                 new MyRolesQuery(),
                 new ShopQuery(),
-                new MakePrivateRoom(),
+                new MakePrivateRoomQuery(),
                 new MakePublicRoomQuery(),
                 new SettingsQuery(),
                 new ChangeNameQuery(),
+                new LeaveQuery(),
+                new SettingsRoomQuery(),
             };
         }
         
@@ -78,12 +80,17 @@ namespace MafiaTelegramBot.Models
             };
         }
         
-        public static Task<Message> SendWithMarkdown2(long chatId, string message, IReplyMarkup replyMarkup = null)
+        public static async Task<Message> SendWithMarkdown2(long chatId, string message, IReplyMarkup replyMarkup = null)
         {
-            var newMessage = message.Replace(".", "\\.");
+            var newMessage = await Task.Run(()=> message
+                .Replace(".", "\\.")
+                .Replace("@", "\\@")
+                .Replace("#", "\\#")
+                .Replace("!", "\\!")
+            );
             return replyMarkup == null
-                ? Get().SendTextMessageAsync(chatId, newMessage, ParseMode.MarkdownV2)
-                : Get().SendTextMessageAsync(chatId, newMessage, ParseMode.MarkdownV2, replyMarkup: replyMarkup);
+                ? await Get().SendTextMessageAsync(chatId, newMessage, ParseMode.MarkdownV2)
+                : await Get().SendTextMessageAsync(chatId, newMessage, ParseMode.MarkdownV2, replyMarkup: replyMarkup);
         }
     }
 }

+ 2 - 2
MafiaTelegramBot/Models/Commands/CreateGameCommand.cs

@@ -14,7 +14,7 @@ namespace MafiaTelegramBot.Models.Commands
             var userId = update.Message.From.Id;
             await Bot.Get().SendChatActionAsync(chatId, ChatAction.Typing);
 
-            var message = strings.set_room_settings;
+            var message = strings.settings_room;
             
             var inlineKeyboard = new InlineKeyboardMarkup(new[]
             {
@@ -22,7 +22,7 @@ namespace MafiaTelegramBot.Models.Commands
                 new[] {InlineKeyboardButton.WithCallbackData(strings.make_private_room, $"{strings.make_private_room_callback}|{userId}")}
             });
             
-            return await Bot.SendWithMarkdown2(chatId, message, replyMarkup: inlineKeyboard);
+            return await Bot.SendWithMarkdown2(chatId, message, inlineKeyboard);
         }
     }
 }

+ 11 - 2
MafiaTelegramBot/Models/Commands/CustomMessageHandlingCommand.cs

@@ -4,6 +4,7 @@ using MafiaTelegramBot.DataBase;
 using MafiaTelegramBot.Resources;
 using Telegram.Bot.Types;
 using Telegram.Bot.Types.Enums;
+using Telegram.Bot.Types.ReplyMarkups;
 
 namespace MafiaTelegramBot.Models.Commands
 {
@@ -26,7 +27,7 @@ namespace MafiaTelegramBot.Models.Commands
         private static async Task<Message> ChangeNicknameLogic(long userId, long chatId, string message)
         {
             var user = await UserDao.GetUserById(userId);
-            await user.UpdateName(message);
+            await user!.UpdateName(message);
             return await Bot.SendWithMarkdown2(chatId, $"{strings.name_updated} _*{message}*_");
         }
 
@@ -34,9 +35,17 @@ namespace MafiaTelegramBot.Models.Commands
         {
             var user = await UserDao.GetUserById(userId);
             var resultCode = await RoomController.CreateNewGame(user, message);
+            var keyboard = new InlineKeyboardMarkup(new []
+            {
+                new []{
+                    InlineKeyboardButton.WithCallbackData(strings.settings, $"{strings.settings_room_callback}|{userId}"),
+                    InlineKeyboardButton.WithCallbackData(strings.leave, $"{strings.leave_callback}|{userId}")
+                }
+            });
             return resultCode switch
             {
-                Constants.CODE_OK => await Bot.SendWithMarkdown2(chatId, $"{strings.room_with_name} _*{message}*_ {strings.was_created}"),
+                Constants.CODE_OK => await Bot.SendWithMarkdown2(chatId, $"{strings.room_with_name} _*{message}*_ {strings.was_created}", keyboard),
+                Constants.USER_ALREADY_IN_GAME => await Bot.SendWithMarkdown2(chatId, $"{strings.user_already_playing} _*{user?.GetCurrentGame()}*_"),
                 Constants.GAME_EXISTS => await Bot.SendWithMarkdown2(chatId, $"{strings.room} _*{message}*_ {strings.already_exists}"),
                 _ => await Bot.SendWithMarkdown2(chatId, strings.unexpected_error)
             };

+ 12 - 0
MafiaTelegramBot/Models/Commands/StartCommand.cs

@@ -26,6 +26,18 @@ namespace MafiaTelegramBot.Models.Commands
             var message = await Bot.SendWithMarkdown2(chatId, strings.start_message, keyboard);
             var userId = update.Message.From.Id;
             var username = update.Message.From.Username;
+            username = await Task.Run(()=> username
+                .Replace(".", "\\.")
+                .Replace("`", "\\`")
+                .Replace("@", "\\@")
+                .Replace("#", "\\#")
+                .Replace("!", "\\!")
+                .Replace("*", "\\*")
+                .Replace("_", "\\_")
+                .Replace("'", "\\'")
+                .Replace("~", "\\~")
+                .Replace("[", "\\[")
+            );
             await UserDao.AddNewUser(userId, chatId, username);
             return message;
         }

+ 30 - 0
MafiaTelegramBot/Models/Inlines/LeaveQuery.cs

@@ -0,0 +1,30 @@
+using System.Threading.Tasks;
+using MafiaTelegramBot.Controllers;
+using MafiaTelegramBot.DataBase;
+using MafiaTelegramBot.Resources;
+using Telegram.Bot.Types;
+using Telegram.Bot.Types.Enums;
+
+namespace MafiaTelegramBot.Models.Inlines
+{
+    public class LeaveQuery : Query
+    {
+        protected override string Name => strings.leave_callback;
+        public override async Task<Message> Execute(Update update)
+        {
+            var chatId = update.CallbackQuery.Message.Chat.Id;
+            await Bot.Get().SendChatActionAsync(chatId, ChatAction.Typing);
+            var data = update.CallbackQuery.Data;
+            var userId = long.Parse(data.Split('|')[1]);
+            var user = await UserDao.GetUserById(userId);
+            var game = user!.GetCurrentGame();
+            var result = await RoomController.LeaveFromGame(user);
+            return result switch
+            {
+                Constants.CODE_OK => await Bot.SendWithMarkdown2(chatId, $"{strings.leave_from_game} _*{game}*_"),
+                Constants.USER_NOT_IN_GAME => await Bot.SendWithMarkdown2(chatId, strings.not_in_game),
+                _ => await Bot.SendWithMarkdown2(chatId, strings.unexpected_error)
+            };
+        }
+    }
+}

+ 1 - 1
MafiaTelegramBot/Models/Inlines/MakePrivateRoom.cs → MafiaTelegramBot/Models/Inlines/MakePrivateRoomQuery.cs

@@ -5,7 +5,7 @@ using Telegram.Bot.Types.ReplyMarkups;
 
 namespace MafiaTelegramBot.Models.Inlines
 {
-    public class MakePrivateRoom : Query
+    public class MakePrivateRoomQuery : Query
     {
         protected override string Name => strings.make_private_room_callback;
         public override async Task<Message> Execute(Update update)

+ 4 - 0
MafiaTelegramBot/Models/Inlines/Query.cs

@@ -5,6 +5,10 @@ namespace MafiaTelegramBot.Models.Inlines
 {
     public abstract class Query : UpdateModel
     {
+        protected override bool Contains(string command)
+        {
+            return command == Name;
+        }
         public static Task Update(Update update)
         {
             var data = update.CallbackQuery.Data;

+ 17 - 0
MafiaTelegramBot/Models/Inlines/SettingsRoomQuery.cs

@@ -0,0 +1,17 @@
+using System.Threading.Tasks;
+using Telegram.Bot.Types;
+using Telegram.Bot.Types.Enums;
+
+namespace MafiaTelegramBot.Models.Inlines
+{
+    public class SettingsRoomQuery : Query
+    {
+        protected override string Name => strings.settings_room_callback;
+        public override async Task<Message> Execute(Update update)
+        {
+            var chatId = update.CallbackQuery.Message.Chat.Id;
+            await Bot.Get().SendChatActionAsync(chatId, ChatAction.Typing);
+            return await Bot.SendWithMarkdown2(chatId, strings.settings_room);
+        }
+    }
+}

+ 1 - 1
MafiaTelegramBot/Models/UpdateModel.cs

@@ -11,7 +11,7 @@ namespace MafiaTelegramBot.Models
         
         public abstract Task<Message> Execute(Update update);
 
-        private bool Contains(string command)
+        protected virtual bool Contains(string command)
         {
             return command.Contains(Name);
         }

+ 6 - 2
MafiaTelegramBot/Resources/Constants.cs

@@ -2,16 +2,20 @@ namespace MafiaTelegramBot.Resources
 {
     public static class Constants
     {
+        public const int CODE_OK = 0; //only this can be zero
+        
         public const int PLAYER_LIMITS_MIN = 1;
         public const int PLAYER_LIMITS_MAX = 16;
 
-        public const int CODE_OK = 0;
-        
+
         public const int TOO_MANY_PLAYERS = 1;
         public const int TOO_FEW_PLAYERS = -1;
         public const int GAME_ALREADY_RUNNING = 2;
 
         public const int GAME_EXISTS = 1;
         public const int USER_ALREADY_IN_GAME = 2;
+        public const int USER_NOT_IN_GAME = 2;
+
+        public const int ROOM_IS_FILLED = 1;
     }
 }

+ 63 - 9
MafiaTelegramBot/Resources/strings.Designer.cs

@@ -150,6 +150,33 @@ namespace MafiaTelegramBot {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to Выйти.
+        /// </summary>
+        internal static string leave {
+            get {
+                return ResourceManager.GetString("leave", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to leave.
+        /// </summary>
+        internal static string leave_callback {
+            get {
+                return ResourceManager.GetString("leave_callback", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Вы покинули игру.
+        /// </summary>
+        internal static string leave_from_game {
+            get {
+                return ResourceManager.GetString("leave_from_game", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to Приватная комната.
         /// </summary>
@@ -223,29 +250,29 @@ namespace MafiaTelegramBot {
         }
         
         /// <summary>
-        ///   Looks up a localized string similar to Комната.
+        ///   Looks up a localized string similar to Вы не находитесь сейчас в игре!.
         /// </summary>
-        internal static string room {
+        internal static string not_in_game {
             get {
-                return ResourceManager.GetString("room", resourceCulture);
+                return ResourceManager.GetString("not_in_game", resourceCulture);
             }
         }
         
         /// <summary>
-        ///   Looks up a localized string similar to Комната с именем.
+        ///   Looks up a localized string similar to Комната.
         /// </summary>
-        internal static string room_with_name {
+        internal static string room {
             get {
-                return ResourceManager.GetString("room_with_name", resourceCulture);
+                return ResourceManager.GetString("room", resourceCulture);
             }
         }
         
         /// <summary>
-        ///   Looks up a localized string similar to Задайте настройки комнаты.
+        ///   Looks up a localized string similar to Комната с именем.
         /// </summary>
-        internal static string set_room_settings {
+        internal static string room_with_name {
             get {
-                return ResourceManager.GetString("set_room_settings", resourceCulture);
+                return ResourceManager.GetString("room_with_name", resourceCulture);
             }
         }
         
@@ -267,6 +294,24 @@ namespace MafiaTelegramBot {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to Задайте настройки комнаты.
+        /// </summary>
+        internal static string settings_room {
+            get {
+                return ResourceManager.GetString("settings_room", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to settings_room.
+        /// </summary>
+        internal static string settings_room_callback {
+            get {
+                return ResourceManager.GetString("settings_room_callback", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to Магазин.
         /// </summary>
@@ -321,6 +366,15 @@ namespace MafiaTelegramBot {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to Вы уже находитесь в игре.
+        /// </summary>
+        internal static string user_already_playing {
+            get {
+                return ResourceManager.GetString("user_already_playing", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to была создана.
         /// </summary>

+ 19 - 1
MafiaTelegramBot/Resources/strings.resx

@@ -90,7 +90,7 @@
     <data name="command_not_found" xml:space="preserve">
         <value>Команда не найдена</value>
     </data>
-    <data name="set_room_settings" xml:space="preserve">
+    <data name="settings_room" xml:space="preserve">
         <value>Задайте настройки комнаты</value>
     </data>
     <data name="choose" xml:space="preserve">
@@ -117,4 +117,22 @@
     <data name="already_exists" xml:space="preserve">
         <value>уже существует</value>
     </data>
+    <data name="user_already_playing" xml:space="preserve">
+        <value>Вы уже находитесь в игре</value>
+    </data>
+    <data name="settings_room_callback" xml:space="preserve">
+        <value>settings_room</value>
+    </data>
+    <data name="leave" xml:space="preserve">
+        <value>Выйти</value>
+    </data>
+    <data name="leave_callback" xml:space="preserve">
+        <value>leave</value>
+    </data>
+    <data name="leave_from_game" xml:space="preserve">
+        <value>Вы покинули игру</value>
+    </data>
+    <data name="not_in_game" xml:space="preserve">
+        <value>Вы не находитесь сейчас в игре!</value>
+    </data>
 </root>