The social platform for uncensored discourse

Share and discover content from around the web in one place. Vote on what you like or dislike, and engage in uncensored discussion with the community.

Create account

Publish, vote, and discuss. All without censorship.

Independent

We're not owned by big tech. We're a handful of individuals from different backgrounds working together to foster free speech social media.

Free speech

We don't believe in censoring. You're free to say and discuss anything that would be protected by the First Amendment in the public square.

Privacy-focused

The Ruqqus team will not share or sell your data to outside parties. We do not allow advertisements that track you either.

Did we mention open-source?

We like to keep things transparent. For this reason, our entire codebase is open-source and available on Github. View our algorithms right from your browser. No biased trending or sorting manipulation on Ruqqus.

View our code
from flask import render_template, session
from time import time, strftime, gmtime
from sqlalchemy import *

from ruqqus.helpers.base36 import *
from ruqqus.__main__ import Base, db

class Vote(Base):

    __tablename__="votes"

    id=Column(Integer, primary_key=True)
    user_id=Column(Integer, ForeignKey("users.id"))
    vote_type=Column(Integer)
    submission_id=Column(Integer, ForeignKey("submissions.id"))
    created_utc=Column(Integer, default=0)

    
    def __init__(self, *args, **kwargs):
        
        if "created_utc" not in kwargs:
            kwargs["created_utc"]=int(time())

        super().__init__(*args, **kwargs)
            

    def change_to(self, x):

        """
        1 - upvote
        0 - novote
        -1 - downvote
        """
        if x in ["-1","0","1"]:
            x=int(x)
        elif x not in [-1, 0, 1]:
            abort(400)

        self.vote_type=x
        self.created_utc=int(time())

        db.add(self)
        db.commit()

class CommentVote(Base):

    __tablename__="commentvotes"

    id=Column(Integer, primary_key=True)
    user_id=Column(Integer, ForeignKey("users.id"))
    vote_type=Column(Integer)
    comment_id=Column(Integer, ForeignKey("comments.id"))
    created_utc=Column(Integer, default=0)

    def __init__(self, *args, **kwargs):
        
        if "created_utc" not in kwargs:
            kwargs["created_utc"]=int(time())

        super().__init__(*args, **kwargs)
            

    def change_to(self, x):

        """
        1 - upvote
        0 - novote
        -1 - downvote
        """
        if x in ["-1","0","1"]:
            x=int(x)
        elif x not in [-1, 0, 1]:
            abort(400)

        self.vote_type=x
        self.created_utc=int(time())

        db.add(self)
        db.commit()
from flask import render_template, request, abort
import time
from sqlalchemy import *
from sqlalchemy.orm import relationship
import math
from urllib.parse import urlparse
import random

from ruqqus.helpers.base36 import *
from ruqqus.helpers.lazy import lazy
from ruqqus.__main__ import Base, db, cache
from .user import User
from .votes import Vote
from .domains import Domain
from .flags import Flag

