update_data.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. package main
  2. import (
  3. "fmt"
  4. "math"
  5. "strings"
  6. tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api"
  7. )
  8. func (c *Connection) UpdateData() {
  9. LogInfo.Println("Updating data!")
  10. // Getting list of unique wallets in user table
  11. var walletList []string
  12. result := c.GormDb.Model(&User{}).
  13. Not("wallet = ?", "").
  14. Select("DISTINCT(wallet)").
  15. Scan(&walletList)
  16. if result.Error != nil {
  17. LogError.Println(result.Error)
  18. return
  19. }
  20. for _, wallet := range walletList {
  21. c.UpdateWallet(wallet)
  22. }
  23. }
  24. func (c *Connection) UpdateWallet(wallet string) {
  25. LogInfo.Printf(">> Getting data for wallet %s\n", wallet)
  26. url := fmt.Sprintf("%s/miner/%s", appSettings.ApiUrl, wallet)
  27. LogInfo.Print("From: " + url)
  28. currentStats, err := MinerStats(url)
  29. if err != nil {
  30. if strings.Contains(err.Error(), "No data for miner") {
  31. LogInfo.Println("No currentStats data for miner")
  32. } else {
  33. LogError.Println(err)
  34. }
  35. return
  36. }
  37. if currentStats.Status == "OK" {
  38. if currentStats.Data == (JsonCurrentStats{}).Data {
  39. // if fmt.Sprintf("%T", currentStats.(map[string]interface{})["data"]) != "map[string]interface {}" {
  40. LogInfo.Printf("data in response from %s for wallet %s not an interface!\n", appSettings.ApiUrl, wallet)
  41. return
  42. }
  43. // data := currentStats.(map[string]interface{})["data"].(map[string]interface{})
  44. LogInfo.Printf("Creating new record for miner %s, time %d\n", wallet, currentStats.Data.Time)
  45. // Line 28 of UpdateData.cs
  46. // NOTE: No use for creating new record here
  47. var newMinerRecord Miner
  48. newMinerRecord.Wallet = wallet
  49. newMinerRecord.Time = currentStats.Data.Time
  50. newMinerRecord.ReportedHashrate = currentStats.Data.ReportedHashrate
  51. newMinerRecord.CurrentHashrate = currentStats.Data.CurrentHashrate
  52. newMinerRecord.ValidShares = currentStats.Data.ValidShares
  53. newMinerRecord.StaleShares = currentStats.Data.StaleShares
  54. newMinerRecord.InvalidShares = currentStats.Data.InvalidShares
  55. newMinerRecord.Workers = currentStats.Data.ActiveWorkers
  56. newMinerRecord.Unpaid = currentStats.Data.Unpaid
  57. LogInfo.Printf("New miner record creating complete %s", newMinerRecord.Wallet)
  58. // Line 42 of UpdateData.cs
  59. // Search for latest record for miner
  60. var lastMinerRecord Miner
  61. result := c.GormDb.
  62. Where("wallet = ?", newMinerRecord.Wallet).
  63. Order("time desc").
  64. Limit(1).
  65. Find(&lastMinerRecord)
  66. if result.Error != nil {
  67. LogError.Println(result.Error)
  68. return
  69. }
  70. // No previous records for miner
  71. // Or previous record from different time
  72. if result.RowsAffected == 0 || lastMinerRecord.Time != newMinerRecord.Time {
  73. result = c.GormDb.Create(&newMinerRecord)
  74. if result.Error != nil {
  75. LogInfo.Println(result.Error)
  76. return
  77. }
  78. LogInfo.Printf("Added new row for miner %s\n", newMinerRecord.Wallet)
  79. // Line 54 of UpdateData.cs
  80. if lastMinerRecord != (Miner{}) && newMinerRecord.Unpaid < lastMinerRecord.Unpaid {
  81. var walletChats []int64
  82. result := c.GormDb.Model(&User{}).
  83. Where("wallet = ?", newMinerRecord.Wallet).
  84. Select("chat_id").
  85. Scan(&walletChats)
  86. if result.Error != nil {
  87. LogError.Println(result.Error)
  88. return
  89. }
  90. for _, chat := range walletChats {
  91. LogInfo.Println("Sended 'Payout detected!' message to chat ", chat)
  92. go myBotClient.Send(tgbotapi.NewMessage(chat, "Payout detected!"))
  93. }
  94. }
  95. // Line 64 of UpdateData.cs
  96. LogInfo.Printf("Getting workers data for wallet %s\n", wallet)
  97. url = fmt.Sprintf("%s/miner/%s", appSettings.ApiUrl, wallet)
  98. LogInfo.Print("From: " + url)
  99. currentWorker, err := Workers(url)
  100. if err != nil {
  101. if strings.Contains(err.Error(), "No data for workers") {
  102. LogInfo.Println("No workers data for miner")
  103. } else {
  104. LogError.Println(err)
  105. }
  106. return
  107. }
  108. if currentWorker.Status == "OK" {
  109. if len(currentWorker.Data) == 0 {
  110. LogInfo.Printf("data in response from %s for workers of wallet %s not an interface!\n", appSettings.ApiUrl, wallet)
  111. return
  112. }
  113. for i := range currentWorker.Data {
  114. workerData := currentWorker.Data[i]
  115. LogInfo.Printf("Creating new worker record for %s, time %d\n", workerData.Worker, workerData.Time)
  116. var newWorkerRecord Worker
  117. newWorkerRecord.Wallet = newMinerRecord.Wallet
  118. newWorkerRecord.Time = workerData.Time
  119. newWorkerRecord.Worker = workerData.Worker
  120. newWorkerRecord.ReportedHashrate = workerData.ReportedHashrate
  121. newWorkerRecord.CurrentHashrate = workerData.CurrentHashrate
  122. newWorkerRecord.ValidShares = workerData.ValidShares
  123. newWorkerRecord.StaleShares = workerData.StaleShares
  124. newWorkerRecord.InvalidShares = workerData.InvalidShares
  125. LogInfo.Printf("New worker record creating complete %s", newWorkerRecord.Worker)
  126. //Search for latest record for worker
  127. var lastWorkerRecord Worker
  128. result = c.GormDb.
  129. Where("worker = ?", workerData.Worker).
  130. Order("time desc").
  131. Limit(1).
  132. Find(&lastWorkerRecord)
  133. if result.Error != nil {
  134. LogError.Println(result.Error)
  135. }
  136. // Line 85 of UpdateData.cs
  137. if lastWorkerRecord != (Worker{}) {
  138. // Search for latest miner record... again?
  139. var lastMinerRecord1 Miner
  140. result = c.GormDb.
  141. Where("wallet = ?", newMinerRecord.Wallet).
  142. Order("time desc").
  143. Limit(1).
  144. Find(&lastMinerRecord1)
  145. if result.Error != nil {
  146. LogError.Println(result.Error)
  147. }
  148. //Line 91 of UpdateData.cs
  149. if lastMinerRecord1 != (Miner{}) {
  150. //check for payout
  151. if newMinerRecord.Unpaid < lastMinerRecord1.Unpaid {
  152. // Adding new payout field to db
  153. url := fmt.Sprintf("%s/miner/%s/payouts", appSettings.ApiUrl, wallet)
  154. var payouts JsonPayouts
  155. err := UnmasrshalFromUrl(url, &payouts)
  156. if err != nil {
  157. LogError.Println(err)
  158. return
  159. }
  160. lastPayout := payouts.Data[0]
  161. LogInfo.Println("Last payout time =", lastPayout.PaidOn)
  162. var newPayoutRecord Payout
  163. newPayoutRecord.Wallet = wallet
  164. newPayoutRecord.Time = lastPayout.PaidOn
  165. newPayoutRecord.Amount = lastPayout.Amount
  166. newPayoutRecord.Worker = workerData.Worker
  167. workerAmount := float64(lastWorkerRecord.WorkerUnpaid+
  168. (float64(lastPayout.Amount-lastMinerRecord.Unpaid))) *
  169. (float64(workerData.ReportedHashrate) / float64(newMinerRecord.ReportedHashrate))
  170. if math.IsNaN(workerAmount) || math.IsInf(workerAmount, 0) {
  171. workerAmount = lastWorkerRecord.WorkerUnpaid
  172. }
  173. newPayoutRecord.WorkerAmount = workerAmount
  174. workerUnpaid := float64(newMinerRecord.Unpaid) *
  175. (float64(workerData.ReportedHashrate) / float64(newMinerRecord.ReportedHashrate))
  176. LogDebug.Println("newMinerRecord.Unpaid:", newMinerRecord.Unpaid)
  177. LogDebug.Println("lastMinerRecord.Unpaid:", lastMinerRecord.Unpaid)
  178. LogDebug.Println("workerData.ReportedHashrate:", workerData.ReportedHashrate)
  179. LogDebug.Println("newMinerRecord.ReportedHashrate:", newMinerRecord.ReportedHashrate)
  180. LogDebug.Println("workerUnpaid:", workerUnpaid)
  181. if math.IsNaN(workerUnpaid) || math.IsInf(workerUnpaid, 0) {
  182. LogDebug.Println("workerUnpaid is NaN or Inf")
  183. workerUnpaid = 0
  184. }
  185. newWorkerRecord.WorkerUnpaid = workerUnpaid
  186. result = c.GormDb.Create(&newPayoutRecord)
  187. if result.Error != nil {
  188. LogError.Println(result.Error)
  189. return
  190. }
  191. LogInfo.Println("Add newPayoutRecord, time =", newPayoutRecord.Time)
  192. //removing old records
  193. result = c.GormDb.
  194. Where("wallet = ? AND time < ?", newPayoutRecord.Wallet, newPayoutRecord.Time).
  195. Delete(Worker{})
  196. if result.Error != nil {
  197. LogError.Println(result.Error)
  198. }
  199. result = c.GormDb.
  200. Where("wallet = ? AND time < ?", newPayoutRecord.Wallet, newPayoutRecord.Time).
  201. Delete(Miner{})
  202. if result.Error != nil {
  203. LogError.Println(result.Error)
  204. }
  205. result = c.GormDb.
  206. Where("wallet = ? AND time < ?", newPayoutRecord.Wallet, newPayoutRecord.Time).
  207. Delete(Payout{})
  208. if result.Error != nil {
  209. LogError.Println(result.Error)
  210. }
  211. //Line 135 of UpdateData.cs
  212. } else {
  213. //no check that last balance and prev balance are the same
  214. //don't sure > or >=
  215. //TODO rewrite this
  216. var max int64
  217. result := c.GormDb.Model(&Payout{}).
  218. Where("wallet = ?", lastWorkerRecord.Wallet).
  219. Order("time desc").
  220. Limit(1).
  221. Select("time").
  222. Scan(&max)
  223. if result.Error != nil {
  224. LogWarn.Printf("No payouts data for %s! Time is set to 0!\n", lastWorkerRecord.Wallet)
  225. LogError.Println(result.Error)
  226. max = 0
  227. }
  228. if lastWorkerRecord.Time > max {
  229. workerUnpaid := float64(lastWorkerRecord.WorkerUnpaid+
  230. float64(newMinerRecord.Unpaid-lastMinerRecord.Unpaid)) *
  231. (float64(workerData.ReportedHashrate) / float64(newMinerRecord.ReportedHashrate))
  232. if math.IsNaN(workerUnpaid) || math.IsInf(workerUnpaid, 0) {
  233. workerUnpaid = lastWorkerRecord.WorkerUnpaid
  234. }
  235. newWorkerRecord.WorkerUnpaid = workerUnpaid
  236. // Line 169 of UpdateData.cs
  237. } else {
  238. workerUnpaid := float64((newMinerRecord.Unpaid - lastMinerRecord.Unpaid)) *
  239. (float64(workerData.ReportedHashrate) / float64(newMinerRecord.ReportedHashrate))
  240. if math.IsNaN(workerUnpaid) || math.IsInf(workerUnpaid, 0) {
  241. workerUnpaid = lastWorkerRecord.WorkerUnpaid
  242. }
  243. newWorkerRecord.WorkerUnpaid = workerUnpaid
  244. var targetedChats []int64
  245. result = c.GormDb.
  246. Where(&User{Wallet: newMinerRecord.Wallet}).
  247. Select("DISTINCT(chat_id)").
  248. Scan(&targetedChats)
  249. if result.Error != nil {
  250. LogError.Println(result.Error)
  251. } else {
  252. msg := fmt.Sprintf("Debug info: Your worker %s hasn't been zeroed on payout!", workerData.Worker)
  253. for _, chatId := range targetedChats {
  254. go myBotClient.Send(tgbotapi.NewMessage(int64(chatId), msg))
  255. }
  256. LogDebug.Printf("Worker %s on address %s hasn't been zeroed on payout!\n", workerData.Worker, wallet)
  257. }
  258. }
  259. }
  260. }
  261. // Line 196 of UpdateData.cs
  262. } else {
  263. LogDebug.Println("Setting WorkerUnpaid to 0")
  264. newWorkerRecord.WorkerUnpaid = 0
  265. }
  266. var rowsCount int64
  267. result = c.GormDb.Model(&Worker{}).
  268. Where("worker = ? and time = ?", newWorkerRecord.Worker, newWorkerRecord.Time).
  269. Count(&rowsCount)
  270. if result.Error != nil {
  271. LogError.Println(result.Error)
  272. return
  273. }
  274. if rowsCount != 0 {
  275. LogInfo.Printf("Error adding new row: row with worker: %s, time: %d already exists!\n", newWorkerRecord.Worker, newWorkerRecord.Time)
  276. return
  277. }
  278. result = c.GormDb.Create(&newWorkerRecord)
  279. if result.Error != nil {
  280. LogError.Println(result.Error)
  281. } else {
  282. LogInfo.Printf("Added new row for worker %s\n", newWorkerRecord.Worker)
  283. }
  284. }
  285. }
  286. // Line 222 of UpdateData.cs
  287. } else {
  288. LogInfo.Printf("Row with wallet: %s and time: %d already exists!", wallet, currentStats.Data.Time)
  289. }
  290. } else {
  291. LogError.Printf("Error response from pool for %s!\n", wallet)
  292. }
  293. }