def unfollow(): """ This function is used to unfollow other user. This function will delete 100 latest post from the other user and won't show post from the user in the future input: user ID to be unfollowed return: unfollow user ID and delete 100 latest posts from timeline """ if not g.user: flash('You are not signed in') return redirect(url_for('index', error='Unfollow Error')) error = None if request.method == 'POST': if 'unfollowUserID' not in request.form: error = 'Invalid account' flash(error) elif request.form['unfollowUserID'] not in r_server.lrange( 'following:%s' % escape(session['user_id']), 0, 100 ): error = "You are not following this person" flash(error) if not error: if r_server.lrem( 'following:%s' % escape( session['user_id'] ), int(request.form['unfollowUserID']), 0 ) and r_server.lrem( 'followed:%s' % request.form['unfollowUserID'], int(session['user_id']), 0 ): for post in r_server.lrange( 'posts:%s' % request.form['unfollowUserID'], 0, 100 ): r_server.zrem( "timeline:%s" % escape( session['user_id'] ), post ) flash('successfully unfollow the account') return redirect( url_for( 'index', userID=request.form['unfollowUserID'] ) ) else: error = "Failed to unfollow" flash(error) else: error = "Please choose who you want to unfollow" flash(error) return redirect(url_for('index', error="Unfollow Error"))
def follow(): """ This function allow user to follow other users and have that other user's post appear in the timeline This has limitation of only taking the 100 latest post of the followed user at first time it follow input: userID to be followed return: timeline of other user is added to the logged in user and post from other user will also appear in the future """ if not g.user: flash('You are not signed in') return redirect(url_for('index', error='Follow Error')) error = None if request.method == 'POST': if 'followUserID' not in request.form: error = 'Invalid account' flash(error) elif request.form['followUserID'] in r_server.lrange( 'following:%s' % escape(session['user_id']), 0, 100 ): error = "You already follow this person" flash(error) if not error: if r_server.lpush( 'following:%s' % escape( session['user_id'] ), int(request.form['followUserID']) ) and r_server.lpush( 'followed:%s' % request.form['followUserID'], int(session['user_id']) ): for post in r_server.lrange( 'posts:%s' % request.form['followUserID'], 0, 100 ): r_server.zadd( "timeline:%s" % escape( session['user_id'] ), int(post), post ) flash('successfully follow the account') return redirect( url_for( 'index', userID=request.form['followUserID'] ) ) else: error = "Failed to follow" flash(error) else: error = "Unable to follow" flash(error) return redirect(url_for('index', error='Follow Error'))
def deletePost(): """ This function can be used to delete user's post, but user must have be the one who posted it input: post_ID return: success: delete post from the database failure: user doesn't have authority to delete the post """ if not g.user: flash('You are not signed in') return redirect(url_for('index', error='Deletion Error')) error = None if request.method == 'POST': if 'inputPostID' not in request.form: error = "ID is unavailable" flash(error) elif request.form['inputPostID'] in r_server.lrange( 'posts:%s' % escape(session['user_id']), 0, 1000): postID = request.form["inputPostID"] if r_server.hget('post:%s' % postID, 'fileType'): k = Key(bucket) k.key = S3_KEY_PREFIX+'post/'+postID k.key += '.'+r_server.hget('post:%s' % postID, 'fileType') bucket.delete_key(k) if r_server.lrem( 'posts:%s' % escape(session['user_id']), int(postID), 0 ) and r_server.delete( 'post:%s' % postID ) and r_server.zrem( 'timeline:%s' % escape(session['user_id']), postID ) and r_server.zrem('timeline:', postID): for follower in r_server.lrange( 'followed:%s' % escape(session['user_id']), 0, 1000): r_server.zrem("timeline:%s" % follower, postID) flash('deletion successfull') return redirect(url_for('index')) else: flash('deletion failed') return redirect(url_for('index', error='delete error')) else: error = "you are not allowed to delete the post" flash(error) else: error = "you are not allowed to delete the post" flash(error) return redirect(url_for('index', error='Deletion Error'))
def editPost(): """ This function can be used to edit the user's post, but user has to be the one who posted it input: editPostID return: success: post is updated and saved in the database failure: post cannot be edited because the user has no authority """ if not g.user: error = 'You are not signed in' flash(error) return redirect(url_for('index', error='Edit Error')) error = None if request.method == 'POST': if 'editPostID' not in request.form: error = "ID is unavailable" flash(error) if 'inputEditPost' not in request.form: error = "You should put some thoughts" flash(error) if 'editImg' in request.files: filen = request.files['editImg'] else: filen = None if filen and not allowed_file(filen.filename): error = "Picture format is wrong" flash(error) if not error and request.form['editPostID'] in r_server.lrange( 'posts:%s' % escape(session['user_id']), 0, 1000): postID = request.form["editPostID"] r_server.hset('post:%s' % postID, 'content', request.form['inputEditPost'].encode('utf8')) if filen: k = Key(bucket) k.key = S3_KEY_PREFIX+'post/'+postID k.key += '.'+filen.filename.rsplit('.', 1)[1] k.set_contents_from_file(filen) k.make_public() flash("edit successfull") return redirect(url_for('index')) else: error = "you are not allowed to edit the post" flash(error) else: error = "you are not allowed to edit the post" flash(error) return redirect(url_for('index', error='Edit Error'))
def index(userID=None): """ This is main function and page of the web application input: without userID parameter, user will see his/her own timeline [userID] of a user to see a user's timeline return: user_id not in session will return user to index.html user_id in session will redirect user to timeline.html """ error = None if not error and 'error' in request.args: error = request.args['error'] if g.user: others = False followed = False if 'pagination' in request.args and int( request.args['pagination']) > 0: pagination = int(request.args['pagination']) else: pagination = 1 if not userID or userID == session['user_id']: userID = session['user_id'] else: if userID in r_server.lrange('following:%s' % escape( session['user_id']), 0, 1000): followed = True others = True # upper and lower postID of post shown minimum = (pagination-1)*numitem maximum = pagination*numitem-1 # list of shown postID posts = r_server.zrange('timeline:%s' % userID, minimum, maximum, True) # get total length of existing post from user plen = int(math.ceil(int(r_server.zcard( 'timeline:%s' % userID))/float(numitem))) # get the current accessed user Data userData = r_server.hgetall('user:%s' % userID) # posts to show in timeline postData = {} # profile of the user who post userPost = {} # number of follower from current user follower = r_server.llen( 'followed:%s' % escape(session['user_id'])) # number of following from current user following = r_server.llen( 'following:%s' % escape(session['user_id'])) # number of follower from userID followerO = r_server.llen('followed:%s' % userID) # number of following from userID followingO = r_server.llen('following:%s' % userID) for post in posts: postData[post] = r_server.hgetall('post:%s' % post) userPost[post] = r_server.hgetall('user:%s' % postData[post].get('userID')) return render_template('timeline.html', plen=plen, pagination=pagination, followed=followed, userData=userData, posts=posts, postData=postData, userPost=userPost, others=others, follower=follower, following=following, followerO=followerO, userID=userID, followingO=followingO, error=error) else: posts = r_server.zrange('timeline:', 0, 100, True) postData = {} userPost = {} for post in posts: postData[post] = r_server.hgetall('post:%s' % post) userPost[post] = r_server.hgetall('user:%s' % postData[post].get('userID')) return render_template('index.html', CLIENT_ID=CLIENT_ID, posts=posts, postData=postData, userPost=userPost, error=error)
def share(): """"This function will create new post in the user timeline and user's follower timeline if successfull, user can also attach the picture inside the post input: user's post content and image file return: success: add new post to user and user's follower timeline failure: return to timeline page and show error """ if not g.user: error = 'You are not signed in' flash(error) return redirect(url_for('index', error='Share Error')) error = None filen = None if request.method == 'POST': if 'inputPost' not in request.form: error = 'Please write your thoughts first' flash(error) elif len(request.form['inputPost']) > 300: error = 'Your thought is too long' flash(error) try: if 'uploadImg' in request.files: filen = request.files['uploadImg'] if filen and not allowed_file(filen.filename): error = 'Please upload correct file' flash(error) except IOError: error = 'File cannot be found' flash(error) if not error: r_server.incr('next_postID') postID = r_server.get('next_postID') if r_server.hmset( "post:%s" % postID, { 'content': request.form['inputPost'].encode('utf8'), 'userID': session['user_id'], 'datetime': datetime.now(timezone('UTC')).strftime( "%Y-%m-%dT%H:%M:%S") } ) and r_server.lpush( 'posts:%s' % escape(session['user_id']), postID ) and r_server.zadd( 'timeline:%s' % escape( session['user_id'] ), postID, postID ) and r_server.zadd( 'timeline:', postID, postID ): for follower in r_server.lrange( 'followed:%s' % escape( session['user_id']), 0, 1000): r_server.zadd( "timeline:%s" % follower, postID, postID ) try: if filen: fileType = filen.filename.rsplit('.', 1)[1] k = Key(bucket) k.key = S3_KEY_PREFIX+'post/'+postID k.key += '.'+fileType k.set_contents_from_file(filen) k.make_public() r_server.hset("post:%s" % postID, "imageURL", k.generate_url(0).split('?', 1)[0]) r_server.hset("post:%s" % postID, "fileType", fileType) except IOError: error = 'File cannot be found' flash(error) r_server.decr('next_postID') return redirect(url_for('index', error='Upload File Error')) else: r_server.decr('next_postID') return redirect(url_for('index')) else: error = "Your thought failed to be posted" flash(error) else: error = "your thought is abstract" flash(error) return redirect(url_for('index', error='Share Error'))