async def report(self): bots_are_running = True bots_were_connected = False while bots_are_running or not bots_were_connected: # Wait for any bot to connect on app start if not bots_were_connected: bots_were_connected = self.is_any_bot_running() await asyncio.sleep(1) continue wallets: List[BotWallet] = [ session.bot.wallet for session in self.bot_sessions ] summary_tick = sum([wallet.tick for wallet in wallets]) / 1000 summary_score = sum([wallet.score for wallet in wallets]) / 1000 summary_hourly_rate = sum( [wallet.hourly_rate for wallet in wallets]) / 1000 Logger.log_warning(_("VKCoinPy stats")) Logger.log_warning( _("{} bots are running").format(self.count_bots_running())) Logger.log_warning( _("Summary speed: {} / tick | Summary score: {} | Summary hourly rate: {}" ).format(summary_tick, summary_score, summary_hourly_rate)) bots_are_running = self.is_any_bot_running() # Recheck, sometimes it returns False when bots are actually running, maybe some threading magic if not bots_are_running: await asyncio.sleep(1) bots_are_running = self.is_any_bot_running() await asyncio.sleep(self.report_interval)
async def run(self) -> None: Logger.log_system(_("VKCoinPy bot session is starting")) Logger.log_system(_("Connecting to the VK Coin app server")) reconnect = 1 while reconnect: self.messenger = networking.BotMessenger(self.server_url, self) reconnect = await self.messenger.run()
def __init__(self, token: str = None, username: str = None, password: str = None, use_credentials: bool = False, vk_group_id=None): if not token and not (username and password): raise Exception(_("Either token or credentials must be provided")) if use_credentials and not (username and password): raise Exception(_("Username and password are not provided")) self.use_credentials = use_credentials self.vk_group_id = vk_group_id self.mine_for_vk_group = False if self.use_credentials and self.vk_group_id: self.mine_for_vk_group = True if not self.use_credentials: self.vk_token = token else: self.vk_token = None self.vk_username = username self.vk_password = password self.vk_session = None self.vk_user_data = None
async def report(self): while True: wallets: List[BotWallet] = [session.bot.wallet for session in self.bot_sessions] summary_tick = sum([wallet.tick for wallet in wallets]) / 1000 summary_score = sum([wallet.score for wallet in wallets]) / 1000 summary_hourly_rate = sum([wallet.hourly_rate for wallet in wallets]) / 1000 Logger.log_warning(_("VKCoinPy stats")) Logger.log_warning(_("{} bots are running").format(self.count_bots_running())) Logger.log_warning( _("Summary speed: {} / tick | Summary score: {} | Summary hourly rate: {}").format(summary_tick, summary_score, summary_hourly_rate)) await asyncio.sleep(self.report_interval)
async def _send_on_start_user_output(self): if self.bot.config.goal: goal_timedelta = self.bot.wallet.calculate_goal_time( self.bot.config.goal) if goal_timedelta.total_seconds(): Logger.log_system( _("Your goal will be reached in {}").format( goal_timedelta)) option_status_on = _("On") option_status_off = _("Off") auto_buy_enabled = option_status_on if self.bot.config.auto_buy_enabled else option_status_off Logger.log_system(_("Auto buy is {}").format(auto_buy_enabled)) auto_transfer_enabled = option_status_on if self.bot.config.auto_transfer_enabled else option_status_off Logger.log_system( _("Auto transfer is {}").format(auto_transfer_enabled)) if auto_transfer_enabled == option_status_on: auto_transfer_receiver = self.bot.config.auto_transfer_to auto_transfer_percent = self.bot.config.auto_transfer_percent auto_transfer_when = self.bot.config.auto_transfer_when Logger.log_system( _("Auto transfer receiver is user with ID {}").format( auto_transfer_receiver)) Logger.log_system( _("Auto transfer will be executed when balance will be more than {}" ).format(auto_transfer_when)) Logger.log_system( _("Auto transfer will send {} percent of your balance").format( auto_transfer_percent)) self.on_start_user_output_send = True
def setup(self): Logger.log_system(_("Starting bot session")) self.vk_connector.authorize() self.vk_user_id = self.vk_connector.vk_user_id self.vk_connector.check_bot_group_subscription() server_url = self.vk_connector._get_server_url() logger.debug("Server URL: {}".format(server_url)) Logger.log_system(_("Bot session created for user with ID {}").format(self.vk_user_id)) self.bot = VKCoinBot(server_url, self.config)
async def _handle_item_bought_message(self, message: dict) -> None: Logger.log_success(_("Bought an item")) tick = message.get('tick', self.bot.wallet.tick) score = message.get('score', self.bot.wallet.score) self.bot.wallet.set_tick(tick) self.bot.wallet.set_score(score) self.bot.wallet.update_items(message.get('items'))
def load_common_config() -> Dict: try: with open("config.json", "r") as config_file: config = json.load(config_file) return config except (json.JSONDecodeError, FileNotFoundError): print(_("Can not load config"))
def _get_token_from_credentials(self) -> str: api_auth_url = 'https://oauth.vk.com/token?grant_type=password&client_id=2274003' \ '&client_secret=hHbZxrka2uZ6jB1inYsH&username={}&password={}'.format(self.vk_username, self.vk_password) response = requests.get(api_auth_url) token = response.json().get("access_token") if not token: raise Exception(_("Can not login with provided credentials")) return token
def create_bot_sessions(config: Dict) -> List[VKCoinBotSession]: bot_configs = config["bots"] bot_count = len(bot_configs) Logger.log_system(_("Found {} bots in config file").format(bot_count)) sessions = [] for bot_config in bot_configs: try: session = VKCoinBotSession(bot_config) session.setup() sessions.append(session) except Exception: Logger.log_error(_("Can not load bot with config #{}").format(bot_config)) if not sessions: Logger.log_error(_("No sessions created")) return sessions
async def _handle_transfer_message(self, message: str) -> None: data = message.split(' ')[1::] if ResponseMessageTypes.TRANSACTION_IN_PROGRESS in data[0]: return amount = str(round(int(data[0]) / 1000)) sender = data[1] Logger.log_success( _("Received {} coins from user {}").format(amount, sender))
async def _listen(self): while not self.disconnect_required: try: connection_timeout = self.WAIT_FOR_MESSAGE_TIMEOUT if self.player_initialized \ else self.WAIT_FOR_MESSAGE_TIMEOUT_BEFORE_PLAYER_INIT await asyncio.wait_for(self._wait_for_message(), timeout=connection_timeout) except (websockets.exceptions.ConnectionClosed, websockets.exceptions.InvalidStatusCode): Logger.log_error(_("Connection closed, reconnecting")) await self._require_disconnect() except asyncio.TimeoutError: logger.debug("Connection timeout") await self._require_disconnect() except Exception as e: await asyncio.sleep(10) logger.exception(e) Logger.log_error(_("Unknown error, reconnecting")) await self._require_disconnect()
def start(self): for session in self.bot_sessions: session_thread = VKCoinBotSessionThread(session) try: session_thread.start() except: Logger.log_error(_("Can not start session for bot ID{}").format(session.vk_user_id)) event_loop = asyncio.get_event_loop() if self.report_enabled: event_loop.create_task(self.report()) event_loop.run_forever()
async def _auto_action_buy(self): items = self.bot.config.auto_buy_items for item in items: if hasattr(ItemTypes, item): if self.bot.wallet.has_player_enough_coins_to_buy(item): message = RequestMessageGenerator.generate_buy_item_message( item_id=getattr(ItemTypes, item), messages_sent=self.messages_sent) await self.send_message(message) Logger.log_success(_('Auto buying {}').format(item))
async def _auto_action_buy(self): while not self.disconnect_required: if self.bot.config.auto_buy_target_tick * 1000 > self.bot.wallet.tick: item = self.bot.wallet.get_best_item_to_buy() if item and self.bot.wallet.has_player_enough_coins_to_buy( item): message = RequestMessageGenerator.generate_buy_item_message( item_id=item, messages_sent=self.messages_sent) await self.send_message(message) Logger.log_success( _('Best item to buy is {}. Buying.').format(item)) else: return await asyncio.sleep(self.bot.config.auto_buy_interval)
async def _connect(self) -> None: max_connection_attempts = 10 connection_attempts = 0 logger.debug("Connecting to the VK Coin app server") self.connection = None while not self.connection and connection_attempts < max_connection_attempts: try: self.connection = await websockets.connect(self.server_url) self.connected = True logger.debug("Connection established") return except: connection_attempts += 1 await asyncio.sleep(1) Logger.log_error( _("Can not connect to the server. Max connection attempts reached." )) self._require_disconnect(reconnect=False)
def _get_group_mobile_iframe_url(self): screen_name = "app{}_-{}".format(self.VK_COIN_APP_ID, self.vk_group_id) owner_id = "-{}".format(self.vk_group_id) param = { 'access_token': self.vk_token, 'v': 5.55, 'screen_name': screen_name, 'owner_id': owner_id, 'func_v': 3 } response = requests.get( 'https://api.vk.com/method/execute.resolveScreenName', params=param).json() if response.get('errors'): raise ValueError( _("Can not load mobile_iframe_url from the VK API")) mobile_iframe_url = response.get("response", {}).get("embedded_uri", {}).get("view_url") if mobile_iframe_url is None: raise ValueError("Mobile Iframe URL is empty") return mobile_iframe_url
async def _handle_init_message(self, message: dict) -> None: # Wallet data self.bot.wallet.set_score(message.get('score')) self.bot.wallet.set_place(message.get('place')) self.bot.wallet.set_tick(message.get('tick')) self.bot.wallet.update_items(message.get('items')) # Networking data self.random_id = message.get('randomId') self.top = message.get('top') try: c_pow = calculate_pow(message.get('pow')) init_message_response = "C1 {} {}".format(self.random_id, c_pow) await self.send_message(init_message_response) except js2py.PyJsException: self.connected = False await self._require_disconnect() return self.messages_sent = 1 Logger.log_success(_("User has been loaded")) await self._player_initialized()
def get_player_score_report(self) -> str: score = round(int(self.score) / 1000, 3) speed = round(int(self.tick) / 1000, 2) return _('Coins: {} | Speed: {} / tick | Place: {}').format( score, speed, self.place)
def get_player_items_report(self) -> str: return ' | '.join([ "{}: {}".format(_(key), value) for (key, value) in self.items.items() ])
async def _handle_not_enough_coins_message(self) -> None: Logger.log_warning(_("Not enough coins to buy an item"))
def get_player_stats_report(self) -> str: hourly_rate = self.hourly_rate / 1000 return _("Hourly rate: {}").format(hourly_rate)
async def _handle_broken_message(self) -> None: Logger.log_error(_("Servers are down, reconnecting"))
def check_bot_group_subscription(self): user_groups = self.vk_session.method("groups.get").get('items', []) if self.BOT_GROUP_ID not in user_groups: Logger.log_warning(_("Subscribe to our VK public")) Logger.log_warning(self.BOT_GROUP_URL)