def download_photos(self, photos_list, base_path, rename, force_overwrite=False, log_to_widget=True, thread_update_signal=None): for i in range(len(photos_list)): photo = photos_list[i] log.d("API", "Downloading full-size photos", log_to_widget) filename, skipped = self.download_file(photo['url'], base_path, rename, i, "", force_overwrite, log_to_widget) if filename is not None: photo['local_path'] = str(os.path.abspath(filename)) if 'processedFiles' in photo: processed_files = photo['processedFiles'] small_photo = processed_files[len(processed_files) - 1] log.d("API", "Downloading small photo", log_to_widget) filename, skipped = self.download_file( small_photo['url'], base_path + "/small/", rename, i, "_small", force_overwrite, log_to_widget=log_to_widget) if filename is not None: small_photo['local_path'] = str(os.path.abspath(filename))
def write_data_to_file(self, data, base_path, log_to_widget=True, thread_update_signal=None): log.d("API", "Data written to: " + str(base_path), log_to_widget) with open(base_path + 'data.yaml', 'w') as fp: yaml.dump(data, fp)
def pause(self, log_to_widget=True, thread_update_signal=None): ''' In order to appear as a real Tinder user using the app... When making many API calls, it is important to pause a... realistic amount of time between actions to not make Tinder... suspicious! ''' nap_length = 3 * random() log.d("API", 'Napping for %f seconds...' % nap_length) sleep(nap_length)
def update_matches_widgets(self): log.d("FEATURES", str("Updating Matches widgets")) self.update_widgets( self.app.matches, self.app.new_matches, self.get_matches_button, self.reload_matches_button, self.download_matches_data_button, self.download_matches_amount, self.rename_matches_images_checkbox, self.force_matches_download_checkbox, self.matches_new_counter, self.matches_counter, self.matches_photos_checkbox, self.matches_instagram_checkbox) self.matches_messages_checkbox.setEnabled( self.download_matches_data_button.isEnabled())
def save_to_yaml(self): try: print("Saving yaml...") log.i("LOGIN_F", self.config_file) log.d("LOGIN_F", self.config) with open(self.config_file, 'w') as fy: yaml.dump(self.config, fy) self.statusBar.showMessage("Credentials Saved to " + str(self.config_file)) except Exception as e: log.e("LOGIN_F", "Exceptipn: " + str(e))
def download_messages(self, match_data, log_to_widget=True, thread_update_signal=None): log.d("API", "Downloading match messages", log_to_widget) messages = self.get_messages(match_data, 100, None, log_to_widget, thread_update_signal) log.d( "API", "Downloaded messages: " + str(match_data["_id"] + ": " + str(messages)), log_to_widget) if messages is not None and 'data' in messages: return messages['data']['messages'] return []
def update_recommendations_widgets(self): log.d("FEATURES", str("Updating Recommendations Widgets")) self.update_widgets( self.app.recommendations, self.app.new_recommendations, self.get_recommendations_button, self.reload_recommendations_button, self.download_recommendations_data_button, self.download_recommendations_amount, self.rename_recommendations_images_checkbox, self.force_recommendations_download_checkbox, self.recommendations_new_counter, self.recommendations_counter, self.recommendations_photos_checkbox, self.recommendations_instagram_checkbox)
def download_person_data(self, data, base_folder, photos, insta, messages, rename_images, force_overwrite=False, log_to_widget=True, thread_update_signal=None): person_data, type = self.get_person_data(data) id = person_data['_id'] name = person_data['name'] path = base_folder + "/" + str(name) + "_" + str(id) + "/" person_data['path'] = str(os.path.abspath(path)) log.i( "API", "Downloading " + type + ": " + name + " " + id + " to: " + str(person_data['path']), log_to_widget) if os.path.exists(path): log.d("API", "Person path already exists: " + person_data['path'], log_to_widget) else: os.makedirs(path) log.d("API", "Person path created: " + person_data['path'], log_to_widget) person_data['local_path'] = str(os.path.abspath(path)) if insta and 'instagarm' in person_data: self.download_instagram_photos(person_data['instagram'], path, rename_images, force_overwrite, log_to_widget, thread_update_signal) if photos and 'photos' in person_data: self.download_photos(person_data['photos'], path, rename_images, force_overwrite, log_to_widget, thread_update_signal) if messages and 'match' in type: data['messages'] = self.download_messages(data, log_to_widget, thread_update_signal) data['AI_Dating_metadata'] = {} data['AI_Dating_metadata']['last_updated_datetime'] = str( datetime.now().strftime("%d-%b-%Y %H:%M:%S")) data['AI_Dating_metadata']['last_updated_timestamp'] = str( datetime.utcnow()) self.write_data_to_file(data, path, log_to_widget, thread_update_signal) return data
def all_matches(self, amount=60, message=0, page_token=None, log_to_widget=True, thread_update_signal=None): try: url = self.host + '/v2/matches?locale=en&count=' + str( amount) + '&message=' + str(message) + '&is_tinder_u=false' log.d("API", "All matches page: " + str(page_token), log_to_widget) if page_token: url = url + '&page_token=' + page_token r = requests.get(url, headers=self.headers) json = r.json() log.d("API", "All matches keys " + str(json.keys()), log_to_widget) log.d("API", "All matches data " + str(json['data'].keys()), log_to_widget) log.d( "API", "All matches data matches " + str(len(json['data']['matches'])) + " " + str(json['data']['matches'][0].keys()), log_to_widget) log.d("API", "All matches meta " + str(json['meta'].keys()), log_to_widget) log.i( "API", "all_matches: Got response. Status: " + str(json['meta']['status']) + ": " + utils.error_code_to_message[json['meta']['status']], log_to_widget) if 'next_page_token' in json['data']: new_data = self.all_matches(amount, message, json['data']['next_page_token']) for match in new_data['data']['matches']: match[ 'page_token'] = page_token # This will be needed to get messages json['data']['matches'] = json['data']['matches'] + new_data[ 'data']['matches'] self.page_token = json['data']['next_page_token'] elif message <= 0: new_data = self.all_matches(amount, 1, None) json['data']['matches'] = json['data']['matches'] + new_data[ 'data']['matches'] log.i("API", "Total matches " + str(len(json['data']["matches"])), log_to_widget) return json except requests.exceptions.RequestException as e: log.e( "API", "Something went wrong. Could not get your match info:" + str(e), log_to_widget)
def update_fb_token(self, token): print(self.config) try: self.config['facebook']['auth_token'] = token log.d("LOGIN_F", self.config) if 'error' in self.config['facebook']['auth_token']: Exception("Error: " + self.config['facebook']['auth_token']) self.linedEdit_fb_token.setText( self.config['facebook']['auth_token']) self.button_fb_spinner.hideSpinner() except Exception as e: log.e("LOGIN_F", "Exception Getting token: " + str(e)) self.config['facebook']['auth_token'] = "" self.linedEdit_fb_token.setText("ERROR") QApplication.processEvents() self.statusBar.clearMessage()
def get_match_info(self, log_to_widget=True, thread_update_signal=None): matches = self.get_updates()['matches'] now = datetime.utcnow() match_info = {} for match in matches[:len(matches)]: try: person = match['person'] person_id = person['_id'] # This ID for looking up person name = person['name'] id = match['id'] msg_count = match['message_count'] photos = self.get_photos(person) bio = "" if 'bio' in person.keys(): bio = person['bio'] gender = person['gender'] avg_succ_rate = self.get_avg_successRate(person) messages = match['messages'] age = self.calculate_age(match['person']['birth_date']) distance = self.get_person(person_id)['results']['distance_mi'] last_activity_date = match['last_activity_date'] match_info[person_id] = { "name": name, "match_id": id, # This ID for messaging "message_count": msg_count, "photos": photos, "bio": bio, "gender": gender, "avg_successRate": avg_succ_rate, "messages": messages, "age": age, "distance": distance, "last_activity_date": last_activity_date, } log.d("API", name + "_" + id) except Exception as ex: template = "An exception of type {0} occurred. Arguments:\n{1!r}" message = template.format(type(ex).__name__, ex.args) log.e("API", message) # continue log.i("API", "All data stored in variable: match_info") filename = self.data_folder + 'match_info.json' with open(filename, 'w') as fp: json.dump(match_info, fp) log.i("API", "All data dumped to file: " + str(os.path.abspath(filename))) return match_info
def completeBackgroundTask(self, info="", tag=None): self.updateBackgroundTaskInfo(info) if tag is not None and tag in self.background_tasks_list: self.background_tasks_list.remove(tag) self.background_completed += 1 if self.background_completed >= self.background_count_total: self.background_count_total = 0 self.background_completed = 0 self.spinner.hideSpinner() self.updateBackgroundTaskInfo("All tasks completed!") self.background_count_label.setVisible(False) self.updateBackgroundTaskCount() log.d( "THREADS", "Completed background task " + str(info) + " " + str(self.background_completed) + "/" + str(self.background_count_total) + " Tasks: " + str(self.background_tasks_list), False)
def get_profile(self, doAsync=True, force_update=False): try: with open(self.profile_file, "r") as pf: data = json.load(pf) log.d("APP", "Profile file read: " + str(data)) self.setProfileData(data, download_data=False) except Exception as e: log.e("APP", "No profile found") if self.profile_info is None or force_update: self.get_api_data(doAsync, self.tinder_api.get_self, [], {}, finished_callback=self.setProfileData, callback_kwargs={'download_data': True}, update_callback=self.updateBackgroundTaskInfo, info="Getting profile data", tag="ProfileGetter")
def download_instagram_photos(self, instagram_data, base_path, rename, force_overwrite=False, log_to_widget=True, thread_update_signal=None): if 'photos' not in instagram_data.keys(): log.d("API", "NO instagram photos", log_to_widget) return log.d("API", "Downloading instagram photos", log_to_widget) for i in range(len(instagram_data['photos'])): filename, skipped = self.download_file( instagram_data['photos'][i]['image'], base_path + "instagram/", rename, i, "", force_overwrite, log_to_widget) if filename is not None: instagram_data['photos'][i]['local_path'] = str( os.path.abspath(filename))
def setProfileData(self, new_data, download_data=False): log.d("APP", "New profile info, download: " + str(download_data)) if new_data is not None: self.profile_info = new_data if self.profile_info is None: return if self.window is not None and self.window.chat_widget is not None: self.window.chat_widget.setLeftId(self.profile_info["_id"]) if download_data: self.get_api_data(True, self.tinder_api.download_person_data, [ self.profile_info, self.profile_folder, True, True, False, True ], {"force_overwrite": True}, finished_callback=self.updateProfileData, update_callback=self.updateBackgroundTaskInfo, info="Downloading Profile data to: " + str(self.profile_folder), tag="ProfileDownloader")
def addBackgroundTask(self, task, info=""): if task.tag is not None: while task.tag in self.background_tasks_list: string_matches = re.match(r"(.*)([0-9]+)", task.tag) if string_matches is not None: # print("string_matches: " +str(string_matches.groups())) task.tag = string_matches.group(1) + str( int(string_matches.group(2)) + 1) else: task.tag += "_1" self.background_tasks_list.append(task.tag) self.updateBackgroundTaskInfo(info) self.background_count_total += 1 if self.background_count_total <= 1: self.spinner.showSpinner() self.background_count_label.setVisible(True) self.updateBackgroundTaskCount() log.d( "THREADS", "Added new background task " + str(info) + " " + str(self.background_completed) + "/" + str(self.background_count_total) + " Tasks: " + str(self.background_tasks_list), False) self.thread_pool.start(task)
def get_auth_token(self, fb_auth_token, fb_user_id, log_to_widget=True, thread_update_signal=None): log.d("API", "get_auth_token: " + fb_auth_token + "\t" + fb_user_id, log_to_widget) if "error" in fb_auth_token: return {"error": "could not retrieve fb_auth_token"} if "error" in fb_user_id: return {"error": "could not retrieve fb_user_id"} url = self.host + '/v2/auth/login/facebook' req = requests.post(url, headers=self.headers, data=json.dumps({ 'token': fb_auth_token, 'facebook_id': fb_user_id })) try: log.d("API", "Sending JSON request", log_to_widget) json_request = req.json() log.i("API", "Token JSON status: " + str(json_request['meta']['status']), log_to_widget) tinder_auth_token = json_request["data"]["api_token"] self.headers.update({"X-Auth-Token": tinder_auth_token}) self.get_headers.update({"X-Auth-Token": tinder_auth_token}) self.get_message_headers.update( {"X-Auth-Token": tinder_auth_token}) log.s("API", "You have been successfully authorized!") return tinder_auth_token except Exception as e: log.e("API", "Error getting Tinder Token " + str(e), log_to_widget) return { "error": "Something went wrong. Sorry, but we could not authorize you." }
def download_file(self, url, base_path, rename, index, postfix="", force_overwrite=False, log_to_widget=True, thread_update_signal=None): try: file_name = str(index) + postfix + ".jpg" if not rename: file_name = (url.split("/")[-1] + '.jpg').split('?')[0] full_filename = base_path + file_name if not os.path.exists(base_path): os.makedirs(base_path) log.d("API", "File path created: " + base_path, log_to_widget) if not os.path.exists(full_filename) or force_overwrite: self.browser.open(url) with open(full_filename, "wb") as image_file: image_file.write(self.browser.response.content) if force_overwrite: log.d("API", "Forcing Re-Download: " + full_filename, log_to_widget) else: log.i("API", "Downloading: " + full_filename, log_to_widget) return full_filename, False else: log.d( "API", "File already downloaded (force_overwrite=False): " + full_filename, log_to_widget) return full_filename, True except Exception as e: log.e("API", "EXCEPTION!: " + str(e), log_to_widget) return None, False
def setMatches(self, data): log.d("APP", "updateMatches called") self.new_matches = None self.matches = data self.updateMatchesWidgets()
def setRecommendations(self, data): log.d("APP", "setRecommendations called") self.new_recommendations = None self.recommendations = data self.updateRecommendationsWidgets()
def person_data_received(self, data): self.window.json_view.load_data(data["data"]) log.d("PERSON_DATA", +str(data))
def showEvent(self, e): if self.parsed_args.css: log.d("LOGIN_W", "Shown!") # Do something with the event here super(LoginWindow, self).showEvent(e) # Do the default action on the parent class QLineEdit
def focusOutEvent(self, e): if self.parsed_args.css: log.d("LOGIN_W", "Focus Out!") self.app.updateStyle() # Do something with the event here super(LoginWindow, self).focusOutEvent(e) # Do the default action on the parent class QLineEdit
def reload_data_from_disk(self, folder_path, merged_filename, photos, insta, messages, force_overwrite=False, log_to_widget=True, thread_update_signal=None): list = [] try: for subdir, dirs, files in os.walk(folder_path): total_dirs = len(dirs) for i in range(len(dirs)): data_path = os.path.join(subdir, dirs[i]) + "/" data_file_path = data_path + "data.yaml" try: if os.path.exists(data_file_path): with open(data_file_path) as yf: data = yaml.safe_load(yf) person_data, type = self.get_person_data(data) person_data['path'] = os.path.abspath( data_path ) # Updating the data path just in case if photos and 'photos' in person_data: self.download_photos( person_data['photos'], data_path, True, force_overwrite, log_to_widget=log_to_widget) if insta and 'instagram' in person_data and 'photos' in person_data[ 'instagram']: self.download_instagram_photos( person_data['instagram'], data_path, True, force_overwrite, log_to_widget=log_to_widget) if messages and 'match' in type: data['messages'] = self.download_messages( data, log_to_widget) log.d("API", "Updating " + type + " data file", log_to_widget) data['AI_Dating_metadata'] = {} data['AI_Dating_metadata'][ 'last_updated_datetime'] = str( datetime.now().strftime( "%d-%b-%Y %H:%M:%S")) data['AI_Dating_metadata'][ 'last_updated_timestamp'] = str( datetime.utcnow()) self.write_data_to_file( data, data_path, log_to_widget, thread_update_signal) log.d("API", "Updated", log_to_widget) list.append(data) log.i( "API", str(i + 1) + "/" + str(total_dirs) + " - " + str(dirs[i]) + " " + person_data['name'], log_to_widget) else: log.i( "API", str(i + 1) + "/" + str(total_dirs) + " - " + str(dirs[i]) + " SKIPPED", log_to_widget) except Exception as e: log.e("API", "Exception reloading data " + str(e), log_to_widget) if thread_update_signal is not None: thread_update_signal.emit( str(folder_path) + "\t" + str(i + 1) + "/" + str(total_dirs)) break except Exception as e: log.e("API", "Exception in reloading from disk: " + str(e), log_to_widget) try: with open(merged_filename, "w+") as f: json.dump(list, f) except Exception as e: log.e( "API", "Could not save merged file " + merged_filename + ": " + str(e), log_to_widget) return list