-
Notifications
You must be signed in to change notification settings - Fork 71
/
Copy pathTelegramIntegration.Messaging.cs
158 lines (131 loc) · 5.01 KB
/
TelegramIntegration.Messaging.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// ==========================================================================
// Notifo.io
// ==========================================================================
// Copyright (c) Sebastian Stehle
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Globalization;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using Notifo.Domain.Integrations.Resources;
using Telegram.Bot;
using Telegram.Bot.Types.Enums;
using TelegramChat = Telegram.Bot.Types.Chat;
using TelegramUpdate = Telegram.Bot.Types.Update;
using TelegramUser = Telegram.Bot.Types.User;
namespace Notifo.Domain.Integrations.Telegram;
public sealed partial class TelegramIntegration : IMessagingSender, IIntegrationHook
{
private const int Attempts = 5;
private const string TelegramChatId = nameof(TelegramChatId);
public void AddTargets(IDictionary<string, string> targets, UserInfo user)
{
var chatId = GetChatId(user);
if (!string.IsNullOrWhiteSpace(chatId))
{
targets[TelegramChatId] = chatId;
}
}
public async Task<DeliveryResult> SendAsync(IntegrationContext context, MessagingMessage message,
CancellationToken ct)
{
if (!message.Targets.TryGetValue(TelegramChatId, out var chatId))
{
return DeliveryResult.Skipped();
}
await SendMessageAsync(context, message.Text, chatId, ct);
return DeliveryResult.Handled;
}
private async Task SendMessageAsync(IntegrationContext context, string text, string chatId,
CancellationToken ct)
{
var accessToken = AccessToken.GetString(context.Properties);
// Try a few attempts to get a non-disposed server instance.
for (var i = 1; i <= Attempts; i++)
{
try
{
var client = clientPool.GetBotClient(accessToken);
await client.SendTextMessageAsync(chatId, text, null, ParseMode.Markdown, cancellationToken: ct);
break;
}
catch (ObjectDisposedException)
{
if (i == Attempts)
{
throw;
}
}
}
}
public async Task HandleRequestAsync(IntegrationContext context, HttpContext httpContext,
CancellationToken ct)
{
var update = await ParseUpdateAsync(httpContext.Request.Body);
switch (update.Type)
{
case UpdateType.Message when IsUpdate(update):
await UpdateUser(
context,
update.Message?.From!,
update.Message?.Chat!,
default);
break;
case UpdateType.MyChatMember:
var chatId = GetChatId(update.MyChatMember!.Chat);
await SendMessageAsync(context, GetWelcomeMessage(context), chatId, default);
await UpdateUser(
context,
update.MyChatMember.From,
update.MyChatMember.Chat,
default);
break;
}
}
private async Task UpdateUser(IntegrationContext context, TelegramUser from, TelegramChat chat,
CancellationToken ct)
{
var chatId = GetChatId(chat);
var username = from.Username;
if (string.IsNullOrWhiteSpace(username))
{
await SendMessageAsync(context, GetUserNotFoundMessage(context), chatId, ct);
return;
}
var user = await context.IntegrationAdapter.FindUserByPropertyAsync(context.AppId, UserUsername.Name, username, default);
if (user == null)
{
await SendMessageAsync(context, GetUserNotFoundMessage(context), chatId, ct);
return;
}
await context.IntegrationAdapter.UpdateUserAsync(context.AppId, user.Id, TelegramChatId, chatId, default);
}
private static string GetChatId(TelegramChat chat)
{
return chat.Id.ToString(CultureInfo.InvariantCulture)!;
}
private static string GetWelcomeMessage(IntegrationContext context)
{
return string.Format(CultureInfo.InvariantCulture, Texts.Telegram_WelcomeMessage, context.AppName);
}
private static string GetUserNotFoundMessage(IntegrationContext context)
{
return string.Format(CultureInfo.InvariantCulture, Texts.Telegram_UserNotFound, context.AppName);
}
private static string? GetChatId(UserInfo user)
{
return UserChatId.GetString(user.Properties);
}
private static bool IsUpdate(TelegramUpdate update)
{
return update.Message is { Type: MessageType.Text, Text: "/update" };
}
private static async Task<TelegramUpdate> ParseUpdateAsync(Stream stream)
{
using (var streamReader = new StreamReader(stream))
{
var json = await streamReader.ReadToEndAsync();
return JsonConvert.DeserializeObject<TelegramUpdate>(json)!;
}
}
}