Skip to content

Instantly share code, notes, and snippets.

@kovachwt
Last active October 9, 2017 13:04
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kovachwt/c77a2253b72a92c75c9e0ab272ff5e0a to your computer and use it in GitHub Desktop.
Save kovachwt/c77a2253b72a92c75c9e0ab272ff5e0a to your computer and use it in GitHub Desktop.
KafanaBot (Telegram bot / .NET Core 1.1)
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
<PackageReference Include="Telegram.Bot" Version="13.0.0-beta-02" />
</ItemGroup>
</Project>
using System;
using System.IO;
using System.Diagnostics;
using System.Threading;
using System.Linq;
using System.Collections.Generic;
using System.Reflection;
using Newtonsoft.Json;
using Telegram.Bot;
using Telegram.Bot.Args;
using Telegram.Bot.Types;
using Telegram.Bot.Types.Enums;
namespace LezetBot
{
class Program
{
public static ManualResetEvent _quitEvent = new ManualResetEvent(false);
const string apiKey = "YOUR_KEY_HERE";
static TelegramBotClient Bot = new TelegramBotClient(apiKey);
static string BotUsername = null;
static Dictionary<int, string> UserKeywords = new Dictionary<int, string>();
static object lckUserKeywords = new object();
static Dictionary<int, long> UserChatIDs = new Dictionary<int, long>();
static object lckUserChatIDs = new object();
static Dictionary<int, string> Usernames = new Dictionary<int, string>();
static object lckUsernames = new object();
static Dictionary<long, List<int>> ChatUsers = new Dictionary<long, List<int>>();
static object lckChatUsers = new object();
static string SaveFile;
static object lckSavefile = new object();
static string LogFile;
static object lckLogFile = new object();
static void Main(string[] args)
{
Console.CancelKeyPress += (sender, eArgs) => {
_quitEvent.Set();
eArgs.Cancel = true;
};
LogFile = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + Path.DirectorySeparatorChar + "lezetbot.log";
SaveFile = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + Path.DirectorySeparatorChar + "lezetbot.json";
LoadSaved();
Bot.OnMessage += BotOnMessageReceived;
Bot.OnMessageEdited += BotOnMessageReceived;
Bot.OnReceiveError += BotOnReceiveError;
var me = Bot.GetMeAsync().Result;
BotUsername = me.Username;
Console.Title = BotUsername;
Bot.StartReceiving();
_quitEvent.WaitOne();
Bot.StopReceiving();
SaveData();
}
static void Log(bool iserror, string text)
{
string logtxt = (iserror ? "ERROR: " : "") + text;
Console.WriteLine(logtxt);
lock (lckLogFile)
System.IO.File.AppendAllText(LogFile, logtxt + Environment.NewLine);
}
static void LoadSaved()
{
lock (lckSavefile)
{
if (System.IO.File.Exists(SaveFile))
{
string json = System.IO.File.ReadAllText(SaveFile);
var data = JsonConvert.DeserializeObject<Tuple<Dictionary<int, string>, Dictionary<int, long>, Dictionary<int, string>, Dictionary<long, List<int>>>>(json);
if (data.Item1 != null)
UserKeywords = data.Item1;
if (data.Item2 != null)
UserChatIDs = data.Item2;
if (data.Item3 != null)
Usernames = data.Item3;
if (data.Item4 != null)
ChatUsers = data.Item4;
}
}
}
static void SaveData()
{
lock (lckSavefile)
{
var data = new Tuple<Dictionary<int, string>, Dictionary<int, long>, Dictionary<int, string>, Dictionary<long, List<int>>>(UserKeywords, UserChatIDs, Usernames, ChatUsers);
System.IO.File.WriteAllText(SaveFile, JsonConvert.SerializeObject(data));
}
}
static string GetKeywords(int uid)
{
lock (lckUserKeywords)
{
return UserKeywords.ContainsKey(uid) ? UserKeywords[uid] : null;
}
}
static void SetKeywords(int uid, string keywords)
{
lock (lckUserKeywords)
{
UserKeywords[uid] = keywords;
}
SaveData();
}
static long GetChatID(int uid)
{
lock (lckUserChatIDs)
{
return UserChatIDs.ContainsKey(uid) ? UserChatIDs[uid] : long.MinValue;
}
}
static void SetChatID(int uid, long chatid)
{
lock (lckUserChatIDs)
{
if (!UserChatIDs.ContainsKey(uid) || UserChatIDs[uid] != chatid)
{
UserChatIDs[uid] = chatid;
SaveData();
}
}
}
static string GetUsername(int uid)
{
lock (lckUsernames)
{
return Usernames.ContainsKey(uid) ? Usernames[uid] : null;
}
}
static void SetUsername(int uid, string username)
{
lock (lckUsernames)
{
if (!Usernames.ContainsKey(uid) || Usernames[uid] != username)
{
Usernames[uid] = username;
SaveData();
}
}
}
static List<int> GetUsers(long chatid)
{
lock (lckChatUsers)
{
List<int> result = new List<int>();
if (ChatUsers.ContainsKey(chatid))
result.AddRange(ChatUsers[chatid]);
return result;
}
}
static void AddUser(long chatid, int uid)
{
lock (lckChatUsers)
{
if (!ChatUsers.ContainsKey(chatid))
ChatUsers[chatid] = new List<int>();
if (!ChatUsers[chatid].Contains(uid))
{
ChatUsers[chatid].Add(uid);
SaveData();
}
}
}
static void DelUser(long chatid, int uid)
{
lock (lckChatUsers)
{
if (ChatUsers.ContainsKey(chatid) && ChatUsers[chatid].Contains(uid))
{
ChatUsers[chatid].Remove(uid);
SaveData();
}
}
}
private static async void BotOnMessageReceived(object sender, MessageEventArgs e)
{
var msg = e.Message;
if (msg == null) return;
if (msg.Chat.Type == ChatType.Private)
SetChatID(msg.From.Id, msg.Chat.Id);
if (!String.IsNullOrEmpty(msg.From.Username))
SetUsername(msg.From.Id, msg.From.Username);
if (msg.Chat.Type != ChatType.Private)
{
AddUser(msg.Chat.Id, msg.From.Id);
if (msg.LeftChatMember != null)
DelUser(msg.Chat.Id, msg.LeftChatMember.Id);
if (msg.NewChatMembers != null && msg.NewChatMembers.Count() > 0)
foreach (User u in msg.NewChatMembers)
AddUser(msg.Chat.Id, u.Id);
}
if (msg.Type != MessageType.TextMessage) return;
string text = msg.Text.ToLower();
//Console.WriteLine(msg.Date.ToString("HH:mm:ss ") + msg.From.Username + ": " + text);
bool msgtobot = false;
if (text.StartsWith("@" + BotUsername.ToLower() + " "))
{
text = text.Substring(BotUsername.Length + 1).Trim();
msgtobot = true;
}
if (msg.Chat.Type == ChatType.Private || msgtobot)
{
if (text.StartsWith("/keywords "))
{
string keywords = text.Substring("/keywords ".Length);
var punctuation = keywords.Where(Char.IsPunctuation).Distinct().ToArray();
var words = keywords.Split().Select(x => x.Trim(punctuation)).Where(w => w.Trim() != "");
keywords = String.Join(" ", words.Distinct().ToArray());
SetKeywords(msg.From.Id, keywords);
await Bot.SendTextMessageAsync(msg.Chat.Id, "Done, new keywords are: " + keywords);
}
else if (text.StartsWith("/delkeywords"))
{
SetKeywords(msg.From.Id, "");
await Bot.SendTextMessageAsync(msg.Chat.Id, "Done, no more keywords.");
}
else if (text.StartsWith("/showkeywords"))
{
string keywords = GetKeywords(msg.From.Id);
await Bot.SendTextMessageAsync(msg.Chat.Id, "Your keywords are: " + keywords);
}
else
{
var usage = @"Usage:
/keywords - send a new list of notification keywrods (list of keywords separated by spaces)
/delkeywords - empty your list of notification keywords (no more notifications)
/showkeywords - show your current notification keywords
";
await Bot.SendTextMessageAsync(msg.Chat.Id, usage);
}
if (!UserChatIDs.ContainsKey(msg.From.Id))
SetChatID(msg.From.Id, msg.From.Id);
return;
}
if (msg.Chat.Type != ChatType.Private)
{
var punctuation = text.Where(Char.IsPunctuation).Distinct().ToArray();
var words = text.Split().Select(x => x.Trim(punctuation)).Where(x => x.Trim() != "");
if (words.Count() == 0) return;
var chatusers = GetUsers(msg.Chat.Id);
List<int> users;
lock (lckUserKeywords)
users = UserKeywords.Keys.ToList();
foreach (int uid in users)
{
if (msg.From.Id == uid) continue;
if (!chatusers.Contains(uid)) continue;
string username = GetUsername(uid);
if (!String.IsNullOrEmpty(username) && text.Contains("@" + username.ToLower()))
continue;
var keywords = GetKeywords(uid).Split();
foreach (string keyword in keywords)
if (words.Contains(keyword) || words.Where(w => w.StartsWith(keyword)).Count() > 0)
{
SendNotification(uid, keyword, msg);
break;
}
}
}
}
static async void SendNotification(int uid, string word, Message msg)
{
Log(false, "Sending notification for " + word + " to " + uid + ", text: " + msg.Text);
long chatid = GetChatID(uid);
if (chatid == long.MinValue)
{
chatid = uid;
Log(true, "Can't find chat id for uid " + uid + " to send notification...");
}
await Bot.ForwardMessageAsync(chatid, msg.Chat.Id, msg.MessageId);
}
private static void BotOnReceiveError(object sender, ReceiveErrorEventArgs e)
{
Log(true, e.ApiRequestException.ToString());
if (Debugger.IsAttached)
Debugger.Break();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment