public HandlerMatch Match(MiddlewareData middlewareData) { var command = middlewareData.Features.RequireOne <CommandFeature>().Command; var commandMatched = Attribute.Command.Nullable() .Map(a => command.Command.Map(b => a.Equals(b, StringComparison.OrdinalIgnoreCase)).OrElse(false)) .OrElse(false); var commandsMatched = Attribute.Commands.Nullable() .Map(a => command.Command.Map(b => a.Contains(b, StringComparer.OrdinalIgnoreCase)).OrElse(false)) .OrElse(false); var commandPatternMatched = Attribute.CommandPattern.Nullable() .Map(pattern => new Regex(pattern, RegexOptions.Compiled)) .Map(pattern => command.Command.Map(pattern.IsMatch).OrElse(false)) .OrElse(false); var typeMatched = Attribute.Type.Nullable() .Map(filter => filter.Equals(command.Type, StringComparison.Ordinal)) .OrElse(true); if (typeMatched && (commandMatched || commandsMatched || commandPatternMatched)) { return(HandlerMatch.CreateMatched(this)); } return(HandlerMatch.CreateUnmatched()); }
public async Task <MiddlewareData> InvokeAsync(MiddlewareData data, IMiddlewaresChain chain) { var chatId = _contextManager.GetChatId(data); var messageId = _contextManager.GetMessageId(data); var chatContext = await _storage.LoadChatContext(chatId); var messageContext = Enumerable.Empty <KeyValuePair <string, object> >(); if (_contextManager.HasMessageContext(data)) { messageContext = await _storage.LoadMessageContext(chatId, messageId); } var newData = data.UpdateFeatures(f => f.AddExclusive <ChatContextFeature>(new ChatContextFeature(chatContext)) .AddExclusive <MessageContextFeature>(new MessageContextFeature(messageId, messageContext))); var resultData = await chain.NextAsync(newData); var newChatContext = resultData.Features.RequireOne <ChatContextFeature>(); await _storage.SaveChatContext(chatId, newChatContext.Items); var newMessageContext = resultData.Features.RequireOne <MessageContextFeature>(); foreach (var id in newMessageContext.MessageIds) { await _storage.SaveMessageContext(chatId, id, newMessageContext.Items); } return(resultData); }
public async Task <IHandlerResult> ExecuteAsync(MiddlewareData middlewareData) { var filters = _method.GetCustomAttributes <FilterAttribute>(); var filterResult = await FilterUtils.ExecuteFilters(filters, _serviceProvider, middlewareData); if (filterResult.Action == FilterAction.SkipHandler) { return(null); } if (filterResult.Action == FilterAction.BreakExecution) { return(filterResult.MiddlewareData .Map(HandlerResultCreators.UpdateMiddlewareData) .OrElseGet(HandlerResultCreators.Empty)); } var parameters = _parametersMatcher.MatchParameters(filterResult.MiddlewareData.Value, _method.GetParameters()); if (!parameters.IsPresent) { return(null); } var instance = _serviceProvider.GetInstance(_method.DeclaringType); var result = _method.Invoke(instance, parameters.Value.Select(v => v.Value).ToArray()); if (result is Task task) { return(await task.ContinueWith(PrepareResult)); } return(PrepareResult(result)); }
public async Task <Maybe <IIdentity> > HandleAuthenticationAsync(MiddlewareData data, IPrincipal principal) { var telegramIdentity = principal.GetIdentity <TelegramIdentity>() .OrElseThrow(() => new InvalidOperationException("TelegramIdentity is required")); var telegramUserId = telegramIdentity.Id; var filter = Builders <T> .Filter.Eq(u => u.UserId, telegramUserId); var newUser = await _identityFactory.CreateIdentityAsync(principal); var update = new BsonDocument { { "$setOnInsert", newUser.ToBsonDocument() } }; IIdentity identity = await GetDatabase().GetCollection <T>(CollectionNames.UsersCollection) .FindOneAndUpdateAsync( filter: filter, update: update, options: new FindOneAndUpdateOptions <T>() { IsUpsert = true, ReturnDocument = ReturnDocument.After } ); return(identity.NotNull()); }
private async Task ProcessUpdates(CancellationToken token) { await Task.Yield(); while (!token.IsCancellationRequested) { UpdateInfo updateInfo; if (!_updatesQueue.TryDequeue(out updateInfo)) { await Task.Delay(TimeSpan.FromSeconds(1), token); continue; } try { var inputData = new MiddlewareData() .UpdateFeatures(f => f.AddExclusive <UpdateInfoFeature>(new UpdateInfoFeature(updateInfo))); await _middlewaresChain.NextAsync(inputData); } catch (Exception e) { _logger.LogError(0, e, "Unhandled exception occured"); } } }
public IEnumerable <IHandler> CreateHandlers(MiddlewareData middlewareData) { return(_descriptors .Select(d => d.Match(middlewareData)) .Where(m => m.Successful) .Select(m => new Handler(_serviceProvider, _parametersMatcher, m.Descriptor.Method))); }
private static RoutingData ParseRoutingData(MiddlewareData data) { var updateFeature = data.Features.RequireOne <UpdateInfoFeature>(); string messageText; if (updateFeature.Update.CallbackQuery != null) { var callback = updateFeature.Update.CallbackQuery; messageText = callback.Data; } else { var message = updateFeature.GetAnyMessage(); messageText = message.Text; } var match = FindCommandRegex.Match(messageText); if (!match.Success) { return(new RoutingData("", "", new string[0], messageText)); } var path = match.Groups[1].Value; var parts = path.Split(':'); var content = match.Groups[2].Value; return(new RoutingData(path, path, parts, content)); }
public async Task <MiddlewareData> InvokeAsync(MiddlewareData input) { var fields = input.Features.RequireOne <RouterFeature>().Fields; var action = fields["action"]; MethodInfo method; if (!_methods.TryGetValue(action, out method)) { throw new Exception($"Action '{action}' not found"); } var parameters = method.GetParameters(); var values = _actionParametersMapper.MapParameters(input, parameters); object objResult; if (typeof(Task <object>).GetTypeInfo().IsAssignableFrom(method.ReturnType)) { var task = (Task <object>)method.Invoke(_instance, values); objResult = await task; } else { objResult = await Task.Run(() => method.Invoke(_instance, values)); } var actionResult = objResult as IActionResult; if (actionResult != null) { return(actionResult.Render(input)); } throw new Exception("Cannot process result"); }
public async Task <MessageContext> Render(MiddlewareData middlewareData, ITelegramClient telegramClient, CancellationToken cancellationToken) { var context = middlewareData.Features.RequireOne <SessionFeature>().Context; var message = middlewareData.Features.RequireOne <UpdateInfoFeature>().GetAnyMessage(); if (message == null) { throw new InvalidOperationException("Cannot send response"); } if (context.SentMessageIds.Any()) { await telegramClient.UpdateMessage(new UpdateMessageData( message.Chat.Id.ToString(), context.SentMessageIds.First(), _messageData ), cancellationToken); return(MessageContext.Empty()); } var chatId = message.Chat.Id.ToString(); var newMessage = await telegramClient.SendMessage(new SendMessageData( chatId, _messageData ), cancellationToken); return(MessageContext.Builder() .AddMessageId(newMessage.Id) .Build()); }
public async Task <MiddlewareData> InvokeAsync(MiddlewareData data, IMiddlewaresChain chain) { var controller = _controllerFactory.GetController(data); var newData = await controller.InvokeAsync(data); return(await chain.NextAsync(newData)); }
public async Task <MiddlewareData> InvokeAsync(MiddlewareData data, IMiddlewaresChain chain) { var commandInfo = await _commandParser.ParseAsync(data); var newData = data.UpdateFeatures(f => f.Add <CommandFeature>(new CommandFeature(commandInfo))); return(await chain.NextAsync(newData)); }
public Task <MiddlewareData> RenderAsync(MiddlewareData data) { if (_func != null) { return(Task.FromResult(_func(data))); } return(Task.FromResult(_middlewareData)); }
public async Task <MessageContext> Render(MiddlewareData middlewareData, ITelegramClient telegramClient, CancellationToken cancellationToken) { var newMessage = await telegramClient.SendMessage(new SendMessageData(_chatId, _messageData), cancellationToken); return(MessageContext.Builder() .AddMessageId(newMessage.Id) .Build()); }
public bool HasMessageContext(MiddlewareData middlewareData) { var updateInfo = middlewareData.Features.RequireOne <UpdateInfoFeature>(); var contextMessageId = updateInfo.Update.EditedMessage?.Id ?? updateInfo.Update.EditedChannelPost?.Id ?? updateInfo.Update.CallbackQuery?.Message.Id; return(contextMessageId != null); }
public async Task <MiddlewareData> InvokeAsync(MiddlewareData data, IMiddlewaresChain chain) { try { return(await chain.NextAsync(data)); } catch (Exception e) { return(GetHandler(e.GetType()).HandleException(data, e)); } }
public CommandInfo Parse(MiddlewareData data) { var updateInfo = data.Features.RequireOne <UpdateInfoFeature>(); if (updateInfo.Update.CallbackQuery != null) { return(MatchCommand(TelegramCommandTypes.InlineKeyboardCommand, updateInfo.Update.CallbackQuery.Data, ParseCallbackQueryRegex)); } return(MatchCommand(TelegramCommandTypes.TextMessageCommand, updateInfo.GetAnyMessage().Text, ParseCommandRegex)); }
public override MiddlewareData HandleException(MiddlewareData middlewareData, Exception exception) { _logger.LogError(0, exception, "Unexpected error occurred"); var message = new BaseOutMessage() { Text = $"Error occured: [{exception.GetType().Name}] {exception.Message}" }; return(middlewareData.AddRenderMessageFeature(message)); }
public override MiddlewareData HandleException(MiddlewareData middlewareData, NoSuchHandlerException exception) { _logger.LogInformation("Cannot find handler for message"); var message = new BaseOutMessage() { Text = "Unknown command" }; return(middlewareData.AddRenderMessageFeature(message)); }
public async Task <MiddlewareData> RenderAsync(MiddlewareData data) { var lastData = data; foreach (var result in _results) { lastData = await result.RenderAsync(lastData); } return(lastData); }
public async Task <MiddlewareData> InvokeAsync(MiddlewareData data, IMiddlewaresChain chain) { var userPreferences = data.Features.GetOne <UserPreferencesFeature>() .Map(f => f.UserPreferences) .OrElse(DefaultUserPreferences.Instance); var routingData = ParseRoutingData(data); var prevRoutingData = await LoadSavedRoutingData(data); if (prevRoutingData != null) { routingData = JoinRoutingData(prevRoutingData, routingData); } var dataWithContext = data.UpdateFeatures(f => f.ReplaceExclusive <SessionFeature>( e => e.SetRoutingData(prevRoutingData) ) ); _logger.LogDebug($"Try find route for {routingData.Path} ({routingData.UserCommand})"); var match = _router.FindRoute(routingData); var chatId = dataWithContext.Features.RequireOne <UpdateInfoFeature>().GetAnyMessage().Chat.Id; if (!match.IsMatched) { await _sessionStorage.ClearRoutingDataAsync(chatId); var message = _localizationManager.Localize( userPreferences: userPreferences, key: LocalizationKeys.UnknownCommand, parameters: new { text = routingData.UserCommand } ); return(dataWithContext.AddResponseRenderer(message)); } if (!match.IsCompleted) { await _sessionStorage.SaveRoutingDataAsync(chatId, routingData); var responseMessage = MessageData.Builder() .SetText(_localizationManager.Localize(userPreferences, LocalizationKeys.SelectOneForCompletion)) .SetInlineKeyboardMarkup(bldr => BuildResponseMarkup(bldr, match.UncompletedRoutes)) .Build(); return(dataWithContext.AddResponseRenderer(responseMessage)); } await _sessionStorage.ClearRoutingDataAsync(chatId); var route = match.CompletedRoute; var feature = new RouterFeature(route.Route, routingData, route.Fields); var dataWithRoute = dataWithContext.UpdateFeatures(f => f.AddExclusive <RouterFeature>(feature)); return(await chain.NextAsync(dataWithRoute)); }
public async Task <MiddlewareData> InvokeAsync(MiddlewareData data, IMiddlewaresChain chain) { var resultData = await chain.NextAsync(data); foreach (var message in resultData.Features.GetAll <RenderMessageFeature>().Select(f => f.Message)) { var renderrer = GetRenderer(message.GetType()); resultData = await renderrer.RenderAsync(resultData, message); } return(resultData); }
public Task <Maybe <IIdentity> > HandleAuthenticationAsync(MiddlewareData data, IPrincipal principal) { var message = data.Features.RequireOne <UpdateInfoFeature>().GetAnyMessage(); if (message == null) { return(Task.FromResult(Maybe <IIdentity> .Empty())); } var userId = message.User?.Id ?? message.Chat.Id; var userName = message.User?.UserName ?? message.Chat.UserName; var identity = new TelegramIdentity(userId.ToString(), userName); return(Task.FromResult(Maybe <IIdentity> .Of(identity))); }
public Task <FilterResult> FilterAsync(FilterAttribute attribute, MiddlewareData data) { var principal = data.Features.RequireOne <AuthenticationFeature>().Principal; if (!principal.IsAuthenticated()) { var message = new BaseOutMessage() { Text = "Unauthorized access" }; var result = FilterResult.BreakExecution(data.AddRenderMessageFeature(message)); return(Task.FromResult(result)); } return(Task.FromResult(FilterResult.NextFilter(data))); }
private async Task <RoutingData> LoadSavedRoutingData(MiddlewareData data) { var message = data.Features.RequireOne <UpdateInfoFeature>().GetAnyMessage(); var chatId = message.Chat.Id; var messageId = message.Id; var context = await _sessionStorage.LoadMessageContextAsync(chatId, messageId); if (context != null) { return(context.RoutingData); } return(await _sessionStorage.GetRoutingDataAsync(chatId)); }
public Task <MiddlewareData> RenderAsync(MiddlewareData data) { var messageContent = new MessageContent(Text); InlineKeyboardMarkup.Nullable().IfPresent(m => messageContent.ReplyMarkup = m); var message = new TelegramOutMessage(messageContent) { UpdateMessage = Update, MessageId = MessageId, ChatId = ChatId }; return(Task.FromResult(data.AddRenderMessageFeature(message))); }
public async Task <MiddlewareData> InvokeAsync(MiddlewareData data, IMiddlewaresChain chain) { var principal = new CombinablePrincipal(); foreach (var authenticationHandler in _authenticationHandlers) { var identity = await authenticationHandler.HandleAuthenticationAsync(data, principal); principal = identity.Map(principal.AddIdentity).OrElse(principal); } var newData = data.UpdateFeatures(f => f.AddExclusive <AuthenticationFeature>(new AuthenticationFeature(principal))); return(await chain.NextAsync(newData)); }
public object[] MapParameters(MiddlewareData data, IEnumerable <ParameterInfo> parameters) { var allValues = data.Features.GetAllOfBaseType <IParameterValuesSource>() .SelectMany(source => source.GetValues()) .Union(new [] { new ParameterValue("middlewareData", data) }); var groupped = parameters.GroupJoin( inner: allValues, outerKeySelector: p => p.ParameterType, innerKeySelector: v => v.Type, resultSelector: (parameter, values) => new { parameter, values = values.ToArray() }, comparer: ParametersEqualityComparer.Instance ); return(groupped.Select(g => SelectValue(g.parameter, g.values)).ToArray()); }
public IController GetController(MiddlewareData input) { var fields = input.Features.RequireOne <RouterFeature>().Fields; var controller = fields["controller"]; TypeInfo type; if (!_types.TryGetValue(controller, out type)) { throw new Exception("Controller not found"); } var instance = _serviceProvider.GetInstance(type.UnderlyingSystemType); return(instance as IController ?? new ActionsController(_actionParametersMapper, instance)); }
public async Task <MiddlewareData> InvokeAsync(MiddlewareData data, IMiddlewaresChain chain) { foreach (var handler in _handlerFactory.CreateHandlers(data)) { var result = await handler.ExecuteAsync(data); if (result == null) // TODO fix this check { continue; } var resultData = await result.RenderAsync(data); return(await chain.NextAsync(resultData)); } throw new NoSuchHandlerException(); }
public static async Task <ModuleResponseCode> RouteAsync(string Path, LanguageManager STR_LANG, WebHttpContextRaw ContextRaw) { string Version = Assembly.GetExecutingAssembly().GetName().Version.ToString(); //Set HTTP Header to this ContextRaw.Response.SetHeader("X-Powered-By", $"HS Server Framework (Web)/{Version}"); ContextRaw.Response.SetHeader("Server", $"HS Server (Web)/{Version}"); MiddlewareData data = await Middleware.RouteAsync(new MiddlewareData(Path, STR_LANG, ContextRaw)); ModuleResponseCode ResultCode = (ModuleResponseCode)data.StatusCode; if (!data.IsClose && ContextRaw.Response.IsWritable) { ResultCode = await Router.RouteAsync(data); } //MiddleWareData data_post = await MiddleWare_Post.RouteAsync(Path, Params, STR_LANG, ContextRaw); return(ResultCode); }