Skip to content

Commit 7e9d5b7

Browse files
committed
Merge branch 'release/v0.15'
2 parents deef978 + 67854e4 commit 7e9d5b7

File tree

11 files changed

+213
-106
lines changed

11 files changed

+213
-106
lines changed

Deployf.Botf/BotController.cs

Lines changed: 2 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -69,77 +69,8 @@ protected ValueTask AState<T>(T state, string? name = null) where T : notnull
6969

7070
protected async ValueTask GlobalState(object? state)
7171
{
72-
if(state == null)
73-
{
74-
if(await Store!.Contain(FromId, Consts.GLOBAL_STATE))
75-
{
76-
var oldState = await Store!.Get(FromId, Consts.GLOBAL_STATE, null);
77-
if (oldState != null)
78-
{
79-
await Call(true, oldState);
80-
}
81-
}
82-
await Store!.Remove(FromId, Consts.GLOBAL_STATE);
83-
await CallClear();
84-
}
85-
else
86-
{
87-
if (await Store!.Contain(FromId, Consts.GLOBAL_STATE))
88-
{
89-
var oldState = await Store!.Get(FromId, Consts.GLOBAL_STATE, null);
90-
if (oldState != null)
91-
{
92-
await Call(true, oldState);
93-
}
94-
}
95-
await Store!.Set(FromId, Consts.GLOBAL_STATE, state);
96-
await Call(false, state);
97-
}
98-
99-
async ValueTask Call(bool leave, object oldState)
100-
{
101-
var routes = Context!.Services.GetRequiredService<BotControllerRoutes>();
102-
var controllerType = routes.GetStateType(oldState.GetType());
103-
if (controllerType != null)
104-
{
105-
var controller = (BotControllerState)Context!.Services.GetRequiredService(controllerType);
106-
controller.Init(Context, CancelToken);
107-
controller.User = User;
108-
await controller.OnBeforeCall();
109-
if (leave)
110-
{
111-
await controller.OnLeave();
112-
}
113-
else
114-
{
115-
await controller.OnEnter();
116-
}
117-
await controller.OnAfterCall();
118-
}
119-
}
120-
121-
async ValueTask CallClear()
122-
{
123-
var handlersContainer = Context!.Services.GetRequiredService<BotControllerHandlers>();
124-
var lookup = handlersContainer.GetHandlers(Handle.ClearState);
125-
if(lookup == null)
126-
{
127-
return;
128-
}
129-
130-
var invoker = Context.Services.GetRequiredService<BotControllersInvoker>();
131-
foreach (var handler in lookup)
132-
{
133-
if(Context.IsHandlingStopRequested())
134-
{
135-
break;
136-
}
137-
if(handler.TryFilter(Context))
138-
{
139-
await invoker.Invoke(Context, CancelToken, handler.TargetMethod);
140-
}
141-
}
142-
}
72+
var service = Context.Services.GetRequiredService<IGlobalStateService>();
73+
await service.SetState(FromId, state, cancelToken: CancelToken);
14374
}
14475
#endregion
14576

Deployf.Botf/Middlewares/BotControllersAuthMiddleware.cs

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public async Task HandleAsync(IUpdateContext context, UpdateDelegate next, Cance
1919
if(context.Items.TryGetValue("controller", out var value) && value is BotController controller)
2020
{
2121
var method = (MethodInfo)context.Items["action"];
22-
var user = await GetUser(context);
22+
var user = await _tokenService.GetUser(context.GetSafeUserId());
2323
context.Items["user"] = user;
2424
controller.User = user;
2525
AuthMethod(controller, method);
@@ -52,31 +52,4 @@ void AuthMethod(BotController controller, MethodInfo method)
5252
throw new UnauthorizedAccessException();
5353
}
5454
}
55-
56-
async Task<UserClaims> GetUser(IUpdateContext context)
57-
{
58-
var tgUserId = context.GetSafeUserId();
59-
if (!tgUserId.HasValue)
60-
{
61-
_log.LogWarning("Telegram userId not found!");
62-
return new UserClaims();
63-
}
64-
65-
var (userId, roles) = await _tokenService.GetUserIdWithRoles(tgUserId.Value);
66-
if (userId == null)
67-
{
68-
_log.LogDebug("User with {tgUserId} not found in database", tgUserId.Value);
69-
return new UserClaims();
70-
}
71-
72-
var claim = new UserClaims()
73-
{
74-
Roles = roles ?? new string[0],
75-
IsAuthorized = true,
76-
Id = userId
77-
};
78-
79-
_log.LogDebug("User {@User} with {tgUserId} found", claim, tgUserId.Value);
80-
return claim;
81-
}
8255
}

