mongo = Mongo(env.get("RELAY_MONGO_URI", "mongodb://localhost:27017"))
db = mongo.db(env.get("RELAY_MONGO_DATABASE", "twitter_clone"))
users = db.collection("twitter_clone_users")
posts = db.collection("twitter_clone_posts")
follows = db.collection("twitter_clone_follows")
counters = db.collection("twitter_clone_counters")
fn count_items(items)
total = 0
for (item in items)
total += 1
return total
fn text_or_empty(value)
if (value == None)
return ""
return str(value)
fn number_or_zero(value)
if (value == None)
return 0
try
return int(str(value))
except
return 0
fn api_error(status, message)
return Response(
message,
status=status,
content_type="text/plain; charset=utf-8"
)
fn request_input(name)
form = request["form"]
if (form != None)
value = form[name]
if (value != None)
return value
query = request["query"]
if (query != None)
value = query[name]
if (value != None)
return value
json_data = request["json"]
if (json_data != None)
value = json_data[name]
if (value != None)
return value
return None
fn username_key(username)
return "user:" + username
fn follow_key(follower_username, following_username)
return "follow:" + follower_username + ":" + following_username
fn counter_key(name)
return "counter:" + name
fn post_key(seq)
return "post:" + str(seq)
fn find_user(username)
return users.find_one({"_id": username_key(username)})
fn current_user_doc()
username = session["username"]
if (username == None)
return None
user = find_user(str(username))
if (user == None)
session["username"] = None
return None
return user
fn active_viewer_username()
viewer = current_user_doc()
if (viewer == None)
return None
return str(viewer["username"])
fn next_sequence(name)
doc = counters.find_one_and_update({"_id": counter_key(name)}, {"$inc": {"value": 1}}, upsert=True)
return int(doc["value"])
fn is_username_char(ch)
return (
ch == "_" ||
ch == "a" || ch == "b" || ch == "c" || ch == "d" || ch == "e" || ch == "f" ||
ch == "g" || ch == "h" || ch == "i" || ch == "j" || ch == "k" || ch == "l" ||
ch == "m" || ch == "n" || ch == "o" || ch == "p" || ch == "q" || ch == "r" ||
ch == "s" || ch == "t" || ch == "u" || ch == "v" || ch == "w" || ch == "x" ||
ch == "y" || ch == "z" ||
ch == "0" || ch == "1" || ch == "2" || ch == "3" || ch == "4" ||
ch == "5" || ch == "6" || ch == "7" || ch == "8" || ch == "9"
)
fn is_valid_username(username)
size = count_items(username)
if (size < 3 || size > 20)
return False
for (ch in username)
if (is_username_char(ch) == False)
return False
return True
fn is_valid_password(password)
size = count_items(password)
return (size >= 6 && size <= 72)
fn is_valid_bio(bio)
return count_items(bio) <= 160
fn is_valid_post_body(body)
size = count_items(body)
return (size >= 1 && size <= 280)
fn user_brief_from_doc(user_doc)
return {
"username": text_or_empty(user_doc["username"]),
"bio": text_or_empty(user_doc["bio"])
}
fn public_user_from_doc(user_doc, viewer_username = None)
username = text_or_empty(user_doc["username"])
followers_count = follows.count({"following_username": username})
following_count = follows.count({"follower_username": username})
posts_count = posts.count({"author_username": username})
viewer_is_following = False
if (viewer_username != None && viewer_username != username)
existing_follow = follows.find_one({"_id": follow_key(viewer_username, username)})
viewer_is_following = (existing_follow != None)
return {
"username": username,
"bio": text_or_empty(user_doc["bio"]),
"joined_seq": number_or_zero(user_doc["joined_seq"]),
"followers_count": followers_count,
"following_count": following_count,
"posts_count": posts_count,
"viewer_is_following": viewer_is_following,
"is_self": (viewer_username == username)
}
fn serialize_post_doc(post_doc)
author_username = text_or_empty(post_doc["author_username"])
author_doc = find_user(author_username)
author = {"username": author_username, "bio": ""}
if (author_doc != None)
author = user_brief_from_doc(author_doc)
return {
"id": text_or_empty(post_doc["_id"]),
"seq": number_or_zero(post_doc["seq"]),
"body": text_or_empty(post_doc["body"]),
"author": author
}
fn insert_post_desc(sorted_posts, post)
out = []
inserted = False
for (existing in sorted_posts)
if (inserted == False && post["seq"] > existing["seq"])
out += [post]
inserted = True
out += [existing]
if (inserted == False)
out += [post]
return out
fn sort_posts_desc(posts_list)
sorted_posts = []
for (post in posts_list)
sorted_posts = insert_post_desc(sorted_posts, post)
return sorted_posts
fn collect_posts(filter)
raw_posts = posts.find(filter, sort={"seq": -1}, limit=100)
items = []
for (raw_post in raw_posts)
try
items += [serialize_post_doc(raw_post)]
except
continue
return sort_posts_desc(items)
fn discover_posts()
return collect_posts({})
fn user_posts(username)
return collect_posts({"author_username": username})
fn home_feed_posts(username)
items = user_posts(username)
follow_docs = follows.find({"follower_username": username})
for (follow_doc in follow_docs)
followed_username = text_or_empty(follow_doc["following_username"])
followed_posts = user_posts(followed_username)
for (post in followed_posts)
items += [post]
return sort_posts_desc(items)