def delete(api: Client, target_id: str, target_type: str, parent_id: str = '') -> None: """ Delete a post or comment chosen by the current user Arguments: api (Client) : Object instagram Client target_id (str) : Id of the post or comment to delete target_type (str) : String that can be post or comment parent_id (str) : In the event that a comment is deleted, it stores the id of the post that contains said comment, """ if target_type == 'post': result = api.delete_media(media_id=target_id) else: result = api.delete_comment(media_id=parent_id, comment_id=target_id) if result['status'] == 'ok': print_write_chatbot( f"The {target_type} has been successfully removed!\n", color='green', attrs_color=['bold']) else: print_write_chatbot( f"The {target_type} could not be removed. Please try again later\n", color='red', attrs_color=['bold'])
def connection_instagram_api() -> object: """ The user is asked if he has an instagram account to connect, if he does not have, the Crux account will be used Returns: object (instagram.Client()) - instagram.Client object """ response = input_user_chat("Would you like to connect to Instagram? (yes/no): ") credentials = {} if user_answer_is_yes(response.lower()): username = input_user_chat("Please enter your username: "******"Please enter your password: "******"By not using the instagram tool with your personal page," " we will provide the service with our Instagram account crux.bot", color = 'blue', attrs_color = ['bold']) instagram_api = instagram.connection_instagram(user_credentials = credentials) return instagram_api
def upload_to_albums(facebook_api: facebook.GraphAPI) -> None: """ Uploads a picture from the user to the album the user must select Arguments: facebook_api (object) : facebook api graph """ path = input_user_chat("Please enter the path of your picture: ") if path: albums_id = [] show_albums(facebook_api, albums_id) select = int(input_user_chat("Select the album: ")) - 1 select = validate_number(select, albums_id) caption = input_user_chat("Caption: ") try: facebook_api.put_photo(image = open(path, 'rb'), album_path = albums_id[select - 1] + "/photos", message = caption) print_write_chatbot("The photo has been uploaded successfully!", color = "green", attrs_color = ["bold"]) except Exception as error: write_log(STATUS_FILE, f"There was a problem opening the file, error: {error}", "Exception") print_write_chatbot(f"There was a problem opening the file, error: {error}", color = "red", attrs_color = ["bold"])
def get_new_profile_data(profile_data: dict, attributes: dict, new_profile_data: dict, genders: list) -> None: """ The user is asked for the new values for the personal data of the profile, and the values are stored in the new_profile_data dictionary Arguments: profile_data (dict) : All personal account data attributes (dict) : Stores all available fields that can be changed new_profile_data (dict) : Empty dictionary that will store the new values genders (list) : List of available genres """ for key, attribute in attributes.items(): print_account_warnings(attribute) change_attribute = input_user_chat( f"Do you want to change {key}? yes/no: ") if user_answer_is_yes(change_attribute): new_value = input_user_chat(f"Enter the new value for {key}: ") secure = input_user_chat(f"\nAre you sure to change {key} " f"to '{new_value}'? yes/no: ") if user_answer_is_yes(secure): if attribute == 'is_private': new_value = get_new_account_privacy(new_value) elif attribute == 'gender': new_value = get_new_user_gender(new_value, genders) new_profile_data[attribute] = new_value else: print_write_chatbot(f"No changes have been made to the {key}") else: new_profile_data[attribute] = profile_data[attribute]
def ask_name() -> True: """ Ask the user for his/her name """ name = input_user_chat("What's your name? ", first_time = True) print_write_chatbot(f"Hi {name}!") save_username(name)
def connection_api(user_credentials: dict = {}) -> object: """ If the user does not enter their credentials, those of crux are used. Returns the facebook Api and checks if there was any error while connecting to Facebook Arguments: user_credentials (str): users token Returns: object - (facebook_api) """ facebook_api = '' if not user_credentials: credentials = get_credentials() page_token = credentials['facebook']['token'] else: page_token = user_credentials["token"] try: facebook_api = facebook.GraphAPI(access_token = page_token, version = "2.12") except Exception as err: write_log(STATUS_FILE, str(err), 'Exception') print("Error") else: write_log(STATUS_FILE, 'Successfully connected with Facebook the api', 'GraphAPI') print_write_chatbot('You have successfully connected with the Facebook api!\n', color = 'green', attrs_color = ["bold"]) return facebook_api
def connection_aux_api(username: str, password: str) -> object: """ This connection is made specifically for sending messages Arguments: username (str) : The username of the current instagram account password (str) : The password of the current instagram account Returns: object """ aux_api = '' try: logging.disable(logging.CRITICAL) aux_api = Bot() aux_api.login(username=username, password=password, use_cookie=False) except Exception as error: write_log(STATUS_FILE, str(error), 'Exception') print_write_chatbot(f"There was an error:{error}", color="red", attrs_color=['bold']) write_log(STATUS_FILE, "You have successfully connected with the app", 'instagram.Bot') return aux_api
def message_actions(api: Client, action_type: str = 'send') -> None: """ The last events of each chat of the current user will be shown or a message will be sent to a user chosen by the current user Arguments: api(client): client object of Instagram action_type (str) : Can be send or show """ print_write_chatbot("IMPORTANT!!\n", color='red', attrs_color=['bold', 'blink', 'underline']) print_write_chatbot( "Thanks to Mark Zuckerberg, we can only show the latest events from each chat" ".\nWhether it is a like to a comment, share a profile / reel / publication / a message\n", color='red', attrs_color=['bold', 'underline']) try: if action_type != 'send': last_messages = api.direct_v2_inbox()['inbox'] show_last_messages(last_messages, api.authenticated_user_id) else: send_message(api) except Exception as error: print(f"There was an error:{error}")
def show_last_messages(last_messages: dict, bot_id: str) -> None: """ Print the last events of the chats of the current user Arguments: last_messages (dict) : Dict which contains all the information of the last event for each chat bot_id (str): Id of the current instagram account """ text_show = '' message_number = 1 title = colored('Messages: \n', 'white', attrs=['bold']) text_show += title text_to_bot = 'Messages: \n' chat_messages = last_messages['threads'] if chat_messages: for conversations in last_messages['threads']: user = conversations['users'][0]['full_name'] text_show += colored(f"\t-Nº{message_number} - {user}: \n", 'white', attrs=['bold']) text_to_bot += f"\t-Nº{message_number} - {user}: \n" i_sent = conversations['items'][0]['user_id'] == int(bot_id) its_me = "You sent" if i_sent else "He sent" message = prepare_format_message(conversations, its_me) text_show += message message_number += 1 print_write_chatbot(text_show) else: print_write_chatbot("You don't have any chat\n", color='red', attrs_color=['bold'])
def get_follows(api: Client, show: bool = True, follow_type: str = 'following') -> dict: """ Depending on the follow_type, a dictionary will be obtained that contains the users who follow the current user or those that the current user is following Arguments: api (Client) : Object instagram Client show (bool) : Indicates whether the filtered user names should be printed or not follow_type (str) : Can be following or followed """ rank = api.generate_uuid() user_id = api.authenticated_user_id if follow_type == 'following': results = api.user_following(user_id, rank) prefix = "You are" else: results = api.user_followers(user_id, rank) prefix = "Your" text = f"{prefix} {follow_type}: \n" if show: print_write_chatbot(text, color='blue', attrs_color=['bold', 'underline']) for user in results['users']: print_write_chatbot(f"{user['username']}") return results
def follower_count(facebook_api: facebook.GraphAPI) -> None: """ Prints the count of followers of the page Arguments: facebook_api (object) : facebook api graph """ followers = facebook_api.get_object(id = 'me', fields = 'followers_count') print_write_chatbot(f"Number of followers: {str(followers['followers_count'])}\n")
def connection_instagram(user_credentials: dict = {}) -> object: """ The connection with the instagram api is generated (instagram_private_api module) Arguments: user_credentials (dict) = Dictionary in which the credentials of the user's instagram account are stored (default {}) Returns: object - The Client object """ api = '' if not user_credentials: credentials = get_credentials() username = credentials['instagram']['username'] password = credentials['instagram']['password'] else: username = user_credentials['username'] password = user_credentials['password'] settings_file = os.path.abspath('credentials/instagram_api.json') if os.path.isfile(settings_file): delete_expired_cookie(settings_file) if not os.path.isfile(settings_file): # If the credentials do not exist, do a new login try: api = Client( username, password, on_login=lambda x: on_login_callback(x, settings_file)) except Exception as err: write_log(STATUS_FILE, str(err), "Exception") else: # If the credentials do not exist, do a new login cached_settings = get_cached_settings(settings_file) device_id = cached_settings.get('device_id') try: api = Client(username, password, device_id=device_id, settings=cached_settings) except Exception as e: write_log(STATUS_FILE, str(e), "Exception") print_write_chatbot( "You have successfully connected with the instagram! \n", color='green', attrs_color=['bold']) return api
def like(facebook_api: facebook.GraphAPI, selection: int) -> None: """ Likes the selection and prints the success of the action Arguments: facebook_api (object) : facebook api graph selection (int) : The number of the post the user selected Returns: object - (facebook_api) """ facebook_api.put_like(object_id = selection) print_write_chatbot("The post has been liked successfully!\n", color = 'green', attrs_color = ["bold"])
def delete_post(facebook_api: facebook.GraphAPI, selection: str) -> None: """ Deletes the selected post Arguments: facebook_api (object) : facebook api graph selection (int) : The number of the post the user selected Returns: object - (facebook_api) """ facebook_api.delete_object(id = selection) print_write_chatbot("The post has been successfully removed!\n", color = 'green', attrs_color = ["bold"])
def print_account_warnings(attribute: str) -> None: """ Prints on screen the warnings for certain attributes when changing the profile data Arguments: attribute (str) : The current attribute to change """ if attribute == 'full_name': print_write_chatbot("IMPORTANT!\n", color='red', attrs_color=['bold', 'blink']) print_write_chatbot( "If you have changed the full name 2 times within a period of 14 days, " "you will not be able to modify your full name, just leave it empty," " the program will not be able to change the full name.\n Be aware of your decision\n", color='red', attrs_color=['bold']) elif attribute == 'is_private': print_write_chatbot( "\nTo change your account from private to public or vice versa, enter public or private" ) elif attribute == 'gender': print_write_chatbot( "\nTo change your gender, enter male/female/unspecified")
def print_welcome_message() -> None: """ Prints the welcome message of Crux with effects """ text = "Hello! I am Crux. I am the boss here. Gosh I'm sorry ... " \ "I mean bot! Oh my, I'm damned if they find out" \ " I said that ... \nAh, well, before Elon Musk finds me and sends me to Mars.\n" animation(text) subtitle = colored("There's something I want to tell you.\n", 'blue', attrs = ['bold', 'underline']) animation(subtitle) print_write_chatbot(text + subtitle, print_text = False) welcome_message()
def edit_post(facebook_api: facebook.GraphAPI, selection: int, message: str) -> None: """ Edits the selection and prints the success of the action Arguments: facebook_api (object) : facebook api graph selection (int) : The number of the post the user selected message (str) : New message of post Returns: object - (facebook_api) """ facebook_api.put_object(parent_object = selection, connection_name = '', message = message) print_write_chatbot("Posting has been updated successfully!\n", color = 'green', attrs_color = ["bold"])
def comment(facebook_api: facebook.GraphAPI, selection: int) -> None: """ Ask what would you like to comment, comments your response and prints the success of the action Arguments: facebook_api (object) : facebook api graph selection (int) : The number of the post the user selected Returns: object - (facebook_api) """ text = input_user_chat("What would you like to comment: ").capitalize() facebook_api.put_comment(object_id = selection, message = text) print_write_chatbot("It has been successfully commented!\n", color = 'green', attrs_color = ["bold"])
def edit_profile(api: Client) -> None: """ Available personal data is edited. What are full name, private account, biography, url, email, phone number and gender Arguments: api (Client) - object Client instagram """ # I call _call_api because the original function "current_user" was passing wrong parameters # and the request was not made correctly user_profile = api._call_api('accounts/current_user/', query={'edit': 'true'})['user'] text_to_print = "Your actual profile is: \n" genders = ['male', 'female', 'unspecified'] print_write_chatbot(text_to_print) attributes = { 'Full name': 'full_name', 'Private account': 'is_private', 'Biography': 'biography', 'External url': 'external_url', 'Email': 'email', 'Phone number': 'phone_number', 'Gender': 'gender', } new_profile_data = {} all_data = show_profile_data(user_profile, attributes, genders) text_to_print += all_data get_new_profile_data(user_profile, attributes, new_profile_data, genders) try: status_account = api.set_account_private( ) if new_profile_data['is_private'] else api.set_account_public() result = api.edit_profile( first_name=new_profile_data['full_name'], biography=new_profile_data['biography'], external_url=new_profile_data['external_url'], email=new_profile_data['email'], gender=int(new_profile_data['gender']), phone_number=new_profile_data['phone_number']) if result and status_account['status'] == 'ok': text = "Profile has been modified successfully!" print_write_chatbot(message=text, color='green', attrs_color=['bold']) else: text = "There was a problem updating the profile, please try again\n" print_write_chatbot(message=text, color='red', attrs_color=['bold']) except Exception as error: write_log(STATUS_FILE, str(error), 'Exception') print_write_chatbot(f"There was an error:{error}", color='red', attrs_color=['bold'])
def upload_post(facebook_api: facebook.GraphAPI) -> None: """ Uploads the post written by the user and prints the success of the action if there are no errors Arguments: facebook_api (object) : facebook api graph """ user_message = input_user_chat("What would you like to write?: ") try: facebook_api.put_object(parent_object = 'me', connection_name = 'feed', message = user_message) print_write_chatbot("Posting has been updated successfully!\n", color = 'green', attrs_color = ["bold"]) except Exception as err: write_log(STATUS_FILE, str(err), 'Exception') print_write_chatbot(f"Error to upload a post {err}", color = "red", attrs_color = ['bold'])
def show_albums(facebook_api: facebook.GraphAPI, albums_id: list) -> None: """ Prints a list of albums of the user Arguments: facebook_api (facebook.GraphAPI) albums_id (list): Contains the albums of the user """ albums = facebook_api.get_connections(id = 'me', connection_name = 'albums') info_list = albums['data'] print_write_chatbot("Your albums are: ") for count, info in enumerate(info_list, 1): print(count, info["name"]) albums_id.append(info["id"])
def upload_photo(facebook_api: facebook.GraphAPI) -> None: """ Asks the user the path of the photo and the caption the user wants to upload, and uploads the photo and the caption Arguments: facebook_api (object) : facebook api graphThe facebook api """ path = search_file() caption = input_user_chat("Caption: ") try: facebook_api.put_photo(image = open(path, 'rb'), message = caption) print_write_chatbot("The photo has been uploaded successfully!", color = 'green', attrs_color = ["bold"]) except Exception as error: write_log(STATUS_FILE, f"There was a problem uploading the file, error: {error}", 'Exception') print_write_chatbot(f"There was a problem uploading the file, error: {error}", color = "red", attrs_color = ["bold"])
def search_file() -> str: """ A file is searched and validated based on an absolute path Returns: str - Absoulte path of file """ found_file = False path = '' while not found_file: path = os.path.abspath(input_user_chat("Enter the file path, the file must be .jpg: ")) if os.path.exists(path): found_file = True else: print_write_chatbot(f"The path doesnt exists, please enter a correct path \n", color = "red", attrs_color = ["bold"]) return path
def validate_number_post(post_number: int, max_number: int) -> int: """ Validates if the position of the post entered by the user is in a range of 0 and the number of posts - 1 Arguments: post_number (int) : Post number max_number (int) : The number of posts - 1 Returns: int - The position of the post """ while post_number < 0 or post_number >= max_number: print_write_chatbot(message="Number post incorrect", color='red', attrs_color=['bold']) post_number = int(input_user_chat("Enter a valid posting number: ")) return post_number
def validate_comment_number(comments, comment_number) -> int: """ Validates if the position of the comment entered by the user is in dict with all comments Arguments: comments (dict) : Dict with all comments comment_number (int) : Position of the comment Returns: int - The position of the comment """ while not comments['comments'][comment_number]: print_write_chatbot( message= "The comment doesnt exist, please enter a correct comment number", color='red', attrs_color=['bold']) comment_number = int(input_user_chat("Number comment: ")) return comment_number
def connection_facebook_api() -> object: """ The user is asked if he has an facebook page to connect, if he does not have, the Crux account will be used Returns: object (facebook.GraphAPI()) - facebook.GraphAPI object """ response = input_user_chat("Would you like to connect to Facebook? (yes/no): ") credentials = {} if user_answer_is_yes(response.lower()): page_token = input_user_chat("Please enter your page access token: ") credentials = {'token': page_token} else: print_write_chatbot("By not using the facebook tool with your personal page, " "we will provide the service with our" "Facebook page Crux.cruz", color = 'blue', attrs_color = ['bold']) facebook_api = facebook.connection_api(user_credentials = credentials) return facebook_api
def if_text_in_info(info: dict, posts_id: list, count: int): """ Prints the number, the created time and the contend of the post, and appends its id in the post_id list Arguments: info (dict) : Data of the posts in the graph posts_id (list) : List of the posts of the page count (int) : The number of the post """ if "message" in info: text_description = f": {info['message']}" elif "story" in info: text_description = f": {info['story']}" else: text_description = '' print_write_chatbot(f"{count}, {info['created_time'][0:10]} {text_description}") posts_id.append(info["id"])
def unlike_post(api: Client, post_id: str) -> None: """ Put a unlike in a post chosen by the user Arguments: api (Client) : Object instagram Client post_id (str) : Id of the post """ result = api.delete_like(post_id) if result['status'] == 'ok': print_write_chatbot(f"The post is unliked correctly!\n", color='green', attrs_color=['bold']) else: print_write_chatbot( f"There was a problem disliking the post, please try again later!\n", color='red', attrs_color=['bold'])
def show_profile_data(profile: dict, attributes: dict, genders: list) -> str: """ The personal data values that are available for editing are printed on the screen. Arguments: profile (dict) : The profile data attributes (dict) : Dict which contains all available attributes for edit genders (list) : List of the available genders Returns: str - Formatted string with the profile data """ presentation_profile_data = '' for key, attribute in attributes.items(): if attribute == 'gender': presentation_profile_data += f'{key} : {genders[int(profile[attribute]) - 1]}\n' else: presentation_profile_data += f'{key} : {profile[attribute]}\n' print_write_chatbot(presentation_profile_data) return presentation_profile_data
def like_post(api: Client, post_id: str, own_feed: bool = False) -> None: """ Put a like in a post chosen by the user Arguments: api (Client) : object instagram Client post_id (str) : Id of the post own_feed (bool) : If it's the current user's feed """ if not already_liked(api, post_id, own_feed=own_feed): result = api.post_like(media_id=post_id) if result['status'] == 'ok': text = "The post has been liked correctly!\n" print_write_chatbot(text, color='green', attrs_color=['bold']) else: print_write_chatbot( f"There was a problem liking the post, try again later!\n", color='red', attrs_color=['bold', 'underline']) else: if want_unlike_target('post'): unlike_post(api, post_id) else: print_write_chatbot("The like has been left as it was\n")