Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ obj/
riderModule.iml
/_ReSharper.Caches/
.idea/
/.vs/TgBotFramework
10 changes: 10 additions & 0 deletions examples/EchoBotProject/EchoBotProject.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<None Remove="Resources\ru\game.stage.json" />
<None Remove="Resources\ru\publicChat.handler.json" />
</ItemGroup>

<ItemGroup>
<EmbeddedResource Include="Resources\ru\game.stage.json" />
<EmbeddedResource Include="Resources\ru\publicChat.handler.json" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\TgBotFramework\TgBotFramework.csproj" />
</ItemGroup>
Expand Down
8 changes: 7 additions & 1 deletion examples/EchoBotProject/Handlers/PublicChatEcho.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,27 @@
using Microsoft.Extensions.Logging;
using Telegram.Bot;
using TgBotFramework;
using TgBotFramework.Attributes;
using TgBotFramework.MessageReader;
using TgBotFramework.WrapperExtensions;

namespace EchoBotProject.Handlers
{
[Handler("publicChat")]
public class PublicChatEcho : IUpdateHandler<BotExampleContext>
{
private readonly ILogger<PublicChatEcho> _logger;
private readonly IMessageReader<PublicChatEcho, BotExampleContext> _messageReader;

public PublicChatEcho(ILogger<PublicChatEcho> logger)
public PublicChatEcho(ILogger<PublicChatEcho> logger, IMessageReader<PublicChatEcho, BotExampleContext> messageReader)
{
_messageReader = messageReader;
_logger = logger;
}

public async Task HandleAsync(BotExampleContext context, UpdateDelegate<BotExampleContext> next, CancellationToken cancellationToken)
{
await context.Client.SendTextMessageAsync(context.Update.GetSenderId(), _messageReader.GetMessage("greetings"));
_logger.LogInformation("This update {0} was from public chat {1}", context.Update.Id, context.Update.GetChat());
}
}
Expand Down
5 changes: 5 additions & 0 deletions examples/EchoBotProject/Resources/ru/game.stage.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"exit": "Okay, you got out, lets play ping-pong with counter",
"exit.provocativeMessage": "Cmon, find EXIT"

}
3 changes: 3 additions & 0 deletions examples/EchoBotProject/Resources/ru/publicChat.handler.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"greetings": "Hello, my dear friend!"
}
12 changes: 10 additions & 2 deletions examples/EchoBotProject/States/GameState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,30 @@
using TgBotFramework;
using TgBotFramework.Attributes;
using TgBotFramework.WrapperExtensions;
using TgBotFramework.MessageReader;

namespace EchoBotProject.States
{
[State(Stage = "game")]
public class GameState<TContext> : BasicState<TContext> where TContext : IUpdateContext
{
private readonly IMessageReader<GameState<TContext>, TContext> _messageReader;

public GameState(IMessageReader<GameState<TContext>, TContext> messageReader)
{
_messageReader = messageReader;
}

public override async Task HandleAsync(TContext context, UpdateDelegate<TContext> next, CancellationToken cancellationToken)
{
if (context.Update.Message?.Text != null && context.Update.Message.Text == "/exit")
{
await context.Client.SendTextMessageAsync(context.Update.GetChat(), "Okay, you got out, lets play ping-pong with counter", cancellationToken: cancellationToken);
await context.Client.SendTextMessageAsync(context.Update.GetChat(), _messageReader.GetMessage("exit"), cancellationToken: cancellationToken);
await Exit(context);
}
else
{
await context.Client.SendTextMessageAsync(context.Update.GetChat(), "Cmon, find EXIT", cancellationToken: cancellationToken);
await context.Client.SendTextMessageAsync(context.Update.GetChat(), _messageReader.GetMessage("exit.provocativeMessage"), cancellationToken: cancellationToken);
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions examples/EchoBotWebExample/EchoBotWebExample.csproj.user
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ActiveDebugProfile>IIS Express</ActiveDebugProfile>
</PropertyGroup>
</Project>
27 changes: 27 additions & 0 deletions examples/EchoBotWebExample/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:56028/",
"sslPort": 44336
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"EchoBotWebExample": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:5001;http://localhost:5000"
}
}
}
10 changes: 4 additions & 6 deletions examples/EchoBotWebExample/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Telegram.Bot;
using TgBotFramework;
using TgBotFramework.UpdatePipeline;

namespace EchoBotWebExample
{
Expand All @@ -42,11 +40,9 @@ public void ConfigureServices(IServiceCollection services)
services.AddScoped<UpdateLogger>();
services.AddScoped<GlobalExceptionHandler>();


// register deps for pipeline
services.ServicesForExamplePipelineBuilder();



services.AddDbContext<BotFrameworkContext>(x =>
x.UseSqlite("Data Source=BotFramework.db",
builder => builder.MigrationsAssembly("EchoBotProject")));
Expand All @@ -59,7 +55,9 @@ public void ConfigureServices(IServiceCollection services)

.UseMiddleware<GlobalExceptionHandler>()


.AddMessageReader<PublicChatEcho>()
.AddMessageReader<GameState<BotExampleContext>>()

// you may use this approach to logging but be aware that not all update objects can be converted back to json
.UseMiddleware<UpdateLogger>()
// if you want to use states...
Expand Down
27 changes: 27 additions & 0 deletions examples/WebhookExample/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:56027/",
"sslPort": 44374
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"WebhookExample": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:5001;http://localhost:5000"
}
}
}
6 changes: 6 additions & 0 deletions examples/WebhookExample/WebhookExample.csproj.user
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ActiveDebugProfile>IIS Express</ActiveDebugProfile>
</PropertyGroup>
</Project>
18 changes: 18 additions & 0 deletions src/TgBotFramework/Attributes/HandlerAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TgBotFramework.Attributes
{
public class HandlerAttribute : System.Attribute
{
public string Stage { get; }

public HandlerAttribute(string stage)
{
Stage = stage;
}
}
}
8 changes: 8 additions & 0 deletions src/TgBotFramework/BotFrameworkBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using TgBotFramework.Attributes;
using TgBotFramework.MessageReader;
using TgBotFramework.StageManaging;
using TgBotFramework.UpdatePipeline;