class Submission(Base):

    __tablename__="submissions"

    id = Column(BigInteger, primary_key=True)
    author_id = Column(BigInteger, ForeignKey(User.id))
    title = Column(String(500), default=None)
    url = Column(String(500), default=None)
    edited_utc = Column(BigInteger, default=0)
    created_utc = Column(BigInteger, default=0)
    is_banned = Column(Boolean, default=False)
    is_deleted=Column(Boolean, default=False)
    distinguish_level=Column(Integer, default=0)
    created_str=Column(String(255), default=None)
    stickied=Column(Boolean, default=False)
    comments=relationship("Comment", lazy="dynamic", backref="submissions")
    body=Column(String(2000), default="")
    body_html=Column(String(2200), default="")
    embed_url=Column(String(256), default="")
    domain_ref=Column(Integer, ForeignKey("domains.id"))
    flags=relationship("Flag", lazy="dynamic", backref="submission")
    is_approved=Column(Integer, default=0)
    approved_utc=Column(Integer, default=0)


    #These are virtual properties handled as postgres functions server-side
    #There is no difference to SQLAlchemy, but they cannot be written to
    #appts = db.session.query(Appointment).from_statement(func.getopenappointments(current_user.id))
    ups = Column(Integer, server_default=FetchedValue())
    downs=Column(Integer, server_default=FetchedValue())
    age=Column(Integer, server_default=FetchedValue())
    comment_count=Column(Integer, server_default=FetchedValue())
    flag_count=Column(Integer, server_default=FetchedValue())
    score=Column(Float, server_default=FetchedValue())
    rank_hot=Column(Float, server_default=FetchedValue())
    rank_fiery=Column(Float, server_default=FetchedValue())
    

    def __init__(self, *args, **kwargs):

        if "created_utc" not in kwargs:
            kwargs["created_utc"]=int(time.time())
            kwargs["created_str"]=time.strftime("%I:%M %p on %d %b %Y", time.gmtime(kwargs["created_utc"]))


        super().__init__(*args, **kwargs)
        
    def __repr__(self):
        return f"<Submission(id={self.id})>"


    @property
    #@cache.memoize(timeout=60)
    def domain_obj(self):
        if not self.domain_ref:
            return None
        
        return db.query(Domain).filter_by(id=self.domain_ref).first()


    @property
    @cache.memoize(timeout=60)
    def score_percent(self):
        try:
            return int((self.ups/(self.ups+self.downs))*100)
        except ZeroDivisionError:
            return 0

    @property
    def base36id(self):
        return base36encode(self.id)

    @property
    def fullname(self):
        return f"t2_{self.base36id}"

    @property
    def permalink(self):
        return f"/post/{self.base36id}"
                                      
    def rendered_page(self, comment=None, v=None):

        #check for banned
        if self.is_banned:
            if v and v.admin_level>=3:
                template="submission.html"
            else:
                template="submission_banned.html"
        else:
            template="submission.html"

        #load and tree comments
        #calling this function with a comment object will do a comment permalink thing
        self.tree_comments(comment=comment)
        
        #return template
        return render_template(template, v=v, p=self, sort_method=request.args.get("sort","Hot").capitalize(), linked_comment=comment)

    @property
    @lazy
    def author(self):
        return db.query(User).filter_by(id=self.author_id).first()


    @property
    @lazy
    def domain(self):

        if not self.url:
            return "text post"
        domain= urlparse(self.url).netloc
        if domain.startswith("www."):
            domain=domain.split("www.")[1]
        return domain
    
    @property
    def score_fuzzed(self, k=0.01):
        real=self.score
        a=math.floor(real*(1-k))
        b=math.ceil(real*(1+k))
        return random.randint(a,b)        

    def tree_comments(self, comment=None):

        def tree_replies(thing, layer=1):

            thing.__dict__["replies"]=[]
            i=len(comments)-1
        
            while i>=0:
                if comments[i].parent_fullname==thing.fullname:
                    thing.__dict__["replies"].append(comments[i])
                    comments.pop(i)

                i-=1
                
            if layer <=8:
                for reply in thing.replies:
                    tree_replies(reply, layer=layer+1)
                
        ######
                
        if comment:
            self.replies=[comment]
            return



        #get sort type
        sort_type = request.args.get("sort","hot")


        #Treeing is done from the end because reasons, so these sort orders are reversed
        if sort_type=="hot":
            comments=self.comments.order_by(text("comments.rank_hot ASC")).all()
        elif sort_type=="top":
            comments=self.comments.order_by(text("comments.score ASC")).all()
        elif sort_type=="new":
            comments=self.comments.order_by(text("comments.created_utc")).all()
        elif sort_type=="disputed":
            comments=self.comments.order_by(text("comments.rank_fiery ASC")).all()
        elif sort_type=="random":
            c=self.comments.all()
            comments=random.sample(c, k=len(c))
        else:
            abort(422)



        tree_replies(self)

        

        
    @property
    def age_string(self):

        age=self.age

        if age<60:
            return "just now"
        elif age<3600:
            minutes=int(age/60)
            return f"{minutes} minute{'s' if minutes>1 else ''} ago"
        elif age<86400:
            hours=int(age/3600)
            return f"{hours} hour{'s' if hours>1 else ''} ago"
        elif age<2592000:
            days=int(age/86400)
            return f"{days} day{'s' if days>1 else ''} ago"

        now=time.gmtime()
        ctd=time.gmtime(self.created_utc)
        months=now.tm_mon-ctd.tm_mon+12*(now.tm_year-ctd.tm_year)

        if months < 12:
            return f"{months} month{'s' if months>1 else ''} ago"
        else:
            years=now.tm_year-ctd.tm_year
            return f"{years} year{'s' if years>1 else ''} ago"

    @property
    def edited_string(self):

        age=int(time.time())-self.edited_utc

        if age<60:
            return "just now"
        elif age<3600:
            minutes=int(age/60)
            return f"{minutes} minute{'s' if minutes>1 else ''} ago"
        elif age<86400:
            hours=int(age/3600)
            return f"{hours} hour{'s' if hours>1 else ''} ago"
        elif age<2592000:
            days=int(age/86400)
            return f"{days} day{'s' if days>1 else ''} ago"

        now=time.gmtime()
        ctd=time.gmtime(self.created_utc)
        months=now.tm_mon-ctd.tm_mon+12*(now.tm_year-ctd.tm_year)

        if months < 12:
            return f"{months} month{'s' if months>1 else ''} ago"
        else:
            years=now.tm_year-ctd.tm_year
            return f"{years} year{'s' if years>1 else ''} ago"
        

    @property
    def created_date(self):
        return time.strftime("%d %B %Y", time.gmtime(self.created_utc))

    @property
    def edited_date(self):
        return time.strftime("%d %B %Y", time.gmtime(self.edited_utc))

    @property
    def active_flags(self):
        if self.is_approved:
            return 0
        else:
            return self.flags.filter(Flag.created_utc>self.approved_utc).count()

    @property
    def approved_by(self):
        return db.query(User).filter_by(id=self.is_approved).first()
