def getNewID(curr): ''' Get an appropriate user id and return it. input: curr -- sqlite3.Cursor ''' valid = False uid = None while not valid: if not uid: uid = input("Enter your id: ") if uid.isalnum(): if isUidUnique(curr, uid): if len(uid) > 4: prompt = bcolor.warning("Warning: maximum id length is 4. Use '{}' instead? [y/n] ".format(uid[:4])) uin = getValidInput(prompt, ['y', 'n']) uid = uid[:4] if uin == 'y' else None else: valid = True else: print(bcolor.errmsg("error: user id already taken.")) uid = None else: print(bcolor.errmsg("error: password cannot contain any special characters.")) uid = None return uid
def signIn(curr): ''' Prompts the user to enter their user ID and password. Checks if they exist in the database. If not, it returns the user ID. Inputs: curr -- sqlite3.Cursor Returns: str ''' validInfo = False while not validInfo: uid = input('\nEnter your user ID: ') pwd = getpass.getpass('Enter your password: '******'SELECT * FROM users WHERE uid = :userID COLLATE NOCASE AND pwd = :password;', {'userID': uid, 'password': pwd}) userRow = curr.fetchone() if userRow: validInfo = True print(bcolor.green('You have successfully signed in.')) return userRow['uid'] else: print(bcolor.errmsg('error: invalid user ID or password.')) prompt = bcolor.warning('Do you still want to sign in? [y/n] ') uin = getValidInput(prompt, ['y','n']) if uin == 'n': return None
def castVote(conn, curr, pid, uid): ''' Prompt the user to cast a vote to the selected post. Inputs: conn -- sqlite3.Connection curr -- sqllite3.Connection pid -- selected post (str) uid -- uid of the current user (str) ''' print('\n' + bcolor.pink('< Vote on the Post >')) prompt = 'Do you want to vote on this post? [y/n] ' confirm = page.getValidInput(prompt, ['y', 'n']) if confirm == 'y': # checks if the user has already voted for the selected post curr.execute('SELECT * FROM votes WHERE pid = ? and uid = ?;', [pid, uid]) if curr.fetchone(): print( bcolor.errmsg( "action failed: you've already voted for this post.")) else: vdate = str(date.today()) vno = getVno(curr) curr.execute('INSERT INTO votes VALUES (?, ?, ?, ?);', [pid, vno, vdate, uid]) conn.commit() print() print(bcolor.green('Voting Completed!'))
def giveBadge(conn, curr, uid): ''' Gives a badge to the poster of the selected post. Inputs: conn -- sqlite3.Connection curr -- sqlite3.Cursor uid -- poster of the selected post (str) ''' bdate = str(date.today()) if not badgeAvailable(curr): print(bcolor.errmsg("action failed: badge is not available now.")) elif isBadgeGivenTdy(curr, uid, bdate): print(bcolor.errmsg("action failed: this poster has already received a badge today.")) else: print(bcolor.pink('\n< Give a Badge >')) displayAvailBadges(curr) valid = False while not valid: bname = getBadge() badgeRow = getBadgeRow(curr, bname) if badgeRow: # badge already exists prompt = 'Do you want to give badge: "{}" to the poster? [y/n] '.format(badgeRow['bname']) uin = page.getValidInput(prompt, ['y','n']) if uin == 'y': curr.execute('INSERT INTO ubadges VALUES (?, ?, ?);',(uid, bdate, badgeRow['bname'])) conn.commit() print(bcolor.green('\nBadge Awarded to the poster!')) valid = True else: print(bcolor.errmsg('action failed: badge: "{}" is not available.'.format(bname))) if not valid: prompt = 'Do you still want to give a badge? [y/n] ' valid = not page.continueAction(prompt)
def getDBFrom(argv): ''' Return the db file name from sys.argv. Assumes the db file exists in the same file. ''' if len(argv) != 2: print(bcolor.errmsg("Usage: python3 main.py [file]")) sys.exit(1) return argv[1]
def getNewPassword(): ''' Get a new password from the user. Passwords are case-sensitive and can only contain alphanumeric characters. Return: pwd -- str ''' valid = False while not valid: pwd = getpass.getpass("Enter your password: "******"Enter the password again: ") if pwd == pwd2: valid = True else: print(bcolor.errmsg("error: passwords do not match.")) else: print(bcolor.errmsg("error: password cannot contain any special characters.")) return pwd
def getValidInput(prompt, validEntries): ''' Prompt the user with the provided prompt. If the user input is not in validEntries, print error. inputs: prompt -- str validEntries -- list ''' while True: i = input(prompt).lower() if i in validEntries: return i print(bcolor.errmsg("error: invalid entry\n"))
def getBadge(): ''' Prompt the user for a badge name. Return: bname -- str ''' validBadge = False while not validBadge: bname = input('\nEnter a badge name to give from the list above: ').strip() if bname != '': validBadge = True else: print(bcolor.errmsg('error: badge name cannot be empty.')) return bname
def addTag(conn, curr, pid): ''' Add tags to the selected post. Inputs: conn -- sqlite3.Connection curr -- sqllite3.Cursor pid -- pid of the selected post (str) ''' print(bcolor.pink('\n< Add Tags >')) currentTags = getCurrentTag(curr, pid) displayCurrentTag(currentTags) valid = False while not valid: newTags = getValidTag() numNewTags = len(newTags) duplicates, nonDuplicates = getDuplicateTag(currentTags, newTags) numDups = len(duplicates) dsuffix = genSuffix(duplicates) tagsToAdd = True if numDups > 0: print(bcolor.errmsg('error: post already has the following tag{}: {}'.format(dsuffix, ', '.join(duplicates)))) if numNewTags == numDups: # user enters duplicates only tagsToAdd = False prompt = 'Do you want to add another tag to the post? [y/n] ' valid = not page.continueAction(prompt) else: newTags = nonDuplicates nsuffix = genSuffix(newTags) if tagsToAdd: prompt = 'Do you want to add: "{}" ? [y/n] '.format('", "'.join(newTags)) uin = page.getValidInput(prompt, ['y','n']) if uin == 'y': valid = True insertTag(conn, curr, pid, newTags) print(bcolor.green("\nTag{} Added!".format(nsuffix))) else: prompt = 'Do you still want to add tags to the post? [y/n] ' valid = not page.continueAction(prompt)
def getValidTag(): ''' Prompt the user for tags and return them. Return: newTags -- list ''' validTag = False while not validTag: tags = input('\nEnter tags to add, each separated by a comma: ') newTags = [] for x in tags.split(','): x = x.strip() if x and x not in newTags: newTags.append(x) if len(newTags) > 0: validTag = True else: print(bcolor.errmsg('error: tag name cannot be empty')) return newTags
def mainMenu(conn, curr, uid): ''' The main loop of the main menu available after successful sign in. Inputs: conn -- sqlite3.Connection curr -- sqlite3.Cursor uid -- uid of signed in user ''' isPriv = isPrivileged(curr, uid) valid = False while not valid: name = getName(curr, uid) printMainPage(name, isPriv) option = getValidInput('Enter a command: ', ['pq', 'sp', 'so', 'q']) if option == 'pq': action.postQ(conn, curr, uid) elif option == 'sp': targetPost, act = action.searchPosts(curr, isPriv) if len(targetPost) > 0 and act != '': executeAction(conn, curr, act, uid, targetPost['pid'], targetPost['poster']) else: print(bcolor.errmsg('No posts found.')) elif option == 'so': if checkSignout(): print('...') print(bcolor.green('You have been signed out.')) valid = True elif option == 'q': print('...') print(bcolor.green('You have been signed out.')) sys.exit(0)
def getKeywords(): ''' Prompt the user for search keywords and return them. return: keywords -- dict ''' os.system('clear') print(bcolor.pink('< Search Posts >')) prompt = "Enter keywords to search, each separated by a comma: " valid = False while not valid: keywords = input(prompt).lower().split(',') keywords = filter(lambda kw: len(kw.strip()) > 0, keywords) keywords = list(map(lambda kw: '%' + kw.strip() + '%', keywords)) keywords = {'kw{}'.format(i): kw for i, kw in enumerate(keywords)} if len(keywords) > 0: valid = True else: print(bcolor.errmsg('error: search keywords cannot be empty')) return keywords