static async Task <int> Main(string[] args) { IApiInicializer initializer = new ApiFileInicializer("../../../files/ini.txt"); IMessageApi botApi = initializer.GetApi(); TokenBotAuthorizer tokenBotAuthorizer = new TokenBotAuthorizer("../../../files/remember.json", Globals.TokenAPI); //IAuthorizer authorizer = new DefaultAuthorizer(); Add authorization! //DictTagsService tagsService = new DictTagsService(); ApiFeedService apiFeedService = new ApiFeedService(Globals.FeedAPI, Globals.TagAPI, Globals.SpecialTagAPI, tokenBotAuthorizer); ApiUsersService apiUsersService = new ApiUsersService(Globals.UsersAPI, Globals.UsersRolesAPI, tokenBotAuthorizer); //IMessageConditionHandler commandConditionHandler = new CommandHandler(tagsService, botApi); PlainTextHandler emptyTextHandler = new PlainTextHandler(apiFeedService, botApi); AttachmentHandler attachmentHandler = new AttachmentHandler(botApi, apiUsersService); //WallPostEventsHandler wallPostEventsHandler = new WallPostEventsHandler(botApi, apiFeedService); WallPostEventsHandler wallPostEventsHandler = new WallPostEventsHandler(apiFeedService); ButtonHandler buttonHandler = new ButtonHandler(apiFeedService, apiUsersService, botApi); emptyTextHandler.AddTagToWallPost += wallPostEventsHandler.AddTagToPost; attachmentHandler.AddingPostEvent += wallPostEventsHandler.HandlePost; buttonHandler.AddingTagEvent += emptyTextHandler.AddingTag; buttonHandler.CancelTag += emptyTextHandler.StopAddingTag; buttonHandler.UserAddingTagToPost += emptyTextHandler.AddingTagToPost; buttonHandler.CancelUserAddingTagToPost += emptyTextHandler.StopAddingTagToPost; buttonHandler.AddingAdminEvent += emptyTextHandler.AddingAdmin; buttonHandler.CancelAdmin += emptyTextHandler.StopAddingAdmin; buttonHandler.RemovingAdmin += emptyTextHandler.RemovingAdmin; buttonHandler.CancelRemovingAdmin += emptyTextHandler.StopRemovingAdmin; buttonHandler.Cancel += wallPostEventsHandler.Cancel; buttonHandler.Send = wallPostEventsHandler; buttonHandler.AttachedTagsMessage += wallPostEventsHandler.AttachedTagsMessage; buttonHandler.AddingTagToPostEvent += wallPostEventsHandler.AddTagToPost; buttonHandler.DetachingTagEvent += wallPostEventsHandler.DetachTagFromPost; buttonHandler.GetUserNameEvent += botApi.GetUserName; while (true) { IEnumerable <Message> newMessages; try { newMessages = botApi.NewMessages(); } catch (TaskCanceledException e) { Console.WriteLine("timeout error caught!"); Console.WriteLine("new request"); newMessages = botApi.NewMessages(); } foreach (Message message in newMessages) { if (attachmentHandler.Condition(message)) { MessagesSendParams sendParams = await attachmentHandler.Reply(message); botApi.SendMessage(sendParams); } /*if (commandConditionHandler.Condition(message)) * { * botApi.SendMessage(commandConditionHandler.Reply(message)); * }*/ if (emptyTextHandler.Condition(message)) { MessagesSendParams sendParams = await emptyTextHandler.Reply(message); botApi.SendMessage(sendParams); } if (buttonHandler.Condition(message)) { MessagesSendParams sendParams = await buttonHandler.Reply(message); botApi.SendMessage(sendParams); } } } }
public ButtonHandler(ApiFeedService feedService, ApiUsersService usersService, IMessageApi messageApi) { _feedService = feedService; _usersService = usersService; _messageApi = messageApi; }
public async Task <MessagesSendParams> Reply(Message message) { string payload = message.Payload; string replyText = "hehehoho"; string help = "Для добавления поста пришлите его в сообщения боту.\n" + "Кнопка \"Добавить пост\" переводит бота в режим ожидания поста. " + "Её нажатие необязательно, и нужно для отображения клавиатуры в режиме настройки поста\n" + "После нажатия \"Добавить тэг\" бот будет ожидать первое отправленное вами текстовое сообщение, " + "и создаст новый тэг с таким названием.\n" + "После нажатия \"Список тэгов\" бот выведет все тэги, имеющиеся на данный момент."; if (!String.IsNullOrEmpty(message.Payload)) { long userId = 0; if (message.FromId != null) { userId = (long)message.FromId; } AccessLevel userAccess = await _usersService.GetAccess(userId); var d = JsonSerializer.Deserialize <Dictionary <String, String> >(payload); switch (d["command"]) { case "start": { replyText = help; var keyboardBuilder = Keyboards.MainMenuKeyboardBuilder(); MessagesSendParams sendParams = new MessagesSendParams() { PeerId = message.PeerId, Message = help, RandomId = new Random().Next(), Keyboard = keyboardBuilder.Build() }; return(sendParams); } case "addTag": { AddingTagEvent?.Invoke(userId); if (userAccess == AccessLevel.NotAuthorized) { return new MessagesSendParams() { PeerId = message.PeerId, Message = "Операция недоступна пользователям без модераторского доступа", RandomId = new Random().Next(), Keyboard = Keyboards.MainMenuKeyboardBuilder().Build() } } ; var keyboardBuilder = new KeyboardBuilder(); keyboardBuilder.AddButton(new MessageKeyboardButtonAction() { Type = KeyboardButtonActionType.Text, Label = "Отмена", Payload = "{\"command\": \"tagsAddingCancel\"}" }, KeyboardButtonColor.Negative); return(new MessagesSendParams() { PeerId = message.PeerId, Message = "Для добавления тэга, введите название тэга в поле ввода сообщения и отправьте сообщение.\n" + "Если вы хотите добавить несколько тэгов, разделяйте их символами \',\'. " + "Другие введённые вами символы, в том числе и пробелы, " + "будут считаться частью имени тэга", RandomId = new Random().Next(), Keyboard = keyboardBuilder.Build() }); } case "tagsAddingCancel": { if (userAccess == AccessLevel.NotAuthorized) { return new MessagesSendParams() { PeerId = message.PeerId, Message = "Операция недоступна пользователям без модераторского доступа", RandomId = new Random().Next(), Keyboard = Keyboards.MainMenuKeyboardBuilder().Build() } } ; CancelTag?.Invoke(userId); var keyboardBuilder = Keyboards.MainMenuKeyboardBuilder(); return(new MessagesSendParams() { PeerId = message.PeerId, Message = "Отмена добавления тэга", RandomId = new Random().Next(), Keyboard = keyboardBuilder.Build() }); } case "addPost": { if (userAccess == AccessLevel.NotAuthorized) { return new MessagesSendParams() { PeerId = message.PeerId, Message = "Операция недоступна пользователям без модераторского доступа", RandomId = new Random().Next(), Keyboard = Keyboards.MainMenuKeyboardBuilder().Build() } } ; return(new MessagesSendParams() { PeerId = message.PeerId, RandomId = new Random().Next(), Message = "Ожидание отправки поста...", Keyboard = Keyboards.PostHandlingKeyboardBuilder().Build() }); } case "tagsList": { var tags = await _feedService.GetTagsList(); var specialTags = await _feedService.GetSpecialTagsList(); string tagsString = "<empty list>"; if (tags != null || tags.Length != 0) { tagsString = tags.Aggregate((s1, s2) => s1 + "; " + s2); } string specialTagsString = "<empty list>"; if (specialTags != null || specialTags.Length != 0) { specialTagsString = specialTags.Aggregate((s1, s2) => s1 + "; " + s2); } replyText = "Основные тэги:\n" + tagsString + "\nТэги факультетов:\n" + specialTagsString; return(new MessagesSendParams() { RandomId = new Random().Next(), PeerId = message.PeerId, Message = replyText, Keyboard = Keyboards.MainMenuKeyboardBuilder().Build() }); } case "tagsListPostHandling": { var tags = await _feedService.GetTagsList(); var specialTags = await _feedService.GetSpecialTagsList(); string tagsString = "<empty list>"; if (tags != null || tags.Length != 0) { tagsString = tags.Aggregate((s1, s2) => s1 + "; " + s2); } string specialTagsString = "<empty list>"; if (specialTags != null || specialTags.Length != 0) { specialTagsString = specialTags.Aggregate((s1, s2) => s1 + "; " + s2); } replyText = "Основные тэги:\n" + tagsString + "\nТэги факультетов:\n" + specialTagsString; return(new MessagesSendParams() { RandomId = new Random().Next(), PeerId = message.PeerId, Message = replyText, Keyboard = Keyboards.PostHandlingKeyboardBuilder().Build() }); } case "cancelPost": { if (userAccess == AccessLevel.NotAuthorized) { return new MessagesSendParams() { PeerId = message.PeerId, Message = "Операция недоступна пользователям без модераторского доступа", RandomId = new Random().Next(), Keyboard = Keyboards.MainMenuKeyboardBuilder().Build() } } ; CancelUserAddingTagToPost?.Invoke(userId); return(Cancel?.Invoke(userId, message)); } case "attachTag": { if (userAccess == AccessLevel.NotAuthorized) { return new MessagesSendParams() { PeerId = message.PeerId, Message = "Операция недоступна пользователям без модераторского доступа", RandomId = new Random().Next(), Keyboard = Keyboards.MainMenuKeyboardBuilder().Build() } } ; _tagsList = await _feedService.GetAllTags(); UserAddingTagToPost?.Invoke(userId); _messageApi.SendMessage(new MessagesSendParams() { RandomId = new Random().Next(), PeerId = message.PeerId, Message = "Вы можете выбрать тэги по из предложенных в следующем сообщении, или ввести тэги вручную." + "Вводя тэги вручную в поле ввода сообщений, разделяйте тэги символами \',\'. Помните, что пробелы " + "считаются частью имени тэга.", Keyboard = Keyboards.PostHandlingKeyboardBuilder().Build() //Keyboard = Keyboards.InputTagAttachingKeyboardBuilder().Build() }); IKeyboardBuilder keyboardBuilder = Keyboards.TagsKeyboardBuilders(_tagsList)[0]; return(new MessagesSendParams() { RandomId = new Random().Next(), PeerId = message.PeerId, Message = "Выбирете тэг из предложенных. Для переключения на следующую страницу нажмите зелёную кнопку.", Keyboard = keyboardBuilder.Build() }); } case "tagsAttachingInputCancel": { if (userAccess == AccessLevel.NotAuthorized) { return new MessagesSendParams() { PeerId = message.PeerId, Message = "Операция недоступна пользователям без модераторского доступа", RandomId = new Random().Next(), Keyboard = Keyboards.MainMenuKeyboardBuilder().Build() } } ; CancelUserAddingTagToPost?.Invoke(userId); var keyboardBuilder = Keyboards.MainMenuKeyboardBuilder(); return(new MessagesSendParams() { PeerId = message.PeerId, Message = "Отмена прикрепления тэга", RandomId = new Random().Next(), Keyboard = keyboardBuilder.Build() }); } case "detachTag": { if (userAccess == AccessLevel.NotAuthorized) { return new MessagesSendParams() { PeerId = message.PeerId, Message = "Операция недоступна пользователям без модераторского доступа", RandomId = new Random().Next(), Keyboard = Keyboards.MainMenuKeyboardBuilder().Build() } } ; CancelUserAddingTagToPost?.Invoke(userId); return(AttachedTagsMessage?.Invoke(userId, 0, message)); } case "nextPage": { if (userAccess == AccessLevel.NotAuthorized) { return new MessagesSendParams() { PeerId = message.PeerId, Message = "Операция недоступна пользователям без модераторского доступа", RandomId = new Random().Next(), Keyboard = Keyboards.MainMenuKeyboardBuilder().Build() } } ; int current = int.Parse(d["current"]); int from = int.Parse(d["from"]); IKeyboardBuilder keyboardBuilder; if (current == from) { keyboardBuilder = Keyboards.TagsKeyboardBuilders(_tagsList)[0]; } else { keyboardBuilder = Keyboards.TagsKeyboardBuilders(_tagsList)[current]; } return(new MessagesSendParams() { RandomId = new Random().Next(), PeerId = message.PeerId, Message = "Выбирете тэг", Keyboard = keyboardBuilder.Build() }); } case "nextPageAttached": { if (userAccess == AccessLevel.NotAuthorized) { return new MessagesSendParams() { PeerId = message.PeerId, Message = "Операция недоступна пользователям без модераторского доступа", RandomId = new Random().Next(), Keyboard = Keyboards.MainMenuKeyboardBuilder().Build() } } ; int current = int.Parse(d["current"]); int from = int.Parse(d["from"]); IKeyboardBuilder keyboardBuilder; if (current == from) { current = 0; } return(AttachedTagsMessage?.Invoke(userId, current, message)); } case "buttonTag": { if (userAccess == AccessLevel.NotAuthorized) { return new MessagesSendParams() { PeerId = message.PeerId, Message = "Операция недоступна пользователям без модераторского доступа", RandomId = new Random().Next(), Keyboard = Keyboards.MainMenuKeyboardBuilder().Build() } } ; if (message.Text == null) { throw new Exception(); } string tag = message.Text; return(AddingTagToPostEvent?.Invoke(userId, tag, message)); } case "detachButtonTag": { if (userAccess == AccessLevel.NotAuthorized) { return new MessagesSendParams() { PeerId = message.PeerId, Message = "Операция недоступна пользователям без модераторского доступа", RandomId = new Random().Next(), Keyboard = Keyboards.MainMenuKeyboardBuilder().Build() } } ; if (message.Text == null) { throw new Exception(); } string tag = message.Text; return(DetachingTagEvent?.Invoke(userId, tag, message)); } case "sendPost": { if (userAccess == AccessLevel.NotAuthorized) { return new MessagesSendParams() { PeerId = message.PeerId, Message = "Операция недоступна пользователям без модераторского доступа", RandomId = new Random().Next(), Keyboard = Keyboards.MainMenuKeyboardBuilder().Build() } } ; CancelUserAddingTagToPost?.Invoke(userId); return(await Send.Send(userId, message, false)); } case "help": { return(new MessagesSendParams() { RandomId = new Random().Next(), PeerId = message.PeerId, Message = help, Keyboard = Keyboards.MainMenuKeyboardBuilder().Build() }); } case "postEventHelp": { CancelUserAddingTagToPost?.Invoke(userId); return(new MessagesSendParams() { RandomId = new Random().Next(), PeerId = message.PeerId, Message = "Чтобы начать работу с постом, необходимо отправить его в сообщения боту." + "\"Прикрепить тэг\" используется для прикрепления тэга к посту." + "\"Отправить\" используется для отправки поста вместе с прикреплёнными тэгами" + "Чтобы отменить добавление поста нажмите \"Отмена\"", Keyboard = Keyboards.PostHandlingKeyboardBuilder().Build() }); } case "acceptSend": { if (userAccess == AccessLevel.NotAuthorized) { return new MessagesSendParams() { PeerId = message.PeerId, Message = "Операция недоступна пользователям без модераторского доступа", RandomId = new Random().Next(), Keyboard = Keyboards.MainMenuKeyboardBuilder().Build() } } ; CancelUserAddingTagToPost?.Invoke(userId); return(await Send.Send(userId, message, true)); } case "declineSend": { if (userAccess == AccessLevel.NotAuthorized) { return new MessagesSendParams() { PeerId = message.PeerId, Message = "Операция недоступна пользователям без модераторского доступа", RandomId = new Random().Next(), Keyboard = Keyboards.MainMenuKeyboardBuilder().Build() } } ; CancelUserAddingTagToPost?.Invoke(userId); return(new MessagesSendParams() { RandomId = new Random().Next(), PeerId = message.PeerId, Message = "Отправка отменена. Возвращаюсь к обработке поста.", Keyboard = Keyboards.PostHandlingKeyboardBuilder().Build() }); } case "adminPanel": { if (userAccess != AccessLevel.Admin) { return new MessagesSendParams() { PeerId = message.PeerId, Message = "Операция недоступна пользователям без администраторского доступа", RandomId = new Random().Next(), Keyboard = Keyboards.MainMenuKeyboardBuilder().Build() } } ; return(new MessagesSendParams() { RandomId = new Random().Next(), PeerId = message.PeerId, Message = "Чтобы добавить администратора/модератора, нажмите \"Добавить админа\".", Keyboard = Keyboards.AdminPanelKeyboardBuilder().Build() }); } case "adminsList": { List <UserData> botAdmins = new List <UserData>(); try { botAdmins = await _usersService.GetAdmins(); } catch (Exception e) { return(new MessagesSendParams() { PeerId = message.PeerId, Message = $"Ошибка при отправке запроса", RandomId = new Random().Next(), Keyboard = Keyboards.AdminPanelKeyboardBuilder().Build() }); } if (botAdmins.Count == 0) { return new MessagesSendParams() { PeerId = message.PeerId, Message = $"Ошибка при отправке запроса", RandomId = new Random().Next(), Keyboard = Keyboards.AdminPanelKeyboardBuilder().Build() } } ; StringBuilder sb = new StringBuilder(); foreach (UserData botAdmin in botAdmins) { var t = this.GetUserNameEvent(botAdmin.IdVk); string s = $"[id{botAdmin.IdVk}|{t.Item1} {t.Item2}] - " + $"{ApiUsersService.AccessLevelName(botAdmin.Role)}\n"; sb.Append(s); } return(new MessagesSendParams() { PeerId = message.PeerId, Message = sb.ToString(), RandomId = new Random().Next(), Keyboard = Keyboards.AdminPanelKeyboardBuilder().Build() }); } case "addAdmin": { if (userAccess != AccessLevel.Admin) { return new MessagesSendParams() { PeerId = message.PeerId, Message = "Операция недоступна пользователям без администраторского доступа", RandomId = new Random().Next(), Keyboard = Keyboards.MainMenuKeyboardBuilder().Build() } } ; AddingAdminEvent?.Invoke(userId); var keyboardBuilder = new KeyboardBuilder(); keyboardBuilder.AddButton(new MessageKeyboardButtonAction() { Type = KeyboardButtonActionType.Text, Label = "Отмена", Payload = "{\"command\": \"adminAddingCancel\"}" }, KeyboardButtonColor.Negative); return(new MessagesSendParams() { PeerId = message.PeerId, Message = "Для добавления админа, скопируйте ссылку на пользователя ВКонтакте " + "в поле ввода сообщения и отправьте сообщение.", RandomId = new Random().Next(), Keyboard = keyboardBuilder.Build() }); } case "adminAddingCancel": { if (userAccess != AccessLevel.Admin) { return new MessagesSendParams() { PeerId = message.PeerId, Message = "Операция недоступна пользователям без администраторского доступа", RandomId = new Random().Next(), Keyboard = Keyboards.MainMenuKeyboardBuilder().Build() } } ; CancelAdmin?.Invoke(userId); var keyboardBuilder = Keyboards.AdminPanelKeyboardBuilder(); return(new MessagesSendParams() { PeerId = message.PeerId, Message = "Отмена добавления админа", RandomId = new Random().Next(), Keyboard = keyboardBuilder.Build() }); } case "addModeratorAccess": { if (userAccess != AccessLevel.Admin) { return new MessagesSendParams() { PeerId = message.PeerId, Message = "Операция недоступна пользователям без администраторского доступа", RandomId = new Random().Next(), Keyboard = Keyboards.MainMenuKeyboardBuilder().Build() } } ; long moderId = long.Parse(d["userId"]); try { bool status = await _usersService.AddAdmin(moderId, AccessLevel.Moderator); if (status) { return new MessagesSendParams() { PeerId = message.PeerId, Message = $"Пользователь vk.com/id{moderId} добавлен как модератор", RandomId = new Random().Next(), Keyboard = Keyboards.AdminPanelKeyboardBuilder().Build() } } ; else { return(new MessagesSendParams() { PeerId = message.PeerId, Message = $"Произошла ошибка при добавлении пользователя.", RandomId = new Random().Next(), Keyboard = Keyboards.AdminPanelKeyboardBuilder().Build() }); } } catch (Exception e) { return(new MessagesSendParams() { PeerId = message.PeerId, Message = $"Произошла ошибка при добавлении пользователя.", RandomId = new Random().Next(), Keyboard = Keyboards.AdminPanelKeyboardBuilder().Build() }); } } case "addAdminAccess": { if (userAccess != AccessLevel.Admin) { return new MessagesSendParams() { PeerId = message.PeerId, Message = "Операция недоступна пользователям без администраторского доступа", RandomId = new Random().Next(), Keyboard = Keyboards.MainMenuKeyboardBuilder().Build() } } ; long adminId = long.Parse(d["userId"]); try { bool status = await _usersService.AddAdmin(adminId, AccessLevel.Admin); if (status) { return new MessagesSendParams() { PeerId = message.PeerId, Message = $"Пользователь vk.com/id{adminId} добавлен как администратор", RandomId = new Random().Next(), Keyboard = Keyboards.AdminPanelKeyboardBuilder().Build() } } ; else { return new MessagesSendParams() { PeerId = message.PeerId, Message = $"Произошла ошибка при добавлении пользователя.", RandomId = new Random().Next(), Keyboard = Keyboards.AdminPanelKeyboardBuilder().Build() } }; } catch (Exception e) { return(new MessagesSendParams() { PeerId = message.PeerId, Message = $"Произошла ошибка при добавлении пользователя.", RandomId = new Random().Next(), Keyboard = Keyboards.AdminPanelKeyboardBuilder().Build() }); } } case "removeAdmin": { if (userAccess != AccessLevel.Admin) { return new MessagesSendParams() { PeerId = message.PeerId, Message = "Операция недоступна пользователям без администраторского доступа", RandomId = new Random().Next(), Keyboard = Keyboards.MainMenuKeyboardBuilder().Build() } } ; RemovingAdmin?.Invoke(userId); var keyboardBuilder = new KeyboardBuilder(); keyboardBuilder.AddButton(new MessageKeyboardButtonAction() { Type = KeyboardButtonActionType.Text, Label = "Отмена", Payload = "{\"command\": \"declineRemoveAdmin\"}" }, KeyboardButtonColor.Negative); return(new MessagesSendParams() { PeerId = message.PeerId, Message = "Для удаения админа, скопируйте ссылку на пользователя ВКонтакте " + "в поле ввода сообщения и отправьте сообщение.", RandomId = new Random().Next(), Keyboard = keyboardBuilder.Build() }); } case "declineRemoveAdmin": { if (userAccess != AccessLevel.Admin) { return new MessagesSendParams() { PeerId = message.PeerId, Message = "Операция недоступна пользователям без администраторского доступа", RandomId = new Random().Next(), Keyboard = Keyboards.MainMenuKeyboardBuilder().Build() } } ; CancelRemovingAdmin?.Invoke(userId); var keyboardBuilder = Keyboards.AdminPanelKeyboardBuilder(); return(new MessagesSendParams() { PeerId = message.PeerId, Message = "Отмена удаления админа", RandomId = new Random().Next(), Keyboard = keyboardBuilder.Build() }); } case "acceptRemoveAdmin": { if (userAccess != AccessLevel.Admin) { return new MessagesSendParams() { PeerId = message.PeerId, Message = "Операция недоступна пользователям без администраторского доступа", RandomId = new Random().Next(), Keyboard = Keyboards.MainMenuKeyboardBuilder().Build() } } ; long adminId = long.Parse(d["userId"]); try { bool status = await _usersService.DeleteAdmin(adminId); if (status) { return new MessagesSendParams() { PeerId = message.PeerId, Message = $"Пользователь vk.com/id{adminId} удалён из списка админов", RandomId = new Random().Next(), Keyboard = Keyboards.AdminPanelKeyboardBuilder().Build() } } ; else { return new MessagesSendParams() { PeerId = message.PeerId, Message = $"Произошла ошибка при удалении пользователя.", RandomId = new Random().Next(), Keyboard = Keyboards.AdminPanelKeyboardBuilder().Build() } }; } catch (Exception e) { return(new MessagesSendParams() { PeerId = message.PeerId, Message = $"Произошла ошибка при удалении пользователя.", RandomId = new Random().Next(), Keyboard = Keyboards.AdminPanelKeyboardBuilder().Build() }); } } case "backToMain": { if (userAccess != AccessLevel.Admin) { return new MessagesSendParams() { PeerId = message.PeerId, Message = "Операция недоступна пользователям без администраторского доступа", RandomId = new Random().Next(), Keyboard = Keyboards.MainMenuKeyboardBuilder().Build() } } ; return(new MessagesSendParams() { RandomId = new Random().Next(), PeerId = message.PeerId, Message = "Назад", Keyboard = Keyboards.MainMenuKeyboardBuilder().Build() }); } } return(IMessageApi.DefaultTextMessage(message, replyText)); } return(IMessageApi.DefaultTextMessage(message, "Неизвестная команда. Используйте кнопку \"Помощь\"")); } }
public AttachmentHandler(IMessageApi messageApi, ApiUsersService apiUsersService) { _messageApi = messageApi; _usersService = apiUsersService; }