InstaFollowersOverseer/Telegram/TelegramWrapper.cs

185 lines
7.7 KiB
C#

using System.Net.Http;
using Telegram.Bot;
using Telegram.Bot.Polling;
using Telegram.Bot.Types;
using Telegram.Bot.Types.Enums;
using InstaFollowersOverseer.Instagram;
namespace InstaFollowersOverseer;
public static class TelegramWrapper
{
private static ContextLogger TelegramLogger = new("telegram", ParentLogger);
private static TelegramBotClient Bot=null!;
public static async Task InitAsync()
{
try
{
TelegramLogger.LogInfo("initializing telegram wrapper");
if (CurrentConfig is null)
throw new NullReferenceException("config is null");
Bot = new TelegramBotClient(CurrentConfig.botToken, new HttpClient());
await Bot.SetMyCommandsAsync(new BotCommand[]
{
new() { Command = "start", Description = "starts the bot"},
// new() { Command = "help", Description = "shows commands list" },
new() { Command = "oversee", Description = "[instagram username] - " +
"enables notifications about instagram user's followers" },
new() { Command = "list", Description = "shows list of overseeing instagram users" }
});
var receiverOptions = new ReceiverOptions
{
// AllowedUpdates = { }, // receive all update types
};
TelegramLogger.LogInfo("bot starting recieving long polls");
Bot.StartReceiving(BotApiUpdateHandler, BotApiExceptionHandler, receiverOptions, Program.MainCancelToken);
TelegramLogger.LogInfo("telegram wrapper initialized successfully");
}
catch (OperationCanceledException) {}
catch (Exception ex)
{
TelegramLogger.LogError("init", ex);
Program.Stop();
}
}
private static Task BotApiExceptionHandler(ITelegramBotClient bot, Exception ex, CancellationToken cls)
{
TelegramLogger.LogError(ex);
return Task.CompletedTask;
}
/// parses text from markdown to html and sends to telegram chat
public static async Task SendMessage(ChatId chatId, HtmlMessageBuilder message, int? replyToMesId=null)
{
string html = message.ToHtml();
await Bot.SendTextMessageAsync(chatId, html,
replyToMessageId: replyToMesId,
parseMode: ParseMode.Html);
message.Clear();
}
public static async Task SendInfo(ChatId chatId, HtmlMessageBuilder message, int? replyToMesId=null)
{
TelegramLogger.LogInfo(message);
await SendMessage(chatId, message, replyToMesId);
}
public static async Task SendError(ChatId chatId, HtmlMessageBuilder message, int? replyToMesId=null)
{
TelegramLogger.LogWarn(message);
await SendMessage(chatId, new HtmlMessageBuilder().BeginStyle(TextStyle.Bold | TextStyle.Italic)
.Text("error: ").EndStyle().Text(message), replyToMesId);
}
public static async Task SendError(ChatId chatId, Exception ex, int? replyToMesId=null)
{
TelegramLogger.LogWarn(ex);
await SendMessage(chatId, new HtmlMessageBuilder().BeginStyle(TextStyle.Bold | TextStyle.Italic)
.Text("error: ").EndStyle().Text(ex.Message), replyToMesId);
}
private static async Task BotApiUpdateHandler(ITelegramBotClient bot, Update update, CancellationToken cls)
{
try
{
switch (update.Type)
{
case UpdateType.Message:
{
var message = update.Message!;
if (message.Text!.StartsWith('/'))
{
TelegramLogger.LogInfo($"user {message.Chat.Id} sent command {message.Text}");
var spl = message.Text.SplitToList(' ');
string command = spl[0].Substring(1);
spl.RemoveAt(0);
string[] args = spl.ToArray();
await ExecCommandAsync(command, args, message);
}
else TelegramLogger.LogDebug($"message recieved: {message.Text}");
break;
}
/*case UpdateType.InlineQuery:
break;
case UpdateType.ChosenInlineResult:
break;
case UpdateType.CallbackQuery:
break;*/
default:
TelegramLogger.LogWarn($"unknown update type: {update.Type}");
break;
}
}
catch (OperationCanceledException) {}
catch (Exception ex)
{
TelegramLogger.LogWarn("UpdateHandler", ex);
}
}
private static async Task ExecCommandAsync(string command, string[] args, Message message)
{
try
{
HtmlMessageBuilder rb = new();
long senderId = message.From?.Id ?? message.Chat.Id;
string senderName = message.From?.FirstName ?? message.Chat.FirstName ??
message.Chat.Username ?? "UnknownUser";
switch (command)
{
case "start":
await SendInfo(message.Chat, rb.Text("bot started"));
break;
case "oversee":
{
string usernameOrUrl = args[0];
await SendInfo(message.Chat, rb.Text("searching for instagram user"), message.MessageId);
var user = await InstagramWrapper.TryGetUserAsync(usernameOrUrl);
if (user is null)
{
await SendError(message.Chat, rb.Text("user ").Text(usernameOrUrl).Text(" not found"));
return;
}
await SendInfo(message.Chat, rb.Text("user ").Text(usernameOrUrl).Text(" found"));
// user id or chat id
CurrentUsersData.AddOrSet(senderId, new InstagramObservableParams(usernameOrUrl));
CurrentUsersData.SaveToFile();
break;
}
case "list":
{
var userData = CurrentUsersData.Get(senderId);
if (userData is null)
{
await SendError(message.Chat, rb.Text("no data for user"), message.MessageId);
return;
}
rb.Text(userData.Count).Text("instagram users:\n");
foreach (var iuParams in userData)
{
rb.BeginStyle(TextStyle.Bold).Text(iuParams.instagramUsername).EndStyle().Text(" - ");
var iu = await InstagramWrapper.TryGetUserAsync(iuParams.instagramUsername);
rb.Text(iu is null ? "user no longer exists" : iu.FullName);
rb.SetUrl("https://www.instagram.com/"+iuParams.instagramUsername)
.BeginStyle(TextStyle.Link)
.Text(iuParams.instagramUsername)
.EndStyle().Text('\n');
}
await SendInfo(message.Chat, rb, message.MessageId);
break;
}
default:
await SendError(message.Chat, rb.Text("ivalid command"), message.MessageId);
break;
}
}
catch(OperationCanceledException){}
catch (Exception ex)
{
await SendError(message.Chat, ex);
}
}
}