123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592 |
- using System;
- using System.Linq;
- using System.Threading.Tasks;
- using Telegram.Bot;
- using Telegram.Bot.Args;
- using Telegram.Bot.Types;
- using Telegram.Bot.Types.Enums;
- using System.Net.Http;
- using System.Threading;
- using EFDatabase;
- using Microsoft.EntityFrameworkCore;
- using Quartz;
- using Quartz.Impl;
- namespace EthermineBotTelegramCore
- {
- partial class Program
- {
- static ITelegramBotClient botClient;
- static botdb Botdb;
- private static async Task Main(string[] args)
- {
- botClient = new TelegramBotClient("1785154817:AAGhXD9yQVn9HPdWTcmGJUBeZ8nA50SzHbY");
- var me = botClient.GetMeAsync().Result;
- {
- string message = $"Hello, World! I am user {me.Id} and my name is {me.FirstName}.";
- Console.WriteLine(message);
- await Logger.LogInfo(message);
- }
-
- //enter credentials for DB
- if (args.Length >= 2)
- {
- AppSettings.user = args[0];
- AppSettings.password = args[1];
- }
- else
- {
- Console.Out.Write("User:");
- AppSettings.user = Console.ReadLine();
- Console.Out.Write("Password:");
- AppSettings.password = Console.ReadLine();
- }
-
- //init DB
- Botdb = new botdb();
- if (Botdb.Database.CanConnect())
- {
- // Grab the Scheduler instance from the Factory
- StdSchedulerFactory factory = new StdSchedulerFactory();
- IScheduler scheduler = await factory.GetScheduler();
- // and start it off
- await scheduler.Start();
- // define the job and tie it to our HelloJob class
- IJobDetail job = JobBuilder.Create<DataUpdater>()
- .WithIdentity("job1", "group1")
- .UsingJobData("connectionString", "server=" + AppSettings.dbIp + ";port=3306;database=botdb;uid=" + AppSettings.user + "; pwd=" + AppSettings.password)
- .Build();
- // Trigger the job to run now, and then repeat it
- ITrigger trigger = TriggerBuilder.Create()
- .WithIdentity("trigger1", "group1")
- .StartNow()
- .WithSimpleSchedule(x => x
- .WithIntervalInSeconds(240)
- .RepeatForever())
- .Build();
- // Tell quartz to schedule the job using our trigger
- await scheduler.ScheduleJob(job, trigger);
- {
- string message = "Scheduler started!";
- Console.WriteLine(message);
- await Logger.LogInfo(message);
- }
-
- Thread.Sleep(5000);
-
- //start receive messages
- botClient.OnMessage += BotOnMessage;
- botClient.StartReceiving();
- Console.WriteLine("Press any key to exit");
- Console.ReadKey();
-
- Logger.Stop();
- await scheduler.Shutdown();
- botClient.StopReceiving();
- }
- else
- {
- string message = "Don't connected! Check auth data and restart!";
- Console.WriteLine(message);
- await Logger.LogError(message);
- Logger.Stop();
- }
- }
- private static async void BotOnMessage(object sender, MessageEventArgs e) {
- if (e.Message.Text != null)
- {
- Console.WriteLine($"Received a text message in chat {e.Message.Chat.Id}.");
- char[] delimeters = { ' ', '@' };
-
- var message = e.Message;
- if (message == null || message.Type != MessageType.Text)
- return;
- string command = message.Text.Split(delimeters).First();
- switch (command)
- {
- // add user into database
- case "/start":
- await Logger.LogInfo(
- $"Received a text message {command} in chat {e.Message.Chat.Id}.");
- AddUser(e.Message.Chat);
- break;
-
- // add user into database
- case "/stop":
- await Logger.LogInfo(
- $"Received a text message {command} in chat {e.Message.Chat.Id}.");
- DeleteUser(e.Message.Chat);
- break;
-
- // connect wallet to user
- case "/setwallet":
- await Logger.LogInfo(
- $"Received a text message {command} in chat {e.Message.Chat.Id}.");
- SetWallet(e);
- break;
- // get actual data from ethermine
- case "/actual":
- await Logger.LogInfo(
- $"Received a text message {command} in chat {e.Message.Chat.Id}.");
- if (message.Text.Split(' ').Length > 1)
- GetActualData(e);
- else
- GetActualDataFromDatabase(e.Message.Chat);
- break;
-
- // get actual data from ethermine
- case "/rate":
- await Logger.LogInfo(
- $"Received a text message {message.Text.Split(delimeters).First()} in chat {e.Message.Chat.Id}.");
- GetActualRate(e);
- break;
-
- // send help
- case "/help":
- await Logger.LogInfo(
- $"Received a text message {message.Text.Split(delimeters).First()} in chat {e.Message.Chat.Id}.");
- await SendHelp(e.Message.Chat);
- break;
-
- // send last payout
- case "/lastpayout":
- await Logger.LogInfo(
- $"Received a text message {message.Text.Split(delimeters).First()} in chat {e.Message.Chat.Id}.");
- await GetLastPayout(e.Message.Chat);
- break;
- default:
- if (e.Message.Chat.Id > 0)
- await botClient.SendTextMessageAsync(
- chatId: e.Message.Chat,
- text: "Incorrect message");
- break;
- }
- }
- }
- //send reauest to pool api and gets back json than parse it and send message with data from it
- private static async void GetActualData(MessageEventArgs e)
- {
- try
- {
- var url = AppSettings.poolApiUrl + "/miner/" + e.Message.Text.Split(' ')[1] + "/currentStats";
- var currnentStats = JsonDownloader._download_serialized_json_data<JsonCurrentStats>(url);
- await botClient.SendTextMessageAsync(
- chatId: e.Message.Chat,
- text: "Updated: " + DateTimeOffset.FromUnixTimeSeconds(currnentStats.data.time).LocalDateTime
- .ToString("f") + "\n"
- + "Reported Hashrate: " + Math.Round(currnentStats.data.reportedHashrate / 1000000D, 3) +
- " MH/s\n"
- + "Current Hashrate: " + Math.Round(currnentStats.data.currentHashrate / 1000000D, 3) +
- " MH/s\n"
- + "Valid Shares: " + currnentStats.data.validShares + "\n"
- + "Stale Shares: " + currnentStats.data.staleShares + "\n"
- + "Workers: " + currnentStats.data.activeWorkers + "\n"
- + "Unpaid Balance: " + Math.Round(currnentStats.data.unpaid / Math.Pow(10, 18), 5) + AppSettings.currency + "\n");
- }
- catch (Exception exception)
- {
- await Console.Out.WriteLineAsync("An exception occurred while executing /actual command. See log file to get full info.");
- await Logger.LogError("An exception occurred while executing /actual command.");
- await Logger.LogError(exception.Message);
- await Logger.LogError(exception.Source);
- await Logger.LogError(exception.StackTrace);
-
- await botClient.SendTextMessageAsync(
- chatId: e.Message.Chat,
- text: "An exception occurred while executing this command.");
- }
- }
- //get last data from tables miners and workers from DB and send message to user
- private static async void GetActualDataFromDatabase(Chat e)
- {
- try
- {
- var wallet = Botdb.users
- .Where(u => u.chat_id == e.Id)
- .Select(u => u.wallet)
- .FirstOrDefault();
- if (wallet != null)
- {
- var lastMinerRecord = Botdb.miners
- .Where(w => w.wallet == wallet)
- .OrderByDescending(w => w.time)
- .FirstOrDefault();
-
- if (lastMinerRecord != null)
- {
- //var lastWorkerRecord = new workers();
- long lastTime = Botdb.workers
- .Where(w => w.wallet == wallet)
- .Max(w => w.time);
-
- var lastWorkerRecord = Botdb.workers
- .Where(w => w.wallet == wallet && w.time == lastTime)
- .OrderByDescending(w => w.time)
- .ToList();
-
- if (lastWorkerRecord.First() != null)
- {
- await botClient.SendTextMessageAsync(
- chatId: e,
- text: $"Miner {lastMinerRecord.wallet} stats:\n" +
- "Updated: " + DateTimeOffset.FromUnixTimeSeconds(lastMinerRecord.time)
- .LocalDateTime
- .ToString("f") + "\n"
- + "Reported Hashrate: " + Math.Round(lastMinerRecord.reported_hashrate / 1000000D, 3) + " MH/s\n"
- + "Current Hashrate: " + Math.Round(lastMinerRecord.current_hashrate / 1000000D, 3) + " MH/s\n"
- + "Valid Shares: " + lastMinerRecord.valid_shares + "\n"
- + "Stale Shares: " + lastMinerRecord.stale_shares + "\n"
- + "Workers: " + lastMinerRecord.workers + "\n"
- + "Unpaid Balance: " + Math.Round(lastMinerRecord.unpaid / Math.Pow(10, 18), 5) + AppSettings.currency +
- "\n");
- for (int i = 0; i < lastWorkerRecord.Count; i++)
- {
- Thread.Sleep(1000);
- if (i!=0 && i%20 == 0) //TODO SOMETIHNG BETTER THAN USUAL TIMER
- Thread.Sleep(30000);
- try
- {
- await botClient.SendTextMessageAsync(
- chatId: e,
- text: $"Worker {lastWorkerRecord[i].worker} stats:\n" +
- "Updated: " + DateTimeOffset.FromUnixTimeSeconds(lastWorkerRecord[i].time)
- .LocalDateTime
- .ToString("f") + "\n"
- + "Reported Hashrate: " + Math.Round(lastWorkerRecord[i].reported_hashrate / 1000000D, 3) + " MH/s\n"
- + "Current Hashrate: " + Math.Round(lastWorkerRecord[i].current_hashrate / 1000000D, 3) + " MH/s\n"
- + "Valid Shares: " + lastWorkerRecord[i].valid_shares + "\n"
- + "Stale Shares: " + lastWorkerRecord[i].stale_shares + "\n"
- + "Unpaid Balance: " + Math.Round(lastWorkerRecord[i].worker_unpaid / Math.Pow(10, 18), 5) + AppSettings.currency +
- "\n");
- }
- catch (HttpRequestException exception)
- {
- await Console.Out.WriteLineAsync("An exception occurred on sending messages while executing /actual command.");
- await Logger.LogError(exception.Message);
- await Logger.LogError(exception.Source);
- await Logger.LogError(exception.StackTrace);
- }
- }
- }
- else
- {
- await botClient.SendTextMessageAsync(
- chatId: e,
- text: "No workers data for now!");
- }
- }
- else
- {
- await botClient.SendTextMessageAsync(
- chatId: e,
- text: "No miner data for now!");
- }
- }
- else
- {
- await botClient.SendTextMessageAsync(
- chatId: e,
- text: "Set wallet at first! Use /setwallet");
- }
- }
- catch (Exception exception)
- {
- await Console.Out.WriteLineAsync("An exception occurred while executing /actual command. See log file to get full info.");
- await Logger.LogError("An exception occurred while executing /actual command.");
- await Logger.LogError(exception.Message);
- await Logger.LogError(exception.Source);
- await Logger.LogError(exception.StackTrace);
-
- await botClient.SendTextMessageAsync(
- chatId: e,
- text: "An exception occurred while executing this command.");
- }
- }
-
- private static async void GetActualRate(MessageEventArgs e)
- {
- try
- {
- var url = AppSettings.poolApiUrl + "/networkStats";
- var networkStats = JsonDownloader._download_serialized_json_data<JsonNetworkStats>(url);
- await botClient.SendTextMessageAsync(
- chatId: e.Message.Chat,
- text: "ETH: " + Math.Round(networkStats.data.usd, 2) + "\n"
- + "BTC: " + Math.Round(networkStats.data.usd / networkStats.data.btc, 2)
- );
- }
- catch (Exception exception)
- {
- await Console.Out.WriteLineAsync("An exception occurred while executing /rate command. See log file to get full info.");
- await Logger.LogError("An exception occurred while executing /rate command.");
- await Logger.LogError(exception.Message);
- await Logger.LogError(exception.Source);
- await Logger.LogError(exception.StackTrace);
-
- await botClient.SendTextMessageAsync(
- chatId: e.Message.Chat,
- text: "An exception occurred while executing this command.");
- }
- }
- private static async void AddUser(Chat e)
- {
- try
- {
- if (Botdb.users.Where(users => users.chat_id == e.Id).FirstOrDefault() == null)
- {
- var newuser = new users();
- newuser.chat_id = e.Id;
- Botdb.users.Add(newuser);
- Botdb.SaveChanges();
- await botClient.SendTextMessageAsync(
- chatId: e,
- text: "Added new user to database. Now you can connect your miner wallet using command /setwallet <address>");
- }
- else
- {
- await botClient.SendTextMessageAsync(
- chatId: e,
- text: "Already registered");
- }
- }
- catch (Exception exception)
- {
- await Console.Out.WriteLineAsync("An exception occurred while executing /start command. See log file to get full info.");
- await Logger.LogError("An exception occurred while executing /start command.");
- await Logger.LogError(exception.Message);
- await Logger.LogError(exception.Source);
- await Logger.LogError(exception.StackTrace);
-
- await botClient.SendTextMessageAsync(
- chatId: e,
- text: "An exception occurred while executing this command.");
- }
- }
- private static async void SetWallet(MessageEventArgs e)
- {
- try
- {
- if (Botdb.users.Where(u => u.chat_id == e.Message.Chat.Id).FirstOrDefault() != null)
- {
- if (e.Message.Text.Split(' ')[1].Length > 2)
- {
- if (e.Message.Text.Split(' ')[1].Contains("0x"))
- {
- Botdb.users.Where(u => u.chat_id == e.Message.Chat.Id).FirstOrDefault().wallet =
- e.Message.Text.Split(' ')[1];
- }
- else
- {
- Botdb.users.Where(u => u.chat_id == e.Message.Chat.Id).FirstOrDefault().wallet =
- "0x" + e.Message.Text.Split(' ')[1];
- }
- await Botdb.SaveChangesAsync();
- await botClient.SendTextMessageAsync(
- chatId: e.Message.Chat,
- text: $"Wallet {"0x" + e.Message.Text.Split(' ')[1]} set!");
- }
- else
- {
- await botClient.SendTextMessageAsync(
- chatId: e.Message.Chat,
- text: "Too short!");
- }
- //Botdb.SaveChanges();
- }
- else
- {
- await botClient.SendTextMessageAsync(
- chatId: e.Message.Chat,
- text: "You not registered! Type /start first!");
- }
- }
- catch (Exception exception)
- {
- await Console.Out.WriteLineAsync("An exception occurred while executing /setwallet command. See log file to get full info.");
- await Logger.LogError("An exception occurred while executing /setwallet command.");
- await Logger.LogError(exception.Message);
- await Logger.LogError(exception.Source);
- await Logger.LogError(exception.StackTrace);
-
- await botClient.SendTextMessageAsync(
- chatId: e.Message.Chat,
- text: "An exception occurred while executing this command.");
- }
- }
-
- static async void DeleteUser(Chat e)
- {
- try
- {
- if (Botdb.users.Where(users => users.chat_id == e.Id).FirstOrDefault() != null)
- {
- var deletableWallet = Botdb.users.Where(u => u.chat_id == e.Id).First().wallet;
- if (Botdb.users.Where(u => u.wallet == deletableWallet).Count() > 1)
- {
- Botdb.users.RemoveRange(Botdb.users.Where(u=> u.chat_id == e.Id));
- }
- else
- {
- Botdb.workers.RemoveRange(Botdb.workers.Where(w=> w.wallet == deletableWallet));
- Botdb.miners.RemoveRange(Botdb.miners.Where(m=> m.wallet == deletableWallet));
- Botdb.payouts.RemoveRange(Botdb.payouts.Where(p=> p.wallet == deletableWallet));
- Botdb.users.RemoveRange(Botdb.users.Where(u=> u.chat_id == e.Id));
- }
-
- await Botdb.SaveChangesAsync();
- await botClient.SendTextMessageAsync(
- chatId: e,
- text: "Done!");
- }
- else
- {
- await botClient.SendTextMessageAsync(
- chatId: e,
- text: "Already deleted");
- }
- }
- catch (Exception exception)
- {
- await Console.Out.WriteLineAsync("An exception occurred while executing /delete command. See log file to get full info.");
- await Logger.LogError("An exception occurred while executing /delete command.");
- await Logger.LogError(exception.Message);
- await Logger.LogError(exception.Source);
- await Logger.LogError(exception.StackTrace);
-
- await botClient.SendTextMessageAsync(
- chatId: e,
- text: "An exception occurred while executing this command.");
- }
- }
- //gets data from pool API in json, calculates unpaid for each worker and adds it to DB
- //public static async Task UpdateData()
- static async Task SendHelp(Chat e)
- {
- try
- {
- await botClient.SendTextMessageAsync(
- chatId: e,
- text: $"This is bot tracks your miner stats and calculates unpaid per worker.\n"
- + $"How to start:\n"
- + $"1) \"/start\" - it will add you to database\n"
- + $"2) \"/setwallet <wallet>\" - it will set wallet for tracking, bot will start to add info about your miner and workers to database\n"
- + $"3) \"/actual\" - it will send you up to date data about your worker\n"
- + $"4) \"/lastpayout\" - it will send you last payout data with calculated worker unpaid for that period if avaliable\n"
- + $"5) \"/stop\" - it will clear all data about you from database\n"
- + $"Additional commands:\n"
- + $"\"/rate\" - get actual ETH and BTC rate from ethermine\n"
- + $"\"/actual <wallet>\" - get up to date data about any wallet without unpaid per worker\n");
- }
- catch (Exception exception)
- {
- await Console.Out.WriteLineAsync("An exception occurred while executing /help command. See log file to get full info.");
- await Logger.LogError(exception.Message);
- await Logger.LogError(exception.Source);
- await Logger.LogError(exception.StackTrace);
-
- await botClient.SendTextMessageAsync(
- chatId: e,
- text: "An exception occurred while executing this command.");
- }
-
- }
- static async Task GetLastPayout(Chat e)
- {
- try
- {
- var wallet = Botdb.users
- .Where(u => u.chat_id == e.Id)
- .Select(u => u.wallet)
- .FirstOrDefault();
- if (wallet != null)
- {
- //TODO rewrite this
- long payoutTime;
- try
- {
- payoutTime = Botdb.payouts
- .Where(p => p.wallet == wallet)
- .OrderByDescending(p => p.time)
- .Select(p => p.time)
- .MaxAsync().Result;
- }
- catch (Exception exception)
- {
- string message = $"No payouts data for {wallet}! Time is set to 0!";
- await Console.Out.WriteLineAsync(message);
- await Logger.LogWarn(message);
- //await Logger.LogError(exception.Message);
- //await Logger.LogError(exception.Source);
- //await Logger.LogError(exception.StackTrace);
- payoutTime = 0;
- }
-
- var dbPayoutRecords = Botdb.payouts
- .Where(p => p.wallet == wallet && p.time == payoutTime)
- .OrderByDescending(p => p.time);
- if (dbPayoutRecords.FirstOrDefault() != null)
- {
- string message = "Payout date: " +
- DateTimeOffset.FromUnixTimeSeconds(dbPayoutRecords.First().time).LocalDateTime
- .ToString("f") + "\n" + "Amount: " +
- Math.Round(dbPayoutRecords.First().amount / 1000000000000000000D, 5) + AppSettings.currency + "\n";
- foreach (var payoutRecord in dbPayoutRecords)
- {
- message +=
- $"Worker {payoutRecord.worker} paid: {Math.Round(payoutRecord.worker_amount / 1000000000000000000D, 5)} {AppSettings.currency}\n";
- }
- message += "Data source: Bot database \n";
- await botClient.SendTextMessageAsync(
- chatId: e,
- text: message);
- }
- else
- {
- var url = AppSettings.poolApiUrl + "/miner/" + wallet + "/payouts";
- var payouts = JsonDownloader._download_serialized_json_data<JsonPayouts>(url);
-
- await botClient.SendTextMessageAsync(
- chatId: e,
- text: "Payout date: " + DateTimeOffset.FromUnixTimeSeconds(payouts.data[0].paidOn).LocalDateTime.ToString("f") + "\n"
- + "Amount: " + Math.Round(payouts.data[0].amount / 1000000000000000000D, 5) + AppSettings.currency + "\n"
- + "Data source: Ethermine API \n");
- }
- }
- else
- {
- await botClient.SendTextMessageAsync(
- chatId: e,
- text: "Set wallet at first! Use /setwallet");
- }
- }
- catch (Exception exception)
- {
- await Console.Out.WriteLineAsync("An exception occurred while executing /lastpayout command. See log file to get full info.");
- await Logger.LogError(exception.Message);
- await Logger.LogError(exception.Source);
- await Logger.LogError(exception.StackTrace);
-
- await botClient.SendTextMessageAsync(
- chatId: e,
- text: "An exception occurred while executing this command.");
- }
- }
- }
- }
|