from werkzeug.security import generate_password_hash, check_password_hash
from flask import render_template, session, request
from time import strftime, time, gmtime
from sqlalchemy import *
from sqlalchemy.orm import relationship, deferred
from os import environ
from secrets import token_hex
import random

from ruqqus.helpers.base36 import *
from ruqqus.helpers.security import *
from ruqqus.helpers.lazy import lazy
from .votes import Vote
from .alts import Alt
from ruqqus.__main__ import Base, db, cache

class User(Base):

    __tablename__="users"
    id = Column(Integer, primary_key=True)
    username = Column(String, default=None)
    email = Column(String, default=None)
    passhash = Column(String, default=None)
    created_utc = Column(BigInteger, default=0)
    admin_level = Column(Integer, default=0)
    is_activated = Column(Boolean, default=False)
    reddit_username = Column(String, default=None)
    over_18=Column(Boolean, default=False)
    creation_ip=Column(String, default=None)
    most_recent_ip=Column(String, default=None)
    submissions=relationship("Submission", lazy="dynamic", backref="users")
    comments=relationship("Comment", lazy="dynamic", primaryjoin="Comment.author_id==User.id")
    votes=relationship("Vote", lazy="dynamic", backref="users")
    commentvotes=relationship("CommentVote", lazy="dynamic", backref="users")
    bio=deferred(Column(String, default=""))
    bio_html=deferred(Column(String, default=""))
    badges=relationship("Badge", lazy="dynamic", backref="user")
    real_id=Column(String, default=None)
    notifications=relationship("Notification", lazy="dynamic", backref="user")
    referred_by=Column(Integer, default=None)
    is_banned=Column(Integer, default=0)
    ban_reason=Column(String, default="")

    #properties defined as SQL server-side functions
    energy = deferred(Column(Integer, server_default=FetchedValue()))
    referral_count=deferred(Column(Integer, server_default=FetchedValue()))



    def __init__(self, **kwargs):

        if "password" in kwargs:

            kwargs["passhash"]=self.hash_password(kwargs["password"])
            kwargs.pop("password")

        kwargs["created_utc"]=int(time())

        super().__init__(**kwargs)

    @property
    @cache.memoize(timeout=60)
    def karma(self):
        return self.energy


    @property
    def base36id(self):
        return base36encode(self.id)

    @property
    def fullname(self):
        return f"t1_{self.base36id}"

    @property
    def banned_by(self):

        if not self.is_banned:
            return None

        return db.query(User).filter_by(id=self.is_banned).first()
    
    def vote_status_on_post(self, post):

        vote = self.votes.filter_by(submission_id=post.id).first()
        if not vote:
            return 0
        
        return vote.vote_type


    def vote_status_on_comment(self, comment):

        vote = self.commentvotes.filter_by(comment_id=comment.id).first()
        if not vote:
            return 0
        
        return vote.vote_type
    
    def update_ip(self, remote_addr):
        
        if not remote_addr==self.most_recent_ip:
            self.most_recent_ip = remote_addr
            db.add(self)

        existing=self.ips.filter_by(ip=remote_addr).first()

        if existing:
            existing.created_utc=time()
            db.add(existing)
            
        else:
            db.add(IP(user_id=self.id, ip=remote_addr))
        
        db.commit()

    def hash_password(self, password):
        return generate_password_hash(password, method='pbkdf2:sha512', salt_length=8)

    def verifyPass(self, password):
        return check_password_hash(self.passhash, password)
        
    def rendered_userpage(self, v=None):

        if self.is_banned and (not v or v.admin_level < 3):
            return render_template("userpage_banned.html", u=self, v=v)

        page=int(request.args.get("page","1"))
        page=max(page, 1)

        
        if v:
            if v.admin_level or v.id==self.id:
                listing=[p for p in self.submissions.order_by(text("created_utc desc")).offset(25*(page-1)).limit(26)]
            else:
                listing=[p for p in self.submissions.filter_by(is_banned=False).order_by(text("created_utc desc")).offset(25*(page-1)).limit(26)]
        else:
            listing=[p for p in self.submissions.filter_by(is_banned=False).order_by(text("created_utc desc")).offset(25*(page-1)).limit(26)]

        #we got 26 items just to see if a next page exists
        next_exists=(len(listing)==26)
        listing=listing[0:25]

        return render_template("userpage.html", u=self, v=v, listing=listing, page=page, next_exists=next_exists)

    def rendered_comments_page(self, v=None):

        if self.is_banned and (not v or v.admin_level < 3):
            return render_template("userpage_banned.html", u=self, v=v)
        
        page=int(request.args.get("page","1"))

        if v:
            if v.admin_level or v.id==self.id:
                listing=[p for p in self.comments.order_by(text("created_utc desc")).offset(25*(page-1)).limit(26)]
            else:
                listing=[p for p in self.comments.filter_by(is_banned=False).order_by(text("created_utc desc")).offset(25*(page-1)).limit(26)]
        else:
            listing=[p for p in self.comments.filter_by(is_banned=False).order_by(text("created_utc desc")).offset(25*(page-1)).limit(26)]

        #we got 26 items just to see if a next page exists
        next_exists=(len(listing)==26)
        listing=listing[0:25]
        
        return render_template("userpage_comments.html", u=self, v=v, listing=listing, page=page, next_exists=next_exists)

    @property
    def formkey(self):

        if "session_id" not in session:
            session["session_id"]=token_hex(16)

        msg=f"{session['session_id']}{self.id}"

        return generate_hash(msg)

    def validate_formkey(self, formkey):

        return validate_hash(f"{session['session_id']}{self.id}", formkey)
    
    @property
    def url(self):
        return f"/@{self.username}"

    @property
    def permalink(self):
        return self.url

    @property
    @lazy
    def created_date(self):

        return strftime("%d %B %Y", gmtime(self.created_utc))

    def __repr__(self):
        return f"<User(username={self.username})>"


    @property
    @lazy
    def color(self):

        random.seed(f"{self.id}+{self.username}")

        R=random.randint(32, 223)
        G=random.randint(32, 223)
        B=random.randint(32, 223)
        

        return str(base_encode(R, 16))+str(base_encode(G, 16))+str(base_encode(B, 16))

    def notifications_page(self, page=1, include_read=False):

        page=int(page)

        notifications=self.notifications.filter_by(is_banned=False, is_deleted=False)

        if not include_read:
            notifications=notifications.filter_by(read=False)

        notifications = notifications.order_by(text("notifications.created_utc desc")).offset(25*(page-1)).limit(25)

        comments=[n.comment for n in notifications]

        for n in notifications:
            if not n.read:
                n.read=True
                db.add(n)
                db.commit()

        return render_template("notifications.html", v=self, notifications=comments)
    
    @property
    def notifications_count(self):

        return self.notifications.filter_by(read=False, is_banned=False, is_deleted=False).count()

    @property
    @cache.memoize(timeout=60)
    def post_count(self):

        return self.submissions.filter_by(is_banned=False).count()

    @property
    @cache.memoize(timeout=60) 
    def comment_count(self):

        return self.comments.filter_by(is_banned=False, is_deleted=False).count()

    @property
    #@cache.memoize(timeout=60)
    def badge_pairs(self):

        output=[]

        badges=[x for x in self.badges.all()]

        while badges:
            
            to_append=[badges.pop(0)]
            
            if badges:
                to_append.append(badges.pop(0))
                
            output.append(to_append)

        return output

    @property
    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]))
        
        