Expand Down Expand Up @@ -42,6 +43,13 @@ public BotFrameworkBuilder(IServiceCollection services)
services.AddSingleton<BaseBot>(provider => provider.GetService<TBot>());
}

public IBotFrameworkBuilder<TContext> AddMessageReader<TUpdateHandler>(string rootDirectory = "Resources", string language = "ru", Assembly resourceAssembly = null)
where TUpdateHandler : class
{
Services.AddSingleton<IMessageReader<TUpdateHandler, TContext>>(provider => new MessageReader<TUpdateHandler, TContext>(rootDirectory, language, resourceAssembly));
return this;
}

public IBotFrameworkBuilder<TContext> UseLongPolling<T>(LongPollingOptions longPollingOptions) where T : BackgroundService, IPollingManager<TContext>
{
Services.AddHostedService<T>();
Expand Down
3 changes: 3 additions & 0 deletions src/TgBotFramework/IBotFrameworkBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,8 @@ IBotFrameworkBuilder<TContext> SetPipeline(

IBotFrameworkBuilder<TContext> UseStates(Assembly assembly);
IBotFrameworkBuilder<TContext> UseCommands(Assembly getAssembly);

IBotFrameworkBuilder<TContext> AddMessageReader<TUpdateHandler>(string rootDirectory = "Resources", string language = "ru", Assembly resourceAssembly = null)
where TUpdateHandler : class;
}
}
15 changes: 15 additions & 0 deletions src/TgBotFramework/MessageReader/IMessageReader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TgBotFramework.MessageReader
{
public interface IMessageReader<TUpdateHandler, TContext>
where TContext : IUpdateContext
where TUpdateHandler : class
{
string GetMessage(string jsonPath);
}
}
78 changes: 78 additions & 0 deletions src/TgBotFramework/MessageReader/MessageReader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.IO;
using System.Reflection;
using TgBotFramework.Attributes;

namespace TgBotFramework.MessageReader
{
public class MessageReader<TUpdateHandler, TContext> : IMessageReader<TUpdateHandler, TContext>
where TContext : IUpdateContext
where TUpdateHandler : class
{
private readonly Assembly _resourceAssembly;
private readonly string _rootDirectory;
private readonly string _language;
private readonly string _stage;
private readonly Stream _stream;
private readonly StreamReader _fileReader;

public MessageReader(string rootDirectory = "Resources", string language = "ru", Assembly resourceAssembly = null)
{
_rootDirectory = rootDirectory;
_language = language;
_resourceAssembly = resourceAssembly ?? Assembly.GetCallingAssembly();

var handlerAttribute = typeof(TUpdateHandler).GetCustomAttribute<HandlerAttribute>();
if (handlerAttribute != null)
{
_stage = handlerAttribute.Stage + ".handler";
}
else
{
var stateAttribute = typeof(TUpdateHandler).GetCustomAttribute<StateAttribute>();
if (stateAttribute != null)
{
_stage = stateAttribute.Stage + ".stage";
}
}

if (_stage == null)
{
throw new InvalidOperationException("The IUpdateHandler class should contain State or Handler attribute");
}

var resourcePath = $"{_resourceAssembly.GetName().Name}.{_rootDirectory}.{_language}.{_stage}.json";
_stream = _resourceAssembly.GetManifestResourceStream(resourcePath);

if (_stream == null)
{
throw new InvalidOperationException(
$"Assembly {_resourceAssembly.FullName} doesn't contain EmbeddedResource at path {resourcePath}. Resource file cannot be loaded");
}

_fileReader = new StreamReader(_stream);
MessageFileText = _fileReader.ReadToEnd();
}

public string MessageFileText { get; private set; }

public void Dispose()
{
_fileReader.Close();
_stream.Close();
}

public string GetMessage(string jsonPath)
{
JObject JsonObject = JsonConvert.DeserializeObject<JObject>(MessageFileText);
var node = JsonObject.SelectToken(jsonPath);
if (node == null)
{
throw new ArgumentException($"There are no values found by path '{jsonPath}' in stage JSON file '{_stage}'");
}
return node.ToString();
}
}
}