def upload_option(profile: NaClProfile): """ The interface to upload profile to server, working with ds_client module's send(). :param profile: current working profile object :return: None """ option = input( "Do you want to also upload it to the server? (y/n)\n").upper() server = profile.dsuserver username = profile.username password = profile.password message = profile.get_posts() bio = profile.bio # decrypt the bio from the local DSU file / current profile bio = profile.nacl_profile_decrypt(bio) if option == 'Y': print("Send post (p)") print("Update bio (b)") print("Send post and update bio (pb)") option = input() client.send(profile, option, server, PORT, username, password, message, bio) elif option == 'N': print_ok("Done.") else: print_warning('please enter either y or n\n') upload_option(profile)
def create_profile(path: str): """ :param path: :return: """ assert type(path) is str, 'path needs to be str' # get the users data dsuserver = input( 'DSU server (type it directly without quotation marks): ') username = input('username: '******'password: '******'post (optional, skip by pressing enter): ') post.set_entry(entry) bio = input('bio (optional, skip by pressing enter): ') # create the profile and pass data in profile = NaClProfile(dsuserver, username, password) profile.generate_keypair() profile.bio = bio # encrypt the bio profile.bio = profile.encrypt_entry(profile.bio) profile.add_post(post) profile = posts_transclude(profile) display_profile(profile) profile.save_profile(path) print('DSU file storing...') print_ok("Local file stored at: " + str(path)) # ask if the user wants to upload upload_option(profile)
def command_D(commands): """ Functionalities within command D, allow the user to delete a DSU file. :param commands: the input command :return: None """ if len(commands) < 2: print_warning('There needs to be at least 1 input for COMMAND D') else: path = Path(commands[1]) if not str(path).endswith('.dsu'): print_warning('It needs to be a DSU file with .dsu suffix') else: try: path.unlink() print_ok(str(path) + ' DELETED') except FileNotFoundError: print_warning("File not found!")
def posts_transclude(profile: NaClProfile): """ Transclude every single post in the posts list of a profile object. Use it before saving the DSU file in order to change the posts list of the profile object before uploading or saving to local. :param profile: current working Profile object :return: modified Profile object """ # posts here is not the actual _posts private list from the NaClProfile object # they are the decrypted copy of the _posts posts = profile.get_posts() print('Transcluding...') for i in range(len(posts)): if '@weather' in posts[i]['entry']: a = OpenWeather.OpenWeather('92697', 'US') entry = a.transclude(posts[i].get_entry()) # entry = profile.encrypt_entry(entry) posts[i].set_entry(entry) if '@lastfm' in posts[i]['entry']: a = LastFM.LastFM('United States') entry = a.transclude(posts[i].get_entry()) # entry = profile.encrypt_entry(entry) posts[i].set_entry(entry) if '@extracredit' in posts[i]['entry']: a = ExtraCreditAPI.Joke() entry = a.transclude(posts[i].get_entry()) # entry = profile.encrypt_entry(entry) posts[i].set_entry(entry) # empty the actual _posts private list from the NaClProfile object profile._posts = [] # move each post in the posts temporary holder back to the actual _posts for post in posts: profile.add_post(post) print_ok('Transcluded!') return profile
def send(np: NaClProfile, send_type, server: str, port: int, username: str, password: str, message: list, bio: str = None): ''' The send function joins a ds server and sends a message, bio, or both :param np: it is the NaClProfile object passed in from the main program :param send_type: the sending type of this send (post / bio / post and bio) :param server: The ip address for the ICS_32 DS server. :param port: The port where the ICS_32 DS server is accepting connections. :param username: The user name to be assigned to the message. :param password: The password associated with the username. :param message: The list of posts to be sent to the server. :param bio: Optional, a bio for the user. ''' global token sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: sock.connect((str(server), port)) except socket.gaierror: print_warning('The address or port seems incorrect') else: done = "Upload done." send_types = ['p', 'b', 'pb'] # make sure the send type is a valid one if send_type in send_types: # join the server join(sock, username, password, np.public_key) # if connected successfully, the token will be given a value # otherwise it's an empty string. if token != '': if send_type == 'p': post(sock, message, np) print_ok(done) elif send_type == 'b': _bio(sock, bio, np) print_ok(done) elif send_type == 'pb': post(sock, message, np) _bio(sock, bio, np) print_ok(done) else: print_error("Please provide a valid send type.\n" "Upload failed.")
def helper(): print( "\nThis color represents an input prompt or normal system information." ) print_ok("This color represents successful or approved operations.") print_warning( "This color represents user's illegal inputs or unexpected operations." ) print_error("This color represents systematic error or test mode message " "that should be handled by developers.\n") print("""Usage format: [COMMAND] [INPUT] [[-]OPTION] [INPUT] Some tips: If you want to CREATE a file, go to COMMAND: C If you want to MODIFY a file, go to COMMAND: M If you want to UPLOAD a file, go to COMMAND: R COMMAND: L - List the contents of the user specified directory. OPTIONs: -r Output directory content recursively. -f Output only files, excluding directories in the results. -s Output only files that match a given file name. -e Output only files that match a give file extension. Example usage: L c:\\users\\mark\\a1 L c:\\users\\mark\\a1 -r L c:\\users\\mark\\a1 -f L c:\\users\\mark\\a1 -r -s readme.txt L c:\\users\\mark\\a1 -s readme.txt L c:\\users\\mark\\a1 -r -e jpg COMMAND: Q - Quit the program. Example usage: Simply press Q. COMMAND: C - Create a new file in the specified directory. And you need to enter DSU server, username, and password by the following prompt. After the creation of DSU file and profile, the program will ask you if you want to upload things to the DSU server. OPTIONs: -n Specify the name to be used for a new file. Example usage: C c:\\users\\mark\\a1 -n mark COMMAND: M - Modify a saved DSU file and the profile relates to it. After the command is typed in, the system will load up a DSU file to a Profile object to modify the data. It will prompt you how to modify and save the data. Example usage: M (just put in 'M' and wait for the prompt) COMMAND: D - Delete the file. Example usage: D c:\\users\\mark\\a1\\mark.dsu COMMAND: R - Read the contents of a file and upload it to the server. OPTIONs: -l load the specified file from the path, If you want to upload a file directly, use this. After the loading of DSU file and profile, the program will ask you if you want to upload things to the DSU server. Example usage: R c:\\users\\mark\\a1\\mark.dsu R c:\\users\\mark\\a1\\mark.dsu -l API Supports: When you are writing posts, you have some API add-ins support available for better writing! All the keywords will be transcluded before the DSU file is saved. You will see "Transcluding..." when the file is being transcluded. OpenWeather API: You can simply add '@weather' in your post at anywhere, and the '@weather' script will translate to the current weather in Irvine. Supports for your current location will be added later. LastFM API: You can simply add '@lastfm' in your post at anywhere, and the '@lastfm' script will translate to the United Stats' top hit song on LastFM in current time period. Supports for other countries will be added later. Joke API: You can simply add '@extracredit' in your post at anywhere, and the '@extracredit' script will translate to a random joke. !CAUTION!: this api may not be accessible in some regions since the IP address of the api's server is blocked in some area, if you encounter a trancluding problem or connection issue, please connect to UCI's VPN when you are using this feature. """)
def modify_profile(): """ Load up the profile DSU file for modification. :return: None """ path = input('Input the DSU file\'s path which you want to modify.\n' 'For example: C:\\Users\\ThinkPad\\Desktop\\test\\mark.dsu\n') profile = NaClProfile() try: profile.load_profile(path) except DsuFileError: print_warning('This might not be a valid path.') else: prompt = """\nWhich part you want to modify? server (se) username (u) password (pwd) bio (b) posts (p) save modification(s)""" print_ok(path + " is ready for modification.\n") # keep prompting the user to choose an option for modification while True: display_profile(profile) print(prompt) option = input().lower() if option == "u": mod = input("Enter the new username: \n") profile.username = mod elif option == "se": mod = input("Enter the new server address: \n") profile.dsuserver = mod elif option == "pwd": mod = input("Enter the new password: \n") profile.password = mod elif option == "b": mod = input("Enter the new bio: \n") profile.bio = profile.nacl_profile_encrypt(mod) elif option == "p": # get users option option = input("Add (a) or delete (d) a post?\n").lower() if option == "a": entry = input("Write your entry below:\n") post = Profile.Post() post.set_entry(entry) profile.add_post(post) print_ok("Entry added.") elif option == 'd': entry = int(input("Which entry you want to delete?\n")) profile.del_post(entry) print_ok('Entry deleted.') else: print_warning("Please enter either a or d.") elif option == "s": profile = posts_transclude(profile) profile.save_profile(path) display_profile(profile) print_ok("All saved.") break else: print_warning("Please enter a valid option. Or " "input 's' to save (quit).")
def response(sock: socket) -> DataTuple: """ Respond to the user about detailed message retrieved from the server response JSON Sample server JSON response: {"response": {"type": "ok", "message": "Welcome back, ffyuanda", "token": "551db8b5-7adb-4f9c-b610-a8aecd5793b0"}} {"response": {"type": "error", "message": "Post rejected: invalid timestamp"}} :param sock: current connecting socket :return: a DataTuple that contains the info from the server response JSON. """ recv = sock.makefile('r') resp = recv.readline() # resolve the conflict of two modules importing each other from ds_client import test_mode if test_mode: print_error('[Test mode]resp\'s value: ' + resp) # DataTuple conversion resp = extract_json(resp) if resp.type == 'ok': if resp.message.startswith('Welcome back'): print_ok("Successfully logged in.") print_ok('Server says: {}\n'.format(resp.message)) elif resp.message.startswith('Welcome to'): print_ok("Successfully registered in.") print_ok('Server says: {}\n'.format(resp.message)) elif 'Bio' in resp.message: print_ok("Bio successfully updated.") print_ok('Server says: {}\n'.format(resp.message)) elif 'Post' in resp.message: print_ok("Post successfully sent.") print_ok('Server says: {}\n'.format(resp.message)) elif resp.type == 'error': print_error("An error occurs.") print_error('Error message: {}\n'.format(resp.message)) return resp