from flask import render_template
import time
from sqlalchemy import *
from sqlalchemy.orm import relationship, deferred
from random import randint
import math

from ruqqus.helpers.base36 import *
from ruqqus.helpers.lazy import lazy
from ruqqus.__main__ import Base, db, cache
from .user import User
from .submission import Submission
from .votes import CommentVote
from .flags import CommentFlag

class Comment(Base):

    __tablename__="comments"

    id = Column(BigInteger, primary_key=True)
    author_id = Column(BigInteger, ForeignKey(User.id))
    body = Column(String(2000), default=None)
    parent_submission = Column(BigInteger, ForeignKey(Submission.id))
    parent_fullname = Column(BigInteger) #this column is foreignkeyed to comment(id) but we can't do that yet as "comment" class isn't yet defined
    created_utc = Column(BigInteger, default=0)
    edited_timestamp = Column(BigInteger, default=0)
    is_banned = Column(Boolean, default=False)
    body_html = Column(String)
    distinguish_level=Column(Integer, default=0)
    is_deleted = Column(Boolean, default=False)
    is_approved = Column(Integer, default=0)
    approved_utc=Column(Integer, default=0)

    #These are virtual properties handled as postgres functions server-side
    #There is no difference to SQLAlchemy, but they cannot be written to
    ups = Column(Integer, server_default=FetchedValue())
    downs=Column(Integer, server_default=FetchedValue())
    age=Column(Integer, server_default=FetchedValue())
    flags=relationship("CommentFlag", lazy="dynamic", backref="comment")
    flag_count=Column(Integer, server_default=FetchedValue())

    def __init__(self, *args, **kwargs):
                   

        if "created_utc" not in kwargs:
            kwargs["created_utc"]=int(time.time())
            
        for x in kwargs:
            if x not in ["ups","downs","score","rank_hot","rank_fiery","age","comment_count"]:
                self.__dict__[x]=kwargs[x]
                
    def __repr__(self):
        return f"<Comment(id={self.id})"
        

    @property
    @cache.memoize(timeout=60)
    def rank_hot(self):
        return (self.ups-self.down)/(((self.age+100000)/6)**(1/3))

    @property
    @cache.memoize(timeout=60)
    def rank_fiery(self):
        return (math.sqrt(self.ups * self.downs))/(((self.age+100000)/6)**(1/3))

    @property
    @cache.memoize(timeout=60)
    def score(self):
        return self.ups-self.downs
                

    @property
    def base36id(self):
        return base36encode(self.id)

    @property
    def fullname(self):
        return f"t3_{self.base36id}"

    @property
    def is_top_level(self):
        return self.parent_fullname.startswith("t2_")

    @property
    @lazy
    def author(self):
        return db.query(User).filter_by(id=self.author_id).first()

    @property
    @lazy
    def post(self):

        return db.query(Submission).filter_by(id=self.parent_submission).first()
    
    @property
    @lazy
    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()

    @property
    def children(self):

        return db.query(Comment).filter_by(parent_comment=self.id).all()

    @property
    def replies(self):

        if "replies" in self.__dict__:
            return self.__dict__["replies"]
        else:
            return db.query(Comment).filter_by(parent_fullname=self.fullname).all()

    @property
    def permalink(self):

        return f"/post/{self.post.base36id}/comment/{self.base36id}"

    @property
    @cache.memoize(timeout=60)
    def any_descendants_live(self):

        if self.replies==[]:
            return False

        if any([not x.is_banned and not x.is_deleted for x in self.replies]):
            return True

        else:
            return any([x.any_descendants_live for x in self.replies])
        

    def rendered_comment(self, v=None, render_replies=True, standalone=False, level=1):

        if self.is_banned or self.is_deleted:
            if v and v.admin_level>1:
                return render_template("single_comment.html", v=v, c=self, replies=self.replies, render_replies=render_replies, standalone=standalone, level=level)
                
            elif self.any_descendants_live:
                return render_template("single_comment_removed.html", c=self, replies=self.replies, render_replies=render_replies, standalone=standalone, level=level)
            else:
                return ""

        return render_template("single_comment.html", v=v, c=self, replies=self.replies, render_replies=render_replies, standalone=standalone, level=level)
    
    @property
    @cache.memoize(timeout=60)
    def score_fuzzed(self, k=0.01):
        real=self.score
        a=math.floor(real*(1-k))
        b=math.ceil(real*(1+k))
        return randint(a,b)
    
    @property
    def age_string(self):

        age=self.age

        if age<60:
            return "just now"
        elif age<3600:
            minutes=int(age/60)
            return f"{minutes} minute{'s' if minutes>1 else ''} ago"
        elif age<86400:
            hours=int(age/3600)
            return f"{hours} hour{'s' if hours>1 else ''} ago"
        elif age<2592000:
            days=int(age/86400)
            return f"{days} day{'s' if days>1 else ''} ago"

        now=time.gmtime()
        ctd=time.gmtime(self.created_utc)
        months=now.tm_mon-ctd.tm_mon+12*(now.tm_year-ctd.tm_year)

        if months < 12:
            return f"{months} month{'s' if months>1 else ''} ago"
        else:
            years=now.tm_year-ctd.tm_year
            return f"{years} year{'s' if years>1 else ''} ago"

    @property
    def edited_string(self):

        if not self.edited_timestamp:
            return None

        age=int(time.time()-self.edited_timestamp)

        if age<60:
            return "just now"
        elif age<3600:
            minutes=int(age/60)
            return f"{minutes} minute{'s' if minutes>1 else ''} ago"
        elif age<86400:
            hours=int(age/3600)
            return f"{hours} hour{'s' if hours>1 else ''} ago"
        elif age<2592000:
            days=int(age/86400)
            return f"{days} day{'s' if days>1 else ''} ago"

        now=time.gmtime()
        ctd=time.gmtime(self.created_utc)
        months=now.tm_mon-ctd.tm_mon+12*(now.tm_year-ctd.tm_year)

        if months < 12:
            return f"{months} month{'s' if months>1 else ''} ago"
        else:
            years=now.tm_year-ctd.tm_year
            return f"{years} year{'s' if years>1 else ''} ago"

    @property
    def active_flags(self):
        if self.is_approved:
            return 0
        else:
            return self.flag_count
        
