def delete_pending(userId, command): conn = newconn() cur = conn.cursor() if len(command) != 2: return {"success": False, "msg": "Usage: delete_pending [puserId]\nDelete a pending user"} puserId = command[1] if puserId.isdigit(): cur.execute(f"SELECT * FROM UserPending WHERE puserId = {puserId}") if len(cur.fetchall()) == 0: cur.execute(f"SELECT puserId FROM UserPending WHERE username = '******'") t = cur.fetchall() if len(t) == 0: return {"success": False, "msg": "User not found!"} else: puserId = t[0][0] else: puserId = int(puserId) else: cur.execute(f"SELECT puserId FROM UserPending WHERE username = '******'") t = cur.fetchall() if len(t) == 0: return {"success": False, "msg": "User not found!"} else: puserId = t[0][0] cur.execute(f"DELETE FROM UserPending WHERE puserId = {puserId}") cur.execute(f"DELETE FROM UserPendingToken WHERE puserId = {puserId}") conn.commit() return {"success": True, "msg": "User deleted!"}
async def apiClearDeleted(request: Request): ip = request.client.host form = await request.form() conn = newconn() cur = conn.cursor() if not "userId" in form.keys() or not "token" in form.keys( ) or "userId" in form.keys() and (not form["userId"].isdigit() or int(form["userId"]) < 0): raise HTTPException(status_code=401) userId = int(form["userId"]) token = form["token"] if not validateToken(userId, token): raise HTTPException(status_code=401) cur.execute( f"SELECT questionId, question, answer, status FROM QuestionList WHERE userId = {userId} AND status = 3" ) d = cur.fetchall() ts = int(time.time()) cur.execute( f"DELETE FROM QuestionList WHERE userId = {userId} AND status = 3") for dd in d: cur.execute( f"DELETE FROM BookData WHERE userId = {userId} AND questionId = {dd[0]}" ) conn.commit() return {"success": True}
def logout(userId, token): try: if not validateToken(userId, token): return True conn = newconn() cur = conn.cursor() ip = "" loginTime = 0 expireTime = 0 cur.execute( f"SELECT loginTime, expireTime, ip FROM ActiveUserLogin WHERE userId = {userId} AND token = '{token}'" ) t = cur.fetchall() if len(t) > 0: loginTime = t[0][0] expireTime = t[0][1] ip = t[0][2] cur.execute( f"INSERT INTO UserSessionHistory VALUES ({userId}, {loginTime}, {expireTime}, 1, '{ip}')" ) cur.execute( f"DELETE FROM ActiveUserLogin WHERE userId = {userId} AND token = '{token}'" ) conn.commit() return True except: import traceback traceback.print_exc() global errcnt errcnt += 1
def updatePasswordTrialCount(userId, to, ts, ip): try: conn = newconn() cur = conn.cursor() cur.execute(f"SELECT count FROM PasswordTrial WHERE userId = {userId}") t = cur.fetchall() if len(t) == 0: if to == 0: return cur.execute( f"INSERT INTO PasswordTrial VALUES ({userId}, {to}, {ts}, '{ip}')" ) conn.commit() else: if to == 0: cur.execute( f"DELETE FROM PasswordTrial WHERE userId = {userId}") conn.commit() else: cur.execute( f"UPDATE PasswordTrial SET count = {to} WHERE userId = {userId}" ) cur.execute( f"UPDATE PasswordTrial SET lastts = {ts} WHERE userId = {userId}" ) conn.commit() except: global errcnt errcnt += 1
def ban(userId, command): conn = newconn() cur = conn.cursor() if len(command) < 3: return {"success": False, "msg": "Usage: ban [userId] [reason]\nBan account"} uid = 0 if not command[1].isdigit(): uid = usernameToUid(encode(command[1])) else: uid = int(command[1]) if uid <= 0: return {"success": False, "msg": "Invalid user id!"} if uid == userId: return {"success": False, "msg": "You cannot ban yourself!"} cur.execute(f"SELECT userId FROM UserInfo WHERE userId = {uid}") if len(cur.fetchall()) == 0: cur.execute(f"SELECT userId FROM UserInfo WHERE userId = {-uid}") if len(cur.fetchall()) == 0: return {"success": False, "msg": "Account doesn't exist!"} else: return {"success": False, "msg": "Account already banned!"} reason = encode(" ".join(command[2:])) cur.execute(f"UPDATE UserInfo SET userId = {-uid} WHERE userId = {uid}") cur.execute(f"INSERT INTO BanReason VALUES ({uid}, '{reason}')") conn.commit() return {"success": True, "msg": f"Banned user {uid}"}
async def apiSearchDiscovery(request: Request, background_tasks: BackgroundTasks): ip = request.client.host form = await request.form() conn = newconn() cur = conn.cursor() ret = [] global lst, lstupd if time.time() - lstupd > 30: if lstupd == 0: UpdateData() else: background_tasks.add_task(UpdateData) limit = form["search"][:32] limit = ''.join(e for e in limit if e.isalnum()) limit = limit.replace(" ", "") if limit == "": for d in lst.keys(): for dd in lst[d]: ret.append(dd) return {"result": ret} res = process.extract(limit, lst.keys(), limit=None) for d in res: if d[1] >= 10 and d[0] in lst.keys(): for dd in lst[d[0]]: ret.append(dd) return {"result": ret}
def OPLimit(ip, endpoint, maxop = 5, timeout = 300): conn = newconn() cur = conn.cursor() ip = str(ip) ip = encode(ip) cur.execute(f"SELECT count, last FROM OPLimit WHERE ip = '{ip}' AND endpoint = '{endpoint}'") t = cur.fetchall() if len(t) == 0: cur.execute(f"INSERT INTO OPLimit VALUES ('{ip}', '{endpoint}', 1, {int(time.time())})") conn.commit() return False count = t[0][0] last = t[0][1] if last < time.time() - timeout: cur.execute(f"DELETE FROM OPLimit WHERE ip = '{ip}' AND endpoint = '{endpoint}'") cur.execute(f"INSERT INTO OPLimit VALUES ('{ip}', '{endpoint}', 1, {int(time.time())})") conn.commit() return False if count == maxop: return True cur.execute(f"UPDATE OPLimit SET count = count + 1 WHERE ip = '{ip}' AND endpoint = '{endpoint}'") cur.execute(f"UPDATE OPLimit SET last = '{int(time.time())}' WHERE ip = '{ip}' AND endpoint = '{endpoint}'") conn.commit() return False
def get_user_count(userId, command): conn = newconn() cur = conn.cursor() cur.execute(f"SELECT COUNT(*) FROM UserInfo") tot = 0 d = cur.fetchall() if len(d) != 0: tot = d[0][0] cur.execute(f"SELECT COUNT(*) FROM UserInfo WHERE userId > 0") cnt = 0 d = cur.fetchall() if len(d) != 0: cnt = d[0][0] cur.execute(f"SELECT COUNT(*) FROM UserInfo WHERE username = '******'@deleted')}' AND userId > 0") deled = 0 d = cur.fetchall() if len(d) != 0: deled = d[0][0] cur.execute(f"SELECT COUNT(*) FROM UserInfo WHERE userId < 0") banned = 0 d = cur.fetchall() if len(d) != 0: banned = d[0][0] marked_deletion = sessions.CountDeletionMark() cnt -= marked_deletion return {"success": True, "msg": f"Total user: {tot}\nActive user: {cnt - deled}\nBanned / Banned & Deleted user: {banned}\nDisabled (Pending deletion) user: {marked_deletion}\nDeleted user: {deled}"}
async def apiUserEvents(request: Request): ip = request.client.host form = await request.form() conn = newconn() cur = conn.cursor() if not "userId" in form.keys() or not "token" in form.keys() or "userId" in form.keys() and (not form["userId"].isdigit() or int(form["userId"]) < 0): raise HTTPException(status_code=401) userId = int(form["userId"]) token = form["token"] if not validateToken(userId, token): raise HTTPException(status_code=401) page = int(form["page"]) cur.execute(f"SELECT timestamp, msg FROM UserEvent WHERE userId = {userId} ORDER BY timestamp DESC") d = cur.fetchall() ret = [] for dd in d: ret.append({"timestamp": dd[0], "msg": decode(dd[1])}) if len(ret) <= (page - 1) * 20: return {"success": True, "notifications": [], "nextpage": -1} elif len(ret) <= page * 20: return {"success": True, "notifications": ret[(page - 1) * 20 :], "nextpage": -1} else: return {"success": True, "notifications": ret[(page - 1) * 20 : page * 20], "nextpage": page + 1}
async def apiGroupMember(request: Request): ip = request.client.host form = await request.form() conn = newconn() cur = conn.cursor() if not "userId" in form.keys() or not "token" in form.keys() or "userId" in form.keys() and (not form["userId"].isdigit() or int(form["userId"]) < 0): raise HTTPException(status_code=401) userId = int(form["userId"]) token = form["token"] if not validateToken(userId, token): raise HTTPException(status_code=401) groupId = int(form["groupId"]) cur.execute(f"SELECT userId, isEditor FROM GroupMember WHERE groupId = {groupId}") d = cur.fetchall() if not (userId,0,) in d and not (userId,1,) in d: return {"success": False, "msg": f"You must be a member of the group before viewing its info."} info = None cur.execute(f"SELECT name, description, anonymous FROM GroupInfo WHERE groupId = {groupId}") t = cur.fetchall() if len(t) > 0: info = t[0] else: return {"success": False, "msg": "Group not found!"} return {"success": True, "name": decode(info[0]), "description": decode(info[1])}
async def apiUserSessions(request: Request): ip = request.client.host form = await request.form() conn = newconn() cur = conn.cursor() if not "userId" in form.keys() or not "token" in form.keys() or "userId" in form.keys() and (not form["userId"].isdigit() or int(form["userId"]) < 0): raise HTTPException(status_code=401) userId = int(form["userId"]) token = form["token"] if not validateToken(userId, token): raise HTTPException(status_code=401) ss = [] cur.execute(f"SELECT loginTime, expireTime, ua, ip, token FROM ActiveUserLogin WHERE userId = {userId}") d = cur.fetchall() for dd in d: if dd[1] <= int(time.time()): cur.execute(f"DELETE FROM ActiveUserLogin WHERE token = '{dd[4]}' AND userId = {userId}") else: tk = dd[4] tk = tk[tk.find("-")+1:tk.find("-",tk.find("-")+1)] ss.append({"loginTime": dd[0], "expireTime": dd[1], "userAgent": decode(dd[2]), "ip": dd[3], "token": tk}) return ss[::-1]
def checkAdmin(userId): conn = newconn() cur = conn.cursor() cur.execute(f"SELECT userId FROM AdminList WHERE userId = {userId}") if len(cur.fetchall()) == 0: return False return True
def remove_name_tag(userId, command): conn = newconn() cur = conn.cursor() if len(command) != 2: return {"success": False, "msg": "Usage: remove_name_tag [userId]"} uid = 0 if not command[1].isdigit(): uid = usernameToUid(encode(command[1])) else: uid = int(command[1]) if uid == 0: return {"success": False, "msg": "Invalid user id!"} if checkBanned(uid): return {"success": False, "msg": "User has been banned!"} cur.execute(f"SELECT * FROM UserNameTag WHERE userId = {uid}") t = cur.fetchall() if len(t) == 0: return {"success": False, "msg": "User does not have a name tag!"} else: cur.execute(f"DELETE FROM UserNameTag WHERE userId = {uid}") conn.commit() return {"success": True, "msg": f"Removed nametag from user {uid}"}
def add_admin(userId, command): conn = newconn() cur = conn.cursor() if len(command) != 2: return { "success": False, "msg": "Usage: add_admin [userId]\nAdd [userId] to administrator list." } uid = 0 if not command[1].isdigit(): uid = usernameToUid(encode(command[1])) else: uid = int(command[1]) if uid == 0: return {"success": False, "msg": "Invalid user id!"} if checkBanned(uid): return {"success": False, "msg": "User has been banned!"} cur.execute(f"SELECT userId FROM AdminList WHERE userId = {uid}") if len(cur.fetchall()) == 0: cur.execute(f"INSERT INTO AdminList VALUES ({uid})") conn.commit() return { "success": True, "msg": f"Added user {command[1]} to administrator list!" } else: return { "success": True, "msg": f"User {command[1]} is already an administrator!" }
async def apiExportData(request: Request, background_tasks: BackgroundTasks): clearOutdated() ip = request.client.host form = await request.form() conn = newconn() cur = conn.cursor() if not "userId" in form.keys() or not "token" in form.keys( ) or "userId" in form.keys() and (not form["userId"].isdigit() or int(form["userId"]) < 0): raise HTTPException(status_code=401) userId = int(form["userId"]) token = form["token"] if not validateToken(userId, token): raise HTTPException(status_code=401) global threads if threads >= 8: return { "success": False, "msg": "The server is handling too many download requests at this time! Try again later..." } exportType = form["exportType"] bookId = int(form["bookId"]) tk = str(uuid.uuid4()) global dataDownloadToken dataDownloadToken[tk] = (userId, exportType, bookId, int(time.time()), tk) background_tasks.add_task(prepareData, tk) return {"success": True, "token": tk}
def unban(userId, command): conn = newconn() cur = conn.cursor() if len(command) != 2: return {"success": False, "msg": "Usage: unban [userId]\nUnban account"} uid = 0 if not command[1].isdigit(): uid = abs(usernameToUid(encode(command[1]))) else: uid = int(command[1]) if uid == 0: return {"success": False, "msg": "Invalid user id!"} cur.execute(f"SELECT userId FROM UserInfo WHERE userId = {-uid}") if len(cur.fetchall()) == 0: return {"success": False, "msg": "Account isn't banned!"} else: cur.execute(f"SELECT userId FROM UserInfo WHERE userId = {-uid}") if len(cur.fetchall()) == 0: return {"success": False, "msg": "Account doesn't exist!"} else: cur.execute(f"UPDATE UserInfo SET userId = {uid} WHERE userId = {-uid}") cur.execute(f"DELETE FROM BanReason WHERE userId = {uid}") conn.commit() return {"success": True, "msg": f"Unbanned user {uid}"}
async def apiUserPendingGetInfo(request: Request): ip = request.client.host form = await request.form() conn = newconn() cur = conn.cursor() puserId = int(form["puserId"]) ptoken = form["ptoken"] if not ptoken.replace("-", "").isalnum(): return {"success": False, "msg": "Invalid token!"} cur.execute( f"SELECT puserId FROM UserPendingToken WHERE puserId = {puserId} AND token = '{ptoken}'" ) t = cur.fetchall() if len(t) == 0: return {"success": False, "msg": "Session expired!"} cur.execute( f"SELECT username, email FROM UserPending WHERE puserId = {puserId}") t = cur.fetchall() if len(t) == 0: return {"success": False, "msg": "Invalid token!"} username = decode(t[0][0]) email = decode(t[0][1]) return {"success": True, "username": username, "email": email}
def mute(userId, command): conn = newconn() cur = conn.cursor() if len(command) != 3: return {"success": False, "msg": "Usage: mute [userId] [duration]\nMute [userId] for [duration] days\nTo mute forever, set [duration] to -1"} uid = 0 if not command[1].isdigit(): uid = usernameToUid(encode(command[1])) else: uid = int(command[1]) if uid == 0: return {"success": False, "msg": "Invalid user id!"} if checkBanned(uid): return {"success": False, "msg": "User has been banned!"} value = int(command[2]) if uid == userId: return {"success": False, "msg": "You cannot mute yourself!"} if value != -1: value = int(time.time()) + 86400 * value cur.execute(f"SELECT * FROM Privilege WHERE userId = {uid} AND item = 'mute'") if len(cur.fetchall()) == 0: cur.execute(f"INSERT INTO Privilege VALUES ({uid}, 'mute', '{value}')") else: cur.execute(f"UPDATE Privilege SET value = '{value}' WHERE userId = {uid} AND item = 'mute'") conn.commit() return {"success": True, "msg": "User muted"}
async def apiGetUserChart(uid: int, request: Request): ip = request.client.host conn = newconn() cur = conn.cursor() cur.execute(f"SELECT * FROM UserInfo WHERE userId = {uid}") t = cur.fetchall() if len(t) == 0: return {"success": False, "msg": "User not found!"} d1 = [] batch = 3 for i in range(30): cur.execute(f"SELECT COUNT(*) FROM ChallengeRecord WHERE userId = {uid} AND memorized = 1 AND timestamp >= {int(time.time()/86400+1)*86400 - 86400*batch*(i+1)} AND timestamp <= {int(time.time()/86400+1)*86400 - 86400*batch*i}") t = cur.fetchall() memorized = 0 if len(t) > 0: memorized = t[0][0] cur.execute(f"SELECT COUNT(*) FROM ChallengeRecord WHERE userId = {uid} AND memorized = 0 AND timestamp >= {int(time.time()/86400+1)*86400 - 86400*batch*(i+1)} AND timestamp <= {int(time.time()/86400+1)*86400 - 86400*batch*i}") t = cur.fetchall() forgotten = 0 if len(t) > 0: forgotten = t[0][0] d1.append({"index": 30 - i, "memorized": memorized, "forgotten": forgotten}) d2 = [] total_memorized = 0 batch = 3 for i in range(30): cur.execute(f"SELECT COUNT(*) FROM QuestionList WHERE userId = {uid} AND memorizedTimestamp != 0 AND memorizedTimestamp <= {int(time.time()/86400+1)*86400 - 86400*batch*i}") t = cur.fetchall() total = 0 if len(t) > 0: total = t[0][0] total_memorized = max(total_memorized, total) d2.append({"index": 30 - i, "total": total}) cnt = 0 cur.execute(f"SELECT COUNT(*) FROM QuestionList WHERE userId = {uid}") t = cur.fetchall() if len(t) > 0: cnt = t[0][0] tagcnt = 0 cur.execute(f"SELECT COUNT(*) FROM QuestionList WHERE userId = {uid} AND status = 2") t = cur.fetchall() if len(t) > 0: tagcnt = t[0][0] delcnt = 0 cur.execute(f"SELECT COUNT(*) FROM QuestionList WHERE userId = {uid} AND status = 3") t = cur.fetchall() if len(t) > 0: delcnt = t[0][0] return {"success": True, "challenge_history": d1, "total_memorized_history": d2, "tag_cnt": tagcnt, "del_cnt": delcnt, "total_memorized": total_memorized, "total": cnt}
def get_user_info(userId, command): conn = newconn() cur = conn.cursor() if len(command) != 2: return {"success": False, "msg": f"Usage: get_user_info [userId]\nGet detailed user info of [userId]"} uid = 0 if not command[1].isdigit(): uid = usernameToUid(encode(command[1])) else: uid = int(command[1]) if uid == 0: return {"success": False, "msg": "Invalid user id!"} cur.execute(f"SELECT username, email, inviteCode, inviter FROM UserInfo WHERE userId = {uid}") d = cur.fetchall() banned = False if len(d) == 0: cur.execute(f"SELECT username, email, inviteCode, inviter FROM UserInfo WHERE userId = {-uid}") # check banned d = cur.fetchall() if len(d) == 0: return {"success": False, "msg": f"User not found!"} banned = True d = d[0] d = list(d) d[0] = decode(d[0]) inviter = "Unknown" cur.execute(f"SELECT username FROM UserInfo WHERE userId = {d[3]}") t = cur.fetchall() if len(t) > 0: inviter = decode(t[0][0]) if inviter == "default": inviter = "/" cnt = 0 cur.execute(f"SELECT COUNT(*) FROM QuestionList WHERE userId = {abs(uid)}") t = cur.fetchall() if len(t) > 0: cnt = t[0][0] regts = 0 cur.execute(f"SELECT timestamp FROM UserEvent WHERE userId = {abs(uid)} AND event = 'register'") t = cur.fetchall() if len(t) > 0: regts = t[0][0] msg = "" if banned: msg += "Account has been banned\n" if sessions.CheckDeletionMark(uid): msg += "Account deactivated! and marked for deletion\n" return {"success": True, "msg": f"{d[0]} (UID: {uid})\nEmail: {decode(d[1])}\nInvitation Code: {d[2]}\nInviter: {inviter} (UID: {d[3]})\nQuestion Count: {cnt}\nAccount age: {CalculateAge(regts)} day(s)\n{msg}"}
async def apiDeleteBook(request: Request): ip = request.client.host form = await request.form() conn = newconn() cur = conn.cursor() if not "userId" in form.keys() or not "token" in form.keys() or "userId" in form.keys() and (not form["userId"].isdigit() or int(form["userId"]) < 0): raise HTTPException(status_code=401) userId = int(form["userId"]) token = form["token"] if not validateToken(userId, token): raise HTTPException(status_code=401) bookId = int(form["bookId"]) cur.execute(f"SELECT name FROM Book WHERE userId = {userId} AND bookId = {bookId}") t = cur.fetchall() if len(t) == 0: return {"success": False, "msg": "Book does not exist!"} name = t[0][0] cur.execute(f"SELECT * FROM Discovery WHERE publisherId = {userId} AND bookId = {bookId} AND type = 1") if len(cur.fetchall()) != 0: return {"success": False, "msg": "Book published to Discovery! Unpublish it first before deleting the book."} groupId = -1 cur.execute(f"SELECT groupId FROM GroupMember WHERE userId = {userId} AND bookId = {bookId}") d = cur.fetchall() if len(d) != 0: groupId = d[0][0] if groupId != -1: cur.execute(f"SELECT owner, name FROM GroupInfo WHERE groupId = {groupId}") d = cur.fetchall() if len(d) == 0: return {"success": False, "msg": "Group does not exist!"} owner = d[0][0] if userId == owner: return {"success": False, "msg": "You are the owner of the group. You have to transfer group ownership or dismiss the group before deleting the book."} name = d[0][1] cur.execute(f"DELETE FROM GroupSync WHERE groupId = {groupId} AND userId = {userId}") cur.execute(f"DELETE FROM GroupMember WHERE groupId = {groupId} AND userId = {userId}") cur.execute(f"INSERT INTO UserEvent VALUES ({userId}, 'quit_group', {int(time.time())}, '{encode(f'Quit group {decode(name)}')}')") removeAll = form["removeAll"] if removeAll: qs = getBookData(userId, bookId) for q in qs: cur.execute(f"DELETE FROM BookData WHERE userId = {userId} AND questionId = {q}") cur.execute(f"DELETE FROM QuestionList WHERE questionId = {q} AND userId = {userId}") cur.execute(f"DELETE FROM Book WHERE userId = {userId} AND bookId = {bookId}") cur.execute(f"INSERT INTO UserEvent VALUES ({userId}, 'delete_book', {int(time.time())}, '{encode(f'Deleted book {decode(name)}')}')") cur.execute(f"DELETE FROM BookData WHERE userId = {userId} AND bookId = {bookId}") conn.commit() return {"success": True}
def getBookId(userId, questionId): conn = newconn() cur = conn.cursor() cur.execute(f"SELECT bookId FROM BookData WHERE userId = {userId} AND questionId = {questionId}") t = cur.fetchall() ret = [] for tt in t: ret.append(tt[0]) return ret
def getQuestionCount(userId): conn = newconn() cur = conn.cursor() q = 0 cur.execute(f"SELECT COUNT(*) FROM QuestionList WHERE userId = {userId}") d = cur.fetchall() if len(d) > 0: q = d[0][0] conn.close() return q
def usernameToUid(username): conn = newconn() cur = conn.cursor() cur.execute(f"SELECT userId FROM UserInfo WHERE username = '******'") t = cur.fetchall() conn.close() if len(t) > 0: return t[0][0] else: return 0
async def apiDiscoveryUpdate(request: Request): ip = request.client.host form = await request.form() conn = newconn() cur = conn.cursor() if not "userId" in form.keys() or not "token" in form.keys( ) or "userId" in form.keys() and (not form["userId"].isdigit() or int(form["userId"]) < 0): raise HTTPException(status_code=401) userId = int(form["userId"]) token = form["token"] if not validateToken(userId, token): raise HTTPException(status_code=401) discoveryId = int(form["discoveryId"]) title = encode(form["title"]) description = encode(form["description"]) if form["title"] == "" or form["description"] == "": return { "success": False, "msg": "Title and description must be filled!" } # allow admin to update cur.execute(f"SELECT userId FROM AdminList WHERE userId = {userId}") if len(cur.fetchall()) == 0: cur.execute( f"SELECT publisherId FROM Discovery WHERE discoveryId = {discoveryId}" ) publisherId = 0 t = cur.fetchall() if len(t) > 0: publisherId = t[0][0] if publisherId != userId: return { "success": False, "msg": "You are not the publisher of this post!" } if len(title) >= 256: return {"success": False, "msg": "Title too long!"} if len(description) >= 2048: return {"success": False, "msg": "Description too long!"} cur.execute( f"UPDATE Discovery SET title = '{title}' WHERE discoveryId = {discoveryId}" ) cur.execute( f"UPDATE Discovery SET description = '{description}' WHERE discoveryId = {discoveryId}" ) conn.commit() return {"success": True, "msg": "Discovery post updated!"}
async def apiGroupPreview(request: Request): ip = request.client.host form = await request.form() conn = newconn() cur = conn.cursor() groupCode = form["groupCode"] if groupCode.startswith("@"): groupCode = groupCode[1:] if not groupCode.isalnum(): return {"success": False, "msg": "Invalid group code!"} cur.execute(f"SELECT groupId, owner, name, description FROM GroupInfo WHERE groupCode = '{groupCode}'") d = cur.fetchall() if len(d) == 0: return {"success": False, "msg": "Invalid group code!"} d = d[0] groupId = d[0] owner = d[1] name = decode(d[2]) description = decode(d[3]) memberCount = 0 cur.execute(f"SELECT COUNT(*) FROM GroupMember WHERE groupId = {groupId}") t = cur.fetchall() if len(t) > 0: memberCount = t[0][0] ownerUsername = "" cur.execute(f"SELECT username FROM UserInfo WHERE userId = {owner}") t = cur.fetchall() if len(t) > 0: ownerUsername = decode(t[0][0]) if ownerUsername != "@deleted" and owner != 0: cur.execute(f"SELECT tag, tagtype FROM UserNameTag WHERE userId = {abs(owner)}") t = cur.fetchall() if len(t) > 0: ownerUsername = f"<a href='/user/{owner}'><span class='username' style='color:{t[0][1]}'>{ownerUsername}</span></a> <span class='nametag' style='background-color:{t[0][1]}'>{decode(t[0][0])}</span>" else: ownerUsername = f"<a href='/user/{owner}'><span class='username'>{ownerUsername}</span></a>" cur.execute(f"SELECT question, answer FROM GroupQuestion WHERE groupId = {groupId}") d = cur.fetchall() da = {} for dd in d: da[decode(dd[0])] = {"question": decode(dd[0]), "answer": decode(dd[1])} ret = [] for q in sorted(da.keys()): ret.append(da[q]) ret = ret[:10] return {"success": True, "name": name, "description": description, "ownerUsername": ownerUsername, "memberCount": memberCount, "preview": ret}
async def apiQuitGroup(request: Request): ip = request.client.host form = await request.form() conn = newconn() cur = conn.cursor() if not "userId" in form.keys() or not "token" in form.keys( ) or "userId" in form.keys() and (not form["userId"].isdigit() or int(form["userId"]) < 0): raise HTTPException(status_code=401) userId = int(form["userId"]) token = form["token"] if not validateToken(userId, token): raise HTTPException(status_code=401) groupId = int(form["groupId"]) cur.execute( f"SELECT * FROM GroupMember WHERE userId = {userId} AND groupId = {groupId}" ) if len(cur.fetchall()) == 0: return {"success": False, "msg": "You are not in the group!"} cur.execute(f"SELECT owner, name FROM GroupInfo WHERE groupId = {groupId}") d = cur.fetchall() if len(d) == 0: return {"success": False, "msg": "Group does not exist!"} owner = d[0][0] if userId == owner: return { "success": False, "msg": "You are the owner of the group. You have to transfer group ownership before quiting the group." } name = d[0][1] cur.execute( f"DELETE FROM GroupSync WHERE groupId = {groupId} AND userId = {userId}" ) cur.execute( f"DELETE FROM GroupMember WHERE groupId = {groupId} AND userId = {userId}" ) cur.execute( f"INSERT INTO UserEvent VALUES ({userId}, 'quit_group', {int(time.time())}, '{encode(f'Quit group {decode(name)}')}')" ) conn.commit() return { "success": True, "msg": "You have quit the group successfully! The book has became a local one." }
async def apiGetUserPublicInfo(uid: int, request: Request): ip = request.client.host conn = newconn() cur = conn.cursor() cur.execute(f"SELECT username, bio FROM UserInfo WHERE userId = {uid}") t = cur.fetchall() if len(t) == 0 or uid < 0: return {"success": False, "msg": "User not found!"} username = decode(t[0][0]) bio = decode(t[0][1]) cnt = 0 cur.execute(f"SELECT COUNT(*) FROM QuestionList WHERE userId = {uid}") t = cur.fetchall() if len(t) > 0: cnt = t[0][0] tagcnt = 0 cur.execute(f"SELECT COUNT(*) FROM QuestionList WHERE userId = {uid} AND status = 2") t = cur.fetchall() if len(t) > 0: tagcnt = t[0][0] delcnt = 0 cur.execute(f"SELECT COUNT(*) FROM QuestionList WHERE userId = {uid} AND status = 3") t = cur.fetchall() if len(t) > 0: delcnt = t[0][0] chcnt = 0 cur.execute(f"SELECT COUNT(*) FROM ChallengeRecord WHERE userId = {uid}") t = cur.fetchall() if len(t) > 0: chcnt = t[0][0] regts = 0 cur.execute(f"SELECT timestamp FROM UserEvent WHERE userId = {uid} AND event = 'register'") t = cur.fetchall() if len(t) > 0: regts = t[0][0] isAdmin = False cur.execute(f"SELECT * FROM AdminList WHERE userId = {uid}") if len(cur.fetchall()) != 0: isAdmin = True cur.execute(f"SELECT tag, tagtype FROM UserNameTag WHERE userId = {uid}") t = cur.fetchall() if len(t) > 0: username = f"<a href='/user/{uid}'><span class='username' style='color:{t[0][1]}'>{username}</span></a> <span class='nametag' style='background-color:{t[0][1]}'>{decode(t[0][0])}</span>" else: username = f"<a href='/user/{uid}'><span class='username'>{username}</span></a>" return {"success": True, "username": username, "bio": bio, "cnt": cnt, "tagcnt": tagcnt, "delcnt": delcnt, "chcnt": chcnt, "age": CalculateAge(regts), "isAdmin": isAdmin}
def GetTop(): conn = newconn() cur = conn.cursor() global top, toplst cur.execute( f"SELECT discoveryId FROM Discovery ORDER BY likes DESC LIMIT 3") t = cur.fetchall() top = [] for tt in t: top.append(tt[0]) toplst = int(time.time())
def updateQuestionStatus(userId, questionId, status): conn = newconn() cur = conn.cursor() cur.execute(f"SELECT COUNT(*) FROM StatusUpdate WHERE questionId = {questionId} AND userId = {userId}") d = cur.fetchall() questionUpdateId = 0 if len(d) != 0: questionUpdateId = d[0][0] cur.execute(f"INSERT INTO StatusUpdate VALUES ({userId},{questionId},{questionUpdateId},{status},{int(time.time())})") conn.commit() conn.close()