123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581 |
- 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 MySql.Data.MySqlClient;
- using Quartz;
- using Quartz.Impl;
- namespace EthermineBotTelegram
- {
- class Program
- {
- static ITelegramBotClient botClient;
- static EFDatabase.botdb Botdb;
-
- static async Task Main(string[] args)
- {
- botClient = new TelegramBotClient("1785154817:AAGhXD9yQVn9HPdWTcmGJUBeZ8nA50SzHbY");
- var me = botClient.GetMeAsync().Result;
-
- Console.WriteLine(
- $"Hello, World! I am user {me.Id} and my name is {me.FirstName}."
- );
-
- //creating connection to DB
- string user;
- string pass;
- if (args[0] != null && args[1] != null)
- {
- user = args[0];
- pass = args[1];
- }
- else
- {
- Console.Out.Write("User:");
- user = Console.ReadLine();
- Console.Out.Write("Password:");
- pass = Console.ReadLine();
- }
-
- Botdb =
- new botdb("server=" + AppSettings.dbIp + ";port=3306;database=botdb;uid=" + user + "; pwd=" + pass);
- try
- {
- Botdb.Database.Connection.Open();
- Botdb.Database.Connection.Close();
-
- // 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=" + user + "; pwd=" + pass)
- .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);
-
- Console.WriteLine(("Scheduler started!"));
-
- Thread.Sleep(5000);
- //start receive messages
- botClient.OnMessage += BotOnMessage;
- botClient.StartReceiving();
- Console.WriteLine("Press any key to exit");
- Console.ReadKey();
- await scheduler.Shutdown();
- botClient.StopReceiving();
- }
- catch (MySqlException)
- {
- Console.WriteLine("Don't connected! Check auth data and restart!");
- }
- }
- 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;
-
- switch (message.Text.Split(delimeters).First())
- {
- // add user into database
- case "/start":
- AddUser(e.Message.Chat);
- break;
-
- // add user into database
- case "/stop":
- DeleteUser(e.Message.Chat);
- break;
-
- // connect wallet to user
- case "/setwallet":
- SetWallet(e);
- break;
- // get actual data from ethermine
- case "/actual":
- if (message.Text.Split(' ').Length > 1)
- GetActualData(e);
- else
- GetActualDataFromDatabase(e.Message.Chat);
- break;
-
- // get actual data from ethermine
- case "/rate":
- GetActualRate(e);
- break;
-
- // send help
- case "/help":
- //await SendHelp();
- break;
- default:
- //await Usage(message);
- 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
- 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) + " ETH\n");
- }
- catch (Exception exception)
- {
- await Console.Out.WriteLineAsync(exception.Message + " " + 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
- 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 != 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) +
- " ETH\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) +
- " ETH\n");
- }
- catch (HttpRequestException exception)
- {
- await Console.Out.WriteLineAsync(exception.Message + " " + 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(exception.Message + " " + exception.StackTrace);
- // await botClient.SendTextMessageAsync(
- // chatId: e,
- // text: "Something got wrong! Check entered wallet or try later.");
- //}
- }
-
- static async void GetActualRate(MessageEventArgs e)
- {
- try
- {
- var url = AppSettings.poolApiUrl + "/networkStats";
- var networkStats = JsonDownloader._download_serialized_json_data<NetworkStats>(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)
- {
- await botClient.SendTextMessageAsync(
- chatId: e.Message.Chat,
- text: "An exception occurred while executing this command.");
- }
- }
- 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(exception.Message + " " + exception.StackTrace);
- }
- }
- 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(exception.Message + " " + 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.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(exception.Message + " " + 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()
- {
- var walletList = Botdb.users.Where(u=>u.wallet != null).Select(u=> u.wallet).Distinct().ToList();
- foreach (string wallet in walletList)
- {
- try
- {
- var url = AppSettings.poolApiUrl + "/miner/" + wallet + "/currentStats";
- var currnentStats = JsonDownloader._download_serialized_json_data<JsonCurrentStats>(url);
-
- if (currnentStats.status == "OK")
- {
- await Console.Out.WriteLineAsync($"Create new record for {wallet}");
- miners newMinerRecord = new miners();
- newMinerRecord.wallet = wallet;
- newMinerRecord.time = currnentStats.data.time;
- newMinerRecord.reported_hashrate = currnentStats.data.reportedHashrate;
- newMinerRecord.current_hashrate = currnentStats.data.currentHashrate;
- newMinerRecord.valid_shares = currnentStats.data.validShares;
- newMinerRecord.stale_shares = currnentStats.data.staleShares;
- newMinerRecord.invalid_shares = currnentStats.data.invalidShares;
- newMinerRecord.workers = currnentStats.data.activeWorkers;
- newMinerRecord.unpaid = currnentStats.data.unpaid;
- await Console.Out.WriteLineAsync($"New record creating complete {newMinerRecord.wallet}");
- long lastTime = 0;
- if (Botdb.miners.Where(m => m.wallet == newMinerRecord.wallet).FirstOrDefault() != null)
- lastTime = Botdb.miners.Where(m => m.wallet == newMinerRecord.wallet).Max(m => m.time);
- var lastMinerRecord = Botdb.miners.Where(m => m.wallet == newMinerRecord.wallet && m.time == lastTime).FirstOrDefault();
- if (lastMinerRecord == null || lastMinerRecord.time !=
- newMinerRecord.time)
- {
- Botdb.miners.Add(newMinerRecord);
- //await Botdb.SaveChangesAsync();
- await Console.Out.WriteLineAsync($"Added new row for {newMinerRecord.wallet}");
-
- if (lastMinerRecord != null && newMinerRecord.unpaid < lastMinerRecord.unpaid)
- {
- await botClient.SendTextMessageAsync(
- chatId: Botdb.users.Where(user => user.wallet == newMinerRecord.wallet)
- .FirstOrDefault().chat_id,
- text: "Payout detected!");
- }
- url = AppSettings.poolApiUrl + "/miner/" + wallet + "/workers";
- var currentWorker = JsonDownloader._download_serialized_json_data<JsonWorker>(url);
-
- if (currentWorker.status == "OK")
- {
- for (int i = 0; i < currentWorker.data.Count(); i++)
- {
- await Console.Out.WriteLineAsync($"Create new record for {currentWorker.data[i].worker}");
- var newWorkerRecord = new workers();
- newWorkerRecord.wallet = newMinerRecord.wallet;
- newWorkerRecord.time = currentWorker.data[i].time;
- newWorkerRecord.worker = currentWorker.data[i].worker;
- newWorkerRecord.reported_hashrate = currentWorker.data[i].reportedHashrate;
- newWorkerRecord.current_hashrate = currentWorker.data[i].currentHashrate;
- newWorkerRecord.valid_shares = currentWorker.data[i].validShares;
- newWorkerRecord.stale_shares = currentWorker.data[i].staleShares;
- newWorkerRecord.invalid_shares = currentWorker.data[i].invalidShares;
- var lastWorkerRecord = Botdb.workers.Where(w => w.worker == newWorkerRecord.worker)
- .OrderByDescending(w => w.time)
- .FirstOrDefault();
- if (lastWorkerRecord != null)
- {
- await Console.Out.WriteLineAsync($"lastWorkerRecord time = {lastWorkerRecord.time}");
- lastMinerRecord = Botdb.miners.Where(w => w.wallet == newMinerRecord.wallet)
- .OrderByDescending(w => w.time)
- .FirstOrDefault();
- if (lastMinerRecord != null)
- {
- await Console.Out.WriteLineAsync($"lastMinerRecord time = {lastMinerRecord.time}");
- //check for payout
- if (newMinerRecord.unpaid < lastMinerRecord.unpaid)
- {
- url = AppSettings.poolApiUrl + "/miner/" + wallet + "/payouts";
- var payouts = JsonDownloader._download_serialized_json_data<JsonPayouts>(url);
-
- await Console.Out.WriteLineAsync($"Last payout time = {DateTimeOffset.FromUnixTimeSeconds(payouts.data[0].paidOn).LocalDateTime.ToString("f")}");
- var newPayoutRecord = new payouts();
- newPayoutRecord.wallet = wallet;
- newPayoutRecord.time = payouts.data[0].paidOn;
- newPayoutRecord.amount = payouts.data[0].amount;
- newPayoutRecord.worker = newWorkerRecord.worker;
- //calculating payout for worker
- newPayoutRecord.worker_amount = lastWorkerRecord.worker_unpaid +
- (payouts.data[0].amount -
- lastMinerRecord.unpaid) *
- (newWorkerRecord.reported_hashrate /
- ((double) newMinerRecord.reported_hashrate));
- if (Double.IsNaN(newWorkerRecord.worker_unpaid) ||
- Double.IsInfinity(newWorkerRecord.worker_unpaid))
- newPayoutRecord.worker_amount = lastWorkerRecord.worker_unpaid;
- //calculating unpaid for worker
- newWorkerRecord.worker_unpaid = 0 +
- (newMinerRecord.unpaid) *
- (newWorkerRecord.reported_hashrate /
- ((double) newMinerRecord.reported_hashrate));
- if (Double.IsNaN(newWorkerRecord.worker_unpaid) ||
- Double.IsInfinity(newWorkerRecord.worker_unpaid))
- newWorkerRecord.worker_unpaid = 0;
- }
- else
- {
- //no check that last balance and prev balance are the same
- newWorkerRecord.worker_unpaid = lastWorkerRecord.worker_unpaid +
- (newMinerRecord.unpaid -
- lastMinerRecord.unpaid) *
- (newWorkerRecord.reported_hashrate /
- ((double) newMinerRecord.reported_hashrate));
- if (Double.IsNaN(newWorkerRecord.worker_unpaid) ||
- Double.IsInfinity(newWorkerRecord.worker_unpaid))
- newWorkerRecord.worker_unpaid = lastWorkerRecord.worker_unpaid;
- await Console.Out.WriteLineAsync($"newWorkerRecord unpaid change = {newMinerRecord.unpaid - lastMinerRecord.unpaid}");
- }
- }
- else
- {
- newWorkerRecord.worker_unpaid = 0;
- }
- }
- else
- {
- newWorkerRecord.worker_unpaid = 0;
- }
- await Console.Out.WriteLineAsync($"newWorkerRecord worker unpaid = {newWorkerRecord.worker_unpaid}");
- //this if does nothing
- if (lastWorkerRecord == null || newWorkerRecord.time != lastWorkerRecord.time)
- {
- Botdb.workers.Add(newWorkerRecord);
- //await Botdb.SaveChangesAsync();
- }
- //Botdb.SaveChanges();
- else
- {
- Botdb.workers.Add(newWorkerRecord);
- }
- }
- }
- }
- else
- {
- await Console.Out.WriteLineAsync($"Row with wallet: {newMinerRecord.wallet} and time: {newMinerRecord.time} already exists!");
- }
-
- try
- {
- await Botdb.SaveChangesAsync();
- await Console.Out.WriteLineAsync($"Saved");
- }
- catch (Exception exception)
- {
- await Console.Out.WriteLineAsync(exception.Message + " " + exception.StackTrace);
- }
- }
- else
- {
- await Console.Out.WriteLineAsync($"Error response from pool for {wallet}!");
- }
- }
- catch (Exception exception)
- {
- await Console.Out.WriteLineAsync(exception.Message + " " + exception.StackTrace + " " + exception.StackTrace);
- }
- }
- }
- }
- }
|