Deployf.Botf/StartupExtensions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ public static IServiceCollection AddBotf(this IServiceCollection services, BotfO
111111
services.AddScoped<IBotContextAccessor, BotContextAccessor>();
112112

113113
services.AddScoped<BotUserService>();
114+
services.AddScoped<IGlobalStateService, GlobalStateService>();
114115

115116
services.AddTransient<BotfBot>();
116117
services.AddSingleton(options);
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
using Telegram.Bot.Framework;
2+
using Telegram.Bot.Framework.Abstractions;
3+
using Telegram.Bot.Types;
4+
5+
namespace Deployf.Botf;
6+
7+
public class GlobalStateService : IGlobalStateService
8+
{
9+
public readonly IKeyValueStorage Store;
10+
public readonly IBot Bot;
11+
public readonly IServiceProvider Provider;
12+
public readonly BotUserService TokenService;
13+
public readonly BotControllerHandlers Handlers;
14+
public readonly BotControllerRoutes Routes;
15+
public readonly BotControllersInvoker Invoker;
16+
17+
public GlobalStateService(IKeyValueStorage store, BotfBot bot, IServiceProvider provider, BotUserService tokenService, BotControllerHandlers handlers, BotControllerRoutes routes, BotControllersInvoker invoker)
18+
{
19+
Store = store;
20+
Bot = bot;
21+
Provider = provider;
22+
TokenService = tokenService;
23+
Handlers = handlers;
24+
Routes = routes;
25+
Invoker = invoker;
26+
}
27+
28+
public async Task SetState<T>(long userId, T newState, bool callEnter = true, bool callLeave = true, CancellationToken cancelToken = default)
29+
{
30+
var context = new UpdateContext(Bot, new Update(), Provider)
31+
{
32+
UserId = userId,
33+
ChatId = userId
34+
};
35+
var user = await TokenService.GetUser(userId);
36+
if(newState == null)
37+
{
38+
if(await Store!.Contain(userId, Consts.GLOBAL_STATE))
39+
{
40+
var oldState = await Store!.Get(userId, Consts.GLOBAL_STATE, null);
41+
if (callLeave && oldState != null)
42+
{
43+
await Call(true, oldState);
44+
}
45+
}
46+
await Store!.Remove(userId, Consts.GLOBAL_STATE);
47+
await CallClear();
48+
}
49+
else
50+
{
51+
if (await Store!.Contain(userId, Consts.GLOBAL_STATE))
52+
{
53+
var oldState = await Store!.Get(userId, Consts.GLOBAL_STATE, null);
54+
if(callEnter && oldState != null)
55+
{
56+
await Call(true, oldState);
57+
}
58+
}
59+
await Store!.Set(userId, Consts.GLOBAL_STATE, newState);
60+
await Call(false, newState);
61+
}
62+
63+
async ValueTask Call(bool leave, object oldState)
64+
{
65+
var controllerType = Routes.GetStateType(oldState.GetType());
66+
if (controllerType != null)
67+
{
68+
var controller = (BotControllerState)context!.Services.GetRequiredService(controllerType);
69+
controller.Init(context, cancelToken);
70+
controller.User = user;
71+
await controller.OnBeforeCall();
72+
if (leave)
73+
{
74+
await controller.OnLeave();
75+
}
76+
else
77+
{
78+
await controller.OnEnter();
79+
}
80+
await controller.OnAfterCall();
81+
}
82+
}
83+
84+
async ValueTask CallClear()
85+
{
86+
var handlersContainer = Handlers;
87+
var lookup = handlersContainer.GetHandlers(Handle.ClearState);
88+
if(lookup == null)
89+
{
90+
return;
91+
}
92+
93+
foreach (var handler in lookup)
94+
{
95+
if(context.IsHandlingStopRequested())
96+
{
97+
break;
98+
}
99+
if(handler.TryFilter(context))
100+
{
101+
await Invoker.Invoke(context, cancelToken, handler.TargetMethod);
102+
}
103+
}
104+
}
105+
}
106+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace Deployf.Botf;
2+
3+
public interface IGlobalStateService
4+
{
5+
Task SetState<T>(long userId, T newState, bool callEnter = true, bool callLeave = true, CancellationToken cancelToken = default);
6+
}

Deployf.Botf/System/UpdateContextExtensions.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ public static class UpdateContextExtensions
1212

1313
public static long GetChatId(this IUpdateContext context)
1414
{
15+
if (context.ChatId.HasValue)
16+
{
17+
return context.ChatId.Value;
18+
}
19+
1520
return context.Update!.Message!.Chat.Id;
1621
}
1722

@@ -22,6 +27,11 @@ public static long GetUserId(this IUpdateContext context)
2227

2328
public static long? GetSafeChatId(this IUpdateContext context)
2429
{
30+
if (context.ChatId.HasValue)
31+
{
32+
return context.ChatId.Value;
33+
}
34+
2535
return context.Update.Message?.Chat.Id
2636
?? context.Update.EditedMessage?.Chat.Id
2737
?? context.Update.CallbackQuery?.Message?.Chat.Id
@@ -30,6 +40,10 @@ public static long GetUserId(this IUpdateContext context)
3040

3141
public static long? GetSafeUserId(this IUpdateContext context)
3242
{
43+
if (context.UserId.HasValue)
44+
{
45+
return context.UserId.Value;
46+
}
3347
return context.Update.Message?.From?.Id
3448
?? context.Update.EditedMessage?.From?.Id
3549
?? context.Update.CallbackQuery?.From?.Id
@@ -38,6 +52,11 @@ public static long GetUserId(this IUpdateContext context)
3852

3953
public static long UserId(this IUpdateContext context)
4054
{
55+
if (context.UserId.HasValue)
56+
{
57+
return context.UserId.Value;
58+
}
59+
4160
var value = context.Update.Message?.From?.Id
4261
?? context.Update.EditedMessage?.From?.Id
4362
?? context.Update.CallbackQuery?.From?.Id

Deployf.Botf/Telegram.Bot.Framework/Abstractions/IUpdateContext.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,8 @@ public interface IUpdateContext
1111
IServiceProvider Services { get; }
1212

1313
IDictionary<string, object> Items { get; }
14+
15+
long? UserId { get; set; }
16+
long? ChatId { get; set; }
1417
}
1518
}

Deployf.Botf/Telegram.Bot.Framework/UpdateContext.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ public class UpdateContext : IUpdateContext
1313
public IServiceProvider Services { get; }
1414

1515
public IDictionary<string, object> Items { get; }
16+
17+
public long? UserId { get; set; }
18+
public long? ChatId { get; set; }
1619

1720
public UpdateContext(IBot bot, Update u, IServiceProvider services)
1821
{

Deployf.Botf/Users/BotUserService.cs

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,23 @@
1-
namespace Deployf.Botf;
1+
using Telegram.Bot.Framework.Abstractions;
2+
3+
namespace Deployf.Botf;
24

35
public class BotUserService
46
{
57
readonly IBotUserService? _userService;
6-
7-
public BotUserService(IBotUserService? userService)
8+
private readonly ILogger<BotUserService> _log;
9+
10+
public BotUserService(IBotUserService? userService, ILogger<BotUserService> log)
811
{
912
_userService = userService;
13+
_log = log;
1014
}
1115

16+
public BotUserService(ILogger<BotUserService> log)
17+
{
18+
_log = log;
19+
}
20+
1221
public BotUserService()
1322
{
1423
}
@@ -21,4 +30,30 @@ public BotUserService()
2130
}
2231
return (null, null);
2332
}
33+
34+
public async Task<UserClaims> GetUser(long? tgUserId)
35+
{
36+
if (!tgUserId.HasValue)
37+
{
38+
_log.LogWarning("Telegram userId not found!");
39+
return new UserClaims();
40+
}
41+
42+
var (userId, roles) = await GetUserIdWithRoles(tgUserId.Value);
43+
if (userId == null)
44+
{
45+
_log.LogDebug("User with {tgUserId} not found in database", tgUserId.Value);
46+
return new UserClaims();
47+
}
48+
49+
var claim = new UserClaims()
50+
{
51+
Roles = roles ?? new string[0],
52+
IsAuthorized = true,
53+
Id = userId
54+
};
55+
56+
_log.LogDebug("User {@User} with {tgUserId} found", claim, tgUserId.Value);
57+
return claim;
58+
}
2459
}

0 commit comments

Comments
 (0)