def api_vote_comment(post_id, x, v): if x not in ["-1", "0", "1"]: abort(400) x = int(x) comment_id = base36decode(comment_id) comment = db.query(Comment).filter_by(id=comment_id).first() if not comment_id: abort(404) if comment_id.is_banned: abort(403) #check for existing vote existing = db.query(CommentVote).filter_by(user_id=v.id, comment_id=comment_id).first() if existing: existing.change_to(x) return "", 204 vote = Vote(user_id=v.id, vote_type=x, submission_id=post_id) db.add(vote) db.commit() return "", 204
def badge_grant_post(v): user = get_user(request.form.get("username"), graceful=True) if not user: return redirect("/badge_grant?error=no_user") badge_id = int(request.form.get("badge_id")) if user.has_badge(badge_id): return redirect("/badge_grant?error=already_owned") badge = db.query(BadgeDef).filter_by(id=badge_id).first() if badge.kind != 3: abort(403) new_badge = Badge(badge_id=badge_id, user_id=user.id, created_utc=int(time.time())) desc = request.form.get("description") if desc: new_badge.description = desc url = request.form.get("url") if url: new_badge.url = url db.add(new_badge) db.commit() badge_types = db.query(BadgeDef).filter_by(kind=3).order_by( BadgeDef.rank).all() return redirect(user.permalink)
def get_posts(pids, sort="hot", v=None): if v: vt=db.query(Vote).filter(Vote.user_id==v.id, Vote.submission_id.in_(pids)).subquery() posts= db.query(Submission, Title, vt.c.vote_type).filter(Submission.id.in_(pids)).join(Submission.author).join(User.title, isouter=True).join(vt, vt.c.submission_id==Submission.id, isouter=True) items=[i for i in posts.all()] posts=[n[0] for n in items] for i in range(len(posts)): posts[i]._title=items[i][1] vote = items[i][2] if items[i][2] else 0 posts[i]._voted = vote else: posts=db.query(Submission, Title).filter(Submission.id.in_(pids)).join(Submission.author).join(User.title, isouter=True) items=[i for i in posts.all()] posts=[n[0] for n in items] for i in range(len(posts)): posts[i]._title=items[i][1] posts=sorted(posts, key= lambda x: pids.index(x.id)) return posts
def get_comments(cids, v=None, sort_type="new"): if v: vt = db.query(CommentVote).filter( CommentVote.user_id == v.id, CommentVote.comment_id.in_(cids)).subquery() items = db.query(Comment, vt.c.vote_type).filter( Comment.id.in_(cids)).join(vt, isouter=True).order_by( Comment.created_utc.desc()).all() items = [i for i in items] output = [] for i in items: x = i[0] x._voted = i[1] if i[1] else 0 output.append(x) else: x = db.query(Comment).filter(Comment.id.in_(cids)).all() output = [i for i in x] output = sorted(output, key=lambda x: cids.index(x.id)) return output
def my_subs(v): kind = request.args.get("kind", "guilds") page = max(int(request.args.get("page", 1)), 1) if kind == "guilds": b = db.query(Board) contribs = v.contributes.subquery() m = v.moderates.filter_by(accepted=True).subquery() s = v.subscriptions.filter_by(is_active=True).subquery() content = b.join(s, Board.id == s.c.board_id, isouter=True).join(contribs, contribs.c.board_id == Board.id, isouter=True).join( m, m.c.board_id == Board.id, isouter=True) content = content.filter( or_(s.c.id != None, contribs.c.id != None, m.c.id != None)) content = content.order_by(Board.subscriber_count.desc()) content = [x for x in content.offset(25 * (page - 1)).limit(26)] next_exists = (len(content) == 26) content = content[0:25] return render_template("mine/boards.html", v=v, boards=content, next_exists=next_exists, page=page, kind="guilds") elif kind == "users": u = db.query(User) follows = v.following.subquery() content = u.join(follows, User.id == follows.c.target_id, isouter=False) content = content.order_by(User.follower_count.desc()) content = [x for x in content.offset(25 * (page - 1)).limit(26)] next_exists = (len(content) == 26) content = content[0:25] return render_template("mine/users.html", v=v, users=content, next_exists=next_exists, page=page, kind="users") else: abort(422)
def alts(self): alts1 = db.query(User).join( Alt, Alt.user2 == User.id).filter(Alt.user1 == self.id).all() alts2 = db.query(User).join( Alt, Alt.user1 == User.id).filter(Alt.user2 == self.id).all() return list(set([x for x in alts1] + [y for y in alts2]))
def parent(self): if self.is_top_level: return db.query(Submission).filter_by( id=self.parent_submission).first() else: return db.query(Comment).filter_by( id=base36decode(self.parent_fullname.split( sep="_")[1])).first()
def alts(self): alts1=db.query(User).join(Alt, Alt.user2==User.id).filter(Alt.user1==self.id).all() alts2=db.query(User).join(Alt, Alt.user1==User.id).filter(Alt.user2==self.id).all() output= list(set([x for x in alts1]+[y for y in alts2])) output=sorted(output, key=lambda x: x.username) return output
def home(v): page = int(request.args.get("page", 1)) #prevent invalid paging page = max(page, 1) sort_method = request.args.get("sort", "hot") #get list of ids ids = frontlist(sort=sort_method, page=page) #check existence of next page next_exists = (len(ids) == 26) ids = ids[0:25] #check if ids exist if ids: #assemble list of tuples i = 1 tups = [] for x in ids: tups.append((x, i)) i += 1 #tuple string tups = str(tups).lstrip("[").rstrip("]") #hit db for entries posts = db.query(Submission).from_statement( text(f""" select submissions.*, submissions.ups, submissions.downs from submissions join (values {tups}) as x(id, n) on submissions.id=x.id order by x.n""" )).all() else: posts = [] #If page 1, check for sticky if page == 1: sticky = [] sticky = db.query(Submission).filter_by(stickied=True).first() if sticky: posts = [sticky] + posts return render_template("home.html", v=v, listing=posts, next_exists=next_exists, sort_method=sort_method, page=page)
def ip_address(addr, v): #Restricted to trust+safety ranks and above (admin level 4) user_ids = [] for ip in db.query(IP).filter_by(ip=addr).all(): if ip.user_id not in user_ids: user_ids.append(ip.user_id) users = [db.query(User).filter_by(id=x).first() for x in user_ids] users.sort(key=lambda x: x.username) return render_template("ips.html", addr=addr, users=users, v=v)
def help_admins(v): admins = db.query(User).filter(User.admin_level > 1, User.id > 1).order_by(User.id.asc()).all() admins = [x for x in admins] exadmins = db.query(User).filter_by(admin_level=1).order_by( User.id.asc()).all() exadmins = [x for x in exadmins] return render_template("help/admins.html", v=v, admins=admins, exadmins=exadmins)
def recompute(): while True: db.begin(subtransactions=True) now = int(time.time()) cutoff = now - (60860 * 24 * 180) print("Beginning post recompute") i = 0 for post in db.query(classes.submission.Submission).filter_by( is_banned=False, is_deleted=False ).filter(classes.submission.Submission.created_utc > cutoff).order_by( classes.submission.Submission.id.desc()).all(): i += 1 post.score_hot = post.rank_hot post.score_disputed = post.rank_fiery #post.score_top=post.score post.score_activity = post.rank_activity db.add(post) db.commit() #print(f"{i}/{total} - {post.base36id}") print(f"Scored {i} posts. Beginning comment recompute") i = 0 p = db.query(classes.submission.Submission).filter( classes.submission.Submission.created_utc > cutoff).subquery() for comment in db.query(classes.comment.Comment).join( p, classes.comment.Comment.parent_submission == p.c.id).filter( p.c.id != None, p.c.created_utc > cutoff, classes.comment.Comment.is_deleted == False, classes.comment.Comment.is_banned == False).all(): i += 1 comment.score_disputed = comment.rank_fiery comment.score_hot = comment.rank_hot #comment.score_top=comment.score db.add(comment) db.commit() print(f"Scored {i} comments. Sleeping 1min")
def board_mod_queue(boardname, board, v): page = int(request.args.get("page", 1)) posts = db.query(Submission).filter_by( board_id=board.id, is_banned=False, mod_approved=None).filter(Submission.report_count >= 1) if not v.over_18: posts = posts.filter_by(over_18=False) posts = posts.order_by(Submission.report_count.desc()).offset( (page - 1) * 25).limit(26) posts = [x for x in posts] next_exists = (len(posts) == 26) posts = posts[0:25] return render_template("guild/reported_posts.html", listing=posts, next_exists=next_exists, page=page, v=v, b=board)
def subscribe_board(boardname, v): board = get_guild(boardname) #check for existing subscription, canceled or otherwise sub = db.query(Subscription).filter_by(user_id=v.id, board_id=board.id).first() if sub: if sub.is_active: abort(409) else: #reactivate canceled sub sub.is_active = True db.add(sub) db.commit() return "", 204 new_sub = Subscription(user_id=v.id, board_id=board.id) db.add(new_sub) db.commit() #clear your cached guild listings cache.delete_memoized(User.idlist, v, kind="board") return "", 204
def mod_edit_rule(bid, board, v): r = base36decode(request.form.get("rid")) r = db.query(Rules).filter_by(id=r) if not r: abort(500) if board.is_banned: abort(403) if board.has_ban(v): abort(403) body = request.form.get("body", "") with CustomRenderer() as renderer: body_md = renderer.render(mistletoe.Document(body)) body_html = sanitize(body_md, linkgen=True) r.rule_body = body r.rule_html = body_html r.edited_utc = int(time.time()) db.add(r) db.commit() return "", 204
def create_board_get(v): if not v.can_make_guild: return render_template( "message.html", v=v, title="You already lead 10 guilds." if not v.can_join_gms else "Unable to make a guild. For now.", message= "You need to step down from a guild before you can make any more." if not v.can_join_gms else "You need more Reputation.") #check # recent boards made by user cutoff = int(time.time()) - 60 * 60 * 24 recent = db.query(Board).filter(Board.creator_id == v.id, Board.created_utc >= cutoff).all() if len([x for x in recent]) >= 2: return render_template( "message.html", v=v, title="You need to wait a bit.", message= "You can only create up to 2 guilds per day. Try again later." ), 429 return render_template("make_board.html", v=v)
def filter_comment_html(html_text): soup = BeautifulSoup(html_text) links = soup.find_all("a") domain_list=set() for link in links: domain=urlparse(link["href"]).netloc #parse domain into all possible subdomains parts=domain.split(".") for i in range(len(parts)): new_domain=parts[i] for j in range(i+1, len(parts)): new_domain+="."+parts[j] domain_list.add(new_domain) #search db for domain rules that prohibit commenting bans=[x for x in db.query(Domain).filter_by(can_comment=False).filter(Domain.domain.in_(list(domain_list))).all()] if bans: return bans else: return []
def edit_comment(cid, v): c = db.query(Comment).filter_by(id=base36decode(cid)).first() if not c: abort(404) if not c.author_id == v.id: abort(403) if c.is_banned or c.is_deleted: abort(403) body = request.form.get("body", "") with UserRenderer() as renderer: body_md = renderer.render(mistletoe.Document(body)) body_html = sanitize(body_md, linkgen=True) c.body = body c.body_html = body_html c.edited_timestamp = int(time.time()) db.add(c) db.commit() path = request.form.get("current_page", "/") return redirect(f"{path}#comment-{c.base36id}")
def feeds(sort=None): cutoff = int(time.time()) - (60 * 60 * 24) # 1 day posts = db.query(Submission).filter(Submission.created_utc>=cutoff, Submission.is_banned == False, Submission.is_deleted == False, Submission.stickied == False) if sort == "hot": posts = posts.order_by(text("submissions.rank_hot desc")) elif sort == "fiery": posts = posts.order_by(text("submissions.rank_fiery desc")) elif sort == "top": posts = posts.order_by(text("submissions.score desc")) feed = AtomFeed(title=f'Top 5 {sort} Posts from ruqqus', feed_url=request.url, url=request.url_root) posts = posts.limit(5).all() for post in posts: feed.add(post.title, post.body_html, content_type='html', author=post.author.username, url=f"https://ruqqus.com{post.permalink}", updated=datetime.fromtimestamp(post.created_utc), published=datetime.fromtimestamp(post.created_utc)) return feed.get_response()
def searchlisting(q, v=None, page=1, sort="hot"): posts = db.query(Submission).filter( func.lower(Submission.title).contains(q.lower())) if not (v and v.over_18): posts = posts.filter_by(over_18=False) if v and v.hide_offensive: posts = posts.filter_by(is_offensive=False) if not (v and v.admin_level >= 3): posts = posts.filter_by(is_deleted=False, is_banned=False) if sort == "hot": posts = posts.order_by(Submission.score_hot.desc()) elif sort == "new": posts = posts.order_by(Submission.created_utc.desc()) elif sort == "fiery": posts = posts.order_by(Submission.score_fiery.desc()) elif sort == "top": posts = posts.order_by(Submission.score_top.desc()) total = posts.count() posts = [x for x in posts.offset(25 * (page - 1)).limit(26).all()] return total, [x.id for x in posts]
def wrapper(*args, **kwargs): if "user_id" in session: v = db.query(User).filter_by(id=session["user_id"]).first() if not v: abort(401) nonce = session.get("login_nonce", 0) if nonce < v.login_nonce: abort(401) if v.is_banned: abort(403) if v.admin_level < x: abort(403) #v.update_ip(request.remote_addr) else: abort(401) g.v = v response = f(*args, v=v, **kwargs) if isinstance(response, tuple): resp = make_response(response[0]) else: resp = make_response(response) resp.headers.add("Cache-Control", "private") resp.headers.add("Access-Control-Allow-Origin", app.config["SERVER_NAME"]) return resp
def search(v): query = request.args.get("q") sort = request.args.get("sort", "hot").lower() page = max(1, int(request.args.get("page", 1))) posts = db.query(Submission).filter_by( is_banned=False, is_deleted=False).filter( func.lower(Submission.title).contains(query.lower())) if sort == "hot": posts = posts.order_by(text("submissions.rank_hot desc")) elif sort == "new": posts = posts.order_by(Submission.created_utc.desc()) elif sort == "fiery": posts = posts.order_by(text("submissions.rank_fiery desc")) elif sort == "top": posts = posts.order_by(text("submissions.score desc")) total = posts.count() posts = [x for x in posts.offset(25 * (page - 1)).limit(26).all()] next_exists = (len(posts) == 26) results = posts[0:25] return render_template("search.html", v=v, query=query, total=total, page=page, listing=results, sort_method=sort, next_exists=next_exists)
def ban_user(user_id, v): user=db.query(User).filter_by(id=user_id).first() # check for number of days for suspension days = int(request.form.get("days")) if request.form.get('days') else 0 reason = request.form.get("reason", "") if not user: abort(400) if days > 0: if reason: text = f"Your Ruqqus account has been suspended for {days} days. \n reason:\n\n{reason}" else: text = f"Your Ruqqus account has been suspended for {days} days due to a Terms of Service violation." user.ban(admin=v, days=days) else: if reason: text = f"Your Ruqqus account has been permanently suspended for the following reason:\n\n{reason}" else: text = "Your Ruqqus account has been permanently suspended due to a Terms of Service violation." user.ban(admin=v) send_notification(user, text) db.commit() return (redirect(user.url), user)
def random_comment(v): x = db.query(Comment).filter_by(is_banned=False, over_18=False, is_nsfl=False) if v and v.hide_offensive: x = x.filter_by(is_offensive=False) if v: bans = db.query(BanRelationship.id).filter_by(user_id=v.id).all() x = x.filter(Comment.board_id.notin_([i[0] for i in bans])) comment = x.order_by(func.random()).first() return redirect(comment.permalink)
def comment_cid(cid, v): comment = db.query(Comment).filter_by(id=base36decode(cid)).first() if comment: return redirect(comment.permalink) else: abort(404)
def all_mod_queue(v): page = int(request.args.get("page", 1)) board_ids = [ x.board_id for x in v.moderates.filter_by(accepted=True).all() ] posts = db.query(Submission).filter(Submission.board_id.in_(board_ids), Submission.mod_approved == None, Submission.report_count >= 1, Submission.is_banned == False) if not v.over_18: posts = posts.filter_by(over_18=False) posts = posts.order_by(Submission.report_count.desc()).offset( (page - 1) * 25).limit(26) posts = [x for x in posts] next_exists = (len(posts) == 26) posts = posts[0:25] return render_template("guild/reported_posts.html", listing=posts, next_exists=next_exists, page=page, v=v, b=None)
def edit_comment(v): comment_id = request.form.get("id") body = request.form.get("comment", "") with UserRenderer() as renderer: body_md=renderer.render(mistletoe.Document(body)) body_html = sanitize(body_md, linkgen=True) c = db.query(Comment).filter_by(id=base36decode(comment_id)).first() if not c: abort(404) if not c.author_id == v.id: abort(403) if c.is_banned or c.is_deleted: abort(403) c.body=body c.body_html=body_html c.edited_timestamp = time.time() db.add(c) db.commit()
def replies(self): if "replies" in self.__dict__: return self.__dict__["replies"] else: return db.query(Comment).filter_by( parent_fullname=self.fullname).all()
def activate(): token = request.args.get("token", "") email = request.args.get("email", "") id = request.args.get("id", "") time = request.args.get("time", "") user = db.query(User).filter(User.id == id).first() if not user: flash("User Does Not Exist") return redirect(url_for("index")) if user.is_activated == True: flash("Account is already activated") return redirect(url_for("login")) check_hash = validate_hash(f"{email}+{id}+{time}", token) if not check_hash: flash("Invalid Token") return redirect(url_for("index")) if user.is_activated == False: user.is_activated = True db.add(user) db.commit() flash("Account has been activated") return redirect(url_for("login"))
def users_here(x): now = time.time() cutoff = now - 300 return db.query(User).join(IP).filter(IP.created_utc >= cutoff).count()