class Notification(Base):

    __tablename__="notifications"

    id=Column(Integer, primary_key=True)
    user_id=Column(Integer, ForeignKey("users.id"))
    comment_id=Column(Integer, ForeignKey("comments.id"))
    read=Column(Boolean, default=False)

    #Server side computed values (copied from corresponding comment)
    created_utc=Column(Integer, server_default=FetchedValue())
    is_banned=Column(Boolean, server_default=FetchedValue())
    is_deleted=Column(Boolean, server_default=FetchedValue())

    def __repr__(self):

        return f"<Notification(id={self.id})"

    @property
    def comment(self):

        return db.query(Comment).filter_by(id=self.comment_id).first()
View our code
import time
from ruqqus.helpers.wrappers
import *
from flask
import *

from ruqqus.__main__
import app, db, cache
from ruqqus.classes
import *

@cache.memoize(timeout = 30)
def frontlist(sort = "hot", page = 1):

cutoff = int(time.time()) - (60 * 60 * 24 * 30)

posts = db.query(Submission).filter(Submission.created_utc >= cutoff,
Submission.is_banned == False,
Submission.stickied == False)

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"))

posts = [x.id
for x in posts.offset(25 * (page - 1)).limit(25).all()
]

return posts

@app.route("/", methods = ["GET"])
@auth_desired
def home(v):

page = int(request.args.get("page", 1))

sort_method = request.args.get("sort", "hot")

# get list of ids
ids = frontlist(sort = sort_method, page = page)

# 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()

# 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, sort_method = sort_method)

Make a Ruqqus today.

Sign up and become part of the community in less than 17.76 seconds.