TelegramRemindMe/ReminderBot.cs

295 lines
12 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Telegram.Bot;
using Telegram.Bot.Args;
using Telegram.Bot.Types;
using Telegram.Bot.Types.Enums;
using Telegram.Bot.Types.ReplyMarkups;
using Newtonsoft.Json;
using Telegram.Bot.Exceptions;
namespace TelegramRemindMe
{
public static class ReminderBot
{
private static List<ChatEntry> _chats = new List<ChatEntry>();
private static readonly TelegramBotClient Bot =
new TelegramBotClient("bot token here");
public static void Main()
{
Bot.OnMessage += BotOnMessageReceived;
Bot.OnMessageEdited += BotOnMessageReceived;
Bot.OnCallbackQuery += BotOnCallbackQueryReceived;
//Bot.OnInlineQuery += BotOnInlineQueryReceived;
//Bot.OnInlineResultChosen += BotOnChosenInlineResultReceived;
Bot.OnReceiveError += BotOnReceiveError;
if(!System.IO.File.Exists("config.json"))
SaveToJson(_chats);
_chats = ReadJson();
var me = Bot.GetMeAsync().Result;
Console.Title = me.Username;
Bot.StartReceiving();
Console.WriteLine($"Start listening for @{me.Username}");
Console.ReadLine();
Bot.StopReceiving();
}
private static async void BotOnMessageReceived(object sender, MessageEventArgs messageEventArgs)
{
var message = messageEventArgs.Message;
if (message == null || message.Type != MessageType.Text) return;
if (_chats.Find(e => e.ChatId == messageEventArgs.Message.Chat.Id) == null)
_chats.Add(new ChatEntry(messageEventArgs.Message.Chat.Id));
var currentChat = _chats.Find(e => e.ChatId == messageEventArgs.Message.Chat.Id);
if (message.Text.Equals("/cancel"))
{
SendOverview(currentChat, "Action canceled.");
return;
}
switch (currentChat.status)
{
case ChatStatusEnum.WaitingTaskTitle:
currentChat._tasklist.Add(new TaskEntry(message.Text));
//await Bot.SendChatActionAsync(message.Chat.Id, ChatAction.Typing);
SendOverview(currentChat, "Task added successfully!");
return;
case ChatStatusEnum.WaitingTaskComplete:
try
{
var completedItem = int.Parse(message.Text);
if (completedItem < 1 || completedItem > currentChat._tasklist.Count(p => !p.Completed))
throw new ArgumentOutOfRangeException();
currentChat._tasklist.FindAll(p => !p.Completed)[completedItem - 1].Completed = true;
SendOverview(currentChat, "Task has been set as completed.");
}
catch (Exception e)
{
SendOverview(currentChat, $"🛑 Invalid input! [{e.Message}]");
}
return;
case ChatStatusEnum.Idle:
break;
}
switch (message.Text.Split(' ').First())
{
default:
SendOverview(currentChat);
break;
case "/echo":
await Bot.SendChatActionAsync(message.Chat.Id, ChatAction.RecordVideoNote);
await Task.Delay(500);
await Bot.SendChatActionAsync(message.Chat.Id, ChatAction.UploadDocument);
await Task.Delay(500);
await Bot.SendChatActionAsync(message.Chat.Id, ChatAction.RecordAudio);
await Task.Delay(500);
await Bot.SendChatActionAsync(message.Chat.Id, ChatAction.Typing);
await Task.Delay(500);
await Bot.SendTextMessageAsync(
message.Chat.Id,
"MEOW, you woke me up!" + message.Text.Substring(5));
break;
}
}
private static async void BotOnCallbackQueryReceived(object sender,
CallbackQueryEventArgs callbackQueryEventArgs)
{
Console.WriteLine(
$"Received action request from @{callbackQueryEventArgs.CallbackQuery.Message.Chat.Username}: {callbackQueryEventArgs.CallbackQuery.Data}");
if (_chats.Find(e => e.ChatId == callbackQueryEventArgs.CallbackQuery.Message.Chat.Id) == null)
_chats.Add(new ChatEntry(callbackQueryEventArgs.CallbackQuery.Message.Chat.Id));
var currentChat = _chats.Find(e => e.ChatId == callbackQueryEventArgs.CallbackQuery.Message.Chat.Id);
switch (callbackQueryEventArgs.CallbackQuery.Data)
{
case "Add a new task":
currentChat.IsWorkingMessage = true;
//TODO: fix
try
{
currentChat.WorkingMsg = Bot.EditMessageTextAsync(
new ChatId(currentChat.ChatId), callbackQueryEventArgs.CallbackQuery.Message.MessageId,
"How should your new task be called?"
).Result.MessageId;
}
catch (ApiRequestException)
{}
currentChat.status = ChatStatusEnum.WaitingTaskTitle;
break;
case "Set a task as completed":
var sb = new StringBuilder();
var i = 0;
foreach (var entry in currentChat._tasklist.Where(p => !p.Completed))
{
sb.AppendLine($"{++i}) {entry.Title}");
}
sb.AppendLine();
sb.AppendLine("Send me the number of the task you want to complete.");
currentChat.IsWorkingMessage = true;
try
{
currentChat.WorkingMsg = Bot.EditMessageTextAsync(currentChat.ChatId,
callbackQueryEventArgs.CallbackQuery.Message.MessageId, sb.ToString()).Result.MessageId;
}
catch (ApiRequestException)
{}
currentChat.status = ChatStatusEnum.WaitingTaskComplete;
break;
case "Show all tasks":
currentChat.AllTasksShown = true;
currentChat.IsWorkingMessage = true;
currentChat.WorkingMsg = callbackQueryEventArgs.CallbackQuery.Message.MessageId;
SendOverview(currentChat);
currentChat.WorkingMsg = callbackQueryEventArgs.CallbackQuery.Message.MessageId;
await Bot.AnswerCallbackQueryAsync(callbackQueryEventArgs.CallbackQuery.Id, "Showing all tasks");
break;
case "Hide completed tasks":
currentChat.AllTasksShown = false;
currentChat.IsWorkingMessage = true;
currentChat.WorkingMsg = callbackQueryEventArgs.CallbackQuery.Message.MessageId;
SendOverview(currentChat);
await Bot.AnswerCallbackQueryAsync(callbackQueryEventArgs.CallbackQuery.Id,
"Showing only uncompleted tasks");
break;
default:
Console.WriteLine("Wat (Unknown callback action)");
await Bot.AnswerCallbackQueryAsync(
callbackQueryEventArgs.CallbackQuery.Id,
"Wat");
break;
}
}
private static async void SendOverview(ChatEntry chat, string prefixLine = "")
{
SaveToJson(_chats);
var actionKeyboard = new InlineKeyboardMarkup(new[]
{
new[]
{
InlineKeyboardButton.WithCallbackData("Add a new task"),
InlineKeyboardButton.WithCallbackData("Set a task as completed"),
},
new[]
{
InlineKeyboardButton.WithCallbackData(
chat.AllTasksShown ? "Hide completed tasks" : "Show all tasks")
}
});
//await Bot.SendChatActionAsync(chat.ChatId, ChatAction.Typing);
//TODO: why is this firing when workingmsg already deleted?
try
{
if (chat.IsWorkingMessage)
await Bot.DeleteMessageAsync(chat.ChatId, chat.WorkingMsg);
}
catch (ApiRequestException){}
chat.IsWorkingMessage = false;
chat.status = ChatStatusEnum.Idle;
var sb = new StringBuilder();
sb.AppendLine("Your tasks:");
if (chat.AllTasksShown)
{
foreach (var task in chat._tasklist)
{
sb.Append(task.Completed ? "✅ " : "🔶 ");
sb.AppendLine(task.Title);
}
}
else
{
foreach (var task in chat._tasklist.Where(p => !p.Completed))
{
sb.Append("🔶 ");
sb.AppendLine(task.Title);
}
}
sb.AppendLine();
sb.AppendLine("What do you want me to do?");
if (prefixLine != "")
{
var msgid = Bot.SendTextMessageAsync(
chat.ChatId,
prefixLine)
.Result.MessageId;
//await Bot.SendChatActionAsync(chat.ChatId, ChatAction.Typing);
//await Task.Delay(1500);
await Bot.EditMessageTextAsync(chat.ChatId, msgid, sb.ToString(), replyMarkup: actionKeyboard);
}
else
{
//await Bot.SendChatActionAsync(chat.ChatId, ChatAction.Typing);
await Bot.SendTextMessageAsync(chat.ChatId, sb.ToString(), replyMarkup: actionKeyboard);
}
}
private static void BotOnReceiveError(object sender, ReceiveErrorEventArgs receiveErrorEventArgs)
{
Console.WriteLine("Received error: {0} — {1}",
receiveErrorEventArgs.ApiRequestException.ErrorCode,
receiveErrorEventArgs.ApiRequestException.Message);
}
private static void SaveToJson(List<ChatEntry> chats)
{
var str = JsonConvert.SerializeObject(chats);
while (true)
{
try
{
System.IO.File.WriteAllText("config.json", str);
break;
}
catch
{
Console.WriteLine("Unable to write to config.json, retrying...");
}
}
}
private static List<ChatEntry> ReadJson()
{
while (true)
{
try
{
var str = System.IO.File.ReadAllText("config.json");
return JsonConvert.DeserializeObject<List<ChatEntry>>(str);
}
catch
{
Console.WriteLine("Unable to read from config.json, retrying...");
}
}
}
}
}