Guest User

Untitled

a guest
Sep 26th, 2024
131
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.04 KB | None | 0 0
  1. import base64
  2. import json
  3. import time
  4. import random
  5. from datetime import datetime
  6.  
  7. import requests
  8. import threading
  9. from requests.adapters import HTTPAdapter, Retry
  10. from sys import exit
  11.  
  12. from utils import sleep_with_note, init_session
  13.  
  14. DEFAULT_EXCHANGE = 'bingx'
  15.  
  16.  
  17. def clamp(n, min, max):
  18. if n < min:
  19. return min
  20. elif n > max:
  21. return max
  22. else:
  23. return n
  24.  
  25.  
  26. class HamsterKombat:
  27. def __init__(self, bearer_token, proxy, exit_time):
  28. self.exit_time = exit_time
  29. self.session = init_session(bearer_token, proxy)
  30. self.base_url = 'https://api.hamsterkombatgame.io/'
  31. self.user_name = ''
  32. self.level = 1
  33. self.earnPerTap = 1
  34. self.availableTaps = 1000
  35. self.tapsRecoverPerSec = 3
  36. self.maxTaps = 1000
  37. self.totalCoins = 0
  38. self.balanceCoins = 0
  39. self.earnPassivePerHour = 0
  40.  
  41. self.upgrades = {}
  42. self.boosts = {}
  43. self.daily_quest = {}
  44. self.daily_cipher = {}
  45. self.initialize_session()
  46.  
  47. def get_url(self, url):
  48. return self.base_url + url + '/'
  49.  
  50. def initialize_session(self):
  51. self.session.get('https://app.hamsterkombatgame.io/clicker/')
  52. self.session.get('https://hamsterkombatgame.io/clicker/')
  53. auth_url = self.get_url('auth/me-telegram')
  54. res = self.post_and_validate(auth_url, None)
  55. tg_user: dict = res['telegramUser']
  56. self.user_name = next(
  57. (name for key in ['firstName', 'lastName', 'username'] if (name := tg_user.get(key)) and name), None)
  58.  
  59. def get_click_url(self, url_part):
  60. return self.get_url('clicker' + '/' + url_part)
  61.  
  62. def clicked_post(self, url_part):
  63. url = self.get_click_url(url_part)
  64. response = self.post_and_validate(url, None)
  65. return response
  66.  
  67. def sync_game_values(self, sync_data):
  68. def set_sync_attr(name):
  69. setattr(self, name, int(sync_data[name]))
  70. attrs = ['availableTaps',
  71. 'tapsRecoverPerSec',
  72. 'level',
  73. 'earnPerTap',
  74. 'maxTaps',
  75. 'totalCoins',
  76. 'balanceCoins',
  77. 'earnPassivePerHour'
  78. ]
  79. [set_sync_attr(val) for val in attrs]
  80. pass
  81.  
  82. def post_and_validate(self, url, data, ts_1000=False):
  83. last_err = None
  84. i = 0
  85. while i < 15:
  86. i += 1
  87. if data and 'timestamp' in data:
  88. data['timestamp'] = int(time.time() * (1000 if ts_1000 else 1))
  89. res = self.session.post(url, json=data)
  90. if not res.ok:
  91. # print(f'{url=} {data=}')
  92. # print(f'{self.user_name} Error: {res} {res.text}')
  93. last_err = res
  94. sleep_time = 1
  95. if res.status_code == 503 or i == 9:
  96. sleep_time = 100
  97. elif res.status_code == 500:
  98. i -= 1
  99. sleep_time = 5
  100. if res.status_code == 400:
  101. data = res.json()
  102. if 'error_code' in data:
  103. if data['error_code'] == 'UPGRADE_COOLDOWN':
  104. return {'Error': 'UPGRADE_COOLDOWN', 'Data': data['cooldownSeconds']}
  105. if data and 'availableTaps' in data:
  106. data['availableTaps'] = self.set_available_taps(sleep_time)
  107. time.sleep(sleep_time)
  108. continue
  109. else:
  110. return res.json()
  111. raise Exception(f'{self.user_name} post send error {url} {data} {last_err} {last_err.text}')
  112.  
  113. def buy_upgrade(self, upgrade):
  114. # print(f'buyed upgrade\n {upgrade}')
  115. name = upgrade['id']
  116. url = self.get_click_url('buy-upgrade')
  117. data = {
  118. 'upgradeId': name,
  119. 'timestamp': int(time.time()*1000)
  120. }
  121. print(f'{self.user_name} buy upgrade: {name}')
  122. data_for_buy = self.post_and_validate(url, data, True)
  123. if 'Error' in data_for_buy:
  124. if data_for_buy['Error'] == 'UPGRADE_COOLDOWN':
  125. upgrade['cooldownSeconds'] = data_for_buy['Data']
  126. else:
  127. self.upgrades = data_for_buy['upgradesForBuy']
  128. self.daily_quest = data_for_buy['dailyCombo']
  129. self.balanceCoins -= upgrade['price']
  130.  
  131. def buy_boost(self, boost):
  132. # print(f'buyed boost\n {boost}')
  133. name = boost['id']
  134. url = self.get_click_url('buy-boost')
  135. data = {
  136. 'boostId': name,
  137. 'timestamp': int(time.time())
  138. }
  139. print(f'{self.user_name} buy boost: {name}')
  140. self.boosts = self.post_and_validate(url, data)['boostsForBuy']
  141. self.balanceCoins -= boost['price']
  142.  
  143. def check_energy_recharge(self):
  144. for bt in self.boosts:
  145. if bt['id'] == 'BoostFullAvailableTaps':
  146. if bt['cooldownSeconds'] == 0 and (self.availableTaps < (self.maxTaps/5)):
  147. self.buy_boost(bt)
  148. break
  149.  
  150. def check_daily_quest(self):
  151. if len(self.daily_quest['upgradeIds']) == 3 and not self.daily_quest['isClaimed']:
  152. url = self.get_click_url('claim-daily-combo')
  153. self.post_and_validate(url, [])
  154. self.daily_quest['isClaimed'] = True
  155.  
  156. def claim_key(self):
  157. sync_response = self.session.post("https://api.hamsterkombatgame.io/clicker/sync")
  158. user_id = str(sync_response.json()["clickerUser"]["id"])
  159. encoded_cipher = base64.b64encode(f"0300000000|{user_id}".encode()).decode()
  160. time.sleep(1)
  161. start_response = self.session.post("https://api.hamsterkombatgame.io/clicker/start-keys-minigame")
  162.  
  163. if start_response.status_code == 400:
  164. error_response = start_response.json()
  165. if error_response.get("error_code") == "KEYS-MINIGAME_WAITING":
  166. print("Вы уже получили ключи")
  167. return
  168. else:
  169. print(f"Ошибка запуска мини-игры: {start_response.status_code}, {start_response.text}")
  170. return
  171.  
  172. time.sleep(2)
  173.  
  174. claim_response = self.session.post(
  175. "https://api.hamsterkombatgame.io/clicker/claim-daily-keys-minigame",
  176. json={"cipher": encoded_cipher}
  177. )
  178. if claim_response.status_code == 200:
  179. response_json = claim_response.json()
  180. balance_keys = response_json['clickerUser']['balanceKeys']
  181. bonus_keys = response_json['dailyKeysMiniGame']['bonusKeys']
  182. print(f"Баланс ключей: {balance_keys}")
  183. print(f"Ключи за мини-игру: +{bonus_keys}")
  184. return
  185. elif claim_response.status_code == 400:
  186. print("Вы уже получили ключи сегодня")
  187. return
  188. else:
  189. error_message = claim_response.json().get("error_message", "Неизвестная ошибка")
  190. print(f"Ошибка получения ежедневных ключей: {claim_response.status_code}, {error_message}")
  191. return
  192.  
  193. @staticmethod
  194. def daily_cipher_decode(cipher):
  195. modified_cipher = cipher[:3] + cipher[4:]
  196. decoded_bytes = base64.b64decode(modified_cipher)
  197. return decoded_bytes.decode('utf-8')
  198.  
  199. def get_daily_cipher_reward(self):
  200. cipher_b64 = self.daily_cipher['cipher']
  201. cur_word = self.daily_cipher_decode(cipher_b64)
  202. url = self.get_click_url('claim-daily-cipher')
  203. data = {
  204. 'cipher': cur_word
  205. }
  206. self.post_and_validate(url, data)
  207. print(f'{self.user_name} Daily cipher success')
  208. pass
  209.  
  210. @staticmethod
  211. def get_hours_until_listing():
  212. target_date = datetime(2024, 7, 5)
  213. current_time = datetime.now()
  214. time_until = target_date - current_time
  215. return int(time_until.total_seconds() / 3600)
  216.  
  217. def try_to_buy_something(self):
  218. def sort_key(item):
  219. if item['price'] == 0:
  220. return float('inf')
  221. else:
  222. return (item['profitPerHour'] - item['currentProfitPerHour']) / item['price']
  223.  
  224. self.check_energy_recharge()
  225. if self.balanceCoins < (self.earnPassivePerHour * 3):
  226. return
  227. self.upgrades = sorted(self.upgrades, key=sort_key, reverse=True)
  228. self.boosts = sorted(self.boosts, key=lambda x: x['price'])
  229. for bt in self.boosts:
  230. if bt['cooldownSeconds'] > 0:
  231. continue
  232. elif bt['id'] == 'BoostFullAvailableTaps':
  233. continue
  234. elif bt['price'] < (self.balanceCoins / 20) and bt['price'] < 80000: # buy only the cheapest boosts
  235. self.buy_boost(bt)
  236. return
  237. for up in self.upgrades:
  238. if up['isExpired'] or not up['isAvailable']:
  239. continue
  240. if 'maxLevel' in up:
  241. if up['level'] >= up['maxLevel']:
  242. continue
  243. if 'cooldownSeconds' in up:
  244. if up['cooldownSeconds'] > 0:
  245. continue
  246. if up['price'] < self.balanceCoins:
  247. profit = sort_key(up)
  248. if self.balanceCoins < 101_000_000:
  249. if (profit * self.get_hours_until_listing()) < 1.0:
  250. return # first item here have the highest profit, check over no need
  251. self.buy_upgrade(up)
  252. self.check_daily_quest()
  253. return
  254.  
  255. def get_daily_bonus(self, tasks: dict):
  256. bad_names = ['invite_friends', 'subscribe_youtube_channel']
  257. for task in tasks['tasks']:
  258. if not task['isCompleted'] and task['id'] not in bad_names:
  259. taskId = task['id']
  260. url = self.get_click_url('check-task')
  261. data = {
  262. "taskId": taskId
  263. }
  264. self.post_and_validate(url, data)
  265. print(f'{self.user_name} complete task {taskId}')
  266.  
  267. def set_cur_exchange(self):
  268. url = self.get_click_url('select-exchange')
  269. data = {
  270. "exchangeId": DEFAULT_EXCHANGE
  271. }
  272. self.post_and_validate(url, data)
  273. print(f'{self.user_name} set exchange to {DEFAULT_EXCHANGE}')
  274.  
  275. def set_available_taps(self, timeout):
  276. bonus = int(timeout * self.tapsRecoverPerSec)
  277. self.availableTaps += bonus
  278. self.availableTaps = clamp(self.availableTaps, bonus, self.maxTaps)
  279. return self.availableTaps
  280.  
  281. def perform_tap(self):
  282. current_timestamp = int(time.time())
  283. taps = (20 + random.randint(-5, 5)) * self.tapsRecoverPerSec / self.earnPerTap
  284. taps = clamp(taps, 5, 100)
  285. data = {
  286. "count": int(taps),
  287. "availableTaps": self.availableTaps,
  288. "timestamp": current_timestamp
  289. }
  290. response = self.post_and_validate(self.get_url('clicker/tap'), data)
  291. answer = response['clickerUser']
  292. self.sync_game_values(answer)
  293.  
  294. print(f'{self.user_name} Score: {self.balanceCoins}; '
  295. f'Energy: {self.availableTaps}/{self.maxTaps}; '
  296. f'CoinsPerHour: {self.earnPassivePerHour}; '
  297. f'CoinsPerClick: {self.earnPerTap}'
  298. )
  299.  
  300. modifier = self.earnPerTap/self.tapsRecoverPerSec if (self.availableTaps < int(self.maxTaps / 10)) else - 10
  301. sleep_time = clamp(taps / self.tapsRecoverPerSec * self.earnPerTap + modifier, 1, 100)
  302. if self.availableTaps == 0:
  303. sleep_time = (self.maxTaps / self.tapsRecoverPerSec / 10) + random.randint(-3, 3)
  304. self.set_available_taps(sleep_time)
  305. self.try_to_buy_something()
  306. time.sleep(sleep_time)
  307. if time.time() > self.exit_time:
  308. print(f'{self.user_name} goes on break')
  309. exit(0)
  310.  
  311. def run(self):
  312. config = self.clicked_post('config')
  313. self.daily_cipher: dict = config['dailyCipher']
  314. if not self.daily_cipher['isClaimed']:
  315. self.get_daily_cipher_reward()
  316. sync_data = self.clicked_post('sync')['clickerUser']
  317. if sync_data['exchangeId'] != DEFAULT_EXCHANGE:
  318. self.set_cur_exchange()
  319. self.sync_game_values(sync_data)
  320. data_for_buy = self.clicked_post('upgrades-for-buy')
  321. self.upgrades = data_for_buy['upgradesForBuy']
  322. self.daily_quest = data_for_buy['dailyCombo']
  323. self.boosts = self.clicked_post('boosts-for-buy')['boostsForBuy']
  324. tasks = self.clicked_post('list-tasks')
  325. self.check_daily_quest()
  326. self.get_daily_bonus(tasks)
  327. self.claim_key()
  328. while True:
  329. self.perform_tap()
  330.  
  331.  
  332. def main():
  333. debug = False
  334.  
  335. def run_instance(token, proxy, exit_time):
  336. instance = HamsterKombat(token, proxy, exit_time)
  337. instance.run()
  338.  
  339. while True:
  340. with open('config.json', 'r') as file:
  341. data = json.load(file)
  342. tokens = data['tokens']
  343. proxy_tokens = data['proxy_tokens']
  344. proxy = data['proxy']
  345. exit_time = time.time() + 60 * 60 + random.randint(0, 15 * 60)
  346. threads = []
  347. for token in tokens:
  348. thread = threading.Thread(target=run_instance, args=(token, None, exit_time,))
  349. threads.append(thread)
  350. thread.start()
  351. if debug:
  352. break
  353.  
  354. if not debug:
  355. for token in proxy_tokens:
  356. thread = threading.Thread(target=run_instance, args=(token, proxy, exit_time,))
  357. threads.append(thread)
  358. thread.start()
  359.  
  360. for thread in threads:
  361. thread.join()
  362. print('All threads complete. Wait two hour +- 15 min before restart')
  363. total_sleep_time = (60 * 60 * 2) + random.randint(-15 * 60, 15 * 60)
  364. sleep_with_note(total_sleep_time)
  365.  
  366.  
  367. if __name__ == '__main__':
  368. main()
  369.  
Add Comment
Please, Sign In to add comment