def do_show_next_user(self, client: VKinderClient): self.send_typing_activity(client) client.status = STATUSES['decision_wait'] client.active_user = client.get_next_user() # if we already showed all pairs if not client.active_user: self.do_send_to_start_due_to_reach_end(client) self.do_propose_start_search(client) return client.active_user.photos = self.vk_personal.get_user_photos( client.active_user.vk_id) if not client.active_user.photos: client.active_user.photos = self.vk_personal.get_user_photos( client.active_user.vk_id, album_id='wall') photos = [ f'photo{photo.owner_id}_{photo.id}' for photo in client.active_user.photos ] photos_str = ','.join(photos) log( f'[{client.fname} {client.lname}] Showing user: {client.active_user.fname} ' f'{client.active_user.lname} with {len(client.active_user.photos)} photos', self.debug_mode) age_str = f', возраст: {client.active_user.age}' if client.active_user.age else '' user_info = f'{client.active_user.fname} {client.active_user.lname} ' user_info += f'({client.active_user.city_name}{age_str})' user_info += f'{last_seen(client.active_user.last_seen_time)}\nhttps://vk.com/{client.active_user.domain}' keyboard = self.cmd.kb(['yes', 'no', 'ban', None, 'back', 'quit']) self.send_msg(client, user_info, attachment=photos_str, keyboard=keyboard) self.send_msg(client, PHRASES['do_you_like_it']) self.db.save_photos(client)
def save_client(self, client: VKinderClient, force_country_update=False): """ Manual UPSERT of single client in DB """ log(f'[{client.fname} {client.lname}] Saving client\'s info to DB', is_debug_msg=self.debug_mode) client_db = self.__session.query(Clients).filter( Clients.vk_id == client.vk_id).first() if not client_db: client_db = Clients() client_db.vk_id = client.vk_id client_db.fname = client.fname client_db.lname = client.lname client_db.domain = client.domain # preserve country_id and country_name, restore them in case client revisit if not client_db.id or force_country_update: client_db.country_id = client.country_id client_db.country_name = client.country_name elif client_db.id: client.country_id = client_db.country_id client.country_name = client_db.country_name client_db.city_id = client.city_id client_db.city_name = client.city_name client_db.hometown = client.hometown client_db.birth_date = client.birth_date client_db.birth_day = client.birth_day client_db.birth_month = client.birth_month client_db.birth_year = client.birth_year client_db.sex_id = client.sex_id client_db.updated = client.last_contact self.__session.add(client_db) self.__session.commit() # load new id from base if client was just created client.db_id = client_db.id client.searches = self.load_searches(client)
def do_start_search_creating(self, client: VKinderClient): client.status = STATUSES['city_input_wait'] # revert to default for new search client.rating_filter = RATINGS['new'] client.reset_search() keyboard = self.cmd.kb(['country', None, 'back', 'quit']) self.send_msg(client, PHRASES['enter_city_name_in_x'].format( client.country_name), keyboard=keyboard)
def do_show_rated_users(self, msg: str, client: VKinderClient): client.status = STATUSES['loading_users'] if msg in self.cmd.get('banned'): client.rating_filter = RATINGS['banned'] elif msg in self.cmd.get('disliked'): client.rating_filter = RATINGS['disliked'] else: client.rating_filter = RATINGS['liked'] self.db.load_users_from_db(client) if client.found_users: self.do_show_next_user(client) else: self.send_msg(client, PHRASES['no_peoples_found']) self.do_propose_start_search(client)
def do_propose_start_search(self, client: VKinderClient): client.status = STATUSES['invited'] client.rating_filter = RATINGS['new'] if len(client.searches) == 0: keyboard = self.cmd.kb(['yes', 'no']) self.send_msg(client, PHRASES['do_you_want_to_find_pair'], keyboard=keyboard) else: keyboard = self.cmd.kb([ 'new search', 'show history', None, 'liked', 'disliked', 'banned', None, 'quit' ]) self.send_msg(client, PHRASES['you_have_search_history'], keyboard=keyboard)
def do_propose_sex_choose(self, client: VKinderClient): client.status = STATUSES['sex_choose_wait'] sexes = [f'{sex_id}. {sex}' for sex_id, sex in SEXES.items()] keyboard = self.cmd.kb( ['woman', 'man', 'anybody', None, 'back', 'quit']) self.send_msg(client, '\n'.join(sexes), keyboard=keyboard) self.send_msg(client, PHRASES['choose_sex_number'])
def do_propose_max_age_enter(self, client: VKinderClient): client.status = STATUSES['max_age_input_wait'] keyboard = self.cmd.kb(['back', 'quit']) self.send_msg(client, PHRASES['enter_max_age_from_x_127'].format( client.search.min_age), keyboard=keyboard)
def on_country_name_choose(self, country_id: str, client: VKinderClient): result = None try: country_id = int(country_id) if 0 < country_id <= len(client.found_countries): result = country_id except ValueError: pass if result: client.country_id = client.found_countries[result - 1].id client.country_name = client.found_countries[result - 1].title self.db.save_client(client, force_country_update=True) self.send_msg( client, PHRASES['you_chosen_country_x'].format(client.country_name)) self.do_start_search_creating(client) else: self.send_msg(client, PHRASES['no_such_country_in_list'])
def do_propose_city_name_choose(self, city: str, client: VKinderClient): client.status = STATUSES['city_choose_wait'] self.send_typing_activity(client) # this needed to prevent repeated search operations with same city name if city: client.found_cities = self.vk_personal.search_cities( country_id=client.country_id, city_name=city) cities = [ f'{index}. {format_city_name(city)}' for index, city in enumerate(client.found_cities, 1) ] if cities: keyboard = self.cmd.kb(['back', 'quit']) self.send_msg(client, '\n'.join(cities), keyboard=keyboard) self.send_msg(client, PHRASES['choose_city_number']) else: self.send_msg(client, PHRASES['no_such_city_name']) self.do_start_search_creating(client)
def do_propose_status_choose(self, client: VKinderClient): client.status = STATUSES['status_choose_wait'] statuses = [ f'{status_id}. {status}' for status_id, status in LOVE_STATUSES.items() ] keyboard = self.cmd.kb(['back', 'quit']) self.send_msg(client, '\n'.join(statuses), keyboard=keyboard) self.send_msg(client, PHRASES['choose_love_status_number'])
def do_show_search_history(self, client: VKinderClient): client.status = STATUSES['search_history_input_wait'] client.rating_filter = RATINGS['new'] searches = self.db.load_searches(client) client.searches = searches history = [] for index, searches in enumerate(searches, 1): history.append( str(index) + '. ' + PHRASES['x_x_x_from_x_to_x'].format( searches.city_name, SEXES[searches.sex_id], LOVE_STATUSES[ searches.status_id], searches.min_age, searches.max_age)) if history: keyboard = self.cmd.kb(['back', 'quit']) self.send_msg(client, '\n'.join(history), keyboard=keyboard) self.send_msg(client, PHRASES['choose_search_history_number']) else: self.send_msg(client, PHRASES['no_search_history']) self.do_propose_start_search(client)
def on_country_name_input(self, country_name: str, client: VKinderClient): client.status = STATUSES['country_choose_wait'] self.send_typing_activity(client) # this needed to prevent repeated search operations for countries names if not self.countries: self.countries = self.vk_personal.get_countries() # filter countries by country_name client.found_countries = [ country for country in self.countries if country.title.lower().find(country_name) > -1 ] countries = [ f'{index}. {country.title}' for index, country in enumerate(client.found_countries, 1) ] if countries: keyboard = self.cmd.kb(['back', 'quit']) self.send_msg(client, '\n'.join(countries), keyboard=keyboard) self.send_msg(client, PHRASES['choose_country_number']) else: self.send_msg(client, PHRASES['no_such_city_name']) self.do_propose_country_name_input(client)
def do_users_search(self, client: VKinderClient): client.status = STATUSES['loading_users'] params = PHRASES['city_x_sex_x_status_x_age_xx'].format( client.search.city_name, SEXES[client.search.sex_id], LOVE_STATUSES[client.search.status_id], client.search.min_age, client.search.max_age) self.send_msg(client, f'{PHRASES["started_search_peoples"]}\n({params})') self.send_typing_activity(client) self.db.save_search(client) client.found_users = self.vk_personal.search_users( city_id=client.search.city_id, sex_id=client.search.sex_id, love_status_id=client.search.status_id, age_from=client.search.min_age, age_to=client.search.max_age) client.found_users = [ user for user in client.found_users if not user.is_closed and user.last_seen_time ] client.found_users.sort(key=lambda x: x.last_seen_time, reverse=True) if client.found_users: self.db.load_users_ratings_from_db(client) ratings_sum = get_users_ratings_counts(client.found_users) self.send_msg( client, PHRASES['found_x_peoples_x_new_x_liked_x_disliked_x_banned']. format(len(client.found_users), ratings_sum['new'], ratings_sum['liked'], ratings_sum['disliked'], ratings_sum['banned'])) if ratings_sum['new'] > 0: self.db.save_users(client) self.do_show_next_user(client) else: self.send_msg(client, PHRASES['no_new_peoples_found']) self.do_propose_start_search(client) else: self.send_msg(client, PHRASES['no_peoples_found']) self.do_propose_start_search(client)
def on_search_history_choose(self, history_id: str, client: VKinderClient): result = None try: history_id = int(history_id) if 0 < history_id <= len(client.searches): result = history_id except ValueError: pass if result: client.search = client.searches[result - 1] self.do_users_search(client) else: self.send_msg(client, PHRASES['no_such_history_in_list']) self.do_show_search_history(client)
def test_client_save_load(self): assert self.db.is_initialized mock_users_url = 'http://localhost:{port}/'.format( port=self.mock_server_port) with mock.patch('сlasses.vk_api_client.VkApiClient.API_BASE_URL', new_callable=mock.PropertyMock) as mock_f: mock_f.return_value = mock_users_url self.api = VkApiClient(token='', app_id='', user_id='1', debug_mode=True) assert self.api.is_initialized users = self.api.get_users('1') assert len(users) == 2 user = users[0] client = VKinderClient(user) self.db.save_client(client) client_db = self.db.load_client_from_db('1') assert client_db client = VKinderClient(client_db) assert client.vk_id == '1' assert client.fname == 'Павел' assert client.lname == 'Дуров'
def load_users_from_db(self, client: VKinderClient): """ Gets all rated users by client, using rating as filter """ log(f'[{client.fname} {client.lname}] Loading users from DB with rating {client.rating_filter}', is_debug_msg=self.debug_mode) users = self.__session.query(Users).join(ClientsUsers).filter( ClientsUsers.client_id == client.db_id).filter( ClientsUsers.rating_id == client.rating_filter).all() client.found_users = [] for user in users: client.found_users.append( user.convert_to_ApiUser(client.rating_filter)) log(f'[{client.fname} {client.lname}] Loaded {len(client.found_users)} users from DB', is_debug_msg=self.debug_mode)
def get_client(self, vk_id) -> VKinderClient: """ Here we create new instance of clients class and add to clients pool If client already exists, we check his activity timeout and reset client if timeout expired """ client = self.clients_pool.get(vk_id, None) if client: lag = int((datetime.now() - client.last_contact).total_seconds()) if lag > self.client_activity_timeout: self.do_send_to_start_after_absence(client) else: user = self.vk_personal.get_users(vk_id)[0] client = VKinderClient(user) self.db.save_client(client) self.clients_pool.update({user.vk_id: client}) self.do_greet_client(client) return client
def do_propose_country_name_input(self, client: VKinderClient): client.status = STATUSES['country_input_wait'] keyboard = self.cmd.kb(['back', 'quit']) self.send_msg(client, PHRASES['enter_country_name'], keyboard=keyboard)
def do_inform_about_unknown_command(self, client: VKinderClient): client.last_contact = datetime.now() self.send_msg(client, PHRASES['sorry_i_dont_understand_you'])
def do_send_to_start_due_to_reach_end(self, client: VKinderClient): client.status = STATUSES['has_contacted'] self.send_msg(client, PHRASES['well_lets_start_again'])
def do_send_to_start_after_absence(self, client: VKinderClient): client.status = STATUSES['has_contacted'] self.send_msg( client, PHRASES['sorry_x_you_was_absent_for_x_seconds'].format( client.fname, self.client_activity_timeout))
def test_users_save_load(self): mock_users_url = 'http://localhost:{port}/'.format( port=self.mock_server_port) with mock.patch('сlasses.vk_api_client.VkApiClient.API_BASE_URL', new_callable=mock.PropertyMock) as mock_f: mock_f.return_value = mock_users_url self.api = VkApiClient(token='', app_id='', user_id='1', debug_mode=True) assert self.api.is_initialized users = self.api.get_users(['1', '5', 1]) client_1 = VKinderClient(users[0]) assert client_1 client_2 = VKinderClient(users[1]) assert client_2 self.db.save_client(client_1) self.db.save_client(client_2) for i in range(self.db.search_history_limit + 1): client_1.reset_search() client_2.reset_search() client_1.search.sex_id = randrange(0, 2, 1) client_1.search.status_id = randrange(1, 8, 1) client_1.search.city_id = 1 client_1.search.city_name = 'Москва' client_1.search.min_age = randrange(0, 60, 1) client_1.search.max_age = randrange(client_1.search.min_age, 127, 1) client_1.rating_filter = 0 client_2.search.sex_id = randrange(0, 2, 1) client_2.search.status_id = randrange(1, 8, 1) client_2.search.city_id = 2 client_2.search.city_name = 'Санкт-Петербург' client_2.search.min_age = randrange(0, 60, 1) client_2.search.max_age = randrange(client_2.search.min_age, 127, 1) client_2.rating_filter = 0 self.db.save_search(client_1) self.db.save_search(client_2) client_1.found_users = self.api.search_users() client_2.found_users = self.api.search_users(q='babych') assert len(client_1.found_users) > 0 assert len(client_2.found_users) > 0 self.db.save_users(client_1) self.db.save_users(client_2)