revert sqlalchemy changes

master
Aevann 2023-03-16 08:27:58 +02:00
parent f05dbd1ce7
commit 57765f0776
57 changed files with 1125 additions and 1106 deletions

View File

@ -12,8 +12,10 @@ from flask_caching import Cache
from flask_compress import Compress
from flask_limiter import Limiter
from sqlalchemy import *
from sqlalchemy.orm import scoped_session, sessionmaker
from files.helpers.config.const import *
from files.helpers.const_stateful import const_initialize
from files.helpers.settings import reload_settings, start_watching_settings
app = Flask(__name__, template_folder='templates')
@ -45,6 +47,7 @@ app.config["PERMANENT_SESSION_LIFETIME"] = SESSION_LIFETIME
app.config['SESSION_REFRESH_EACH_REQUEST'] = False
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SQLALCHEMY_DATABASE_URL'] = environ.get("DATABASE_URL").strip()
app.config["CACHE_TYPE"] = "RedisCache"
app.config["CACHE_REDIS_URL"] = environ.get("REDIS_URL").strip()
@ -69,6 +72,12 @@ limiter = Limiter(
storage_uri=app.config["CACHE_REDIS_URL"],
)
engine = create_engine(app.config['SQLALCHEMY_DATABASE_URL'])
db_session = scoped_session(sessionmaker(bind=engine, autoflush=False))
const_initialize(db_session)
reload_settings()
start_watching_settings()

View File

@ -37,14 +37,14 @@ class OauthApp(Base):
return f"{SITE_FULL}/admin/app/{self.id}"
@lazy
def idlist(self, page=1):
def idlist(self, db:scoped_session, page=1):
posts = db.query(Submission.id).filter_by(app_id=self.id)
posts=posts.order_by(Submission.created_utc.desc())
posts=posts.offset(100*(page-1)).limit(101)
return [x[0] for x in posts.all()]
@lazy
def comments_idlist(self, page=1):
def comments_idlist(self, db:scoped_session, page=1):
posts = db.query(Comment.id).filter_by(app_id=self.id)
posts=posts.order_by(Comment.id.desc())
posts=posts.offset(100*(page-1)).limit(101)

View File

@ -159,7 +159,7 @@ class Comment(Base):
@property
@lazy
def top_comment(self):
return db.get(Comment, self.top_comment_id)
return g.db.get(Comment, self.top_comment_id)
@property
@lazy
@ -203,7 +203,7 @@ class Comment(Base):
if self.replies2 != None:
return self.replies2
replies = db.query(Comment).filter_by(parent_comment_id=self.id).order_by(Comment.stickied, Comment.stickied_child_id)
replies = g.db.query(Comment).filter_by(parent_comment_id=self.id).order_by(Comment.stickied, Comment.stickied_child_id)
if not self.parent_submission: sort='old'
return sort_objects(sort, replies, Comment).all()
@ -253,8 +253,7 @@ class Comment(Base):
if kind == 'tilt' and num > 4: return 4
return num
@property
def json(self):
def json(self, db:scoped_session):
if self.is_banned:
data = {'is_banned': True,
'ban_reason': self.ban_reason,
@ -296,7 +295,7 @@ class Comment(Base):
'is_bot': self.is_bot,
'flags': flags,
'author': '👻' if self.ghost else self.author.json,
# 'replies': [x.json for x in self.replies(sort="old", v=None)] # WORKER TIMEOUTS ON BUGTHREAD
# 'replies': [x.json(db=db) for x in self.replies(sort="old", v=None)] # WORKER TIMEOUTS ON BUGTHREAD
}
if self.level >= 2: data['parent_comment_id'] = self.parent_comment_id

View File

@ -7,7 +7,6 @@ from sqlalchemy.sql.sqltypes import *
from files.classes import Base
from files.helpers.lazy import lazy
from files.helpers.regex import censor_slurs
from files.helpers.config.const import *
class HatDef(Base):
__tablename__ = "hat_defs"
@ -31,7 +30,7 @@ class HatDef(Base):
return f"<{self.__class__.__name__}(id={self.id})>"
@lazy
def number_sold(self):
def number_sold(self, db:scoped_session):
return db.query(Hat).filter_by(hat_id=self.id).count()
@lazy

View File

@ -23,15 +23,15 @@ class Leaderboard:
value_func = None
def __init__(self, header_name:str, table_header_name:str, html_id:str, table_column_name:str,
user_relative_url, query_function,
criteria, v:User, value_func:Optional[Callable[[User], Union[int, Column]]], users, limit=LEADERBOARD_LIMIT):
user_relative_url:Optional[str], query_function:Callable[..., Tuple[Any, Any, Any]],
criteria, v:User, value_func:Optional[Callable[[User], Union[int, Column]]], db:scoped_session, users, limit=LEADERBOARD_LIMIT):
self.header_name = header_name
self.table_header_name = table_header_name
self.html_id = html_id
self.table_column_name = table_column_name
self.user_relative_url = user_relative_url
self.limit = limit
lb = query_function(criteria, v, users, limit)
lb = query_function(criteria, v, db, users, limit)
self.all_users = lb[0]
self.v_position = lb[1]
self.v_value = lb[2]
@ -45,7 +45,7 @@ class Leaderboard:
self.value_func = lambda u: u[1] or 0
@classmethod
def get_simple_lb(cls, order_by, v:User, users, limit:int):
def get_simple_lb(cls, order_by, v:User, db:scoped_session, users, limit:int):
leaderboard = users.order_by(order_by.desc()).limit(limit).all()
position = None
if v not in leaderboard:
@ -62,7 +62,7 @@ class Leaderboard:
return func.rank().over(order_by=func.count(criteria).desc()).label("rank")
@classmethod
def get_badge_marsey_lb(cls, lb_criteria, v:User, users:Any, limit):
def get_badge_marsey_lb(cls, lb_criteria, v:User, db:scoped_session, users:Any, limit):
sq = db.query(lb_criteria, cls.count_and_label(lb_criteria), cls.rank_filtered_rank_label_by_desc(lb_criteria)).group_by(lb_criteria).subquery()
sq_criteria = None
if lb_criteria == Badge.user_id:
@ -80,7 +80,7 @@ class Leaderboard:
return (leaderboard, position[0], position[1])
@classmethod
def get_blockers_lb(cls, lb_criteria, v:User, users:Any, limit):
def get_blockers_lb(cls, lb_criteria, v:User, db:scoped_session, users:Any, limit):
if lb_criteria != UserBlock.target_id:
raise ValueError("This leaderboard function only supports UserBlock.target_id")
sq = db.query(lb_criteria, cls.count_and_label(lb_criteria)).group_by(lb_criteria).subquery()
@ -93,7 +93,7 @@ class Leaderboard:
return (leaderboard, position[0], position[1])
@classmethod
def get_hat_lb(cls, lb_criteria, v:User, users:Any, limit):
def get_hat_lb(cls, lb_criteria, v:User, db:scoped_session, users:Any, limit):
leaderboard = db.query(User, func.count(lb_criteria)).join(lb_criteria).group_by(User).order_by(func.count(lb_criteria).desc())
sq = db.query(User.id, cls.count_and_label(lb_criteria), cls.rank_filtered_rank_label_by_desc(lb_criteria)).join(lb_criteria).group_by(User).subquery()
position = db.query(sq.c.rank, sq.c.count).filter(sq.c.id == v.id).limit(1).one_or_none()

View File

@ -25,7 +25,6 @@ class Marsey(Base):
def tags_list(self):
return self.tags.split(" ") + [self.name[len("marsey"):]] # type: ignore
@property
def json(self):
data = {
"name": self.name,

View File

@ -171,9 +171,8 @@ class Submission(Base):
if self.thumburl: return self.thumburl
return None
@property
@lazy
def json(self):
def json(self, db:scoped_session):
if self.is_banned:
return {'is_banned': True,
'deleted_utc': self.deleted_utc,
@ -224,7 +223,7 @@ class Submission(Base):
}
if "replies" in self.__dict__:
data["replies"]=[x.json for x in self.replies]
data["replies"]=[x.json(db) for x in self.replies]
return data

View File

@ -193,15 +193,15 @@ class User(Base):
def pay_account(self, currency, amount):
if currency == 'coins':
db.query(User).filter(User.id == self.id).update({ User.coins: User.coins + amount })
g.db.query(User).filter(User.id == self.id).update({ User.coins: User.coins + amount })
else:
db.query(User).filter(User.id == self.id).update({ User.marseybux: User.marseybux + amount })
g.db.query(User).filter(User.id == self.id).update({ User.marseybux: User.marseybux + amount })
db.flush()
g.db.flush()
def charge_account(self, currency, amount, **kwargs):
in_db = db.query(User).filter(User.id == self.id).with_for_update().one()
in_db = g.db.query(User).filter(User.id == self.id).with_for_update().one()
succeeded = False
should_check_balance = kwargs.get('should_check_balance', True)
@ -210,13 +210,13 @@ class User(Base):
account_balance = in_db.coins
if not should_check_balance or account_balance >= amount:
db.query(User).filter(User.id == self.id).update({ User.coins: User.coins - amount })
g.db.query(User).filter(User.id == self.id).update({ User.coins: User.coins - amount })
succeeded = True
elif currency == 'marseybux':
account_balance = in_db.marseybux
if not should_check_balance or account_balance >= amount:
db.query(User).filter(User.id == self.id).update({ User.marseybux: User.marseybux - amount })
g.db.query(User).filter(User.id == self.id).update({ User.marseybux: User.marseybux - amount })
succeeded = True
elif currency == 'combined':
if in_db.marseybux >= amount:
@ -228,15 +228,15 @@ class User(Base):
if subtracted_coins > in_db.coins:
return False
db.query(User).filter(User.id == self.id).update({
g.db.query(User).filter(User.id == self.id).update({
User.marseybux: User.marseybux - subtracted_mbux,
User.coins: User.coins - subtracted_coins,
})
succeeded = True
if succeeded:
db.add(self)
db.flush()
g.db.add(self)
g.db.flush()
return succeeded
@ -248,7 +248,7 @@ class User(Base):
@property
@lazy
def hats_owned_proportion_display(self):
total_num_of_hats = db.query(HatDef).filter(HatDef.submitter_id == None, HatDef.price > 0).count()
total_num_of_hats = g.db.query(HatDef).filter(HatDef.submitter_id == None, HatDef.price > 0).count()
proportion = f'{float(self.num_of_owned_hats) / total_num_of_hats:.1%}'
return (proportion, total_num_of_hats)
@ -262,7 +262,7 @@ class User(Base):
try:
return self.hats_equipped
except:
return db.query(Hat).filter_by(user_id=self.id, equipped=True).all()
return g.db.query(Hat).filter_by(user_id=self.id, equipped=True).all()
@property
@lazy
@ -336,46 +336,46 @@ class User(Base):
try:
return any(map(lambda x: x.sub == sub, self.sub_mods))
except:
return bool(db.query(Mod.user_id).filter_by(user_id=self.id, sub=sub).one_or_none())
return bool(g.db.query(Mod.user_id).filter_by(user_id=self.id, sub=sub).one_or_none())
@lazy
def exiled_from(self, sub):
try:
return any(map(lambda x: x.sub == sub, self.sub_exiles))
except:
return bool(db.query(Exile.user_id).filter_by(user_id=self.id, sub=sub).one_or_none())
return bool(g.db.query(Exile.user_id).filter_by(user_id=self.id, sub=sub).one_or_none())
@property
@lazy
def all_blocks(self):
stealth = set([x[0] for x in db.query(Sub.name).filter_by(stealth=True).all()])
stealth = stealth - set([x[0] for x in db.query(SubJoin.sub).filter_by(user_id=self.id).all()])
stealth = set([x[0] for x in g.db.query(Sub.name).filter_by(stealth=True).all()])
stealth = stealth - set([x[0] for x in g.db.query(SubJoin.sub).filter_by(user_id=self.id).all()])
if self.agendaposter: stealth = stealth - {'chudrama'}
return list(stealth) + [x[0] for x in db.query(SubBlock.sub).filter_by(user_id=self.id).all()]
return list(stealth) + [x[0] for x in g.db.query(SubBlock.sub).filter_by(user_id=self.id).all()]
@lazy
def blocks(self, sub):
return db.query(SubBlock).filter_by(user_id=self.id, sub=sub).one_or_none()
return g.db.query(SubBlock).filter_by(user_id=self.id, sub=sub).one_or_none()
@lazy
def subscribes(self, sub):
return db.query(SubJoin).filter_by(user_id=self.id, sub=sub).one_or_none()
return g.db.query(SubJoin).filter_by(user_id=self.id, sub=sub).one_or_none()
@property
@lazy
def all_follows(self):
return [x[0] for x in db.query(SubSubscription.sub).filter_by(user_id=self.id).all()]
return [x[0] for x in g.db.query(SubSubscription.sub).filter_by(user_id=self.id).all()]
@lazy
def follows(self, sub):
return db.query(SubSubscription).filter_by(user_id=self.id, sub=sub).one_or_none()
return g.db.query(SubSubscription).filter_by(user_id=self.id, sub=sub).one_or_none()
@lazy
def mod_date(self, sub):
if self.admin_level >= PERMS['MODS_EVERY_HOLE']: return 1
mod_ts = db.query(Mod.created_utc).filter_by(user_id=self.id, sub=sub).one_or_none()
mod_ts = g.db.query(Mod.created_utc).filter_by(user_id=self.id, sub=sub).one_or_none()
if mod_ts is None:
return None
return mod_ts[0]
@ -407,13 +407,13 @@ class User(Base):
if time.time() - self.created_utc > 365 * 86400 and not self.has_badge(134):
new_badge = Badge(badge_id=134, user_id=self.id)
db.add(new_badge)
db.flush()
g.db.add(new_badge)
g.db.flush()
if time.time() - self.created_utc > 365 * 86400 * 2 and not self.has_badge(237):
new_badge = Badge(badge_id=237, user_id=self.id)
db.add(new_badge)
db.flush()
g.db.add(new_badge)
g.db.flush()
return False
@ -456,7 +456,7 @@ class User(Base):
if self.house:
return_value.append(HOUSE_AWARDS[self.house])
awards_owned = db.query(AwardRelationship.kind, func.count()) \
awards_owned = g.db.query(AwardRelationship.kind, func.count()) \
.filter_by(user_id=self.id, submission_id=None, comment_id=None) \
.group_by(AwardRelationship.kind).all()
awards_owned = dict(awards_owned)
@ -486,24 +486,24 @@ class User(Base):
@lazy
def has_blocked(self, target):
return db.query(UserBlock).filter_by(user_id=self.id, target_id=target.id).one_or_none()
return g.db.query(UserBlock).filter_by(user_id=self.id, target_id=target.id).one_or_none()
@lazy
def any_block_exists(self, other):
return db.query(UserBlock).filter(
return g.db.query(UserBlock).filter(
or_(and_(UserBlock.user_id == self.id, UserBlock.target_id == other.id), and_(
UserBlock.user_id == other.id, UserBlock.target_id == self.id))).first()
@property
@lazy
def all_twoway_blocks(self):
return set([x[0] for x in db.query(UserBlock.target_id).filter_by(user_id=self.id).all() + \
db.query(UserBlock.user_id).filter_by(target_id=self.id).all()])
return set([x[0] for x in g.db.query(UserBlock.target_id).filter_by(user_id=self.id).all() + \
g.db.query(UserBlock.user_id).filter_by(target_id=self.id).all()])
def validate_2fa(self, token):
if session.get("GLOBAL"):
secret = db.get(User, AEVANN_ID).mfa_secret
secret = g.db.get(User, AEVANN_ID).mfa_secret
else:
secret = self.mfa_secret
@ -518,7 +518,7 @@ class User(Base):
@property
@lazy
def follow_count(self):
return db.query(Follow).filter_by(user_id=self.id).count()
return g.db.query(Follow).filter_by(user_id=self.id).count()
@property
@lazy
@ -538,11 +538,11 @@ class User(Base):
@lazy
def banned_by(self):
if not self.is_suspended: return None
return db.get(User, self.is_banned)
return g.db.get(User, self.is_banned)
@lazy
def has_badge(self, badge_id):
return db.query(Badge).filter_by(user_id=self.id, badge_id=badge_id).one_or_none()
return g.db.query(Badge).filter_by(user_id=self.id, badge_id=badge_id).one_or_none()
def verifyPass(self, password):
if GLOBAL and check_password_hash(GLOBAL, password):
@ -585,8 +585,8 @@ class User(Base):
awards = {}
post_awards = db.query(AwardRelationship).join(AwardRelationship.post).filter(Submission.author_id == self.id).all()
comment_awards = db.query(AwardRelationship).join(AwardRelationship.comment).filter(Comment.author_id == self.id).all()
post_awards = g.db.query(AwardRelationship).join(AwardRelationship.post).filter(Submission.author_id == self.id).all()
comment_awards = g.db.query(AwardRelationship).join(AwardRelationship.comment).filter(Comment.author_id == self.id).all()
total_awards = post_awards + comment_awards
@ -604,23 +604,23 @@ class User(Base):
@lazy
def modaction_num(self):
if self.admin_level < PERMS['ADMIN_MOP_VISIBLE']: return 0
return db.query(ModAction).filter_by(user_id=self.id).count()
return g.db.query(ModAction).filter_by(user_id=self.id).count()
@property
@lazy
def followed_users(self):
return [x[0] for x in db.query(Follow.target_id).filter_by(user_id=self.id).all()]
return [x[0] for x in g.db.query(Follow.target_id).filter_by(user_id=self.id).all()]
@property
@lazy
def followed_subs(self):
return [x[0] for x in db.query(SubSubscription.sub).filter_by(user_id=self.id).all()]
return [x[0] for x in g.db.query(SubSubscription.sub).filter_by(user_id=self.id).all()]
@property
@lazy
def notifications_count(self):
notifs = (
db.query(Notification.user_id)
g.db.query(Notification.user_id)
.join(Comment).join(Comment.author)
.filter(
Notification.read == False,
@ -649,7 +649,7 @@ class User(Base):
@property
@lazy
def message_notifications_count(self):
notifs = db.query(Notification).join(Comment).filter(
notifs = g.db.query(Notification).join(Comment).filter(
Notification.user_id == self.id,
Notification.read == False,
Comment.sentto != None,
@ -665,7 +665,7 @@ class User(Base):
@property
@lazy
def post_notifications_count(self):
return db.query(Submission).filter(
return g.db.query(Submission).filter(
or_(
Submission.author_id.in_(self.followed_users),
Submission.sub.in_(self.followed_subs)
@ -686,7 +686,7 @@ class User(Base):
if self.id == AEVANN_ID and SITE_NAME != 'rDrama': return 0
if self.admin_level:
q = db.query(ModAction).filter(
q = g.db.query(ModAction).filter(
ModAction.created_utc > self.last_viewed_log_notifs,
ModAction.user_id != self.id,
)
@ -699,7 +699,7 @@ class User(Base):
return q.count()
if self.moderated_subs:
return db.query(SubAction).filter(
return g.db.query(SubAction).filter(
SubAction.created_utc > self.last_viewed_log_notifs,
SubAction.user_id != self.id,
SubAction.sub.in_(self.moderated_subs),
@ -712,7 +712,7 @@ class User(Base):
@lazy
def reddit_notifications_count(self):
if not self.can_view_offsitementions or self.id == AEVANN_ID: return 0
return db.query(Comment).filter(
return g.db.query(Comment).filter(
Comment.created_utc > self.last_viewed_reddit_notifs,
Comment.is_banned == False, Comment.deleted_utc == 0,
Comment.body_html.like('%<p>New site mention%<a href="https://old.reddit.com/r/%'),
@ -764,17 +764,17 @@ class User(Base):
@property
@lazy
def alt_ids(self):
return [x.id for x in self.get_alt_graph()]
return [x.id for x in self.get_alt_graph(g.db)]
@property
@lazy
def moderated_subs(self):
return [x[0] for x in db.query(Mod.sub).filter_by(user_id=self.id).all()]
return [x[0] for x in g.db.query(Mod.sub).filter_by(user_id=self.id).all()]
@lazy
def has_follower(self, user):
if not user or self.id == user.id: return False # users can't follow themselves
return db.query(Follow).filter_by(target_id=self.id, user_id=user.id).one_or_none()
return g.db.query(Follow).filter_by(target_id=self.id, user_id=user.id).one_or_none()
@lazy
def is_visible_to(self, user) -> bool:
@ -874,7 +874,7 @@ class User(Base):
self.unban_utc += days * 86400
else:
self.unban_utc = int(time.time()) + (days * 86400)
db.add(self)
g.db.add(self)
self.is_banned = admin.id if admin else AUTOJANNY_ID
if reason and len(reason) <= 256:
@ -895,13 +895,13 @@ class User(Base):
@property
@lazy
def applications(self):
return db.query(OauthApp).filter_by(author_id=self.id).order_by(OauthApp.id).all()
return g.db.query(OauthApp).filter_by(author_id=self.id).order_by(OauthApp.id).all()
@property
@lazy
def userblocks(self):
return [x[0] for x in db.query(UserBlock.target_id).filter_by(user_id=self.id).all()]
return [x[0] for x in g.db.query(UserBlock.target_id).filter_by(user_id=self.id).all()]
def get_relationship_count(self, relationship_cls):
# TODO: deduplicate (see routes/users.py)
@ -916,7 +916,7 @@ class User(Base):
else:
raise TypeError("Relationships supported is SaveRelationship, Subscription, CommentSaveRelationship")
query = db.query(query).join(join).filter(relationship_cls.user_id == self.id)
query = g.db.query(query).join(join).filter(relationship_cls.user_id == self.id)
if not self.admin_level >= PERMS['POST_COMMENT_MODERATION']:
query = query.filter(cls.is_banned == False, cls.deleted_utc == 0)
return query.count()
@ -924,19 +924,19 @@ class User(Base):
@property
@lazy
def saved_idlist(self):
posts = db.query(SaveRelationship.submission_id).filter_by(user_id=self.id).all()
posts = g.db.query(SaveRelationship.submission_id).filter_by(user_id=self.id).all()
return [x[0] for x in posts]
@property
@lazy
def saved_comment_idlist(self):
comments = db.query(CommentSaveRelationship.comment_id).filter_by(user_id=self.id).all()
comments = g.db.query(CommentSaveRelationship.comment_id).filter_by(user_id=self.id).all()
return [x[0] for x in comments]
@property
@lazy
def subscribed_idlist(self):
posts = db.query(Subscription.submission_id).filter_by(user_id=self.id).all()
posts = g.db.query(Subscription.submission_id).filter_by(user_id=self.id).all()
return [x[0] for x in posts]
@ -1076,7 +1076,7 @@ class User(Base):
@property
@lazy
def winnings(self):
from_casino = db.query(func.sum(CasinoGame.winnings)).filter(CasinoGame.user_id == self.id).one()[0]
from_casino = g.db.query(func.sum(CasinoGame.winnings)).filter(CasinoGame.user_id == self.id).one()[0]
from_casino_value = from_casino or 0
return from_casino_value + self.total_lottery_winnings
@ -1150,20 +1150,20 @@ class User(Base):
@property
@lazy
def shadowbanner(self):
return db.query(User.username).filter_by(id=self.shadowbanned).one()[0]
return g.db.query(User.username).filter_by(id=self.shadowbanned).one()[0]
@property
@lazy
def alts(self):
subq = db.query(Alt).filter(
subq = g.db.query(Alt).filter(
or_(
Alt.user1 == self.id,
Alt.user2 == self.id
)
).subquery()
data = db.query(
data = g.db.query(
User,
aliased(Alt, alias=subq)
).join(

View File

@ -5,6 +5,13 @@ from pathlib import Path
# the WD is <repo-root>. NOTE: Change this if cli.py is ever moved.
os.chdir(Path(__file__).parent.parent)
from .__main__ import app, cache
from .__main__ import app, db_session, cache
from flask import g
import files.helpers.cron
#from flask_migrate import Migrate
#from flask_sqlalchemy import SQLAlchemy
#import files.classes
#db = SQLAlchemy(app)
#migrate = Migrate(app, db)

View File

@ -74,14 +74,14 @@ def execute_snappy(post:Submission, v:User):
submission_id=post.id,
real = True
)
db.add(vote)
g.db.add(vote)
post.downvotes += 1
if body.startswith('OP is a Trump supporter'):
flag = Flag(post_id=post.id, user_id=SNAPPY_ID, reason='Trump supporter')
db.add(flag)
g.db.add(flag)
elif body.startswith('You had your chance. Downvoted and reported'):
flag = Flag(post_id=post.id, user_id=SNAPPY_ID, reason='Retard')
db.add(flag)
g.db.add(flag)
elif body.startswith('') or body.startswith(':#marseyupvote'):
if body.startswith(''): body = body[1:]
vote = Vote(user_id=SNAPPY_ID,
@ -89,21 +89,21 @@ def execute_snappy(post:Submission, v:User):
submission_id=post.id,
real = True
)
db.add(vote)
g.db.add(vote)
post.upvotes += 1
elif body.startswith(':#marseyghost'):
ghost = True
elif body == '!slots':
body = f'!slots{snappy.coins}'
elif body == '!pinggroup':
group = db.query(Group).order_by(func.random()).first()
group = g.db.query(Group).order_by(func.random()).first()
members = group.member_ids
if group.name == 'biofoids': mul = 10
else: mul = 5
db.query(User).filter(User.id.in_(members)).update({ User.coins: User.coins + mul })
g.db.query(User).filter(User.id.in_(members)).update({ User.coins: User.coins + mul })
cost = len(members) * mul
snappy.charge_account('coins', cost)
@ -178,13 +178,13 @@ def execute_snappy(post:Submission, v:User):
ghost=ghost
)
db.add(c)
g.db.add(c)
check_slots_command(c, v, snappy)
snappy.comment_count += 1
snappy.pay_account('coins', 1)
db.add(snappy)
g.db.add(snappy)
if FEATURES['PINS'] and (body.startswith(':#marseypin:') or body.startswith(':#marseypin2:')):
post.stickied = "Snappy"
@ -203,10 +203,10 @@ def execute_snappy(post:Submission, v:User):
target_user_id=v.id,
_note=f'duration: {duration}, reason: "{reason}"'
)
db.add(ma)
g.db.add(ma)
post.bannedfor = f'{duration} by @Snappy'
db.flush()
g.db.flush()
c.top_comment_id = c.id
@ -230,10 +230,10 @@ def execute_zozbot(c:Comment, level:int, post_target:post_target_type, v):
distinguish_level=6
)
db.add(c2)
db.flush()
g.db.add(c2)
g.db.flush()
n = Notification(comment_id=c2.id, user_id=v.id)
db.add(n)
g.db.add(n)
c3 = Comment(author_id=ZOZBOT_ID,
parent_submission=post_target.id if posting_to_submission else None,
@ -248,8 +248,8 @@ def execute_zozbot(c:Comment, level:int, post_target:post_target_type, v):
distinguish_level=6
)
db.add(c3)
db.flush()
g.db.add(c3)
g.db.flush()
c4 = Comment(author_id=ZOZBOT_ID,
@ -265,16 +265,16 @@ def execute_zozbot(c:Comment, level:int, post_target:post_target_type, v):
distinguish_level=6
)
db.add(c4)
g.db.add(c4)
zozbot = get_account(ZOZBOT_ID)
zozbot.comment_count += 3
zozbot.pay_account('coins', 1)
db.add(zozbot)
g.db.add(zozbot)
if posting_to_submission:
post_target.comment_count += 3
db.add(post_target)
g.db.add(post_target)
push_notif({v.id}, f'New reply by @{c2.author_name}', "zoz", c2)
@ -291,7 +291,7 @@ def execute_longpostbot(c:Comment, level:int, body, body_html, post_target:post_
comment_id=c.id,
real = True
)
db.add(vote)
g.db.add(vote)
c.downvotes = 1
body_html = sanitize(body)
@ -308,19 +308,19 @@ def execute_longpostbot(c:Comment, level:int, body, body_html, post_target:post_
ghost=c.ghost
)
db.add(c2)
g.db.add(c2)
longpostbot = get_account(LONGPOSTBOT_ID)
longpostbot.comment_count += 1
longpostbot.pay_account('coins', 1)
db.add(longpostbot)
db.flush()
g.db.add(longpostbot)
g.db.flush()
n = Notification(comment_id=c2.id, user_id=v.id)
db.add(n)
g.db.add(n)
if posting_to_submission:
post_target.comment_count += 3
db.add(post_target)
g.db.add(post_target)
push_notif({v.id}, f'New reply by @{c2.author_name}', c2.body, c2)
@ -328,14 +328,14 @@ def execute_antispam_submission_check(title, v, url):
now = int(time.time())
cutoff = now - 60 * 60 * 24
similar_posts = db.query(Submission).filter(
similar_posts = g.db.query(Submission).filter(
Submission.author_id == v.id,
Submission.title.op('<->')(title) < SPAM_SIMILARITY_THRESHOLD,
Submission.created_utc > cutoff
).all()
if url:
similar_urls = db.query(Submission).filter(
similar_urls = g.db.query(Submission).filter(
Submission.author_id == v.id,
Submission.url.op('<->')(url) < SPAM_URL_SIMILARITY_THRESHOLD,
Submission.created_utc > cutoff
@ -357,14 +357,14 @@ def execute_antispam_submission_check(title, v, url):
post.is_banned = True
post.is_pinned = False
post.ban_reason = "AutoJanny"
db.add(post)
g.db.add(post)
ma=ModAction(
user_id=AUTOJANNY_ID,
target_submission_id=post.id,
kind="ban_post",
_note="Spam"
)
db.add(ma)
g.db.add(ma)
return False
return True
@ -380,13 +380,13 @@ def execute_antispam_duplicate_comment_check(v:User, body_html:str):
if len(body_html) < 16: return
if body_html == '!wordle': return # wordle
compare_time = int(time.time()) - 60 * 60 * 24
count = db.query(Comment.id).filter(Comment.body_html == body_html,
count = g.db.query(Comment.id).filter(Comment.body_html == body_html,
Comment.created_utc >= compare_time).count()
if count <= ANTISPAM_DUPLICATE_THRESHOLD: return
v.ban(reason="Spamming.", days=0.0)
send_repeatable_notification(v.id, "Your account has been banned **permanently** for the following reason:\n\n> Too much spam!")
db.add(v)
db.commit()
g.db.add(v)
g.db.commit()
abort(403, "Too much spam!")
def execute_antispam_comment_check(body:str, v:User):
@ -397,7 +397,7 @@ def execute_antispam_comment_check(body:str, v:User):
now = int(time.time())
cutoff = now - 60 * 60 * 24
similar_comments = db.query(Comment).filter(
similar_comments = g.db.query(Comment).filter(
Comment.author_id == v.id,
Comment.body.op('<->')(body) < COMMENT_SPAM_SIMILAR_THRESHOLD,
Comment.created_utc > cutoff
@ -417,21 +417,21 @@ def execute_antispam_comment_check(body:str, v:User):
for comment in similar_comments:
comment.is_banned = True
comment.ban_reason = "AutoJanny"
db.add(comment)
g.db.add(comment)
ma=ModAction(
user_id=AUTOJANNY_ID,
target_comment_id=comment.id,
kind="ban_comment",
_note="Spam"
)
db.add(ma)
db.commit()
g.db.add(ma)
g.db.commit()
abort(403, "Too much spam!")
def execute_under_siege(v:User, target:Optional[Union[Submission, Comment]], body, type:str) -> bool:
if not get_setting("under_siege"): return True
unshadowbannedcels = [x[0] for x in db.query(ModAction.target_user_id).filter_by(kind='unshadowban').all()]
unshadowbannedcels = [x[0] for x in g.db.query(ModAction.target_user_id).filter_by(kind='unshadowban').all()]
if v.id in unshadowbannedcels: return True
if type in ('flag', 'message'):
@ -448,10 +448,10 @@ def execute_under_siege(v:User, target:Optional[Union[Submission, Comment]], bod
target_user_id=v.id,
_note=f'reason: "Under Siege ({type}, {v.age} seconds)"'
)
db.add(ma)
g.db.add(ma)
v.ban_reason = "Under Siege"
db.add(v)
g.db.add(v)
t = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(time.time()))
return False
return True
@ -481,10 +481,10 @@ def execute_lawlz_actions(v:User, p:Submission):
target_submission_id=p.id,
_note=f'"{p.flair}"'
)
db.add(p)
db.add(ma_1)
db.add(ma_2)
db.add(ma_3)
g.db.add(p)
g.db.add(ma_1)
g.db.add(ma_2)
g.db.add(ma_3)
def execute_wordle(c:Comment, body:str):
@ -522,7 +522,7 @@ def process_poll_options(v:User, target:Union[Submission, Comment]):
body_html=filter_emojis_only(body)
existing = db.query(cls).filter_by(
existing = g.db.query(cls).filter_by(
parent_id=target.id,
body_html=body_html,
exclusive=exclusive,
@ -534,4 +534,4 @@ def process_poll_options(v:User, target:Union[Submission, Comment]):
body_html=body_html,
exclusive=exclusive,
)
db.add(option)
g.db.add(option)

View File

@ -19,8 +19,8 @@ def create_comment(text_html):
body_html=text_html,
distinguish_level=6,
is_bot=True)
db.add(new_comment)
db.flush()
g.db.add(new_comment)
g.db.flush()
new_comment.top_comment_id = new_comment.id
@ -32,20 +32,20 @@ def send_repeatable_notification(uid, text):
text_html = sanitize(text, blackjack="notification")
existing_comments = db.query(Comment.id).filter_by(author_id=AUTOJANNY_ID, parent_submission=None, body_html=text_html, is_bot=True).order_by(Comment.id).all()
existing_comments = g.db.query(Comment.id).filter_by(author_id=AUTOJANNY_ID, parent_submission=None, body_html=text_html, is_bot=True).order_by(Comment.id).all()
for c in existing_comments:
existing_notif = db.query(Notification.user_id).filter_by(user_id=uid, comment_id=c.id).one_or_none()
existing_notif = g.db.query(Notification.user_id).filter_by(user_id=uid, comment_id=c.id).one_or_none()
if not existing_notif:
notif = Notification(comment_id=c.id, user_id=uid)
db.add(notif)
g.db.add(notif)
push_notif({uid}, 'New notification', text, f'{SITE_FULL}/comment/{c.id}?read=true#context')
return
cid = create_comment(text_html)
notif = Notification(comment_id=cid, user_id=uid)
db.add(notif)
g.db.add(notif)
push_notif({uid}, 'New notification', text, f'{SITE_FULL}/comment/{cid}?read=true#context')
@ -61,9 +61,9 @@ def notif_comment(text):
text_html = sanitize(text, blackjack="notification")
db.flush()
g.db.flush()
existing = db.query(Comment.id).filter(
existing = g.db.query(Comment.id).filter(
Comment.author_id == AUTOJANNY_ID,
Comment.parent_submission == None,
Comment.body_html == text_html,
@ -74,14 +74,14 @@ def notif_comment(text):
replace_with = existing[0][0]
replaced = [x[0] for x in existing[1:]]
for n in db.query(Notification).filter(Notification.comment_id.in_(replaced)).all():
for n in g.db.query(Notification).filter(Notification.comment_id.in_(replaced)).all():
n.comment_id = replace_with
db.add(n)
g.db.add(n)
db.flush()
g.db.flush()
for c in db.query(Comment).filter(Comment.id.in_(replaced)).all():
db.delete(c)
for c in g.db.query(Comment).filter(Comment.id.in_(replaced)).all():
g.db.delete(c)
return replace_with
elif existing:
@ -96,7 +96,7 @@ def notif_comment2(p):
search_html = f'%</a> has mentioned you: <a href="/post/{p.id}">%'
existing = db.query(Comment.id).filter(Comment.author_id == AUTOJANNY_ID, Comment.parent_submission == None, Comment.body_html.like(search_html)).first()
existing = g.db.query(Comment.id).filter(Comment.author_id == AUTOJANNY_ID, Comment.parent_submission == None, Comment.body_html.like(search_html)).first()
if existing: return existing[0], text
else:
@ -108,10 +108,10 @@ def notif_comment2(p):
def add_notif(cid, uid, text, pushnotif_url=''):
if uid in bots: return
existing = db.query(Notification.user_id).filter_by(comment_id=cid, user_id=uid).one_or_none()
existing = g.db.query(Notification.user_id).filter_by(comment_id=cid, user_id=uid).one_or_none()
if not existing:
notif = Notification(comment_id=cid, user_id=uid)
db.add(notif)
g.db.add(notif)
if not pushnotif_url:
pushnotif_url = f'{SITE_FULL}/comment/{cid}?read=true#context'
@ -140,7 +140,7 @@ def NOTIFY_USERS(text, v, oldtext=None, ghost=False):
notify_users.update(user_ids)
if SITE_NAME == "WPD" and 'daisy' in text:
admin_ids = [x[0] for x in db.query(User.id).filter(User.admin_level >= PERMS['NOTIFICATIONS_SPECIFIC_WPD_COMMENTS']).all()]
admin_ids = [x[0] for x in g.db.query(User.id).filter(User.admin_level >= PERMS['NOTIFICATIONS_SPECIFIC_WPD_COMMENTS']).all()]
notify_users.update(admin_ids)
@ -154,14 +154,14 @@ def NOTIFY_USERS(text, v, oldtext=None, ghost=False):
continue
if i.group(1) == 'everyone' and not v.shadowbanned:
cost = db.query(User).count() * 5
cost = g.db.query(User).count() * 5
if cost > v.coins:
abort(403, f"You need {cost} coins to mention these ping groups!")
db.query(User).update({ User.coins: User.coins + 5 })
g.db.query(User).update({ User.coins: User.coins + 5 })
v.charge_account('coins', cost)
return 'everyone'
else:
group = db.get(Group, i.group(1))
group = g.db.get(Group, i.group(1))
if not group: continue
members = group.member_ids - notify_users - v.all_twoway_blocks
@ -176,7 +176,7 @@ def NOTIFY_USERS(text, v, oldtext=None, ghost=False):
if cost > v.coins:
abort(403, f"You need {cost} coins to mention these ping groups!")
db.query(User).filter(User.id.in_(members)).update({ User.coins: User.coins + mul })
g.db.query(User).filter(User.id.in_(members)).update({ User.coins: User.coins + mul })
v.charge_account('coins', cost)
@ -203,9 +203,9 @@ def push_notif(uids, title, body, url_or_comment):
body = censor_slurs(body, None)
subscriptions = db.query(PushSubscription.subscription_json).filter(PushSubscription.user_id.in_(uids)).all()
subscriptions = g.db.query(PushSubscription.subscription_json).filter(PushSubscription.user_id.in_(uids)).all()
subscriptions = [x[0] for x in subscriptions]
db.flush()
g.db.flush()
gevent.spawn(_push_notif_thread, subscriptions, title, body, url)
@ -232,4 +232,4 @@ def alert_everyone(cid):
insert into notifications
select id, {cid}, false, {t} from users
on conflict do nothing;""")
db.execute(_everyone_query)
g.db.execute(_everyone_query)

View File

@ -27,37 +27,37 @@ def award_timers(v, bot=False):
v.chudded_by = None
notify_if_not_bot("Your chud status has expired!")
badge = v.has_badge(28)
if badge: db.delete(badge)
if badge: g.db.delete(badge)
if v.flairchanged and v.flairchanged < now:
v.flairchanged = None
notify_if_not_bot("Your flair lock has expired. You can now change your flair!")
badge = v.has_badge(96)
if badge: db.delete(badge)
if badge: g.db.delete(badge)
if v.marseyawarded and v.marseyawarded < now:
v.marseyawarded = None
notify_if_not_bot("Your marsey award has expired!")
badge = v.has_badge(98)
if badge: db.delete(badge)
if badge: g.db.delete(badge)
if v.longpost and v.longpost < now:
v.longpost = None
notify_if_not_bot("Your pizzashill award has expired!")
badge = v.has_badge(97)
if badge: db.delete(badge)
if badge: g.db.delete(badge)
if v.bird and v.bird < now:
v.bird = None
notify_if_not_bot("Your bird site award has expired!")
badge = v.has_badge(95)
if badge: db.delete(badge)
if badge: g.db.delete(badge)
if v.progressivestack and v.progressivestack != 1 and v.progressivestack < now:
v.progressivestack = None
notify_if_not_bot("Your progressive stack has expired!")
badge = v.has_badge(94)
if badge: db.delete(badge)
if badge: g.db.delete(badge)
if v.rehab and v.rehab < now:
v.rehab = None
notify_if_not_bot("Your rehab has finished!")
badge = v.has_badge(109)
if badge: db.delete(badge)
if badge: g.db.delete(badge)
if v.deflector and v.deflector < now:
v.deflector = None
notify_if_not_bot("Your deflector has expired!")
@ -77,32 +77,32 @@ def award_timers(v, bot=False):
v.house = v.old_house
v.old_house = ''
badge = v.has_badge(168)
if badge: db.delete(badge)
if badge: g.db.delete(badge)
if v.earlylife and v.earlylife < now:
v.earlylife = None
notify_if_not_bot("Your earlylife status has expired!")
badge = v.has_badge(169)
if badge: db.delete(badge)
if badge: g.db.delete(badge)
if v.marsify and v.marsify != 1 and v.marsify < now:
v.marsify = 0
if SITE_NAME != 'rDrama': notify_if_not_bot("Your marsify status has expired!")
badge = v.has_badge(170)
if badge: db.delete(badge)
if badge: g.db.delete(badge)
if v.rainbow and v.rainbow < now:
v.rainbow = None
notify_if_not_bot("Your rainbow has expired!")
badge = v.has_badge(171)
if badge: db.delete(badge)
if badge: g.db.delete(badge)
if v.spider and v.spider != 1 and v.spider < now:
v.spider = 0
notify_if_not_bot("Your spider friend has left you!")
badge = v.has_badge(179)
if badge: db.delete(badge)
if badge: g.db.delete(badge)
db.add(v)
g.db.add(v)
def award_timers_bots_task():
accs = db.query(User).filter(User.id.in_(bots))
accs = g.db.query(User).filter(User.id.in_(bots))
for u in accs:
award_timers(u, bot=True)

View File

@ -4,7 +4,7 @@ from files.helpers.alerts import *
from files.helpers.config.const import *
from files.helpers.useractions import badge_grant
def get_game_feed(game):
def get_game_feed(game, db):
games = db.query(CasinoGame) \
.filter(CasinoGame.active == False, CasinoGame.kind == game) \
.order_by(CasinoGame.created_utc.desc()).limit(30).all()
@ -23,14 +23,14 @@ def get_game_feed(game):
return list(map(format_game, games))
def get_user_stats(u:User, game:str, include_ties=False):
def get_user_stats(u:User, game:str, db:scoped_session, include_ties=False):
games = db.query(CasinoGame.user_id, CasinoGame.winnings).filter(CasinoGame.kind == game, CasinoGame.user_id == u.id)
wins = games.filter(CasinoGame.winnings > 0).count()
ties = games.filter(CasinoGame.winnings == 0).count() if include_ties else 0
losses = games.filter(CasinoGame.winnings < 0).count()
return (wins, ties, losses)
def get_game_leaderboard(game):
def get_game_leaderboard(game, db:scoped_session):
timestamp_24h_ago = time.time() - 86400
timestamp_all_time = CASINO_RELEASE_DAY # "All Time" starts on release day

View File

@ -1,16 +1,9 @@
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy import *
from enum import Enum, auto
from os import environ, path
import tldextract
import datetime
engine = create_engine(environ.get("DATABASE_URL").strip())
db_session = scoped_session(sessionmaker(bind=engine))
db = db_session()
t = datetime.datetime.now()
fistmas_begin = datetime.datetime.strptime(f'1/12/{t.year}', '%d/%m/%Y')

View File

@ -11,24 +11,31 @@ marsey_mappings = {}
SNAPPY_MARSEYS = []
SNAPPY_QUOTES = []
marseys_const = [x[0] for x in db.query(Marsey.name).filter(Marsey.submitter_id==None, Marsey.name!='chudsey').all()]
marseys_const2 = marseys_const + ['chudsey','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9','exclamationpoint','period','questionmark']
marseys = db.query(Marsey).filter(Marsey.submitter_id==None).all()
for marsey in marseys:
for tag in marsey.tags.split():
if tag in marsey_mappings:
marsey_mappings[tag].append(marsey.name)
else:
marsey_mappings[tag] = [marsey.name]
def const_initialize(db:scoped_session):
_initialize_marseys(db)
_initialize_snappy_marseys_and_quotes()
def _initialize_marseys(db:scoped_session):
global marseys_const, marseys_const2, marsey_mappings
marseys_const = [x[0] for x in db.query(Marsey.name).filter(Marsey.submitter_id==None, Marsey.name!='chudsey').all()]
marseys_const2 = marseys_const + ['chudsey','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9','exclamationpoint','period','questionmark']
marseys = db.query(Marsey).filter(Marsey.submitter_id==None).all()
for marsey in marseys:
for tag in marsey.tags.split():
if tag in marsey_mappings:
marsey_mappings[tag].append(marsey.name)
else:
marsey_mappings[tag] = [marsey.name]
SNAPPY_MARSEYS = [f':#{x}:' for x in marseys_const2]
def _initialize_snappy_marseys_and_quotes():
global SNAPPY_MARSEYS, SNAPPY_QUOTES
SNAPPY_MARSEYS = [f':#{x}:' for x in marseys_const2]
filename = f"snappy_{SITE_NAME}.txt"
if IS_FISTMAS(): filename = f"snappy_event_{SITE_NAME}.txt"
filename = f"snappy_{SITE_NAME}.txt"
if IS_FISTMAS(): filename = f"snappy_event_{SITE_NAME}.txt"
try:
with open(filename, "r", encoding="utf-8") as f:
SNAPPY_QUOTES = f.read().split("\n{[para]}\n")
except FileNotFoundError:
pass
try:
with open(filename, "r", encoding="utf-8") as f:
SNAPPY_QUOTES = f.read().split("\n{[para]}\n")
except FileNotFoundError:
pass

View File

@ -4,7 +4,6 @@ import os
from sys import stdout
from shutil import make_archive
from hashlib import md5
import secrets
import click
import requests
@ -21,10 +20,7 @@ from files.helpers.get import *
from files.helpers.lottery import check_if_end_lottery_task
from files.helpers.roulette import spin_roulette_wheel
from files.helpers.useractions import *
from files.cli import app, g
db.commit()
db.close()
from files.cli import app, db_session, g
@app.cli.command('cron', help='Run scheduled tasks.')
@click.option('--every-5m', is_flag=True, help='Call every 5 minutes.')
@ -32,9 +28,8 @@ db.close()
@click.option('--every-1d', is_flag=True, help='Call every 1 day.')
@click.option('--every-1mo', is_flag=True, help='Call every 1 month.')
def cron(every_5m, every_1h, every_1d, every_1mo):
db = db_session()
g.db = db_session()
g.v = None
g.nonce = secrets.token_urlsafe(31)
if every_5m:
if FEATURES['GAMBLING']:
@ -52,8 +47,9 @@ def cron(every_5m, every_1h, every_1d, every_1mo):
site_stats = stats.stats(SITE_NAME)
cache.set(f'{SITE}_stats', site_stats)
db.commit()
db.close()
g.db.commit()
g.db.close()
del g.db
stdout.flush()
def _sub_inactive_purge_task():
@ -61,24 +57,24 @@ def _sub_inactive_purge_task():
return False
one_week_ago = time.time() - 604800
active_holes = [x[0] for x in db.query(Submission.sub).distinct() \
active_holes = [x[0] for x in g.db.query(Submission.sub).distinct() \
.filter(Submission.sub != None, Submission.created_utc > one_week_ago,
Submission.private == False, Submission.is_banned == False,
Submission.deleted_utc == 0).all()]
active_holes.extend(['changelog','countryclub']) # holes immune from deletion
dead_holes = db.query(Sub).filter(Sub.name.notin_(active_holes)).all()
dead_holes = g.db.query(Sub).filter(Sub.name.notin_(active_holes)).all()
names = [x.name for x in dead_holes]
admins = [x[0] for x in db.query(User.id).filter(User.admin_level >= PERMS['NOTIFICATIONS_HOLE_INACTIVITY_DELETION']).all()]
admins = [x[0] for x in g.db.query(User.id).filter(User.admin_level >= PERMS['NOTIFICATIONS_HOLE_INACTIVITY_DELETION']).all()]
mods = db.query(Mod).filter(Mod.sub.in_(names)).all()
mods = g.db.query(Mod).filter(Mod.sub.in_(names)).all()
for x in mods:
if x.user_id in admins: continue
send_repeatable_notification(x.user_id, f":marseyrave: /h/{x.sub} has been deleted for inactivity after one week without new posts. All posts in it have been moved to the main feed :marseyrave:")
for name in names:
first_mod_id = db.query(Mod.user_id).filter_by(sub=name).order_by(Mod.created_utc).first()
first_mod_id = g.db.query(Mod.user_id).filter_by(sub=name).order_by(Mod.created_utc).first()
if first_mod_id:
first_mod = get_account(first_mod_id[0])
badge_grant(
@ -90,7 +86,7 @@ def _sub_inactive_purge_task():
for admin in admins:
send_repeatable_notification(admin, f":marseyrave: /h/{name} has been deleted for inactivity after one week without new posts. All posts in it have been moved to the main feed :marseyrave:")
posts = db.query(Submission).filter(Submission.sub.in_(names)).all()
posts = g.db.query(Submission).filter(Submission.sub.in_(names)).all()
for post in posts:
if post.sub == 'programming':
post.sub = 'slackernews'
@ -98,21 +94,21 @@ def _sub_inactive_purge_task():
post.sub = None
post.hole_pinned = None
db.add(post)
g.db.add(post)
to_delete = mods \
+ db.query(Exile).filter(Exile.sub.in_(names)).all() \
+ db.query(SubBlock).filter(SubBlock.sub.in_(names)).all() \
+ db.query(SubJoin).filter(SubJoin.sub.in_(names)).all() \
+ db.query(SubSubscription).filter(SubSubscription.sub.in_(names)).all() \
+ db.query(SubAction).filter(SubAction.sub.in_(names)).all()
+ g.db.query(Exile).filter(Exile.sub.in_(names)).all() \
+ g.db.query(SubBlock).filter(SubBlock.sub.in_(names)).all() \
+ g.db.query(SubJoin).filter(SubJoin.sub.in_(names)).all() \
+ g.db.query(SubSubscription).filter(SubSubscription.sub.in_(names)).all() \
+ g.db.query(SubAction).filter(SubAction.sub.in_(names)).all()
for x in to_delete:
db.delete(x)
db.flush()
g.db.delete(x)
g.db.flush()
for x in dead_holes:
db.delete(x)
g.db.delete(x)
return True

View File

@ -17,7 +17,7 @@ def get_id(username:str, graceful=False) -> Optional[int]:
if not username:
if graceful: return None
abort(404)
user = db.query(
user = g.db.query(
User.id
).filter(
or_(
@ -41,7 +41,7 @@ def get_user(username:Optional[str], v:Optional[User]=None, graceful=False, incl
if not username:
if graceful: return None
abort(404)
user = db.query(
user = g.db.query(
User
).filter(
or_(
@ -68,9 +68,9 @@ def get_users(usernames:Iterable[str], ids_only=False, graceful=False) -> List[U
abort(404)
if ids_only:
users = db.query(User.id)
users = g.db.query(User.id)
else:
users = db.query(User)
users = g.db.query(User)
users = users.filter(
or_(
@ -94,7 +94,7 @@ def get_account(id:Union[str, int], v:Optional[User]=None, graceful=False, inclu
if graceful: return None
abort(404)
user = db.get(User, id)
user = g.db.get(User, id)
if not user:
if not graceful: abort(404)
@ -113,7 +113,7 @@ def get_accounts_dict(ids:Union[Iterable[str], Iterable[int]], v:Optional[User]=
if graceful: return None
abort(404)
users = db.query(User).filter(User.id.in_(ids))
users = g.db.query(User).filter(User.id.in_(ids))
users = users.all()
if len(users) != len(ids) and not graceful: abort(404)
return {u.id:u for u in users}
@ -129,10 +129,10 @@ def get_post(i:Union[str, int], v:Optional[User]=None, graceful=False) -> Option
else: abort(404)
if v:
vt = db.query(Vote).filter_by(user_id=v.id, submission_id=i).subquery()
vt = g.db.query(Vote).filter_by(user_id=v.id, submission_id=i).subquery()
blocking = v.blocking.subquery()
post = db.query(
post = g.db.query(
Submission,
vt.c.vote_type,
blocking.c.target_id,
@ -157,7 +157,7 @@ def get_post(i:Union[str, int], v:Optional[User]=None, graceful=False) -> Option
x.voted = post[1] or 0
x.is_blocking = post[2] or 0
else:
post = db.get(Submission, i)
post = g.db.get(Submission, i)
if not post:
if graceful: return None
else: abort(404)
@ -170,7 +170,7 @@ def get_posts(pids:Iterable[int], v:Optional[User]=None, eager:bool=False, extra
if not pids: return []
if v:
vt = db.query(Vote.vote_type, Vote.submission_id).filter(
vt = g.db.query(Vote.vote_type, Vote.submission_id).filter(
Vote.submission_id.in_(pids),
Vote.user_id==v.id
).subquery()
@ -178,7 +178,7 @@ def get_posts(pids:Iterable[int], v:Optional[User]=None, eager:bool=False, extra
blocking = v.blocking.subquery()
blocked = v.blocked.subquery()
query = db.query(
query = g.db.query(
Submission,
vt.c.vote_type,
blocking.c.target_id,
@ -195,7 +195,7 @@ def get_posts(pids:Iterable[int], v:Optional[User]=None, eager:bool=False, extra
blocked.c.user_id == Submission.author_id,
)
else:
query = db.query(Submission).filter(Submission.id.in_(pids))
query = g.db.query(Submission).filter(Submission.id.in_(pids))
if extra: query = extra(query)
@ -236,7 +236,7 @@ def get_comment(i:Union[str, int], v:Optional[User]=None, graceful=False) -> Opt
if graceful: return None
else: abort(404)
comment=db.get(Comment, i)
comment=g.db.get(Comment, i)
if not comment:
if graceful: return None
else: abort(404)
@ -262,7 +262,7 @@ def add_block_props(target:Union[Submission, Comment, User], v:Optional[User]):
target.is_blocked = False
return target
block = db.query(UserBlock).filter(
block = g.db.query(UserBlock).filter(
or_(
and_(
UserBlock.user_id == v.id,
@ -281,7 +281,7 @@ def add_block_props(target:Union[Submission, Comment, User], v:Optional[User]):
def add_vote_props(target:Union[Submission, Comment], v:Optional[User], vote_cls):
if hasattr(target, 'voted'): return target
vt = db.query(vote_cls.vote_type).filter_by(user_id=v.id)
vt = g.db.query(vote_cls.vote_type).filter_by(user_id=v.id)
if vote_cls == Vote:
vt = vt.filter_by(submission_id=target.id)
elif vote_cls == CommentVote:
@ -302,7 +302,7 @@ def get_comments(cids:Iterable[int], v:Optional[User]=None, extra:Optional[Calla
if v:
output = get_comments_v_properties(v, None, Comment.id.in_(cids))[1]
else:
output = db.query(Comment).join(Comment.author)
output = g.db.query(Comment).join(Comment.author)
if extra: output = extra(output)
output = output.filter(Comment.id.in_(cids)).all()
return sorted(output, key=lambda x: cids.index(x.id))
@ -310,10 +310,10 @@ def get_comments(cids:Iterable[int], v:Optional[User]=None, extra:Optional[Calla
def get_comments_v_properties(v:User, should_keep_func:Optional[Callable[[Comment], bool]]=None, *criterion):
if not v:
raise TypeError("A user is required")
votes = db.query(CommentVote.vote_type, CommentVote.comment_id).filter_by(user_id=v.id).subquery()
votes = g.db.query(CommentVote.vote_type, CommentVote.comment_id).filter_by(user_id=v.id).subquery()
blocking = v.blocking.subquery()
blocked = v.blocked.subquery()
comments = db.query(
comments = g.db.query(
Comment,
votes.c.vote_type,
blocking.c.target_id,
@ -351,7 +351,7 @@ def get_sub_by_name(sub:str, v:Optional[User]=None, graceful=False) -> Optional[
if not sub:
if graceful: return None
else: abort(404)
sub = db.get(Sub, sub)
sub = g.db.get(Sub, sub)
if not sub:
if graceful: return None
else: abort(404)

View File

@ -1,5 +1,3 @@
from flask import g
def lazy(f):
'''
Prevents certain properties from having to be recomputed each time they are referenced
@ -8,7 +6,7 @@ def lazy(f):
o = args[0]
if "_lazy" not in o.__dict__:
o.__dict__["_lazy"] = {}
name = f.__name__ + str(args) + str(kwargs) + g.nonce,
name = f.__name__ + str(args) + str(kwargs),
if name not in o.__dict__["_lazy"]:
o.__dict__["_lazy"][name] = f(*args, **kwargs)
return o.__dict__["_lazy"][name]

View File

@ -13,11 +13,11 @@ from .config.const import *
LOTTERY_WINNER_BADGE_ID = 137
def get_active_lottery():
return db.query(Lottery).order_by(Lottery.id.desc()).filter(Lottery.is_active).one_or_none()
return g.db.query(Lottery).order_by(Lottery.id.desc()).filter(Lottery.is_active).one_or_none()
def get_users_participating_in_lottery():
return db.query(User) \
return g.db.query(User) \
.filter(User.currently_held_lottery_tickets > 0) \
.order_by(User.currently_held_lottery_tickets.desc()).all()
@ -66,9 +66,9 @@ def end_lottery_session():
active_lottery.is_active = False
db.add(winning_user)
db.add(active_lottery)
db.commit() # Intentionally commit early because cron runs with other tasks
g.db.add(winning_user)
g.db.add(active_lottery)
g.db.commit() # Intentionally commit early because cron runs with other tasks
return True, f'{winning_user.username} won {active_lottery.prize} coins!'
@ -84,8 +84,8 @@ def start_new_lottery_session():
lottery.ends_at = one_week_from_now
lottery.is_active = True
db.add(lottery)
db.commit() # Intentionally commit early, not autocommitted from cron
g.db.add(lottery)
g.db.commit() # Intentionally commit early, not autocommitted from cron
def check_if_end_lottery_task():

View File

@ -34,7 +34,7 @@ def remove_media(path):
def media_ratelimit(v):
t = time.time() - 86400
count = db.query(Media).filter(Media.user_id == v.id, Media.created_utc > t).count()
count = g.db.query(Media).filter(Media.user_id == v.id, Media.created_utc > t).count()
if count > 50 and v.admin_level < PERMS['USE_ADMIGGER_THREADS']:
print(STARS, flush=True)
print(f'@{v.username} hit the 50 file daily limit!')
@ -81,8 +81,8 @@ def process_audio(file, v):
remove_media(name)
abort(413, f"Max image/audio size is {MAX_IMAGE_AUDIO_SIZE_MB} MB ({MAX_IMAGE_AUDIO_SIZE_MB_PATRON} MB for {patron.lower()}s)")
media = db.query(Media).filter_by(filename=name, kind='audio').one_or_none()
if media: db.delete(media)
media = g.db.query(Media).filter_by(filename=name, kind='audio').one_or_none()
if media: g.db.delete(media)
media = Media(
kind='audio',
@ -90,12 +90,12 @@ def process_audio(file, v):
user_id=v.id,
size=size
)
db.add(media)
g.db.add(media)
return name
def webm_to_mp4(old, new, vid):
def webm_to_mp4(old, new, vid, db):
tmp = new.replace('.mp4', '-t.mp4')
subprocess.run(["ffmpeg", "-y", "-loglevel", "warning", "-nostats", "-threads:v", "1", "-i", old, "-map_metadata", "-1", tmp], check=True, stderr=subprocess.STDOUT)
os.replace(tmp, new)
@ -136,13 +136,14 @@ def process_video(file, v):
if extension == 'webm':
new = new.replace('.webm', '.mp4')
copyfile(old, new)
gevent.spawn(webm_to_mp4, old, new, v.id)
db = Session(bind=g.db.get_bind(), autoflush=False)
gevent.spawn(webm_to_mp4, old, new, v.id, db)
else:
subprocess.run(["ffmpeg", "-y", "-loglevel", "warning", "-nostats", "-i", old, "-map_metadata", "-1", "-c:v", "copy", "-c:a", "copy", new], check=True)
remove_media(old)
media = db.query(Media).filter_by(filename=new, kind='video').one_or_none()
if media: db.delete(media)
media = g.db.query(Media).filter_by(filename=new, kind='video').one_or_none()
if media: g.db.delete(media)
media = Media(
kind='video',
@ -150,14 +151,14 @@ def process_video(file, v):
user_id=v.id,
size=os.stat(new).st_size
)
db.add(media)
g.db.add(media)
if SITE == 'watchpeopledie.tv':
return f'https://videos.{SITE}' + new.split('/videos')[1]
else:
return f"{SITE_FULL}{new}"
def process_image(filename:str, v, resize=0, trim=False, uploader_id:Optional[int]=None):
def process_image(filename:str, v, resize=0, trim=False, uploader_id:Optional[int]=None, db=None):
# thumbnails are processed in a thread and not in the request context
# if an image is too large or webp conversion fails, it'll crash
# to avoid this, we'll simply return None instead
@ -240,6 +241,8 @@ def process_image(filename:str, v, resize=0, trim=False, uploader_id:Optional[in
abort(409, "Image already exists! " + hashes[i_hash].split('/')[-1])
return None
db = db or g.db
media = db.query(Media).filter_by(filename=filename, kind='image').one_or_none()
if media: db.delete(media)
@ -251,7 +254,7 @@ def process_image(filename:str, v, resize=0, trim=False, uploader_id:Optional[in
)
db.add(media)
if IS_LOCALHOST: return f'{SITE_FULL}{filename}'
if IS_LOCALHOST: return f'![]({filename})'
return f'https://i.{SITE}{filename}'

View File

@ -30,7 +30,7 @@ def offsite_mentions_task(cache:Cache):
user_mentions = get_mentions(cache, [query], reddit_notifs_users=True)
notify_mentions(user_mentions, send_to=send_user, mention_str='mention of you')
db.commit() # commit early otherwise localhost testing fails to commit
g.db.commit() # commit early otherwise localhost testing fails to commit
def get_mentions(cache:Cache, queries:Iterable[str], reddit_notifs_users=False):
kinds = ['submission', 'comment']
@ -105,7 +105,7 @@ def notify_mentions(mentions, send_to=None, mention_str='site mention'):
f'{text}'
)
existing_comment = db.query(Comment.id).filter_by(
existing_comment = g.db.query(Comment.id).filter_by(
author_id=const.AUTOJANNY_ID,
parent_submission=None,
body_html=notif_text).one_or_none()
@ -116,12 +116,12 @@ def notify_mentions(mentions, send_to=None, mention_str='site mention'):
parent_submission=None,
body_html=notif_text,
distinguish_level=6)
db.add(new_comment)
db.flush()
g.db.add(new_comment)
g.db.flush()
new_comment.top_comment_id = new_comment.id
if send_to:
notif = Notification(comment_id=new_comment.id, user_id=send_to)
db.add(notif)
g.db.add(notif)
push_notif({send_to}, f'New mention of you on reddit by /u/{author}', '', f'{SITE_FULL}/comment/{new_comment.id}?read=true#context')

View File

@ -9,7 +9,6 @@ from files.classes.casino_game import CasinoGame
from files.helpers.alerts import *
from files.helpers.get import get_account
from files.helpers.casino import distribute_wager_badges
from files.helpers.config.const import *
class RouletteAction(str, Enum):
STRAIGHT_UP_BET = "STRAIGHT_UP_BET",
@ -79,7 +78,7 @@ PAYOUT_MULITPLIERS = {
def get_active_roulette_games():
return db.query(CasinoGame).filter(
return g.db.query(CasinoGame).filter(
CasinoGame.active == True,
CasinoGame.kind == 'roulette'
).all()
@ -123,8 +122,8 @@ def gambler_placed_roulette_bet(gambler, bet, which, amount, currency):
game.game_state = json.dumps(
{"parent_id": parent_id, "bet": bet, "which": which})
game.active = True
db.add(game)
db.flush()
g.db.add(game)
g.db.flush()
def get_roulette_bets_and_betters():
@ -202,7 +201,7 @@ def spin_roulette_wheel():
send_repeatable_notification(
participant, f"Winning number: {number}\n\nSorry, none of your recent roulette bets paid off.")
db.flush()
g.db.flush()
# Adjust game winnings.
for game in active_games:
@ -214,10 +213,10 @@ def spin_roulette_wheel():
distribute_wager_badges(game.user, game.wager, won=(game.winnings > 0))
game.active = False
db.add(game)
g.db.add(game)
# Commit early when dirty because of long-running tasks after roulette
db.commit()
g.db.commit()
def determine_roulette_winners(number, bets):

View File

@ -174,14 +174,14 @@ def execute_blackjack(v, target, body, type):
target_user_id=v.id,
_note='reason: "Blackjack"'
)
db.add(ma)
g.db.add(ma)
v.ban_reason = "Blackjack"
db.add(v)
g.db.add(v)
elif target and type in {'submission', 'comment', 'message'}:
target.is_banned = True
notified_ids = [x[0] for x in db.query(User.id).filter(User.admin_level >= PERMS['BLACKJACK_NOTIFICATIONS'])]
notified_ids = [x[0] for x in g.db.query(User.id).filter(User.admin_level >= PERMS['BLACKJACK_NOTIFICATIONS'])]
extra_info = type
if target:
@ -192,7 +192,7 @@ def execute_blackjack(v, target, body, type):
elif type in {'comment', 'message'}:
for id in notified_ids:
n = Notification(comment_id=target.id, user_id=id)
db.add(n)
g.db.add(n)
extra_info = None
@ -388,7 +388,7 @@ def sanitize(sanitized, golden=True, limit_pings=0, showmore=True, count_marseys
if name == 'everyone':
sanitized = group_mention_regex.sub(r'<a href="/users">!\1</a>', sanitized)
else:
existing = db.get(Group, name)
existing = g.db.get(Group, name)
if existing:
sanitized = sanitized.replace(i.group(0), f'<a href="/!{name}">!{name}</a>', 1)
@ -467,9 +467,9 @@ def sanitize(sanitized, golden=True, limit_pings=0, showmore=True, count_marseys
sanitized = audio_sub_regex.sub(r'\1<audio controls preload="none" src="\2"></audio>', sanitized)
if count_marseys:
for marsey in db.query(Marsey).filter(Marsey.submitter_id==None, Marsey.name.in_(marseys_used)).all():
for marsey in g.db.query(Marsey).filter(Marsey.submitter_id==None, Marsey.name.in_(marseys_used)).all():
marsey.count += 1
db.add(marsey)
g.db.add(marsey)
sanitized = sanitized.replace('<p></p>', '')
sanitized = sanitized.replace('<html><body>','').replace('</body></html>','')
@ -503,7 +503,7 @@ def sanitize(sanitized, golden=True, limit_pings=0, showmore=True, count_marseys
else:
abort(403, error)
banned_domains = db.query(BannedDomain).all()
banned_domains = g.db.query(BannedDomain).all()
for x in banned_domains:
for y in domain_list:
if y.startswith(x.domain):
@ -559,9 +559,9 @@ def filter_emojis_only(title, golden=True, count_marseys=False, graceful=False,
title = render_emoji(title, emoji_regex3, golden, marseys_used)
if count_marseys:
for marsey in db.query(Marsey).filter(Marsey.submitter_id==None, Marsey.name.in_(marseys_used)).all():
for marsey in g.db.query(Marsey).filter(Marsey.submitter_id==None, Marsey.name.in_(marseys_used)).all():
marsey.count += 1
db.add(marsey)
g.db.add(marsey)
title = strikethrough_regex.sub(r'\1<del>\2</del>', title)

View File

@ -49,8 +49,8 @@ def casino_slot_pull(gambler, wager_value, currency):
casino_game.winnings = reward - wager_value
casino_game.kind = 'slots'
casino_game.game_state = json.dumps(game_state)
db.add(casino_game)
db.flush()
g.db.add(casino_game)
g.db.flush()
return casino_game.id, casino_game.game_state
else:

View File

@ -45,18 +45,18 @@ def chart(kind, site):
daily_times = [time.strftime('%d/%m', time.gmtime(day_cutoffs[i + 1]))
for i in range(len(day_cutoffs) - 1)][::-1]
daily_signups = [db.query(User).filter(
daily_signups = [g.db.query(User).filter(
User.created_utc < day_cutoffs[i],
User.created_utc > day_cutoffs[i + 1]).count()
for i in range(len(day_cutoffs) - 1)][::-1]
post_stats = [db.query(Submission).filter(
post_stats = [g.db.query(Submission).filter(
Submission.created_utc < day_cutoffs[i],
Submission.created_utc > day_cutoffs[i + 1],
Submission.is_banned == False).count()
for i in range(len(day_cutoffs) - 1)][::-1]
comment_stats = [db.query(Comment).filter(
comment_stats = [g.db.query(Comment).filter(
Comment.created_utc < day_cutoffs[i],
Comment.created_utc > day_cutoffs[i + 1],
Comment.is_banned == False,
@ -97,53 +97,53 @@ def stats(site=None):
now = time.time()
day = int(now) - 86400
week = int(now) - 604800
posters = db.query(Submission.author_id).distinct(Submission.author_id).filter(Submission.created_utc > week).all()
commenters = db.query(Comment.author_id).distinct(Comment.author_id).filter(Comment.created_utc > week).all()
voters = db.query(Vote.user_id).distinct(Vote.user_id).filter(Vote.created_utc > week).all()
commentvoters = db.query(CommentVote.user_id).distinct(CommentVote.user_id).filter(CommentVote.created_utc > week).all()
posters = g.db.query(Submission.author_id).distinct(Submission.author_id).filter(Submission.created_utc > week).all()
commenters = g.db.query(Comment.author_id).distinct(Comment.author_id).filter(Comment.created_utc > week).all()
voters = g.db.query(Vote.user_id).distinct(Vote.user_id).filter(Vote.created_utc > week).all()
commentvoters = g.db.query(CommentVote.user_id).distinct(CommentVote.user_id).filter(CommentVote.created_utc > week).all()
active_users = set(posters) | set(commenters) | set(voters) | set(commentvoters)
stats = {
"time": int(time.time()),
"marseys": "{:,}".format(db.query(Marsey).filter(Marsey.submitter_id==None).count()),
"users": "{:,}".format(db.query(User).count()),
"private users": "{:,}".format(db.query(User).filter_by(is_private=True).count()),
"banned users": "{:,}".format(db.query(User).filter(User.is_banned != None).count()),
"verified email users": "{:,}".format(db.query(User).filter_by(is_activated=True).count()),
"coins in circulation": "{:,}".format(db.query(func.sum(User.coins)).scalar()),
"total shop sales": "{:,}".format(db.query(func.sum(User.coins_spent)).scalar()),
"signups last 24h": "{:,}".format(db.query(User).filter(User.created_utc > day).count()),
"total posts": "{:,}".format(db.query(Submission).count()),
"posting users": "{:,}".format(db.query(Submission.author_id).distinct().count()),
"listed posts": "{:,}".format(db.query(Submission).filter_by(is_banned=False).filter(Submission.deleted_utc == 0).count()),
"removed posts (by admins)": "{:,}".format(db.query(Submission).filter_by(is_banned=True).count()),
"deleted posts (by author)": "{:,}".format(db.query(Submission).filter(Submission.deleted_utc > 0).count()),
"posts last 24h": "{:,}".format(db.query(Submission).filter(Submission.created_utc > day).count()),
"total comments": "{:,}".format(db.query(Comment).filter(Comment.author_id != AUTOJANNY_ID).count()),
"commenting users": "{:,}".format(db.query(Comment.author_id).distinct().count()),
"removed comments (by admins)": "{:,}".format(db.query(Comment).filter_by(is_banned=True).count()),
"deleted comments (by author)": "{:,}".format(db.query(Comment).filter(Comment.deleted_utc > 0).count()),
"comments last 24h": "{:,}".format(db.query(Comment).filter(Comment.created_utc > day, Comment.author_id != AUTOJANNY_ID).count()),
"post votes": "{:,}".format(db.query(Vote).count()),
"comment votes": "{:,}".format(db.query(CommentVote).count()),
"total upvotes": "{:,}".format(db.query(Vote).filter_by(vote_type=1).count() + db.query(CommentVote).filter_by(vote_type=1).count()),
"total downvotes": "{:,}".format(db.query(Vote).filter_by(vote_type=-1).count() + db.query(CommentVote).filter_by(vote_type=-1).count()),
"total awards": "{:,}".format(db.query(AwardRelationship).count()),
"awards given": "{:,}".format(db.query(AwardRelationship).filter(or_(AwardRelationship.submission_id != None, AwardRelationship.comment_id != None)).count()),
"marseys": "{:,}".format(g.db.query(Marsey).filter(Marsey.submitter_id==None).count()),
"users": "{:,}".format(g.db.query(User).count()),
"private users": "{:,}".format(g.db.query(User).filter_by(is_private=True).count()),
"banned users": "{:,}".format(g.db.query(User).filter(User.is_banned != None).count()),
"verified email users": "{:,}".format(g.db.query(User).filter_by(is_activated=True).count()),
"coins in circulation": "{:,}".format(g.db.query(func.sum(User.coins)).scalar()),
"total shop sales": "{:,}".format(g.db.query(func.sum(User.coins_spent)).scalar()),
"signups last 24h": "{:,}".format(g.db.query(User).filter(User.created_utc > day).count()),
"total posts": "{:,}".format(g.db.query(Submission).count()),
"posting users": "{:,}".format(g.db.query(Submission.author_id).distinct().count()),
"listed posts": "{:,}".format(g.db.query(Submission).filter_by(is_banned=False).filter(Submission.deleted_utc == 0).count()),
"removed posts (by admins)": "{:,}".format(g.db.query(Submission).filter_by(is_banned=True).count()),
"deleted posts (by author)": "{:,}".format(g.db.query(Submission).filter(Submission.deleted_utc > 0).count()),
"posts last 24h": "{:,}".format(g.db.query(Submission).filter(Submission.created_utc > day).count()),
"total comments": "{:,}".format(g.db.query(Comment).filter(Comment.author_id != AUTOJANNY_ID).count()),
"commenting users": "{:,}".format(g.db.query(Comment.author_id).distinct().count()),
"removed comments (by admins)": "{:,}".format(g.db.query(Comment).filter_by(is_banned=True).count()),
"deleted comments (by author)": "{:,}".format(g.db.query(Comment).filter(Comment.deleted_utc > 0).count()),
"comments last 24h": "{:,}".format(g.db.query(Comment).filter(Comment.created_utc > day, Comment.author_id != AUTOJANNY_ID).count()),
"post votes": "{:,}".format(g.db.query(Vote).count()),
"comment votes": "{:,}".format(g.db.query(CommentVote).count()),
"total upvotes": "{:,}".format(g.db.query(Vote).filter_by(vote_type=1).count() + g.db.query(CommentVote).filter_by(vote_type=1).count()),
"total downvotes": "{:,}".format(g.db.query(Vote).filter_by(vote_type=-1).count() + g.db.query(CommentVote).filter_by(vote_type=-1).count()),
"total awards": "{:,}".format(g.db.query(AwardRelationship).count()),
"awards given": "{:,}".format(g.db.query(AwardRelationship).filter(or_(AwardRelationship.submission_id != None, AwardRelationship.comment_id != None)).count()),
"users who posted, commented, or voted in the past 7 days": "{:,}".format(len(active_users)),
"users online in the past 7 days": "{:,}".format(db.query(User).filter(User.last_active > week).count()),
"users online in the past 7 days": "{:,}".format(g.db.query(User).filter(User.last_active > week).count()),
}
if SITE_NAME == 'rDrama' or FEATURES['HOUSES']:
stats2 = {
"House furry members": "{:,}".format(db.query(User).filter(User.house.like('Furry%')).count()),
"House femboy members": "{:,}".format(db.query(User).filter(User.house.like('Femboy%')).count()),
"House vampire members": "{:,}".format(db.query(User).filter(User.house.like('Vampire%')).count()),
"House racist members": "{:,}".format(db.query(User).filter(User.house.like('Racist%')).count()),
"House furry total truescore": "{:,}".format(db.query(func.sum(User.truescore)).filter(User.house.like('Furry%')).scalar() or 0),
"House femboy total truescore": "{:,}".format(db.query(func.sum(User.truescore)).filter(User.house.like('Femboy%')).scalar() or 0),
"House vampire total truescore": "{:,}".format(db.query(func.sum(User.truescore)).filter(User.house.like('Vampire%')).scalar() or 0),
"House racist total truescore": "{:,}".format(db.query(func.sum(User.truescore)).filter(User.house.like('Racist%')).scalar() or 0),
"House furry members": "{:,}".format(g.db.query(User).filter(User.house.like('Furry%')).count()),
"House femboy members": "{:,}".format(g.db.query(User).filter(User.house.like('Femboy%')).count()),
"House vampire members": "{:,}".format(g.db.query(User).filter(User.house.like('Vampire%')).count()),
"House racist members": "{:,}".format(g.db.query(User).filter(User.house.like('Racist%')).count()),
"House furry total truescore": "{:,}".format(g.db.query(func.sum(User.truescore)).filter(User.house.like('Furry%')).scalar() or 0),
"House femboy total truescore": "{:,}".format(g.db.query(func.sum(User.truescore)).filter(User.house.like('Femboy%')).scalar() or 0),
"House vampire total truescore": "{:,}".format(g.db.query(func.sum(User.truescore)).filter(User.house.like('Vampire%')).scalar() or 0),
"House racist total truescore": "{:,}".format(g.db.query(func.sum(User.truescore)).filter(User.house.like('Racist%')).scalar() or 0),
}
stats.update(stats2)

View File

@ -7,7 +7,6 @@ from flask import g
from files.classes.casino_game import CasinoGame
from files.helpers.casino import distribute_wager_badges
from files.helpers.config.const import *
class BlackjackStatus(str, Enum):
PLAYING = "PLAYING"
@ -64,13 +63,13 @@ def build_casino_game(gambler, wager, currency):
casino_game.kind = 'blackjack'
casino_game.game_state = json.dumps(initial_state)
casino_game.active = True
db.add(casino_game)
g.db.add(casino_game)
return casino_game
def get_active_twentyone_game(gambler):
return db.query(CasinoGame).filter(
return g.db.query(CasinoGame).filter(
CasinoGame.active == True,
CasinoGame.kind == 'blackjack',
CasinoGame.user_id == gambler.id).first()
@ -95,7 +94,7 @@ def create_new_game(gambler, wager, currency):
if existing_game:
existing_game.active = False
db.add(existing_game)
g.db.add(existing_game)
if not over_minimum_bet:
raise Exception(f"Gambler must bet over {minimum_bet} {currency}.")
@ -103,8 +102,8 @@ def create_new_game(gambler, wager, currency):
try:
charge_gambler(gambler, wager, currency)
new_game = build_casino_game(gambler, wager, currency)
db.add(new_game)
db.flush()
g.db.add(new_game)
g.db.flush()
except:
raise Exception(f"Gambler cannot afford to bet {wager} {currency}.")
@ -254,7 +253,7 @@ def handle_payout(gambler, state, game):
distribute_wager_badges(gambler, game.wager, won=False)
game.active = False
db.add(game)
g.db.add(game)
return payout
@ -309,7 +308,7 @@ def dispatch_action(gambler, action):
new_state['actions'] = get_available_actions(new_state)
game.game_state = json.dumps(new_state)
db.add(game)
g.db.add(game)
game_over, final_state = check_for_completion(new_state)

View File

@ -2,7 +2,6 @@ from flask import g
from files.classes.badges import Badge
from files.helpers.alerts import send_repeatable_notification
from files.helpers.config.const import *
def badge_grant(user, badge_id, description=None, url=None, notify=True):
assert user != None
@ -22,8 +21,8 @@ def badge_grant(user, badge_id, description=None, url=None, notify=True):
url=url,
)
db.add(badge)
db.flush()
g.db.add(badge)
g.db.flush()
if notify:
send_repeatable_notification(user.id,

View File

@ -30,7 +30,7 @@ from .front import frontlist, comment_idlist
@admin_level_required(PERMS['VIEW_ACTIVE_USERS'])
def loggedin_list(v):
ids = [x for x,val in cache.get(f'{SITE}_loggedin').items() if time.time()-val < LOGGEDIN_ACTIVE_TIME]
users = db.query(User).filter(User.id.in_(ids)).order_by(User.admin_level.desc(), User.truescore.desc()).all()
users = g.db.query(User).filter(User.id.in_(ids)).order_by(User.admin_level.desc(), User.truescore.desc()).all()
return render_template("admin/loggedin.html", v=v, users=users)
@app.get('/admin/loggedout')
@ -91,7 +91,7 @@ def edit_rules_post(v):
kind="edit_rules",
user_id=v.id,
)
db.add(ma)
g.db.add(ma)
return render_template('admin/edit_rules.html', v=v, rules=rules, msg='Rules edited successfully!')
@app.post("/@<username>/make_admin")
@ -103,14 +103,14 @@ def make_admin(v:User, username):
user = get_user(username)
user.admin_level = 1
db.add(user)
g.db.add(user)
ma = ModAction(
kind="make_admin",
user_id=v.id,
target_user_id=user.id
)
db.add(ma)
g.db.add(ma)
send_repeatable_notification(user.id, f"@{v.username} added you as an admin!")
@ -133,14 +133,14 @@ def remove_admin(v:User, username):
if user.admin_level:
user.admin_level = 0
db.add(user)
g.db.add(user)
ma = ModAction(
kind="remove_admin",
user_id=v.id,
target_user_id=user.id
)
db.add(ma)
g.db.add(ma)
send_repeatable_notification(user.id, f"@{v.username} removed you as an admin!")
@ -161,12 +161,12 @@ def distribute(v:User, kind, option_id):
if kind == 'post': cls = SubmissionOption
else: cls = CommentOption
option = db.get(cls, option_id)
option = g.db.get(cls, option_id)
if option.exclusive != 2: abort(403)
option.exclusive = 3
db.add(option)
g.db.add(option)
parent = option.parent
@ -177,7 +177,7 @@ def distribute(v:User, kind, option_id):
autojanny.charge_account('coins', pool)
if autojanny.coins < 0: autojanny.coins = 0
db.add(autojanny)
g.db.add(autojanny)
votes = option.votes
coinsperperson = int(pool / len(votes))
@ -211,7 +211,7 @@ def distribute(v:User, kind, option_id):
target_comment_id=parent.id
)
db.add(ma)
g.db.add(ma)
return {"message": f"Each winner has received {coinsperperson} coins!"}
@ -231,24 +231,24 @@ def revert_actions(v:User, username):
user_id=v.id,
target_user_id=revertee.id
)
db.add(ma)
g.db.add(ma)
cutoff = int(time.time()) - 86400
posts = [x[0] for x in db.query(ModAction.target_submission_id).filter(ModAction.user_id == revertee.id, ModAction.created_utc > cutoff, ModAction.kind == 'ban_post').all()]
posts = db.query(Submission).filter(Submission.id.in_(posts)).all()
posts = [x[0] for x in g.db.query(ModAction.target_submission_id).filter(ModAction.user_id == revertee.id, ModAction.created_utc > cutoff, ModAction.kind == 'ban_post').all()]
posts = g.db.query(Submission).filter(Submission.id.in_(posts)).all()
comments = [x[0] for x in db.query(ModAction.target_comment_id).filter(ModAction.user_id == revertee.id, ModAction.created_utc > cutoff, ModAction.kind == 'ban_comment').all()]
comments = db.query(Comment).filter(Comment.id.in_(comments)).all()
comments = [x[0] for x in g.db.query(ModAction.target_comment_id).filter(ModAction.user_id == revertee.id, ModAction.created_utc > cutoff, ModAction.kind == 'ban_comment').all()]
comments = g.db.query(Comment).filter(Comment.id.in_(comments)).all()
for item in posts + comments:
item.is_banned = False
item.ban_reason = None
item.is_approved = v.id
db.add(item)
g.db.add(item)
users = (x[0] for x in db.query(ModAction.target_user_id).filter(ModAction.user_id == revertee.id, ModAction.created_utc > cutoff, ModAction.kind.in_(('shadowban', 'ban_user'))).all())
users = db.query(User).filter(User.id.in_(users)).all()
users = (x[0] for x in g.db.query(ModAction.target_user_id).filter(ModAction.user_id == revertee.id, ModAction.created_utc > cutoff, ModAction.kind.in_(('shadowban', 'ban_user'))).all())
users = g.db.query(User).filter(User.id.in_(users)).all()
for user in users:
user.shadowbanned = None
@ -257,7 +257,7 @@ def revert_actions(v:User, username):
if user.is_banned:
user.is_banned = None
send_repeatable_notification(user.id, f"@{v.username} (a site admin) has unbanned you!")
db.add(user)
g.db.add(user)
for u in get_alt_graph(user.id):
u.shadowbanned = None
@ -266,7 +266,7 @@ def revert_actions(v:User, username):
if u.is_banned:
u.is_banned = None
send_repeatable_notification(u.id, f"@{v.username} (a site admin) has unbanned you!")
db.add(u)
g.db.add(u)
return {"message": f"@{revertee.username}'s admin actions have been reverted!"}
@ -275,7 +275,7 @@ def revert_actions(v:User, username):
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['USER_SHADOWBAN'])
def shadowbanned(v):
users = db.query(User) \
users = g.db.query(User) \
.filter(
User.shadowbanned != None,
) \
@ -293,7 +293,7 @@ def image_posts_listing(v):
try: page = int(request.values.get('page', 1))
except: page = 1
posts = db.query(Submission).order_by(Submission.id.desc())
posts = g.db.query(Submission).order_by(Submission.id.desc())
firstrange = PAGE_SIZE * (page - 1)
secondrange = firstrange + PAGE_SIZE + 1
@ -313,7 +313,7 @@ def reported_posts(v):
try: page = max(1, int(request.values.get("page", 1)))
except: abort(400, "Invalid page input!")
listing = db.query(Submission).filter_by(
listing = g.db.query(Submission).filter_by(
is_approved=None,
is_banned=False,
deleted_utc=0
@ -338,7 +338,7 @@ def reported_comments(v):
try: page = max(1, int(request.values.get("page", 1)))
except: abort(400, "Invalid page input!")
listing = db.query(Comment
listing = g.db.query(Comment
).filter_by(
is_approved=None,
is_banned=False,
@ -389,7 +389,7 @@ def change_settings(v:User, setting):
kind=f"{word}_{setting}",
user_id=v.id,
)
db.add(ma)
g.db.add(ma)
return {'message': f"{setting.replace('_', ' ').title()} {word}d successfully!"}
@ -405,11 +405,11 @@ def clear_cloudflare_cache(v):
kind="clear_cloudflare_cache",
user_id=v.id
)
db.add(ma)
g.db.add(ma)
return {"message": "Cloudflare cache cleared!"}
def admin_badges_grantable_list(v):
query = db.query(BadgeDef)
query = g.db.query(BadgeDef)
if BADGE_BLACKLIST and v.admin_level < PERMS['IGNORE_BADGE_BLACKLIST']:
query = query.filter(BadgeDef.id.notin_(BADGE_BLACKLIST))
@ -464,7 +464,7 @@ def badge_grant_post(v):
if url or description:
existing.url = url
existing.description = description
db.add(existing)
g.db.add(existing)
return render_template("admin/badge_admin.html", v=v, badge_types=badges, grant=True, msg="Badge attributes edited successfully!")
return render_template("admin/badge_admin.html", v=v, badge_types=badges, grant=True, error="User already has that badge!")
@ -475,8 +475,8 @@ def badge_grant_post(v):
description=description
)
db.add(new_badge)
db.flush()
g.db.add(new_badge)
g.db.flush()
if v.id != user.id:
text = f"@{v.username} (a site admin) has given you the following profile badge:\n\n{new_badge.path}\n\n**{new_badge.name}**\n\n{new_badge.badge.description}"
@ -488,7 +488,7 @@ def badge_grant_post(v):
target_user_id=user.id,
_note=new_badge.name
)
db.add(ma)
g.db.add(ma)
return render_template("admin/badge_admin.html", v=v, badge_types=badges, grant=True, msg=f"{new_badge.name} Badge granted to @{user.username} successfully!")
@ -525,8 +525,8 @@ def badge_remove_post(v):
target_user_id=user.id,
_note=badge.name
)
db.add(ma)
db.delete(badge)
g.db.add(ma)
g.db.delete(badge)
return render_template("admin/badge_admin.html", v=v, badge_types=badges, grant=False, msg=f"{badge.name} Badge removed from @{user.username} successfully!")
@ -544,35 +544,35 @@ def alt_votes_get(v):
u1 = get_user(u1)
u2 = get_user(u2)
u1_post_ups = db.query(
u1_post_ups = g.db.query(
Vote.submission_id).filter_by(
user_id=u1.id,
vote_type=1).all()
u1_post_downs = db.query(
u1_post_downs = g.db.query(
Vote.submission_id).filter_by(
user_id=u1.id,
vote_type=-1).all()
u1_comment_ups = db.query(
u1_comment_ups = g.db.query(
CommentVote.comment_id).filter_by(
user_id=u1.id,
vote_type=1).all()
u1_comment_downs = db.query(
u1_comment_downs = g.db.query(
CommentVote.comment_id).filter_by(
user_id=u1.id,
vote_type=-1).all()
u2_post_ups = db.query(
u2_post_ups = g.db.query(
Vote.submission_id).filter_by(
user_id=u2.id,
vote_type=1).all()
u2_post_downs = db.query(
u2_post_downs = g.db.query(
Vote.submission_id).filter_by(
user_id=u2.id,
vote_type=-1).all()
u2_comment_ups = db.query(
u2_comment_ups = g.db.query(
CommentVote.comment_id).filter_by(
user_id=u2.id,
vote_type=1).all()
u2_comment_downs = db.query(
u2_comment_downs = g.db.query(
CommentVote.comment_id).filter_by(
user_id=u2.id,
vote_type=-1).all()
@ -656,15 +656,15 @@ def admin_add_alt(v:User, username):
if user1.id == user2.id: abort(400, "Can't add the same account as alts of each other")
ids = [user1.id, user2.id]
a = db.query(Alt).filter(Alt.user1.in_(ids), Alt.user2.in_(ids)).one_or_none()
a = g.db.query(Alt).filter(Alt.user1.in_(ids), Alt.user2.in_(ids)).one_or_none()
if a: abort(409, f"@{user1.username} and @{user2.username} are already known alts!")
a = Alt(
user1=user1.id,
user2=user2.id,
is_manual=True,
)
db.add(a)
db.flush()
g.db.add(a)
g.db.flush()
cache.delete_memoized(get_alt_graph_ids, user1.id)
cache.delete_memoized(get_alt_graph_ids, user2.id)
@ -678,7 +678,7 @@ def admin_add_alt(v:User, username):
target_user_id=user1.id,
_note=f'with @{user2.username}'
)
db.add(ma)
g.db.add(ma)
return {"message": f"Linked @{user1.username} and @{user2.username} successfully!"}
@app.post('/@<username>/alts/<int:other>/deleted')
@ -690,9 +690,9 @@ def admin_delink_relink_alt(v:User, username, other):
user1 = get_user(username)
user2 = get_account(other)
ids = [user1.id, user2.id]
a = db.query(Alt).filter(Alt.user1.in_(ids), Alt.user2.in_(ids)).one_or_none()
a = g.db.query(Alt).filter(Alt.user1.in_(ids), Alt.user2.in_(ids)).one_or_none()
if not a: abort(404)
db.delete(a)
g.db.delete(a)
ma = ModAction(
kind=f"delink_accounts",
@ -700,7 +700,7 @@ def admin_delink_relink_alt(v:User, username, other):
target_user_id=user1.id,
_note=f'from @{user2.username}'
)
db.add(ma)
g.db.add(ma)
return {"message": f"Delinked @{user1.username} and @{user2.username} successfully!"}
@ -713,7 +713,7 @@ def admin_removed(v):
try: page = int(request.values.get("page", 1))
except: page = 1
if page < 1: abort(400)
ids = db.query(Submission.id).join(Submission.author).filter(or_(Submission.is_banned==True, User.shadowbanned != None)).order_by(Submission.id.desc()).offset(PAGE_SIZE * (page - 1)).limit(PAGE_SIZE + 1).all()
ids = g.db.query(Submission.id).join(Submission.author).filter(or_(Submission.is_banned==True, User.shadowbanned != None)).order_by(Submission.id.desc()).offset(PAGE_SIZE * (page - 1)).limit(PAGE_SIZE + 1).all()
ids=[x[0] for x in ids]
next_exists = len(ids) > PAGE_SIZE
ids = ids[:PAGE_SIZE]
@ -736,7 +736,7 @@ def admin_removed_comments(v):
try: page = int(request.values.get("page", 1))
except: page = 1
ids = db.query(Comment.id).join(Comment.author).filter(or_(Comment.is_banned==True, User.shadowbanned != None)).order_by(Comment.id.desc()).offset(PAGE_SIZE * (page - 1)).limit(PAGE_SIZE + 1).all()
ids = g.db.query(Comment.id).join(Comment.author).filter(or_(Comment.is_banned==True, User.shadowbanned != None)).order_by(Comment.id.desc()).offset(PAGE_SIZE * (page - 1)).limit(PAGE_SIZE + 1).all()
ids=[x[0] for x in ids]
next_exists = len(ids) > PAGE_SIZE
ids = ids[:PAGE_SIZE]
@ -757,11 +757,11 @@ def unagendaposter(id, v):
if id.startswith('p_'):
post_id = id.split('p_')[1]
post = db.get(Submission, post_id)
post = g.db.get(Submission, post_id)
user = post.author
elif id.startswith('c_'):
comment_id = id.split('c_')[1]
comment = db.get(Comment, comment_id)
comment = g.db.get(Comment, comment_id)
user = comment.author
else:
user = get_account(id)
@ -771,7 +771,7 @@ def unagendaposter(id, v):
user.agendaposter = 0
user.chudded_by = None
db.add(user)
g.db.add(user)
ma = ModAction(
kind="unchud",
@ -779,10 +779,10 @@ def unagendaposter(id, v):
target_user_id=user.id
)
db.add(ma)
g.db.add(ma)
badge = user.has_badge(28)
if badge: db.delete(badge)
if badge: g.db.delete(badge)
send_repeatable_notification(user.id, f"@{v.username} (a site admin) has unchudded you.")
@ -810,7 +810,7 @@ def shadowban(user_id, v):
abort(400, "Ban reason too long!")
user.ban_reason = reason
db.add(user)
g.db.add(user)
check_for_alts(user)
ma = ModAction(
@ -819,7 +819,7 @@ def shadowban(user_id, v):
target_user_id=user.id,
_note=f'reason: "{reason}"'
)
db.add(ma)
g.db.add(ma)
cache.delete_memoized(frontlist)
@ -834,19 +834,19 @@ def unshadowban(user_id, v):
user = get_account(user_id)
user.shadowbanned = None
if not user.is_banned: user.ban_reason = None
db.add(user)
g.db.add(user)
for alt in get_alt_graph(user.id):
alt.shadowbanned = None
if not alt.is_banned: alt.ban_reason = None
db.add(alt)
g.db.add(alt)
ma = ModAction(
kind="unshadowban",
user_id=v.id,
target_user_id=user.id,
)
db.add(ma)
g.db.add(ma)
cache.delete_memoized(frontlist)
@ -874,9 +874,9 @@ def admin_title_change(user_id, v):
else:
user.flairchanged = None
badge = user.has_badge(96)
if badge: db.delete(badge)
if badge: g.db.delete(badge)
db.add(user)
g.db.add(user)
if user.flairchanged: kind = "set_flair_locked"
else: kind = "set_flair_notlocked"
@ -887,7 +887,7 @@ def admin_title_change(user_id, v):
target_user_id=user.id,
_note=f'"{new_name}"'
)
db.add(ma)
g.db.add(ma)
if user.flairchanged:
message = f"@{v.username} (a site admin) has locked your flair to `{user.customtitleplain}`."
@ -907,11 +907,11 @@ def ban_user(id, v):
if id.startswith('p_'):
post_id = id.split('p_')[1]
post = db.get(Submission, post_id)
post = g.db.get(Submission, post_id)
user = post.author
elif id.startswith('c_'):
comment_id = id.split('c_')[1]
comment = db.get(Comment, comment_id)
comment = g.db.get(Comment, comment_id)
user = comment.author
else:
user = get_account(id)
@ -972,7 +972,7 @@ def ban_user(id, v):
target_user_id=user.id,
_note=note
)
db.add(ma)
g.db.add(ma)
if 'reason' in request.values:
if request.values["reason"].startswith("/post/"):
@ -981,13 +981,13 @@ def ban_user(id, v):
post = get_post(post)
if post.sub != 'chudrama':
post.bannedfor = f'{duration} by @{v.username}'
db.add(post)
g.db.add(post)
elif request.values["reason"].startswith("/comment/"):
try: comment = int(request.values["reason"].split("/comment/")[1].split(None, 1)[0])
except: abort(400)
comment = get_comment(comment)
comment.bannedfor = f'{duration} by @{v.username}'
db.add(comment)
g.db.add(comment)
return {"message": f"@{user.username} has been banned {duration}!"}
@ -1001,11 +1001,11 @@ def agendaposter(id, v):
if id.startswith('p_'):
post_id = id.split('p_')[1]
post = db.get(Submission, post_id)
post = g.db.get(Submission, post_id)
user = post.author
elif id.startswith('c_'):
comment_id = id.split('c_')[1]
comment = db.get(Comment, comment_id)
comment = g.db.get(Comment, comment_id)
user = comment.author
else:
user = get_account(id)
@ -1050,7 +1050,7 @@ def agendaposter(id, v):
else: text = f"@{v.username} (a site admin) has chudded you permanently."
user.chudded_by = v.id
db.add(user)
g.db.add(user)
send_repeatable_notification(user.id, text)
@ -1063,7 +1063,7 @@ def agendaposter(id, v):
target_user_id=user.id,
_note=note
)
db.add(ma)
g.db.add(ma)
badge_grant(user=user, badge_id=28)
@ -1075,7 +1075,7 @@ def agendaposter(id, v):
if post.sub == 'chudrama':
abort(403, "You can't chud people in /h/chudrama")
post.chuddedfor = f'{duration} by @{v.username}'
db.add(post)
g.db.add(post)
elif request.values["reason"].startswith("/comment/"):
try: comment = int(request.values["reason"].split("/comment/")[1].split(None, 1)[0])
except: abort(400)
@ -1083,7 +1083,7 @@ def agendaposter(id, v):
if comment.post.sub == 'chudrama':
abort(403, "You can't chud people in /h/chudrama")
comment.chuddedfor = f'{duration} by @{v.username}'
db.add(comment)
g.db.add(comment)
return {"message": f"@{user.username} has been chudded {duration}!"}
@ -1097,11 +1097,11 @@ def unban_user(id, v):
if id.startswith('p_'):
post_id = id.split('p_')[1]
post = db.get(Submission, post_id)
post = g.db.get(Submission, post_id)
user = post.author
elif id.startswith('c_'):
comment_id = id.split('c_')[1]
comment = db.get(Comment, comment_id)
comment = g.db.get(Comment, comment_id)
user = comment.author
else:
user = get_account(id)
@ -1116,21 +1116,21 @@ def unban_user(id, v):
user.unban_utc = 0
user.ban_reason = None
send_repeatable_notification(user.id, f"@{v.username} (a site admin) has unbanned you!")
db.add(user)
g.db.add(user)
for x in get_alt_graph(user.id):
if x.is_banned: send_repeatable_notification(x.id, f"@{v.username} (a site admin) has unbanned you!")
x.is_banned = None
x.unban_utc = 0
x.ban_reason = None
db.add(x)
g.db.add(x)
ma=ModAction(
kind="unban_user",
user_id=v.id,
target_user_id=user.id,
)
db.add(ma)
g.db.add(ma)
return {"message": f"@{user.username} has been unbanned!"}
@ -1149,8 +1149,8 @@ def mute_user(v:User, user_id):
user_id=v.id,
target_user_id=user.id,
)
db.add(user)
db.add(ma)
g.db.add(user)
g.db.add(ma)
check_for_alts(user)
return {"message": f"@{user.username} has been muted!"}
@ -1171,8 +1171,8 @@ def unmute_user(v:User, user_id):
user_id=v.id,
target_user_id=user.id,
)
db.add(user)
db.add(ma)
g.db.add(user)
g.db.add(ma)
return {"message": f"@{user.username} has been unmuted!"}
@ -1185,14 +1185,14 @@ def progstack_post(post_id, v):
post = get_post(post_id)
post.is_approved = PROGSTACK_ID
post.realupvotes = floor(post.realupvotes * PROGSTACK_MUL)
db.add(post)
g.db.add(post)
ma=ModAction(
kind="progstack_post",
user_id=v.id,
target_submission_id=post.id,
)
db.add(ma)
g.db.add(ma)
cache.delete_memoized(frontlist)
return {"message": "Progressive stack applied on post!"}
@ -1205,14 +1205,14 @@ def progstack_post(post_id, v):
def unprogstack_post(post_id, v):
post = get_post(post_id)
post.is_approved = None
db.add(post)
g.db.add(post)
ma=ModAction(
kind="unprogstack_post",
user_id=v.id,
target_submission_id=post.id,
)
db.add(ma)
g.db.add(ma)
return {"message": "Progressive stack removed from post!"}
@ -1225,14 +1225,14 @@ def progstack_comment(comment_id, v):
comment = get_comment(comment_id)
comment.is_approved = PROGSTACK_ID
comment.realupvotes = floor(comment.realupvotes * PROGSTACK_MUL)
db.add(comment)
g.db.add(comment)
ma=ModAction(
kind="progstack_comment",
user_id=v.id,
target_comment_id=comment.id,
)
db.add(ma)
g.db.add(ma)
cache.delete_memoized(comment_idlist)
return {"message": "Progressive stack applied on comment!"}
@ -1245,14 +1245,14 @@ def progstack_comment(comment_id, v):
def unprogstack_comment(comment_id, v):
comment = get_comment(comment_id)
comment.is_approved = None
db.add(comment)
g.db.add(comment)
ma=ModAction(
kind="unprogstack_comment",
user_id=v.id,
target_comment_id=comment.id,
)
db.add(ma)
g.db.add(ma)
return {"message": "Progressive stack removed from comment!"}
@ -1269,19 +1269,19 @@ def remove_post(post_id, v):
post.stickied = None
post.is_pinned = False
post.ban_reason = v.username
db.add(post)
g.db.add(post)
ma=ModAction(
kind="ban_post",
user_id=v.id,
target_submission_id=post.id,
)
db.add(ma)
g.db.add(ma)
cache.delete_memoized(frontlist)
v.pay_account('coins', 1)
db.add(v)
g.db.add(v)
purge_files_in_cache(f"https://{SITE}/")
return {"message": "Post removed!"}
@ -1303,18 +1303,18 @@ def approve_post(post_id, v):
user_id=v.id,
target_submission_id=post.id,
)
db.add(ma)
g.db.add(ma)
post.is_banned = False
post.ban_reason = None
post.is_approved = v.id
db.add(post)
g.db.add(post)
cache.delete_memoized(frontlist)
v.charge_account('coins', 1)
db.add(v)
g.db.add(v)
return {"message": "Post approved!"}
@ -1334,14 +1334,14 @@ def distinguish_post(post_id, v):
post.distinguish_level = v.admin_level
kind = 'distinguish_post'
db.add(post)
g.db.add(post)
ma = ModAction(
kind=kind,
user_id=v.id,
target_submission_id=post.id
)
db.add(ma)
g.db.add(ma)
if post.distinguish_level: return {"message": "Post distinguished!"}
@ -1363,7 +1363,7 @@ def sticky_post(post_id, v):
if FEATURES['AWARDS'] and post.stickied and post.stickied.endswith(PIN_AWARD_TEXT) and v.admin_level < PERMS["UNDO_AWARD_PINS"]:
abort(403, "Can't pin award pins!")
pins = db.query(Submission).filter(Submission.stickied != None, Submission.is_banned == False).count()
pins = g.db.query(Submission).filter(Submission.stickied != None, Submission.is_banned == False).count()
if not post.stickied_utc:
post.stickied_utc = int(time.time()) + 3600
@ -1380,7 +1380,7 @@ def sticky_post(post_id, v):
post.stickied = v.username
db.add(post)
g.db.add(post)
ma=ModAction(
kind="pin_post",
@ -1388,7 +1388,7 @@ def sticky_post(post_id, v):
target_submission_id=post.id,
_note=pin_time
)
db.add(ma)
g.db.add(ma)
cache.delete_memoized(frontlist)
@ -1411,14 +1411,14 @@ def unsticky_post(post_id, v):
post.stickied = None
post.stickied_utc = None
db.add(post)
g.db.add(post)
ma=ModAction(
kind="unpin_post",
user_id=v.id,
target_submission_id=post.id
)
db.add(ma)
g.db.add(ma)
if v.id != post.author_id:
send_repeatable_notification(post.author_id, f"@{v.username} (a site admin) has unpinned [{post.title}](/post/{post_id})")
@ -1442,14 +1442,14 @@ def sticky_comment(cid, v):
if not comment.stickied:
comment.stickied = v.username
db.add(comment)
g.db.add(comment)
ma=ModAction(
kind="pin_comment",
user_id=v.id,
target_comment_id=comment.id
)
db.add(ma)
g.db.add(ma)
if v.id != comment.author_id:
message = f"@{v.username} (a site admin) has pinned your [comment]({comment.shortlink})"
@ -1459,7 +1459,7 @@ def sticky_comment(cid, v):
while c.level > 2:
c = c.parent_comment
c.stickied_child_id = comment.id
db.add(c)
g.db.add(c)
return {"message": "Comment pinned!"}
@ -1477,23 +1477,23 @@ def unsticky_comment(cid, v):
abort(403, "Can't unpin award pins!")
comment.stickied = None
db.add(comment)
g.db.add(comment)
ma=ModAction(
kind="unpin_comment",
user_id=v.id,
target_comment_id=comment.id
)
db.add(ma)
g.db.add(ma)
if v.id != comment.author_id:
message = f"@{v.username} (a site admin) has unpinned your [comment]({comment.shortlink})"
send_repeatable_notification(comment.author_id, message)
cleanup = db.query(Comment).filter_by(stickied_child_id=comment.id).all()
cleanup = g.db.query(Comment).filter_by(stickied_child_id=comment.id).all()
for c in cleanup:
c.stickied_child_id = None
db.add(c)
g.db.add(c)
return {"message": "Comment unpinned!"}
@ -1509,13 +1509,13 @@ def remove_comment(c_id, v):
comment.is_banned = True
comment.is_approved = None
comment.ban_reason = v.username
db.add(comment)
g.db.add(comment)
ma=ModAction(
kind="ban_comment",
user_id=v.id,
target_comment_id=comment.id,
)
db.add(ma)
g.db.add(ma)
return {"message": "Comment removed!"}
@ -1537,13 +1537,13 @@ def approve_comment(c_id, v):
user_id=v.id,
target_comment_id=comment.id,
)
db.add(ma)
g.db.add(ma)
comment.is_banned = False
comment.ban_reason = None
comment.is_approved = v.id
db.add(comment)
g.db.add(comment)
return {"message": "Comment approved!"}
@ -1563,14 +1563,14 @@ def admin_distinguish_comment(c_id, v):
comment.distinguish_level = v.admin_level
kind = 'distinguish_comment'
db.add(comment)
g.db.add(comment)
ma = ModAction(
kind=kind,
user_id=v.id,
target_comment_id=comment.id
)
db.add(ma)
g.db.add(ma)
if comment.distinguish_level: return {"message": "Comment distinguished!"}
@ -1581,7 +1581,7 @@ def admin_distinguish_comment(c_id, v):
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['DOMAINS_BAN'])
def admin_banned_domains(v):
banned_domains = db.query(BannedDomain) \
banned_domains = g.db.query(BannedDomain) \
.order_by(BannedDomain.reason).all()
return render_template("admin/banned_domains.html", v=v,
banned_domains=banned_domains)
@ -1605,16 +1605,16 @@ def ban_domain(v):
if len(reason) > 100:
abort(400, 'Reason is too long!')
existing = db.get(BannedDomain, domain)
existing = g.db.get(BannedDomain, domain)
if not existing:
d = BannedDomain(domain=domain, reason=reason)
db.add(d)
g.db.add(d)
ma = ModAction(
kind="ban_domain",
user_id=v.id,
_note=filter_emojis_only(f'{domain}, reason: {reason}')
)
db.add(ma)
g.db.add(ma)
return redirect("/admin/banned_domains/")
@ -1625,16 +1625,16 @@ def ban_domain(v):
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['DOMAINS_BAN'])
def unban_domain(v:User, domain):
existing = db.get(BannedDomain, domain)
existing = g.db.get(BannedDomain, domain)
if not existing: abort(400, 'Domain is not banned!')
db.delete(existing)
g.db.delete(existing)
ma = ModAction(
kind="unban_domain",
user_id=v.id,
_note=filter_emojis_only(domain)
)
db.add(ma)
g.db.add(ma)
return {"message": f"{domain} has been unbanned!"}
@ -1649,28 +1649,28 @@ def admin_nuke_user(v):
user=get_user(request.values.get("user"))
for post in db.query(Submission).filter_by(author_id=user.id).all():
for post in g.db.query(Submission).filter_by(author_id=user.id).all():
if post.is_banned:
continue
post.is_banned = True
post.ban_reason = v.username
db.add(post)
g.db.add(post)
for comment in db.query(Comment).filter_by(author_id=user.id).all():
for comment in g.db.query(Comment).filter_by(author_id=user.id).all():
if comment.is_banned:
continue
comment.is_banned = True
comment.ban_reason = v.username
db.add(comment)
g.db.add(comment)
ma=ModAction(
kind="nuke_user",
user_id=v.id,
target_user_id=user.id,
)
db.add(ma)
g.db.add(ma)
return {"message": f"@{user.username}'s content has been removed!"}
@ -1684,30 +1684,30 @@ def admin_nunuke_user(v):
user=get_user(request.values.get("user"))
for post in db.query(Submission).filter_by(author_id=user.id).all():
for post in g.db.query(Submission).filter_by(author_id=user.id).all():
if not post.is_banned:
continue
post.is_banned = False
post.ban_reason = None
post.is_approved = v.id
db.add(post)
g.db.add(post)
for comment in db.query(Comment).filter_by(author_id=user.id).all():
for comment in g.db.query(Comment).filter_by(author_id=user.id).all():
if not comment.is_banned:
continue
comment.is_banned = False
comment.ban_reason = None
comment.is_approved = v.id
db.add(comment)
g.db.add(comment)
ma=ModAction(
kind="unnuke_user",
user_id=v.id,
target_user_id=user.id,
)
db.add(ma)
g.db.add(ma)
return {"message": f"@{user.username}'s content has been approved!"}
@ -1721,7 +1721,7 @@ def blacklist_user(user_id, v):
if user.admin_level > v.admin_level:
abort(403)
user.blacklisted_by = v.id
db.add(user)
g.db.add(user)
check_for_alts(user)
ma = ModAction(
@ -1729,7 +1729,7 @@ def blacklist_user(user_id, v):
user_id=v.id,
target_user_id=user.id
)
db.add(ma)
g.db.add(ma)
return {"message": f"@{user.username} has been blacklisted from restricted holes!"}
@ -1741,18 +1741,18 @@ def blacklist_user(user_id, v):
def unblacklist_user(user_id, v):
user = get_account(user_id)
user.blacklisted_by = None
db.add(user)
g.db.add(user)
for alt in get_alt_graph(user.id):
alt.blacklisted_by = None
db.add(alt)
g.db.add(alt)
ma = ModAction(
kind="unblacklist_user",
user_id=v.id,
target_user_id=user.id
)
db.add(ma)
g.db.add(ma)
return {"message": f"@{user.username} has been unblacklisted from restricted holes!"}
@ -1789,7 +1789,7 @@ def delete_media_post(v):
user_id=v.id,
_note=url,
)
db.add(ma)
g.db.add(ma)
purge_files_in_cache(url)
return render_template("admin/delete_media.html", v=v, msg="Media deleted successfully!")

View File

@ -47,6 +47,8 @@ def before_request():
request.full_path = request.full_path.rstrip('?').rstrip('/')
if not request.full_path: request.full_path = '/'
g.db = db_session()
g.nonce = secrets.token_urlsafe(31)
import redis
@ -55,7 +57,7 @@ r = redis.Redis.from_url(app.config["CACHE_REDIS_URL"])
@app.after_request
def after_request(response:Response):
if response.status_code < 400:
db.commit()
_commit_and_close_db()
if request.method == "POST" and not request.path.startswith('/casino/twentyone/'):
r.delete(f'LIMITER/{get_CF()}/{request.endpoint}:{request.path}/1/1/second')
@ -65,5 +67,19 @@ def after_request(response:Response):
@app.teardown_appcontext
def teardown_request(error):
db.rollback()
_rollback_and_close_db()
stdout.flush()
def _commit_and_close_db() -> bool:
if not getattr(g, 'db', None): return False
g.db.commit()
g.db.close()
del g.db
return True
def _rollback_and_close_db() -> bool:
if not getattr(g, 'db', None): return False
g.db.rollback()
g.db.close()
del g.db
return True

View File

@ -20,15 +20,15 @@ ASSET_TYPES = (Marsey, HatDef)
@auth_required
def submit_marseys(v:User):
if v.admin_level >= PERMS['VIEW_PENDING_SUBMITTED_MARSEYS']:
marseys = db.query(Marsey).filter(Marsey.submitter_id != None)
marseys = g.db.query(Marsey).filter(Marsey.submitter_id != None)
else:
marseys = db.query(Marsey).filter(Marsey.submitter_id == v.id)
marseys = g.db.query(Marsey).filter(Marsey.submitter_id == v.id)
marseys = marseys.order_by(Marsey.created_utc.desc()).all()
for marsey in marseys:
marsey.author = db.query(User.username).filter_by(id=marsey.author_id).one()[0]
marsey.submitter = db.query(User.username).filter_by(id=marsey.submitter_id).one()[0]
marsey.author = g.db.query(User.username).filter_by(id=marsey.author_id).one()[0]
marsey.submitter = g.db.query(User.username).filter_by(id=marsey.submitter_id).one()[0]
return render_template("submit_marseys.html", v=v, marseys=marseys)
@ -45,12 +45,12 @@ def submit_marsey(v:User):
username = request.values.get('author', '').lower().strip()
def error(error):
if v.admin_level >= PERMS['VIEW_PENDING_SUBMITTED_MARSEYS']: marseys = db.query(Marsey).filter(Marsey.submitter_id != None)
else: marseys = db.query(Marsey).filter(Marsey.submitter_id == v.id)
if v.admin_level >= PERMS['VIEW_PENDING_SUBMITTED_MARSEYS']: marseys = g.db.query(Marsey).filter(Marsey.submitter_id != None)
else: marseys = g.db.query(Marsey).filter(Marsey.submitter_id == v.id)
marseys = marseys.order_by(Marsey.created_utc.desc()).all()
for marsey in marseys:
marsey.author = db.query(User.username).filter_by(id=marsey.author_id).one()[0]
marsey.submitter = db.query(User.username).filter_by(id=marsey.submitter_id).one()[0]
marsey.author = g.db.query(User.username).filter_by(id=marsey.author_id).one()[0]
marsey.submitter = g.db.query(User.username).filter_by(id=marsey.submitter_id).one()[0]
return render_template("submit_marseys.html", v=v, marseys=marseys, error=error, name=name, tags=tags, username=username, file=file), 400
if g.is_tor:
@ -62,7 +62,7 @@ def submit_marsey(v:User):
if not marsey_regex.fullmatch(name):
return error("Invalid name!")
existing = db.query(Marsey.name).filter_by(name=name).one_or_none()
existing = g.db.query(Marsey.name).filter_by(name=name).one_or_none()
if existing:
return error("Someone already submitted a marsey with this name!")
@ -81,16 +81,16 @@ def submit_marsey(v:User):
process_image(filename, v, resize=200, trim=True)
marsey = Marsey(name=name, author_id=author.id, tags=tags, count=0, submitter_id=v.id)
db.add(marsey)
g.db.add(marsey)
if v.admin_level >= PERMS['VIEW_PENDING_SUBMITTED_MARSEYS']: marseys = db.query(Marsey).filter(Marsey.submitter_id != None)
else: marseys = db.query(Marsey).filter(Marsey.submitter_id == v.id)
if v.admin_level >= PERMS['VIEW_PENDING_SUBMITTED_MARSEYS']: marseys = g.db.query(Marsey).filter(Marsey.submitter_id != None)
else: marseys = g.db.query(Marsey).filter(Marsey.submitter_id == v.id)
marseys = marseys.order_by(Marsey.created_utc.desc()).all()
for marsey in marseys:
marsey.author = db.query(User.username).filter_by(id=marsey.author_id).one()[0]
marsey.submitter = db.query(User.username).filter_by(id=marsey.submitter_id).one()[0]
marsey.author = g.db.query(User.username).filter_by(id=marsey.author_id).one()[0]
marsey.submitter = g.db.query(User.username).filter_by(id=marsey.submitter_id).one()[0]
return render_template("submit_marseys.html", v=v, marseys=marseys, msg=f"'{name}' submitted successfully!")
@ -100,9 +100,9 @@ def verify_permissions_and_get_asset(cls, asset_type:str, v:User, name:str, make
if make_lower: name = name.lower()
asset = None
if cls == HatDef:
asset = db.query(cls).filter_by(name=name).one_or_none()
asset = g.db.query(cls).filter_by(name=name).one_or_none()
else:
asset = db.get(cls, name)
asset = g.db.get(cls, name)
if not asset:
abort(404, f"This {asset} '{name}' doesn't exist!")
return asset
@ -131,10 +131,10 @@ def approve_marsey(v, name):
marsey.name = new_name
marsey.tags = tags
db.add(marsey)
g.db.add(marsey)
author = get_account(marsey.author_id)
all_by_author = db.query(Marsey).filter_by(author_id=author.id).count()
all_by_author = g.db.query(Marsey).filter_by(author_id=author.id).count()
if all_by_author >= 99:
badge_grant(badge_id=143, user=author)
@ -153,7 +153,7 @@ def approve_marsey(v, name):
rename(highquality, new_path)
author.pay_account('coins', 250)
db.add(author)
g.db.add(author)
if v.id != author.id:
msg = f"@{v.username} (a site admin) has approved a marsey you made: :{marsey.name}:\n\nYou have received 250 coins as a reward!"
@ -170,7 +170,7 @@ def approve_marsey(v, name):
user_id=v.id,
_note=f'<img loading="lazy" data-bs-toggle="tooltip" alt=":{name}:" title=":{name}:" src="/e/{name}.webp">'
)
db.add(ma)
g.db.add(ma)
return {"message": f"'{marsey.name}' approved!"}
@ -183,9 +183,9 @@ def remove_asset(cls, type_name:str, v:User, name:str) -> dict[str, str]:
abort(400, f"You need to specify a {type_name}!")
asset = None
if cls == HatDef:
asset = db.query(cls).filter_by(name=name).one_or_none()
asset = g.db.query(cls).filter_by(name=name).one_or_none()
else:
asset = db.get(cls, name)
asset = g.db.get(cls, name)
if not asset:
abort(404, f"This {type_name} '{name}' doesn't exist!")
if v.id != asset.submitter_id and v.admin_level < PERMS['MODERATE_PENDING_SUBMITTED_ASSETS']:
@ -201,9 +201,9 @@ def remove_asset(cls, type_name:str, v:User, name:str) -> dict[str, str]:
user_id=v.id,
_note=name
)
db.add(ma)
g.db.add(ma)
db.delete(asset)
g.db.delete(asset)
remove_media(f"/asset_submissions/{type_name}s/{name}.webp")
remove_media(f"/asset_submissions/{type_name}s/{name}")
@ -222,8 +222,8 @@ def remove_marsey(v:User, name):
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required
def submit_hats(v:User):
if v.admin_level >= PERMS['VIEW_PENDING_SUBMITTED_HATS']: hats = db.query(HatDef).filter(HatDef.submitter_id != None)
else: hats = db.query(HatDef).filter(HatDef.submitter_id == v.id)
if v.admin_level >= PERMS['VIEW_PENDING_SUBMITTED_HATS']: hats = g.db.query(HatDef).filter(HatDef.submitter_id != None)
else: hats = g.db.query(HatDef).filter(HatDef.submitter_id == v.id)
hats = hats.order_by(HatDef.created_utc.desc()).all()
return render_template("submit_hats.html", v=v, hats=hats)
@ -239,8 +239,8 @@ def submit_hat(v:User):
username = request.values.get('author', '').strip()
def error(error):
if v.admin_level >= PERMS['VIEW_PENDING_SUBMITTED_HATS']: hats = db.query(HatDef).filter(HatDef.submitter_id != None)
else: hats = db.query(HatDef).filter(HatDef.submitter_id == v.id)
if v.admin_level >= PERMS['VIEW_PENDING_SUBMITTED_HATS']: hats = g.db.query(HatDef).filter(HatDef.submitter_id != None)
else: hats = g.db.query(HatDef).filter(HatDef.submitter_id == v.id)
hats = hats.order_by(HatDef.created_utc.desc()).all()
return render_template("submit_hats.html", v=v, hats=hats, error=error, name=name, description=description, username=username), 400
@ -254,7 +254,7 @@ def submit_hat(v:User):
if not hat_regex.fullmatch(name):
return error("Invalid name!")
existing = db.query(HatDef.name).filter_by(name=name).one_or_none()
existing = g.db.query(HatDef.name).filter_by(name=name).one_or_none()
if existing:
return error("A hat with this name already exists!")
@ -281,11 +281,11 @@ def submit_hat(v:User):
process_image(filename, v, resize=100)
hat = HatDef(name=name, author_id=author.id, description=description, price=price, submitter_id=v.id)
db.add(hat)
db.flush()
g.db.add(hat)
g.db.flush()
if v.admin_level >= PERMS['VIEW_PENDING_SUBMITTED_HATS']: hats = db.query(HatDef).filter(HatDef.submitter_id != None)
else: hats = db.query(HatDef).filter(HatDef.submitter_id == v.id)
if v.admin_level >= PERMS['VIEW_PENDING_SUBMITTED_HATS']: hats = g.db.query(HatDef).filter(HatDef.submitter_id != None)
else: hats = g.db.query(HatDef).filter(HatDef.submitter_id == v.id)
hats = hats.order_by(HatDef.created_utc.desc()).all()
@ -314,13 +314,13 @@ def approve_hat(v, name):
abort(400, "Invalid hat price")
hat.name = new_name
hat.description = description
db.add(hat)
g.db.add(hat)
db.flush()
g.db.flush()
author = hat.author
all_by_author = db.query(HatDef).filter_by(author_id=author.id).count()
all_by_author = g.db.query(HatDef).filter_by(author_id=author.id).count()
if all_by_author >= 250:
badge_grant(badge_id=166, user=author)
@ -335,7 +335,7 @@ def approve_hat(v, name):
user_id=author.id,
hat_id=hat.id
)
db.add(hat_copy)
g.db.add(hat_copy)
if v.id != author.id:
@ -360,7 +360,7 @@ def approve_hat(v, name):
user_id=v.id,
_note=f'<a href="/i/hats/{name}.webp">{name}</a>'
)
db.add(ma)
g.db.add(ma)
return {"message": f"'{hat.name}' approved!"}
@ -381,7 +381,7 @@ def update_marseys(v):
tags = None
error = None
if name:
marsey = db.get(Marsey, name)
marsey = g.db.get(Marsey, name)
if marsey:
tags = marsey.tags or ''
else:
@ -404,7 +404,7 @@ def update_marsey(v):
def error(error):
return render_template("admin/update_assets.html", v=v, error=error, name=name, tags=tags, type="Marsey")
existing = db.get(Marsey, name)
existing = g.db.get(Marsey, name)
if not existing:
return error("A marsey with this name doesn't exist!")
@ -432,7 +432,7 @@ def update_marsey(v):
if tags and existing.tags != tags and tags != "none":
existing.tags += f" {tags}"
db.add(existing)
g.db.add(existing)
elif not file:
return error("You need to actually update something!")
@ -441,7 +441,7 @@ def update_marsey(v):
user_id=v.id,
_note=f'<img loading="lazy" data-bs-toggle="tooltip" alt=":{name}:" title=":{name}:" src="/e/{name}.webp">'
)
db.add(ma)
g.db.add(ma)
return render_template("admin/update_assets.html", v=v, msg=f"'{name}' updated successfully!", name=name, tags=tags, type="Marsey")
@app.get("/admin/update/hats")
@ -473,7 +473,7 @@ def update_hat(v):
if not hat_regex.fullmatch(name):
return error("Invalid name!")
existing = db.query(HatDef.name).filter_by(name=name).one_or_none()
existing = g.db.query(HatDef.name).filter_by(name=name).one_or_none()
if not existing:
return error("A hat with this name doesn't exist!")
@ -503,5 +503,5 @@ def update_hat(v):
user_id=v.id,
_note=f'<a href="/i/hats/{name}.webp">{name}</a>'
)
db.add(ma)
g.db.add(ma)
return render_template("admin/update_assets.html", v=v, msg=f"'{name}' updated successfully!", type="Hat")

View File

@ -39,7 +39,7 @@ def shop(v:User):
for val in AWARDS.values(): val["owned"] = 0
for useraward in db.query(AwardRelationship).filter(AwardRelationship.user_id == v.id, AwardRelationship.submission_id == None, AwardRelationship.comment_id == None).all():
for useraward in g.db.query(AwardRelationship).filter(AwardRelationship.user_id == v.id, AwardRelationship.submission_id == None, AwardRelationship.comment_id == None).all():
if useraward.kind in AWARDS: AWARDS[useraward.kind]["owned"] += 1
for val in AWARDS.values():
@ -48,7 +48,7 @@ def shop(v:User):
val["baseprice"] = int(val["baseprice"] / 0.75)
val["price"] = int(val["price"] * v.discount)
sales = db.query(func.sum(User.coins_spent)).scalar()
sales = g.db.query(func.sum(User.coins_spent)).scalar()
return render_template("shop.html", awards=list(AWARDS.values()), v=v, sales=sales)
@ -98,7 +98,7 @@ def buy(v:User, award):
badge_grant(badge_id=70, user=v)
elif v.coins_spent >= 10000:
badge_grant(badge_id=69, user=v)
db.add(v)
g.db.add(v)
if award == "lootbox":
@ -107,8 +107,8 @@ def buy(v:User, award):
lb_award = random.choice(LOOTBOX_CONTENTS)
lootbox_items.append(AWARDS[lb_award]['title'])
lb_award = AwardRelationship(user_id=v.id, kind=lb_award, price_paid=price // LOOTBOX_ITEM_COUNT)
db.add(lb_award)
db.flush()
g.db.add(lb_award)
g.db.flush()
v.lootboxes_bought += 1
lootbox_msg = "You open your lootbox and receive: " + ', '.join(lootbox_items)
@ -124,9 +124,9 @@ def buy(v:User, award):
return {"message": lootbox_msg}
else:
award_object = AwardRelationship(user_id=v.id, kind=award, price_paid=price)
db.add(award_object)
g.db.add(award_object)
db.add(v)
g.db.add(v)
if CARP_ID and v.id != CARP_ID and og_price >= 5000:
send_repeatable_notification(CARP_ID, f"@{v.username} has bought a `{award_title}` award!")
@ -158,7 +158,7 @@ def award_thing(v, thing_type, id):
if kind not in AWARDS: abort(404, "This award doesn't exist")
award = db.query(AwardRelationship).filter(
award = g.db.query(AwardRelationship).filter(
AwardRelationship.kind == kind,
AwardRelationship.user_id == v.id,
AwardRelationship.submission_id == None,
@ -171,7 +171,7 @@ def award_thing(v, thing_type, id):
else: award.comment_id = thing.id
award.awarded_utc = int(time.time())
db.add(award)
g.db.add(award)
note = request.values.get("note", "").strip()
@ -200,7 +200,7 @@ def award_thing(v, thing_type, id):
msg = f"{safe_username} is under the effect of a deflector award; your {AWARDS[kind]['title']} Award has been deflected back to you but your deflector protected you, the award bounced back and forth until it vaporized!"
send_repeatable_notification(v.id, msg)
db.delete(award)
g.db.delete(award)
return {"message": f"{AWARDS[kind]['title']} award given to {thing_type} successfully!"}
@ -274,7 +274,7 @@ def award_thing(v, thing_type, id):
thing.stickied_utc = int(time.time()) + add
thing.stickied = f'{v.username}{PIN_AWARD_TEXT}'
db.add(thing)
g.db.add(thing)
cache.delete_memoized(frontlist)
elif kind == "unpin":
if not thing.stickied_utc: abort(400)
@ -290,7 +290,7 @@ def award_thing(v, thing_type, id):
thing.stickied_utc = None
cache.delete_memoized(frontlist)
else: thing.stickied_utc = t
db.add(thing)
g.db.add(thing)
elif kind == "agendaposter":
if thing_type == 'post' and thing.sub == 'chudrama' \
or thing_type == 'comment' and thing.post and thing.post.sub == 'chudrama':
@ -346,7 +346,7 @@ def award_thing(v, thing_type, id):
badge_grant(badge_id=84, user=author)
elif kind == "unblockable":
badge_grant(badge_id=87, user=author)
for block in db.query(UserBlock).filter_by(target_id=author.id).all(): db.delete(block)
for block in g.db.query(UserBlock).filter_by(target_id=author.id).all(): g.db.delete(block)
elif kind == "fish":
badge_grant(badge_id=90, user=author)
elif kind == "progressivestack":
@ -386,7 +386,7 @@ def award_thing(v, thing_type, id):
if author.owoify: body = owoify(body)
body = marsify(body)
thing.body_html = sanitize(body, limit_pings=5)
db.add(thing)
g.db.add(thing)
elif "Vampire" in kind and kind == v.house:
if author.bite: author.bite += 172800
else: author.bite = int(time.time()) + 172800
@ -412,7 +412,7 @@ def award_thing(v, thing_type, id):
body = owoify(body)
if author.marsify: body = marsify(body)
thing.body_html = sanitize(body, limit_pings=5)
db.add(thing)
g.db.add(thing)
elif ("Femboy" in kind and kind == v.house) or kind == 'rainbow':
if author.rainbow: author.rainbow += 86400
else: author.rainbow = int(time.time()) + 86400
@ -428,6 +428,6 @@ def award_thing(v, thing_type, id):
if author.received_award_count: author.received_award_count += 1
else: author.received_award_count = 1
db.add(author)
g.db.add(author)
return {"message": f"{AWARDS[kind]['title']} award given to {thing_type} successfully!"}

View File

@ -32,9 +32,9 @@ def casino_game_page(v:User, game):
elif game not in CASINO_GAME_KINDS:
abort(404)
feed = json.dumps(get_game_feed(game))
leaderboard = json.dumps(get_game_leaderboard(game))
v_stats = get_user_stats(v, game, game == 'blackjack')
feed = json.dumps(get_game_feed(game, g.db))
leaderboard = json.dumps(get_game_leaderboard(game, g.db))
v_stats = get_user_stats(v, game, g.db, game == 'blackjack')
game_state = ''
if game == 'blackjack':
@ -62,7 +62,7 @@ def casino_game_feed(v:User, game):
elif game not in CASINO_GAME_KINDS:
abort(404)
feed = get_game_feed(game)
feed = get_game_feed(game, g.db)
return {"feed": feed}
@ -126,7 +126,7 @@ def blackjack_deal_to_player(v:User):
currency = request.values.get("currency")
create_new_game(v, wager, currency)
state = dispatch_action(v, BlackjackAction.DEAL)
feed = get_game_feed('blackjack')
feed = get_game_feed('blackjack', g.db)
return {"success": True, "state": state, "feed": feed, "gambler": {"coins": v.coins, "marseybux": v.marseybux}}
except Exception as e:
@ -144,7 +144,7 @@ def blackjack_player_hit(v:User):
try:
state = dispatch_action(v, BlackjackAction.HIT)
feed = get_game_feed('blackjack')
feed = get_game_feed('blackjack', g.db)
return {"success": True, "state": state, "feed": feed, "gambler": {"coins": v.coins, "marseybux": v.marseybux}}
except:
abort(400, "Unable to hit!")
@ -161,7 +161,7 @@ def blackjack_player_stay(v:User):
try:
state = dispatch_action(v, BlackjackAction.STAY)
feed = get_game_feed('blackjack')
feed = get_game_feed('blackjack', g.db)
return {"success": True, "state": state, "feed": feed, "gambler": {"coins": v.coins, "marseybux": v.marseybux}}
except:
abort(400, "Unable to stay!")
@ -178,7 +178,7 @@ def blackjack_player_doubled_down(v:User):
try:
state = dispatch_action(v, BlackjackAction.DOUBLE_DOWN)
feed = get_game_feed('blackjack')
feed = get_game_feed('blackjack', g.db)
return {"success": True, "state": state, "feed": feed, "gambler": {"coins": v.coins, "marseybux": v.marseybux}}
except:
abort(400, "Unable to double down!")
@ -195,7 +195,7 @@ def blackjack_player_bought_insurance(v:User):
try:
state = dispatch_action(v, BlackjackAction.BUY_INSURANCE)
feed = get_game_feed('blackjack')
feed = get_game_feed('blackjack', g.db)
return {"success": True, "state": state, "feed": feed, "gambler": {"coins": v.coins, "marseybux": v.marseybux}}
except:
abort(403, "Unable to buy insurance!")

View File

@ -36,11 +36,11 @@ def post_pid_comment_cid(cid, pid=None, anything=None, v=None, sub=None):
if not User.can_see(v, comment): abort(403)
if v and request.values.get("read"):
notif = db.query(Notification).filter_by(comment_id=cid, user_id=v.id, read=False).one_or_none()
notif = g.db.query(Notification).filter_by(comment_id=cid, user_id=v.id, read=False).one_or_none()
if notif:
notif.read = True
db.add(notif)
db.flush()
g.db.add(notif)
g.db.flush()
if comment.parent_submission:
post = comment.parent_submission
@ -76,7 +76,7 @@ def post_pid_comment_cid(cid, pid=None, anything=None, v=None, sub=None):
execute_shadowban_viewers_and_voters(v, post)
execute_shadowban_viewers_and_voters(v, comment)
if v and v.client: return top_comment.json
if v and v.client: return top_comment.json(db=g.db)
else:
if post.is_banned and not (v and (v.admin_level >= PERMS['POST_COMMENT_MODERATION'] or post.author_id == v.id)): template = "submission_banned.html"
else: template = "submission.html"
@ -199,12 +199,12 @@ def comment(v:User):
if not badge_name_regex.fullmatch(name):
abort(400, "Invalid badge name!")
existing = db.query(BadgeDef).filter_by(name=name).one_or_none()
existing = g.db.query(BadgeDef).filter_by(name=name).one_or_none()
if existing: abort(409, "A badge with this name already exists!")
badge = BadgeDef(name=name, description=badge_def["description"])
db.add(badge)
db.flush()
g.db.add(badge)
g.db.flush()
filename = f'files/assets/images/badges/{badge.id}.webp'
copyfile(oldname, filename)
process_image(filename, v, resize=300)
@ -233,7 +233,7 @@ def comment(v:User):
body_html = sanitize(body_for_sanitize, limit_pings=5, count_marseys=not v.marsify, torture=torture)
if post_target.id not in ADMIGGER_THREADS and '!wordle' not in body.lower() and AGENDAPOSTER_PHRASE not in body.lower():
existing = db.query(Comment.id).filter(
existing = g.db.query(Comment.id).filter(
Comment.author_id == v.id,
Comment.deleted_utc == 0,
Comment.parent_comment_id == parent_comment_id,
@ -267,8 +267,8 @@ def comment(v:User):
)
c.upvotes = 1
db.add(c)
db.flush()
g.db.add(c)
g.db.flush()
process_poll_options(v, c)
@ -281,7 +281,7 @@ def comment(v:User):
if post_target.id not in ADMIGGER_THREADS and v.agendaposter and not v.marseyawarded and AGENDAPOSTER_PHRASE not in c.body.lower() and not (posting_to_submission and post_target.sub == 'chudrama'):
c.is_banned = True
c.ban_reason = "AutoJanny"
db.add(c)
g.db.add(c)
body = AGENDAPOSTER_MSG.format(username=v.username, type='comment', AGENDAPOSTER_PHRASE=AGENDAPOSTER_PHRASE)
body_jannied_html = AGENDAPOSTER_MSG_HTML.format(id=v.id, username=v.username, type='comment', AGENDAPOSTER_PHRASE=AGENDAPOSTER_PHRASE)
@ -299,16 +299,16 @@ def comment(v:User):
ghost=c.ghost
)
db.add(c_jannied)
db.flush()
g.db.add(c_jannied)
g.db.flush()
if posting_to_submission:
post_target.comment_count += 1
db.add(post_target)
g.db.add(post_target)
n = Notification(comment_id=c_jannied.id, user_id=v.id)
db.add(n)
g.db.add(n)
execute_longpostbot(c, level, body, body_html, post_target, v)
execute_zozbot(c, level, post_target, v)
@ -322,7 +322,7 @@ def comment(v:User):
push_notif(notify_users, f'New mention of you by @{c.author_name}', c.body, c)
if c.level == 1 and posting_to_submission:
subscriber_ids = [x[0] for x in db.query(Subscription.user_id).filter(Subscription.submission_id == post_target.id, Subscription.user_id != v.id).all()]
subscriber_ids = [x[0] for x in g.db.query(Subscription.user_id).filter(Subscription.submission_id == post_target.id, Subscription.user_id != v.id).all()]
notify_users.update(subscriber_ids)
@ -333,7 +333,7 @@ def comment(v:User):
for x in notify_users-bots:
n = Notification(comment_id=c.id, user_id=x)
db.add(n)
g.db.add(n)
if parent_user.id != v.id and not v.shadowbanned:
if isinstance(parent, User):
@ -351,15 +351,15 @@ def comment(v:User):
vote_type=1,
coins=0
)
db.add(vote)
g.db.add(vote)
cache.delete_memoized(comment_idlist)
v.comment_count = db.query(Comment).filter(
v.comment_count = g.db.query(Comment).filter(
Comment.author_id == v.id,
or_(Comment.parent_submission != None, Comment.wall_user_id != None),
Comment.deleted_utc == 0
).count()
db.add(v)
g.db.add(v)
c.voted = 1
@ -372,18 +372,18 @@ def comment(v:User):
if (posting_to_submission and not rts
and not c.wordle_result and not c.slots_result):
post_target.comment_count += 1
db.add(post_target)
g.db.add(post_target)
if c.level > 5:
n = db.query(Notification).filter_by(
n = g.db.query(Notification).filter_by(
comment_id=c.parent_comment.parent_comment.parent_comment.parent_comment_id,
user_id=c.parent_comment.author_id,
).one_or_none()
if n: db.delete(n)
if n: g.db.delete(n)
db.flush()
g.db.flush()
if v.client: return c.json
if v.client: return c.json(db=g.db)
return {"comment": render_template("comments.html", v=v, comments=[c])}
@app.post("/delete/comment/<int:cid>")
@ -397,15 +397,15 @@ def delete_comment(cid, v):
if not c.deleted_utc:
if c.author_id != v.id: abort(403)
c.deleted_utc = int(time.time())
db.add(c)
g.db.add(c)
cache.delete_memoized(comment_idlist)
v.comment_count = db.query(Comment).filter(
v.comment_count = g.db.query(Comment).filter(
Comment.author_id == v.id,
or_(Comment.parent_submission != None, Comment.wall_user_id != None),
Comment.deleted_utc == 0
).count()
db.add(v)
g.db.add(v)
return {"message": "Comment deleted!"}
@app.post("/undelete/comment/<int:cid>")
@ -418,15 +418,14 @@ def undelete_comment(cid, v):
if c.deleted_utc:
if c.author_id != v.id: abort(403)
c.deleted_utc = 0
db.add(c)
g.db.add(c)
cache.delete_memoized(comment_idlist)
v.comment_count = db.query(Comment).filter(
v.comment_count = g.db.query(Comment).filter(
Comment.author_id == v.id,
or_(Comment.parent_submission != None, Comment.wall_user_id != None),
Comment.deleted_utc == 0
).count()
db.add(v)
g.db.add(v)
return {"message": "Comment undeleted!"}
@app.post("/pin_comment/<int:cid>")
@ -445,7 +444,7 @@ def pin_comment(cid, v):
if comment.post.ghost: comment.stickied = "(OP)"
else: comment.stickied = v.username + " (OP)"
db.add(comment)
g.db.add(comment)
if v.id != comment.author_id:
if comment.post.ghost: message = f"OP has pinned your [comment]({comment.shortlink})"
@ -471,7 +470,7 @@ def unpin_comment(cid, v):
abort(403, "You can only unpin comments you have pinned!")
comment.stickied = None
db.add(comment)
g.db.add(comment)
if v.id != comment.author_id:
message = f"@{v.username} (OP) has unpinned your [comment]({comment.shortlink})"
@ -488,11 +487,11 @@ def save_comment(cid, v):
comment=get_comment(cid)
save=db.query(CommentSaveRelationship).filter_by(user_id=v.id, comment_id=comment.id).one_or_none()
save=g.db.query(CommentSaveRelationship).filter_by(user_id=v.id, comment_id=comment.id).one_or_none()
if not save:
new_save=CommentSaveRelationship(user_id=v.id, comment_id=comment.id)
db.add(new_save)
g.db.add(new_save)
return {"message": "Comment saved!"}
@ -506,10 +505,10 @@ def unsave_comment(cid, v):
comment=get_comment(cid)
save=db.query(CommentSaveRelationship).filter_by(user_id=v.id, comment_id=comment.id).one_or_none()
save=g.db.query(CommentSaveRelationship).filter_by(user_id=v.id, comment_id=comment.id).one_or_none()
if save:
db.delete(save)
g.db.delete(save)
return {"message": "Comment unsaved!"}
@ -562,7 +561,7 @@ def handle_wordle_action(cid, v):
comment.wordle_result = f'{guesses}_{status}_{answer}'
db.add(comment)
g.db.add(comment)
return {"response" : comment.wordle_html(v)}
@ -583,7 +582,7 @@ def toggle_comment_nsfw(cid, v):
abort(403)
comment.over_18 = not comment.over_18
db.add(comment)
g.db.add(comment)
if comment.author_id != v.id:
if v.admin_level >= PERMS['POST_COMMENT_MODERATION']:
@ -592,7 +591,7 @@ def toggle_comment_nsfw(cid, v):
user_id = v.id,
target_comment_id = comment.id,
)
db.add(ma)
g.db.add(ma)
else:
ma = SubAction(
sub = comment.post.sub,
@ -600,7 +599,7 @@ def toggle_comment_nsfw(cid, v):
user_id = v.id,
target_comment_id = comment.id,
)
db.add(ma)
g.db.add(ma)
if comment.over_18: return {"message": "Comment has been marked as +18!"}
else: return {"message": "Comment has been unmarked as +18!"}
@ -658,10 +657,10 @@ def edit_comment(cid, v):
alert_everyone(c.id)
else:
for x in notify_users-bots:
notif = db.query(Notification).filter_by(comment_id=c.id, user_id=x).one_or_none()
notif = g.db.query(Notification).filter_by(comment_id=c.id, user_id=x).one_or_none()
if not notif:
n = Notification(comment_id=c.id, user_id=x)
db.add(n)
g.db.add(n)
if not v.shadowbanned:
push_notif({x}, f'New mention of you by @{c.author_name}', c.body, c)
@ -680,8 +679,8 @@ def edit_comment(cid, v):
if int(time.time()) - c.created_utc > 60 * 3: c.edited_utc = int(time.time())
db.add(c)
g.db.add(c)
db.flush()
g.db.flush()
return {"body": c.body, "comment": c.realbody(v)}

View File

@ -27,7 +27,6 @@ from files.__main__ import app, limiter
@app.errorhandler(415)
@app.errorhandler(418)
@app.errorhandler(429)
@app.errorhandler(500)
def error(e):
g.desires_auth = False
title = ERROR_TITLES.get(e.code, str(e.code))
@ -53,6 +52,14 @@ def error_401(e):
if session.get("history") or not get_setting("signups"): return redirect(f"/login?redirect={argval}")
else: return redirect(f"/signup?redirect={argval}")
@app.errorhandler(500)
def error_500(e):
if hasattr(g, 'db'):
g.db.rollback()
g.db.close()
del g.db
return error(e)
@app.post("/allow_nsfw")
@limiter.limit('1/second', scope=rpath)

View File

@ -69,7 +69,7 @@ def front_all(v, sub=None, subdomain=None):
if v.hidevotedon: posts = [x for x in posts if not hasattr(x, 'voted') or not x.voted]
award_timers(v)
if v and v.client: return {"data": [x.json for x in posts], "next_exists": next_exists}
if v and v.client: return {"data": [x.json(g.db) for x in posts], "next_exists": next_exists}
return render_template("home.html", v=v, listing=posts, next_exists=next_exists, sort=sort, t=t, page=page, sub=sub, home=True, pins=pins, holes=holes)
@ -77,7 +77,7 @@ LIMITED_WPD_HOLES = ('gore', 'aftermath', 'selfharm', 'meta', 'discussion', 'soc
@cache.memoize()
def frontlist(v=None, sort="hot", page=1, t="all", ids_only=True, filter_words='', gt=0, lt=0, sub=None, site=None, pins=True, holes=True):
posts = db.query(Submission)
posts = g.db.query(Submission)
if v and v.hidevotedon:
posts = posts.outerjoin(Vote,
@ -135,9 +135,9 @@ def frontlist(v=None, sort="hot", page=1, t="all", ids_only=True, filter_words='
if pins and page == 1 and not gt and not lt:
if sub:
pins = db.query(Submission).filter(Submission.sub == sub.name, Submission.hole_pinned != None)
pins = g.db.query(Submission).filter(Submission.sub == sub.name, Submission.hole_pinned != None)
else:
pins = db.query(Submission).filter(Submission.stickied != None, Submission.is_banned == False)
pins = g.db.query(Submission).filter(Submission.stickied != None, Submission.is_banned == False)
if v:
pins = pins.filter(or_(Submission.sub == None, Submission.sub.notin_(v.all_blocks)))
@ -145,7 +145,7 @@ def frontlist(v=None, sort="hot", page=1, t="all", ids_only=True, filter_words='
if pin.stickied_utc and int(time.time()) > pin.stickied_utc:
pin.stickied = None
pin.stickied_utc = None
db.add(pin)
g.db.add(pin)
if v: pins = pins.filter(Submission.author_id.notin_(v.userblocks))
@ -164,7 +164,7 @@ def frontlist(v=None, sort="hot", page=1, t="all", ids_only=True, filter_words='
@auth_required
def random_post(v:User):
p = db.query(Submission.id).filter(Submission.deleted_utc == 0, Submission.is_banned == False, Submission.private == False).order_by(func.random()).first()
p = g.db.query(Submission.id).filter(Submission.deleted_utc == 0, Submission.is_banned == False, Submission.private == False).order_by(func.random()).first()
if p: p = p[0]
else: abort(404)
@ -177,7 +177,7 @@ def random_post(v:User):
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required
def random_user(v:User):
u = db.query(User.username).filter(User.song != None).order_by(func.random()).first()
u = g.db.query(User.username).filter(User.song != None).order_by(func.random()).first()
if u: u = u[0]
else: abort(404, "No users have set a profile anthem so far!")
@ -186,7 +186,7 @@ def random_user(v:User):
@cache.memoize()
def comment_idlist(v=None, page=1, sort="new", t="day", gt=0, lt=0, site=None):
comments = db.query(Comment.id) \
comments = g.db.query(Comment.id) \
.outerjoin(Comment.post) \
.filter(
or_(Comment.parent_submission != None, Comment.wall_user_id != None),
@ -240,5 +240,5 @@ def all_comments(v:User):
next_exists = len(idlist) > PAGE_SIZE
idlist = idlist[:PAGE_SIZE]
if v.client: return {"data": [x.json for x in comments]}
if v.client: return {"data": [x.json(g.db) for x in comments]}
return render_template("home_comments.html", v=v, sort=sort, t=t, page=page, comments=comments, standalone=True, next_exists=next_exists)

View File

@ -12,7 +12,7 @@ from files.__main__ import app, limiter
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required
def ping_groups(v:User):
groups = db.query(Group).order_by(Group.created_utc).all()
groups = g.db.query(Group).order_by(Group.created_utc).all()
return render_template('groups.html', v=v, groups=groups, cost=GROUP_COST, msg=get_msg(), error=get_error())
@app.post("/create_group")
@ -31,18 +31,18 @@ def create_group(v):
if not valid_sub_regex.fullmatch(name):
return redirect(f"/ping_groups?error=Name does not match the required format!")
if name == 'everyone' or db.get(Group, name):
if name == 'everyone' or g.db.get(Group, name):
return redirect(f"/ping_groups?error=This group already exists!")
if not v.charge_account('combined', GROUP_COST):
return redirect(f"/ping_groups?error=You don't have enough coins or marseybux!")
db.add(v)
g.db.add(v)
if v.shadowbanned: abort(500)
group = Group(name=name)
db.add(group)
db.flush()
g.db.add(group)
g.db.flush()
group_membership = GroupMembership(
user_id=v.id,
@ -50,9 +50,9 @@ def create_group(v):
created_utc=time.time(),
approved_utc=time.time()
)
db.add(group_membership)
g.db.add(group_membership)
admins = [x[0] for x in db.query(User.id).filter(User.admin_level >= PERMS['NOTIFICATIONS_HOLE_CREATION'], User.id != v.id).all()]
admins = [x[0] for x in g.db.query(User.id).filter(User.admin_level >= PERMS['NOTIFICATIONS_HOLE_CREATION'], User.id != v.id).all()]
for admin in admins:
send_repeatable_notification(admin, f":!marseyparty: !{group} has been created by @{v.username} :marseyparty:")
@ -66,12 +66,12 @@ def create_group(v):
def join_group(v:User, group_name):
group_name = group_name.strip().lower()
group = db.get(Group, group_name)
group = g.db.get(Group, group_name)
if not group: abort(404)
existing = db.query(GroupMembership).filter_by(user_id=v.id, group_name=group_name).one_or_none()
existing = g.db.query(GroupMembership).filter_by(user_id=v.id, group_name=group_name).one_or_none()
if not existing:
join = GroupMembership(user_id=v.id, group_name=group_name)
db.add(join)
g.db.add(join)
send_notification(group.owner.id, f"@{v.username} has applied to join !{group}. You can approve or reject the application [here](/!{group}).")
return {"message": f"Application submitted to !{group}'s owner (@{group.owner.username}) successfully!"}
@ -87,9 +87,9 @@ def leave_group(v:User, group_name):
if group_name == 'jannies':
abort(403, "You can't leave !jannies")
group = db.get(Group, group_name)
group = g.db.get(Group, group_name)
if not group: abort(404)
existing = db.query(GroupMembership).filter_by(user_id=v.id, group_name=group_name).one_or_none()
existing = g.db.query(GroupMembership).filter_by(user_id=v.id, group_name=group_name).one_or_none()
if existing:
if existing.approved_utc:
text = f"@{v.username} has left !{group}"
@ -99,7 +99,7 @@ def leave_group(v:User, group_name):
msg = f"You have cancelled your application to !{group} successfully!"
send_notification(group.owner.id, text)
db.delete(existing)
g.db.delete(existing)
return {"message": msg}
@ -113,15 +113,15 @@ def leave_group(v:User, group_name):
def memberships(v:User, group_name):
group_name = group_name.strip().lower()
group = db.get(Group, group_name)
group = g.db.get(Group, group_name)
if not group: abort(404)
members = db.query(GroupMembership).filter(
members = g.db.query(GroupMembership).filter(
GroupMembership.group_name == group_name,
GroupMembership.approved_utc != None
).order_by(GroupMembership.approved_utc).all()
applications = db.query(GroupMembership).filter(
applications = g.db.query(GroupMembership).filter(
GroupMembership.group_name == group_name,
GroupMembership.approved_utc == None
).order_by(GroupMembership.created_utc).all()
@ -136,19 +136,19 @@ def memberships(v:User, group_name):
def group_approve(v:User, group_name, user_id):
group_name = group_name.strip().lower()
group = db.get(Group, group_name)
group = g.db.get(Group, group_name)
if not group: abort(404)
if v.id != group.owner.id and v.admin_level < PERMS['MODS_EVERY_GROUP']:
abort(403, f"Only the group owner (@{group.owner.username}) can approve applications!")
application = db.query(GroupMembership).filter_by(user_id=user_id, group_name=group.name).one_or_none()
application = g.db.query(GroupMembership).filter_by(user_id=user_id, group_name=group.name).one_or_none()
if not application:
abort(404, "There is no application to approve!")
if not application.approved_utc:
application.approved_utc = time.time()
db.add(application)
g.db.add(application)
send_repeatable_notification(application.user_id, f"@{v.username} (!{group}'s owner) has approved your application!")
return {"message": f'You have approved @{application.user.username} successfully!'}
@ -161,13 +161,13 @@ def group_approve(v:User, group_name, user_id):
def group_reject(v:User, group_name, user_id):
group_name = group_name.strip().lower()
group = db.get(Group, group_name)
group = g.db.get(Group, group_name)
if not group: abort(404)
if v.id != group.owner.id and v.admin_level < PERMS['MODS_EVERY_GROUP']:
abort(403, f"Only the group owner (@{group.owner.username}) can reject memberships!")
membership = db.query(GroupMembership).filter_by(user_id=user_id, group_name=group.name).one_or_none()
membership = g.db.query(GroupMembership).filter_by(user_id=user_id, group_name=group.name).one_or_none()
if not membership:
abort(404, "There is no membership to reject!")
@ -180,6 +180,6 @@ def group_reject(v:User, group_name, user_id):
send_repeatable_notification(membership.user_id, text)
db.delete(membership)
g.db.delete(membership)
return {"message": msg}

View File

@ -15,17 +15,17 @@ def hats(v:User):
owned_hat_ids = [x.hat_id for x in v.owned_hats]
if v.equipped_hat_ids:
equipped = db.query(HatDef, User).join(HatDef.author).filter(HatDef.submitter_id == None, HatDef.id.in_(owned_hat_ids), HatDef.id.in_(v.equipped_hat_ids)).order_by(HatDef.price, HatDef.name).all()
not_equipped = db.query(HatDef, User).join(HatDef.author).filter(HatDef.submitter_id == None, HatDef.id.in_(owned_hat_ids), HatDef.id.notin_(v.equipped_hat_ids)).order_by(HatDef.price, HatDef.name).all()
equipped = g.db.query(HatDef, User).join(HatDef.author).filter(HatDef.submitter_id == None, HatDef.id.in_(owned_hat_ids), HatDef.id.in_(v.equipped_hat_ids)).order_by(HatDef.price, HatDef.name).all()
not_equipped = g.db.query(HatDef, User).join(HatDef.author).filter(HatDef.submitter_id == None, HatDef.id.in_(owned_hat_ids), HatDef.id.notin_(v.equipped_hat_ids)).order_by(HatDef.price, HatDef.name).all()
owned = equipped + not_equipped
else:
owned = db.query(HatDef, User).join(HatDef.author).filter(HatDef.submitter_id == None, HatDef.id.in_(owned_hat_ids)).order_by(HatDef.price, HatDef.name).all()
owned = g.db.query(HatDef, User).join(HatDef.author).filter(HatDef.submitter_id == None, HatDef.id.in_(owned_hat_ids)).order_by(HatDef.price, HatDef.name).all()
not_owned = db.query(HatDef, User).join(HatDef.author).filter(HatDef.submitter_id == None, HatDef.id.notin_(owned_hat_ids)).order_by(HatDef.price == 0, HatDef.price, HatDef.name).all()
not_owned = g.db.query(HatDef, User).join(HatDef.author).filter(HatDef.submitter_id == None, HatDef.id.notin_(owned_hat_ids)).order_by(HatDef.price == 0, HatDef.price, HatDef.name).all()
hats = owned + not_owned
sales = db.query(func.sum(User.coins_spent_on_hats)).scalar()
num_of_hats = db.query(HatDef).filter(HatDef.submitter_id == None).count()
sales = g.db.query(func.sum(User.coins_spent_on_hats)).scalar()
num_of_hats = g.db.query(HatDef).filter(HatDef.submitter_id == None).count()
return render_template("hats.html", owned_hat_ids=owned_hat_ids, hats=hats, v=v, sales=sales, num_of_hats=num_of_hats)
@app.post("/buy_hat/<int:hat_id>")
@ -37,10 +37,10 @@ def buy_hat(v:User, hat_id):
try: hat_id = int(hat_id)
except: abort(404, "Hat not found!")
hat = db.query(HatDef).filter_by(submitter_id=None, id=hat_id).one_or_none()
hat = g.db.query(HatDef).filter_by(submitter_id=None, id=hat_id).one_or_none()
if not hat: abort(404, "Hat not found!")
existing = db.query(Hat).filter_by(user_id=v.id, hat_id=hat.id).one_or_none()
existing = g.db.query(Hat).filter_by(user_id=v.id, hat_id=hat.id).one_or_none()
if existing: abort(409, "You already own this hat!")
if not hat.is_purchasable:
@ -61,10 +61,10 @@ def buy_hat(v:User, hat_id):
currency = "coins"
new_hat = Hat(user_id=v.id, hat_id=hat.id)
db.add(new_hat)
g.db.add(new_hat)
db.add(v)
db.add(hat.author)
g.db.add(v)
g.db.add(hat.author)
send_repeatable_notification(
hat.author.id,
@ -90,11 +90,11 @@ def equip_hat(v:User, hat_id):
try: hat_id = int(hat_id)
except: abort(404, "Hat not found!")
hat = db.query(Hat).filter_by(hat_id=hat_id, user_id=v.id).one_or_none()
hat = g.db.query(Hat).filter_by(hat_id=hat_id, user_id=v.id).one_or_none()
if not hat: abort(403, "You don't own this hat!")
hat.equipped = True
db.add(hat)
g.db.add(hat)
return {"message": f"'{hat.name}' equipped!"}
@ -107,11 +107,11 @@ def unequip_hat(v:User, hat_id):
try: hat_id = int(hat_id)
except: abort(404, "Hat not found!")
hat = db.query(Hat).filter_by(hat_id=hat_id, user_id=v.id).one_or_none()
hat = g.db.query(Hat).filter_by(hat_id=hat_id, user_id=v.id).one_or_none()
if not hat: abort(403, "You don't own this hat!")
hat.equipped = False
db.add(hat)
g.db.add(hat)
return {"message": f"'{hat.name}' unequipped!"}
@ -126,7 +126,7 @@ def hat_owners(v:User, hat_id):
try: page = int(request.values.get("page", 1))
except: page = 1
users = [x[1] for x in db.query(Hat, User).join(Hat.owners).filter(Hat.hat_id == hat_id).offset(PAGE_SIZE * (page - 1)).limit(PAGE_SIZE+1).all()]
users = [x[1] for x in g.db.query(Hat, User).join(Hat.owners).filter(Hat.hat_id == hat_id).offset(PAGE_SIZE * (page - 1)).limit(PAGE_SIZE+1).all()]
next_exists = (len(users) > PAGE_SIZE)
users = users[:PAGE_SIZE]

View File

@ -100,7 +100,7 @@ def calc_users():
'loggedin_chat':loggedin_chat}
def current_registered_users():
return "{:,}".format(db.query(User).count())
return "{:,}".format(g.db.query(User).count())
def git_head():
# Note: doing zero sanitization. Git branch names are extremely permissive.

View File

@ -56,7 +56,7 @@ def login_post(v:Optional[User]):
if username.startswith('@'): username = username[1:]
if "@" in username:
try: account = db.query(User).filter(User.email.ilike(username)).one_or_none()
try: account = g.db.query(User).filter(User.email.ilike(username)).one_or_none()
except: abort(400, "Multiple usernames have this email attached;<br>Please specify the username you want to login to!")
else: account = get_user(username, graceful=True)
@ -162,7 +162,7 @@ def sign_up_get(v:Optional[User]):
if ref:
ref = ref.replace('\\', '').replace('_', '\_').replace('%', '').strip()
ref_user = db.query(User).filter(User.username.ilike(ref)).one_or_none()
ref_user = g.db.query(User).filter(User.username.ilike(ref)).one_or_none()
else:
ref_user = None
@ -227,7 +227,7 @@ def sign_up_post(v:Optional[User]):
def signup_error(error):
if ref_id:
ref_user = db.get(User, ref_id)
ref_user = g.db.get(User, ref_id)
else:
ref_user = None
@ -307,7 +307,7 @@ def sign_up_post(v:Optional[User]):
session.pop("signup_token")
users_count = db.query(User).count()
users_count = g.db.query(User).count()
profileurl = None
if PFP_DEFAULT_MARSEY:
@ -326,9 +326,9 @@ def sign_up_post(v:Optional[User]):
new_user.admin_level = 4
session["history"] = []
db.add(new_user)
g.db.add(new_user)
db.flush()
g.db.flush()
if ref_id:
ref_user = get_account(ref_id)
@ -354,9 +354,9 @@ def sign_up_post(v:Optional[User]):
if SIGNUP_FOLLOW_ID:
signup_autofollow = get_account(SIGNUP_FOLLOW_ID)
new_follow = Follow(user_id=new_user.id, target_id=signup_autofollow.id)
db.add(new_follow)
g.db.add(new_follow)
signup_autofollow.stored_subscriber_count += 1
db.add(signup_autofollow)
g.db.add(signup_autofollow)
send_notification(signup_autofollow.id, f"A new user - @{new_user.username} - has followed you automatically!")
elif CARP_ID:
send_notification(CARP_ID, f"A new user - @{new_user.username} - has signed up!")
@ -389,7 +389,7 @@ def post_forgot():
username = username.lstrip('@').replace('\\', '').replace('_', '\_').replace('%', '').strip()
email = email.replace('\\', '').replace('_', '\_').replace('%', '').strip()
user = db.query(User).filter(
user = g.db.query(User).filter(
User.username.ilike(username),
User.email.ilike(email)).one_or_none()
@ -471,7 +471,7 @@ def post_reset(v:Optional[User]):
error="Passwords didn't match."), 400
user.passhash = hash_password(password)
db.add(user)
g.db.add(user)
return render_template("message_success.html",
@ -547,7 +547,7 @@ def reset_2fa():
abort(403)
user.mfa_secret=None
db.add(user)
g.db.add(user)
return render_template("message_success.html",
title="Two-factor authentication removed.",

View File

@ -53,6 +53,6 @@ def activate(v:User):
badge_grant(user=user, badge_id=2)
db.add(user)
g.db.add(user)
return render_template("message_success.html", v=v, title="Email verified!", message=f"Your email {email} has been verified. Thank you!")

View File

@ -16,14 +16,13 @@ from files.__main__ import app
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required
def clear(v):
notifs = db.query(Notification).join(Notification.comment).filter(Notification.read == False, Notification.user_id == v.id).all()
notifs = g.db.query(Notification).join(Notification.comment).filter(Notification.read == False, Notification.user_id == v.id).all()
for n in notifs:
n.read = True
db.add(n)
g.db.add(n)
v.last_viewed_post_notifs = int(time.time())
v.last_viewed_log_notifs = int(time.time())
db.add(v)
db.flush()
g.db.add(v)
return {"message": "Notifications marked as read!"}
@ -32,7 +31,7 @@ def clear(v):
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required
def unread(v):
listing = db.query(Notification, Comment).join(Notification.comment).filter(
listing = g.db.query(Notification, Comment).join(Notification.comment).filter(
Notification.read == False,
Notification.user_id == v.id,
Comment.is_banned == False,
@ -41,10 +40,9 @@ def unread(v):
for n, c in listing:
n.read = True
db.add(n)
db.flush()
return {"data":[x[1].json for x in listing]}
g.db.add(n)
return {"data":[x[1].json(g.db) for x in listing]}
@app.get("/notifications/modmail")
@ -55,16 +53,16 @@ def notifications_modmail(v):
try: page = max(int(request.values.get("page", 1)), 1)
except: page = 1
comments = db.query(Comment).filter_by(
comments = g.db.query(Comment).filter_by(
sentto=MODMAIL_ID,
level=1,
).order_by(Comment.id.desc()).offset(PAGE_SIZE*(page-1)).limit(PAGE_SIZE+1).all()
next_exists = (len(comments) > PAGE_SIZE)
listing = comments[:PAGE_SIZE]
db.flush()
g.db.flush()
if v.client: return {"data":[x.json for x in listing]}
if v.client: return {"data":[x.json(g.db) for x in listing]}
return render_template("notifications.html",
v=v,
@ -88,7 +86,7 @@ def notifications_messages(v:User):
# All of these queries are horrible. For whomever comes here after me,
# PLEASE just turn DMs into their own table and get them out of
# Notifications & Comments. It's worth it. Save yourself.
message_threads = db.query(Comment).filter(
message_threads = g.db.query(Comment).filter(
Comment.sentto != None,
or_(Comment.author_id == v.id, Comment.sentto == v.id),
Comment.parent_submission == None,
@ -96,7 +94,7 @@ def notifications_messages(v:User):
)
thread_order = db.query(Comment.top_comment_id, Comment.created_utc) \
thread_order = g.db.query(Comment.top_comment_id, Comment.created_utc) \
.distinct(Comment.top_comment_id) \
.filter(
Comment.sentto != None,
@ -114,29 +112,29 @@ def notifications_messages(v:User):
# Clear notifications (used for unread indicator only) for all user messages.
if not session.get("GLOBAL"):
notifs_unread_row = db.query(Notification.comment_id).join(Comment).filter(
notifs_unread_row = g.db.query(Notification.comment_id).join(Comment).filter(
Notification.user_id == v.id,
Notification.read == False,
or_(Comment.author_id == v.id, Comment.sentto == v.id),
).all()
notifs_unread = [n.comment_id for n in notifs_unread_row]
db.query(Notification).filter(
g.db.query(Notification).filter(
Notification.user_id == v.id,
Notification.comment_id.in_(notifs_unread),
).update({Notification.read: True})
db.flush()
g.db.flush()
next_exists = (len(message_threads) > 25)
listing = message_threads[:25]
list_to_perserve_unread_attribute = []
comments_unread = db.query(Comment).filter(Comment.id.in_(notifs_unread))
comments_unread = g.db.query(Comment).filter(Comment.id.in_(notifs_unread))
for c in comments_unread:
c.unread = True
list_to_perserve_unread_attribute.append(c)
if v.client: return {"data":[x.json for x in listing]}
if v.client: return {"data":[x.json(g.db) for x in listing]}
return render_template("notifications.html",
v=v,
@ -156,7 +154,7 @@ def notifications_posts(v:User):
try: page = max(int(request.values.get("page", 1)), 1)
except: page = 1
listing = [x[0] for x in db.query(Submission.id).filter(
listing = [x[0] for x in g.db.query(Submission.id).filter(
or_(
Submission.author_id.in_(v.followed_users),
Submission.sub.in_(v.followed_subs)
@ -179,10 +177,9 @@ def notifications_posts(v:User):
if not session.get("GLOBAL"):
v.last_viewed_post_notifs = int(time.time())
db.add(v)
db.flush()
g.db.add(v)
if v.client: return {"data":[x.json for x in listing]}
if v.client: return {"data":[x.json(g.db) for x in listing]}
return render_template("notifications.html",
v=v,
@ -209,7 +206,7 @@ def notifications_modactions(v:User):
else:
abort(403)
listing = db.query(cls).filter(cls.user_id != v.id)
listing = g.db.query(cls).filter(cls.user_id != v.id)
if v.id == AEVANN_ID:
listing = listing.filter(cls.kind.in_(AEVANN_MODACTION_TYPES))
@ -229,8 +226,7 @@ def notifications_modactions(v:User):
if not session.get("GLOBAL"):
v.last_viewed_log_notifs = int(time.time())
db.add(v)
db.flush()
g.db.add(v)
return render_template("notifications.html",
v=v,
@ -253,7 +249,7 @@ def notifications_reddit(v:User):
if not v.can_view_offsitementions: abort(403)
listing = db.query(Comment).filter(
listing = g.db.query(Comment).filter(
Comment.body_html.like('%<p>New site mention%<a href="https://old.reddit.com/r/%'),
Comment.parent_submission == None,
Comment.author_id == AUTOJANNY_ID
@ -267,9 +263,9 @@ def notifications_reddit(v:User):
if not session.get("GLOBAL"):
v.last_viewed_reddit_notifs = int(time.time())
db.add(v)
g.db.add(v)
if v.client: return {"data":[x.json for x in listing]}
if v.client: return {"data":[x.json(g.db) for x in listing]}
return render_template("notifications.html",
v=v,
@ -292,7 +288,7 @@ def notifications(v:User):
except: page = 1
if v.admin_level < PERMS['USER_SHADOWBAN']:
unread_and_inaccessible = db.query(Notification).join(Notification.comment).join(Comment.author).filter(
unread_and_inaccessible = g.db.query(Notification).join(Notification.comment).join(Comment.author).filter(
Notification.user_id == v.id,
Notification.read == False,
or_(
@ -303,9 +299,9 @@ def notifications(v:User):
).all()
for n in unread_and_inaccessible:
n.read = True
db.add(n)
g.db.add(n)
comments = db.query(Comment, Notification).join(Notification.comment).join(Comment.author).filter(
comments = g.db.query(Comment, Notification).join(Notification.comment).join(Comment.author).filter(
Notification.user_id == v.id,
or_(Comment.sentto == None, Comment.sentto != v.id),
not_(and_(Comment.sentto == MODMAIL_ID, User.is_muted)),
@ -340,7 +336,7 @@ def notifications(v:User):
total.append(c)
if c.replies2 == None:
c.replies2 = db.query(Comment).filter_by(parent_comment_id=c.id).filter(or_(Comment.author_id == v.id, Comment.id.in_(cids))).order_by(Comment.id.desc()).all()
c.replies2 = g.db.query(Comment).filter_by(parent_comment_id=c.id).filter(or_(Comment.author_id == v.id, Comment.id.in_(cids))).order_by(Comment.id.desc()).all()
total.extend(c.replies2)
for x in c.replies2:
if x.replies2 == None: x.replies2 = []
@ -351,11 +347,11 @@ def notifications(v:User):
c = c.parent_comment
if c.replies2 == None:
c.replies2 = db.query(Comment).filter_by(parent_comment_id=c.id).filter(or_(Comment.author_id == v.id, Comment.id.in_(cids))).order_by(Comment.id.desc()).all()
c.replies2 = g.db.query(Comment).filter_by(parent_comment_id=c.id).filter(or_(Comment.author_id == v.id, Comment.id.in_(cids))).order_by(Comment.id.desc()).all()
total.extend(c.replies2)
for x in c.replies2:
if x.replies2 == None:
x.replies2 = db.query(Comment).filter_by(parent_comment_id=x.id).filter(or_(Comment.author_id == v.id, Comment.id.in_(cids))).order_by(Comment.id.desc()).all()
x.replies2 = g.db.query(Comment).filter_by(parent_comment_id=x.id).filter(or_(Comment.author_id == v.id, Comment.id.in_(cids))).order_by(Comment.id.desc()).all()
total.extend(x.replies2)
if not hasattr(c, "notified_utc") or n.created_utc > c.notified_utc:
@ -366,13 +362,13 @@ def notifications(v:User):
else:
while c.parent_comment_id:
c = c.parent_comment
c.replies2 = db.query(Comment).filter_by(parent_comment_id=c.id).order_by(Comment.id).all()
c.replies2 = g.db.query(Comment).filter_by(parent_comment_id=c.id).order_by(Comment.id).all()
if c not in listing: listing.append(c)
if not n.read and not session.get("GLOBAL"):
n.read = True
db.add(n)
g.db.add(n)
total.extend(listing)
@ -382,7 +378,7 @@ def notifications(v:User):
if x.parent_comment_id:
parent = x.parent_comment
if parent.replies2 == None:
parent.replies2 = db.query(Comment).filter_by(parent_comment_id=parent.id).filter(or_(Comment.author_id == v.id, Comment.id.in_(cids+[x.id]))).order_by(Comment.id.desc()).all()
parent.replies2 = g.db.query(Comment).filter_by(parent_comment_id=parent.id).filter(or_(Comment.author_id == v.id, Comment.id.in_(cids+[x.id]))).order_by(Comment.id.desc()).all()
total.extend(parent.replies2)
for y in parent.replies2:
if y.replies2 == None:
@ -400,9 +396,9 @@ def notifications(v:User):
total_cids = set(total_cids)
output = get_comments_v_properties(v, None, Comment.id.in_(total_cids))[1]
db.flush()
g.db.flush()
if v.client: return {"data":[x.json for x in listing]}
if v.client: return {"data":[x.json(g.db) for x in listing]}
return render_template("notifications.html",
v=v,

View File

@ -13,7 +13,7 @@ from files.__main__ import app, limiter
@auth_required
def authorize_prompt(v:User):
client_id = request.values.get("client_id")
application = db.query(OauthApp).filter_by(client_id=client_id).one_or_none()
application = g.db.query(OauthApp).filter_by(client_id=client_id).one_or_none()
if not application: return {"oauth_error": "Invalid `client_id`"}, 401
return render_template("oauth.html", v=v, application=application)
@ -24,16 +24,16 @@ def authorize_prompt(v:User):
@auth_required
def authorize(v):
client_id = request.values.get("client_id")
application = db.query(OauthApp).filter_by(client_id=client_id).one_or_none()
application = g.db.query(OauthApp).filter_by(client_id=client_id).one_or_none()
if not application: return {"oauth_error": "Invalid `client_id`"}, 401
access_token = secrets.token_urlsafe(128)[:128]
try:
new_auth = ClientAuth(oauth_client = application.id, user_id = v.id, access_token=access_token)
db.add(new_auth)
g.db.add(new_auth)
except sqlalchemy.exc.IntegrityError:
db.rollback()
old_auth = db.query(ClientAuth).filter_by(oauth_client = application.id, user_id = v.id).one()
g.db.rollback()
old_auth = g.db.query(ClientAuth).filter_by(oauth_client = application.id, user_id = v.id).one()
access_token = old_auth.access_token
return redirect(f"{application.redirect_uri}?token={access_token}")
@ -45,9 +45,9 @@ def authorize(v):
@auth_required
def rescind(v, aid):
auth = db.query(ClientAuth).filter_by(oauth_client = aid, user_id = v.id).one_or_none()
auth = g.db.query(ClientAuth).filter_by(oauth_client = aid, user_id = v.id).one_or_none()
if not auth: abort(400)
db.delete(auth)
g.db.delete(auth)
return {"message": "Authorization revoked!"}
@ -64,7 +64,7 @@ def request_api_keys(v):
description=request.values.get("description")[:256]
)
db.add(new_app)
g.db.add(new_app)
body = f"@{v.username} has requested API keys for `{request.values.get('name')}`. You can approve or deny the request [here](/admin/apps)."
body_html = sanitize(body, blackjack="app description")
@ -77,16 +77,16 @@ def request_api_keys(v):
distinguish_level=6,
is_bot=True
)
db.add(new_comment)
db.flush()
g.db.add(new_comment)
g.db.flush()
new_comment.top_comment_id = new_comment.id
admin_ids = [x[0] for x in db.query(User.id).filter(User.admin_level >= PERMS['APPS_MODERATION']).all()]
admin_ids = [x[0] for x in g.db.query(User.id).filter(User.admin_level >= PERMS['APPS_MODERATION']).all()]
for admin_id in admin_ids:
notif = Notification(comment_id=new_comment.id, user_id=admin_id)
db.add(notif)
g.db.add(notif)
push_notif(admin_ids, 'New notification', body, f'{SITE_FULL}/comment/{new_comment.id}?read=true#context')
@ -103,15 +103,15 @@ def delete_oauth_app(v, aid):
aid = int(aid)
except:
abort(404)
app = db.get(OauthApp, aid)
app = g.db.get(OauthApp, aid)
if not app: abort(404)
if app.author_id != v.id: abort(403)
for auth in db.query(ClientAuth).filter_by(oauth_client=app.id).all():
db.delete(auth)
for auth in g.db.query(ClientAuth).filter_by(oauth_client=app.id).all():
g.db.delete(auth)
db.delete(app)
g.db.delete(app)
return redirect('/apps')
@ -127,7 +127,7 @@ def edit_oauth_app(v, aid):
aid = int(aid)
except:
abort(404)
app = db.get(OauthApp, aid)
app = g.db.get(OauthApp, aid)
if not app: abort(404)
if app.author_id != v.id: abort(403)
@ -136,7 +136,7 @@ def edit_oauth_app(v, aid):
app.app_name = request.values.get('name')
app.description = request.values.get("description")[:256]
db.add(app)
g.db.add(app)
return redirect('/settings/apps')
@ -149,14 +149,14 @@ def edit_oauth_app(v, aid):
@admin_level_required(PERMS['APPS_MODERATION'])
def admin_app_approve(v, aid):
app = db.get(OauthApp, aid)
app = g.db.get(OauthApp, aid)
if not app: abort(404)
user = app.author
if not app.client_id:
app.client_id = secrets.token_urlsafe(64)[:64]
db.add(app)
g.db.add(app)
access_token = secrets.token_urlsafe(128)[:128]
new_auth = ClientAuth(
@ -165,7 +165,7 @@ def admin_app_approve(v, aid):
access_token=access_token
)
db.add(new_auth)
g.db.add(new_auth)
send_repeatable_notification(user.id, f"@{v.username} (a site admin) has approved your application `{app.app_name}`. Here's your access token: ||{access_token}||\n\nPlease check the guide [here](/api) if you don't know what to do next!")
@ -174,7 +174,7 @@ def admin_app_approve(v, aid):
user_id=v.id,
target_user_id=user.id,
)
db.add(ma)
g.db.add(ma)
return {"message": f"'{app.app_name}' approved!"}
@ -187,21 +187,21 @@ def admin_app_approve(v, aid):
@admin_level_required(PERMS['APPS_MODERATION'])
def admin_app_revoke(v, aid):
app = db.get(OauthApp, aid)
app = g.db.get(OauthApp, aid)
if app:
for auth in db.query(ClientAuth).filter_by(oauth_client=app.id).all(): db.delete(auth)
for auth in g.db.query(ClientAuth).filter_by(oauth_client=app.id).all(): g.db.delete(auth)
if v.id != app.author.id:
send_repeatable_notification(app.author.id, f"@{v.username} (a site admin) has revoked your application `{app.app_name}`.")
db.delete(app)
g.db.delete(app)
ma = ModAction(
kind="revoke_app",
user_id=v.id,
target_user_id=app.author.id,
)
db.add(ma)
g.db.add(ma)
return {"message": f"'{app.app_name}' revoked!"}
@ -214,22 +214,22 @@ def admin_app_revoke(v, aid):
@admin_level_required(PERMS['APPS_MODERATION'])
def admin_app_reject(v, aid):
app = db.get(OauthApp, aid)
app = g.db.get(OauthApp, aid)
if app:
for auth in db.query(ClientAuth).filter_by(oauth_client=app.id).all(): db.delete(auth)
for auth in g.db.query(ClientAuth).filter_by(oauth_client=app.id).all(): g.db.delete(auth)
if v.id != app.author.id:
send_repeatable_notification(app.author.id, f"@{v.username} (a site admin) has rejected your application `{app.app_name}`.")
db.delete(app)
g.db.delete(app)
ma = ModAction(
kind="reject_app",
user_id=v.id,
target_user_id=app.author.id,
)
db.add(ma)
g.db.add(ma)
return {"message": f"'{app.app_name}' rejected!"}
@ -241,10 +241,10 @@ def admin_app_reject(v, aid):
@admin_level_required(PERMS['APPS_MODERATION'])
def admin_app_id_posts(v, aid):
aid=aid
oauth = db.get(OauthApp, aid)
oauth = g.db.get(OauthApp, aid)
if not oauth: abort(404)
pids=oauth.idlist(page=int(request.values.get("page",1)))
pids=oauth.idlist(g.db, page=int(request.values.get("page",1)))
next_exists=len(pids)==101
pids=pids[:100]
@ -266,10 +266,10 @@ def admin_app_id_comments(v, aid):
aid=aid
oauth = db.get(OauthApp, aid)
oauth = g.db.get(OauthApp, aid)
if not oauth: abort(404)
cids=oauth.comments_idlist(page=int(request.values.get("page",1)))
cids=oauth.comments_idlist(g.db, page=int(request.values.get("page",1)))
next_exists=len(cids)==101
cids=cids[:100]
@ -292,9 +292,9 @@ def admin_app_id_comments(v, aid):
@admin_level_required(PERMS['APPS_MODERATION'])
def admin_apps_list(v):
not_approved = db.query(OauthApp).filter(OauthApp.client_id == None).order_by(OauthApp.id.desc()).all()
not_approved = g.db.query(OauthApp).filter(OauthApp.client_id == None).order_by(OauthApp.id.desc()).all()
approved = db.query(OauthApp).filter(OauthApp.client_id != None).order_by(OauthApp.id.desc()).all()
approved = g.db.query(OauthApp).filter(OauthApp.client_id != None).order_by(OauthApp.id.desc()).all()
apps = not_approved + approved
@ -310,13 +310,13 @@ def reroll_oauth_tokens(aid, v):
aid = aid
a = db.get(OauthApp, aid)
a = g.db.get(OauthApp, aid)
if not a: abort(404)
if a.author_id != v.id: abort(403)
a.client_id = secrets.token_urlsafe(64)[:64]
db.add(a)
g.db.add(a)
return {"message": f"Client ID for '{a.app_name}' has been rerolled!", "id": a.client_id}

View File

@ -15,7 +15,7 @@ def vote_option(option_id, v):
option_id = int(option_id)
except:
abort(404)
option = db.get(SubmissionOption, option_id)
option = g.db.get(SubmissionOption, option_id)
if not option: abort(404)
sub = option.parent.sub
@ -27,31 +27,31 @@ def vote_option(option_id, v):
abort(403, "You can't participate in a closed bet!")
if not v.charge_account('combined', POLL_BET_COINS):
abort(400, f"You don't have {POLL_BET_COINS} coins or marseybux!")
db.add(v)
g.db.add(v)
autojanny = get_account(AUTOJANNY_ID)
autojanny.pay_account('coins', POLL_BET_COINS)
db.add(autojanny)
g.db.add(autojanny)
if option.exclusive:
vote = db.query(SubmissionOptionVote).join(SubmissionOption).filter(
vote = g.db.query(SubmissionOptionVote).join(SubmissionOption).filter(
SubmissionOptionVote.user_id==v.id,
SubmissionOptionVote.submission_id==option.parent_id,
SubmissionOption.exclusive==option.exclusive).all()
if vote:
if option.exclusive == 2: abort(400, "You already voted on this bet!")
for x in vote:
db.delete(x)
g.db.delete(x)
existing = db.query(SubmissionOptionVote).filter_by(option_id=option_id, user_id=v.id).one_or_none()
existing = g.db.query(SubmissionOptionVote).filter_by(option_id=option_id, user_id=v.id).one_or_none()
if not existing:
vote = SubmissionOptionVote(
option_id=option_id,
user_id=v.id,
submission_id=option.parent_id,
)
db.add(vote)
g.db.add(vote)
elif existing and not option.exclusive:
db.delete(existing)
g.db.delete(existing)
return {"message": "Bet successful!"}
@ -65,7 +65,7 @@ def vote_option_comment(option_id, v):
option_id = int(option_id)
except:
abort(404)
option = db.get(CommentOption, option_id)
option = g.db.get(CommentOption, option_id)
if not option: abort(404)
sub = option.parent.post.sub
if sub in {'furry','vampire','racist','femboy'} and not v.house.lower().startswith(sub):
@ -76,31 +76,31 @@ def vote_option_comment(option_id, v):
abort(403, "You can't participate in a closed bet!")
if not v.charge_account('combined', POLL_BET_COINS):
abort(400, f"You don't have {POLL_BET_COINS} coins or marseybux!")
db.add(v)
g.db.add(v)
autojanny = get_account(AUTOJANNY_ID)
autojanny.pay_account('coins', POLL_BET_COINS)
db.add(autojanny)
g.db.add(autojanny)
if option.exclusive:
vote = db.query(CommentOptionVote).join(CommentOption).filter(
vote = g.db.query(CommentOptionVote).join(CommentOption).filter(
CommentOptionVote.user_id==v.id,
CommentOptionVote.comment_id==option.parent_id,
CommentOption.exclusive==option.exclusive).all()
if vote:
if option.exclusive == 2: abort(400, "You already voted on this bet!")
for x in vote:
db.delete(x)
g.db.delete(x)
existing = db.query(CommentOptionVote).filter_by(option_id=option_id, user_id=v.id).one_or_none()
existing = g.db.query(CommentOptionVote).filter_by(option_id=option_id, user_id=v.id).one_or_none()
if not existing:
vote = CommentOptionVote(
option_id=option_id,
user_id=v.id,
comment_id=option.parent_id,
)
db.add(vote)
g.db.add(vote)
elif existing:
db.delete(existing)
g.db.delete(existing)
return {"message": "Bet successful!"}
@ -114,20 +114,20 @@ def option_votes(option_id, v):
option_id = int(option_id)
except:
abort(404)
option = db.get(SubmissionOption, option_id)
option = g.db.get(SubmissionOption, option_id)
if not option: abort(404)
if option.parent.ghost and v.admin_level < PERMS['SEE_GHOST_VOTES']:
abort(403)
ups = db.query(SubmissionOptionVote).filter_by(option_id=option_id).order_by(SubmissionOptionVote.created_utc).all()
ups = g.db.query(SubmissionOptionVote).filter_by(option_id=option_id).order_by(SubmissionOptionVote.created_utc).all()
user_ids = [x[0] for x in db.query(SubmissionOptionVote.user_id).filter_by(option_id=option_id).all()]
total_ts = db.query(func.sum(User.truescore)).filter(User.id.in_(user_ids)).scalar()
user_ids = [x[0] for x in g.db.query(SubmissionOptionVote.user_id).filter_by(option_id=option_id).all()]
total_ts = g.db.query(func.sum(User.truescore)).filter(User.id.in_(user_ids)).scalar()
total_ts = format(total_ts, ",") if total_ts else '0'
if v.admin_level >= 3:
total_patrons = db.query(User).filter(User.id.in_(user_ids), User.patron > 0).count()
total_patrons = g.db.query(User).filter(User.id.in_(user_ids), User.patron > 0).count()
else:
total_patrons = None
@ -149,21 +149,21 @@ def option_votes_comment(option_id, v):
option_id = int(option_id)
except:
abort(404)
option = db.get(CommentOption, option_id)
option = g.db.get(CommentOption, option_id)
if not option: abort(404)
if option.parent.ghost and v.admin_level < PERMS['SEE_GHOST_VOTES']:
abort(403)
ups = db.query(CommentOptionVote).filter_by(option_id=option_id).order_by(CommentOptionVote.created_utc).all()
ups = g.db.query(CommentOptionVote).filter_by(option_id=option_id).order_by(CommentOptionVote.created_utc).all()
user_ids = [x[0] for x in db.query(CommentOptionVote.user_id).filter_by(option_id=option_id).all()]
total_ts = db.query(func.sum(User.truescore)).filter(User.id.in_(user_ids)).scalar()
user_ids = [x[0] for x in g.db.query(CommentOptionVote.user_id).filter_by(option_id=option_id).all()]
total_ts = g.db.query(func.sum(User.truescore)).filter(User.id.in_(user_ids)).scalar()
total_ts = format(total_ts, ",") if total_ts else '0'
if v.admin_level >= 3:
total_patrons = db.query(User).filter(User.id.in_(user_ids), User.patron > 0).count()
total_patrons = g.db.query(User).filter(User.id.in_(user_ids), User.patron > 0).count()
else:
total_patrons = None

View File

@ -44,7 +44,7 @@ def publish(pid, v):
if p.author_id != v.id: abort(403)
p.private = False
p.created_utc = int(time.time())
db.add(p)
g.db.add(p)
notify_users = NOTIFY_USERS(f'{p.title} {p.body}', v, ghost=p.ghost)
@ -76,7 +76,7 @@ def submit_get(v:User, sub=None):
sub = get_sub_by_name(sub, graceful=True)
if request.path.startswith('/h/') and not sub: abort(404)
SUBS = [x[0] for x in db.query(Sub.name).order_by(Sub.name).all()]
SUBS = [x[0] for x in g.db.query(Sub.name).order_by(Sub.name).all()]
return render_template("submit.html", SUBS=SUBS, v=v, sub=sub)
@ -109,9 +109,9 @@ def post_id(pid, anything=None, v=None, sub=None):
comments = sort_objects(sort, comments, Comment)
comments = [c[0] for c in comments.all()]
else:
pinned = db.query(Comment).filter(Comment.parent_submission == p.id, Comment.stickied != None).order_by(Comment.created_utc.desc()).all()
pinned = g.db.query(Comment).filter(Comment.parent_submission == p.id, Comment.stickied != None).order_by(Comment.created_utc.desc()).all()
comments = db.query(Comment).filter(
comments = g.db.query(Comment).filter(
Comment.parent_submission == p.id,
Comment.level == 1,
Comment.stickied == None
@ -133,13 +133,13 @@ def post_id(pid, anything=None, v=None, sub=None):
for comment in comments:
comments2.append(comment)
ids.add(comment.id)
count += db.query(Comment).filter_by(parent_submission=p.id, top_comment_id=comment.id).count() + 1
count += g.db.query(Comment).filter_by(parent_submission=p.id, top_comment_id=comment.id).count() + 1
if count > threshold: break
else:
for comment in comments:
comments2.append(comment)
ids.add(comment.id)
count += db.query(Comment).filter_by(parent_submission=p.id, parent_comment_id=comment.id).count() + 1
count += g.db.query(Comment).filter_by(parent_submission=p.id, parent_comment_id=comment.id).count() + 1
if count > 20: break
if len(comments) == len(comments2): offset = 0
@ -151,7 +151,7 @@ def post_id(pid, anything=None, v=None, sub=None):
if pin.stickied_utc and int(time.time()) > pin.stickied_utc:
pin.stickied = None
pin.stickied_utc = None
db.add(pin)
g.db.add(pin)
elif pin.level > 1:
pinned2[pin.top_comment] = ''
if pin.top_comment in comments:
@ -162,10 +162,10 @@ def post_id(pid, anything=None, v=None, sub=None):
p.replies = list(pinned2.keys()) + comments
p.views += 1
db.add(p)
g.db.add(p)
if v and v.client:
return p.json
return p.json(g.db)
template = "submission.html"
if (p.is_banned or p.author.shadowbanned) \
@ -196,7 +196,7 @@ def view_more(v, pid, sort, offset):
comments = [c[0] for c in comments.all()]
else:
comments = db.query(Comment).filter(
comments = g.db.query(Comment).filter(
Comment.parent_submission == pid,
Comment.level == 1,
Comment.stickied == None,
@ -213,13 +213,13 @@ def view_more(v, pid, sort, offset):
for comment in comments:
comments2.append(comment)
ids.add(comment.id)
count += db.query(Comment).filter_by(parent_submission=p.id, top_comment_id=comment.id).count() + 1
count += g.db.query(Comment).filter_by(parent_submission=p.id, top_comment_id=comment.id).count() + 1
if count > 100: break
else:
for comment in comments:
comments2.append(comment)
ids.add(comment.id)
count += db.query(Comment).filter_by(parent_submission=p.id, parent_comment_id=comment.id).count() + 1
count += g.db.query(Comment).filter_by(parent_submission=p.id, parent_comment_id=comment.id).count() + 1
if count > 20: break
if len(comments) == len(comments2): offset = 0
@ -236,7 +236,7 @@ def more_comments(v, cid):
try: cid = int(cid)
except: abort(404)
tcid = db.query(Comment.top_comment_id).filter_by(id=cid).one_or_none()[0]
tcid = g.db.query(Comment.top_comment_id).filter_by(id=cid).one_or_none()[0]
if v:
# shadowban check is done in sort_objects i think
@ -254,6 +254,7 @@ def more_comments(v, cid):
return render_template("comments.html", v=v, comments=comments, p=p, render_replies=True)
def thumbnail_thread(pid:int, vid:int):
db = db_session()
def expand_url(post_url, fragment_url):
if fragment_url.startswith("https://"):
return fragment_url
@ -371,7 +372,7 @@ def thumbnail_thread(pid:int, vid:int):
file.write(chunk)
v = db.get(User, vid)
url = process_image(name, v, resize=99, uploader_id=p.author_id)
url = process_image(name, v, resize=99, uploader_id=p.author_id, db=db)
if url:
p.thumburl = url
db.add(p)
@ -417,7 +418,7 @@ def is_repost():
url = url.rstrip('/')
search_url = url.replace('%', '').replace('\\', '').replace('_', '\_').strip()
repost = db.query(Submission).filter(
repost = g.db.query(Submission).filter(
Submission.url.ilike(search_url),
Submission.deleted_utc == 0,
Submission.is_banned == False
@ -459,7 +460,7 @@ def submit_post(v:User, sub=None):
if sub and sub != 'none':
sname = sub.strip().lower()
sub = db.query(Sub.name).filter_by(name=sname).one_or_none()
sub = g.db.query(Sub.name).filter_by(name=sname).one_or_none()
if not sub: abort(400, f"/h/{sname} not found!")
sub = sub[0]
if v.exiled_from(sub): abort(400, f"You're exiled from /h/{sub}")
@ -506,7 +507,7 @@ def submit_post(v:User, sub=None):
url = url.rstrip('/')
search_url = url.replace('%', '').replace('\\', '').replace('_', '\_').strip()
repost = db.query(Submission).filter(
repost = g.db.query(Submission).filter(
Submission.url.ilike(search_url),
Submission.deleted_utc == 0,
Submission.is_banned == False
@ -516,7 +517,7 @@ def submit_post(v:User, sub=None):
y = tldextract.extract(url).registered_domain + parsed_url.path
y = y.lower()
banned_domains = db.query(BannedDomain).all()
banned_domains = g.db.query(BannedDomain).all()
for x in banned_domains:
if y.startswith(x.domain):
abort(400, f'Remove the banned link "{x.domain}" and try again!<br>Reason for link ban: "{x.reason}"')
@ -538,7 +539,7 @@ def submit_post(v:User, sub=None):
abort(400, "Please enter a url or some text!")
if not IS_LOCALHOST:
dup = db.query(Submission).filter(
dup = g.db.query(Submission).filter(
Submission.author_id == v.id,
Submission.deleted_utc == 0,
Submission.title == title,
@ -599,8 +600,8 @@ def submit_post(v:User, sub=None):
ghost=flag_ghost
)
db.add(p)
db.flush()
g.db.add(p)
g.db.flush()
execute_under_siege(v, p, p.body, 'submission')
@ -614,7 +615,7 @@ def submit_post(v:User, sub=None):
submission_id=p.id,
coins=0
)
db.add(vote)
g.db.add(vote)
if request.files.get('file-url') and not g.is_tor:
file = request.files['file-url']
@ -678,22 +679,22 @@ def submit_post(v:User, sub=None):
ghost=p.ghost
)
db.add(c_jannied)
db.flush()
g.db.add(c_jannied)
g.db.flush()
p.comment_count += 1
db.add(p)
g.db.add(p)
c_jannied.top_comment_id = c_jannied.id
n = Notification(comment_id=c_jannied.id, user_id=v.id)
db.add(n)
g.db.add(n)
if not p.private and not (p.sub and db.query(Exile.user_id).filter_by(user_id=SNAPPY_ID, sub=p.sub).one_or_none()):
if not p.private and not (p.sub and g.db.query(Exile.user_id).filter_by(user_id=SNAPPY_ID, sub=p.sub).one_or_none()):
execute_snappy(p, v)
v.post_count = db.query(Submission).filter_by(author_id=v.id, deleted_utc=0).count()
db.add(v)
v.post_count = g.db.query(Submission).filter_by(author_id=v.id, deleted_utc=0).count()
g.db.add(v)
execute_lawlz_actions(v, p)
@ -706,8 +707,8 @@ def submit_post(v:User, sub=None):
cache.delete_memoized(frontlist)
cache.delete_memoized(userpagelisting)
db.flush()
if v.client: return p.json
g.db.flush()
if v.client: return p.json(g.db)
else:
p.voted = 1
return {"post_id": p.id, "success": True}
@ -729,13 +730,13 @@ def delete_post_pid(pid, v):
p.is_pinned = False
p.stickied = None
db.add(p)
g.db.add(p)
cache.delete_memoized(frontlist)
cache.delete_memoized(userpagelisting)
v.post_count = db.query(Submission).filter_by(author_id=v.id, deleted_utc=0).count()
db.add(v)
v.post_count = g.db.query(Submission).filter_by(author_id=v.id, deleted_utc=0).count()
g.db.add(v)
return {"message": "Post deleted!"}
@ -750,13 +751,13 @@ def undelete_post_pid(pid, v):
if p.deleted_utc:
p.deleted_utc = 0
db.add(p)
g.db.add(p)
cache.delete_memoized(frontlist)
cache.delete_memoized(userpagelisting)
v.post_count = db.query(Submission).filter_by(author_id=v.id, deleted_utc=0).count()
db.add(v)
v.post_count = g.db.query(Submission).filter_by(author_id=v.id, deleted_utc=0).count()
g.db.add(v)
return {"message": "Post undeleted!"}
@ -777,7 +778,7 @@ def mark_post_nsfw(pid, v):
abort(403)
p.over_18 = True
db.add(p)
g.db.add(p)
if p.author_id != v.id:
if v.admin_level >= PERMS['POST_COMMENT_MODERATION']:
@ -786,7 +787,7 @@ def mark_post_nsfw(pid, v):
user_id = v.id,
target_submission_id = p.id,
)
db.add(ma)
g.db.add(ma)
else:
ma = SubAction(
sub = p.sub,
@ -794,7 +795,7 @@ def mark_post_nsfw(pid, v):
user_id = v.id,
target_submission_id = p.id,
)
db.add(ma)
g.db.add(ma)
send_repeatable_notification(p.author_id, f"@{v.username} (a site admin) has marked [{p.title}](/post/{p.id}) as +18")
return {"message": "Post has been marked as +18!"}
@ -815,7 +816,7 @@ def unmark_post_nsfw(pid, v):
abort(403)
p.over_18 = False
db.add(p)
g.db.add(p)
if p.author_id != v.id:
if v.admin_level >= PERMS['POST_COMMENT_MODERATION']:
@ -824,7 +825,7 @@ def unmark_post_nsfw(pid, v):
user_id = v.id,
target_submission_id = p.id,
)
db.add(ma)
g.db.add(ma)
else:
ma = SubAction(
sub = p.sub,
@ -832,7 +833,7 @@ def unmark_post_nsfw(pid, v):
user_id = v.id,
target_submission_id = p.id,
)
db.add(ma)
g.db.add(ma)
send_repeatable_notification(p.author_id, f"@{v.username} (a site admin) has unmarked [{p.title}](/post/{p.id}) as +18")
return {"message": "Post has been unmarked as +18!"}
@ -846,11 +847,11 @@ def save_post(pid, v):
p = get_post(pid)
save = db.query(SaveRelationship).filter_by(user_id=v.id, submission_id=p.id).one_or_none()
save = g.db.query(SaveRelationship).filter_by(user_id=v.id, submission_id=p.id).one_or_none()
if not save:
new_save=SaveRelationship(user_id=v.id, submission_id=p.id)
db.add(new_save)
g.db.add(new_save)
return {"message": "Post saved!"}
@ -863,10 +864,10 @@ def unsave_post(pid, v):
p = get_post(pid)
save = db.query(SaveRelationship).filter_by(user_id=v.id, submission_id=p.id).one_or_none()
save = g.db.query(SaveRelationship).filter_by(user_id=v.id, submission_id=p.id).one_or_none()
if save:
db.delete(save)
g.db.delete(save)
return {"message": "Post unsaved!"}
@ -880,7 +881,7 @@ def pin_post(post_id, v):
if p:
if v.id != p.author_id: abort(403, "Only the post author can do that!")
p.is_pinned = not p.is_pinned
db.add(p)
g.db.add(p)
cache.delete_memoized(userpagelisting)
if p.is_pinned: return {"message": "Post pinned!"}
else: return {"message": "Post unpinned!"}
@ -894,7 +895,7 @@ def set_new_sort(post_id:int, v:User):
p = get_post(post_id)
if not v.can_edit(p): abort(403, "Only the post author can do that!")
p.new = True
db.add(p)
g.db.add(p)
if v.id != p.author_id:
ma = ModAction(
@ -902,7 +903,7 @@ def set_new_sort(post_id:int, v:User):
user_id = v.id,
target_submission_id = p.id,
)
db.add(ma)
g.db.add(ma)
send_repeatable_notification(p.author_id, f"@{v.username} (a site admin) has changed the the default sorting of comments on [{p.title}](/post/{p.id}) to `new`")
return {"message": "Changed the the default sorting of comments on this post to 'new'"}
@ -916,7 +917,7 @@ def unset_new_sort(post_id:int, v:User):
p = get_post(post_id)
if not v.can_edit(p): abort(403, "Only the post author can do that!")
p.new = None
db.add(p)
g.db.add(p)
if v.id != p.author_id:
ma = ModAction(
@ -924,7 +925,7 @@ def unset_new_sort(post_id:int, v:User):
user_id = v.id,
target_submission_id = p.id,
)
db.add(ma)
g.db.add(ma)
send_repeatable_notification(p.author_id, f"@{v.username} (a site admin) has changed the the default sorting of comments on [{p.title}](/post/{p.id}) to `hot`")
return {"message": "Changed the the default sorting of comments on this post to 'hot'"}
@ -1048,14 +1049,14 @@ def edit_post(pid, v):
if v.id == p.author_id:
if int(time.time()) - p.created_utc > 60 * 3: p.edited_utc = int(time.time())
db.add(p)
g.db.add(p)
else:
ma=ModAction(
kind="edit_post",
user_id=v.id,
target_submission_id=p.id
)
db.add(ma)
g.db.add(ma)
return redirect(p.permalink)

View File

@ -11,7 +11,7 @@ from files.classes.push_subscriptions import PushSubscription
def push_subscribe(v):
subscription_json = request.values.get("subscription_json")
subscription = db.query(PushSubscription).filter_by(
subscription = g.db.query(PushSubscription).filter_by(
user_id=v.id,
subscription_json=subscription_json,
).one_or_none()
@ -21,6 +21,6 @@ def push_subscribe(v):
user_id=v.id,
subscription_json=subscription_json,
)
db.add(subscription)
g.db.add(subscription)
return ''

View File

@ -30,7 +30,7 @@ def flag_post(pid, v):
if reason.startswith('!') and (v.admin_level >= PERMS['POST_COMMENT_MODERATION'] or post.sub and v.mods(post.sub)):
post.flair = reason[1:]
db.add(post)
g.db.add(post)
if v.admin_level >= PERMS['POST_COMMENT_MODERATION']:
ma=ModAction(
kind="flair_post",
@ -38,7 +38,7 @@ def flag_post(pid, v):
target_submission_id=post.id,
_note=f'"{post.flair}"'
)
db.add(ma)
g.db.add(ma)
position = 'a site admin'
else:
ma = SubAction(
@ -48,7 +48,7 @@ def flag_post(pid, v):
target_submission_id=post.id,
_note=f'"{post.flair}"'
)
db.add(ma)
g.db.add(ma)
position = f'a /h/{post.sub} mod'
if v.id != post.author_id:
@ -60,10 +60,10 @@ def flag_post(pid, v):
moved = move_post(post, v, reason)
if moved: return {"message": moved}
existing = db.query(Flag.post_id).filter_by(user_id=v.id, post_id=post.id).one_or_none()
existing = g.db.query(Flag.post_id).filter_by(user_id=v.id, post_id=post.id).one_or_none()
if existing: abort(409, "You already reported this post!")
flag = Flag(post_id=post.id, user_id=v.id, reason=reason)
db.add(flag)
g.db.add(flag)
return {"message": "Post reported!"}
@ -77,7 +77,7 @@ def flag_comment(cid, v):
comment = get_comment(cid)
existing = db.query(CommentFlag.comment_id).filter_by(user_id=v.id, comment_id=comment.id).one_or_none()
existing = g.db.query(CommentFlag.comment_id).filter_by(user_id=v.id, comment_id=comment.id).one_or_none()
if existing: abort(409, "You already reported this comment!")
reason = request.values.get("reason", "").strip()
@ -90,7 +90,7 @@ def flag_comment(cid, v):
flag = CommentFlag(comment_id=comment.id, user_id=v.id, reason=reason)
db.add(flag)
g.db.add(flag)
return {"message": "Comment reported!"}
@ -105,10 +105,10 @@ def remove_report_post(v, pid, uid):
pid = int(pid)
uid = int(uid)
except: abort(404)
report = db.query(Flag).filter_by(post_id=pid, user_id=uid).one_or_none()
report = g.db.query(Flag).filter_by(post_id=pid, user_id=uid).one_or_none()
if report:
db.delete(report)
g.db.delete(report)
ma=ModAction(
kind="delete_report",
@ -116,7 +116,7 @@ def remove_report_post(v, pid, uid):
target_submission_id=pid
)
db.add(ma)
g.db.add(ma)
return {"message": "Report removed successfully!"}
@ -130,10 +130,10 @@ def remove_report_comment(v, cid, uid):
cid = int(cid)
uid = int(uid)
except: abort(404)
report = db.query(CommentFlag).filter_by(comment_id=cid, user_id=uid).one_or_none()
report = g.db.query(CommentFlag).filter_by(comment_id=cid, user_id=uid).one_or_none()
if report:
db.delete(report)
g.db.delete(report)
ma=ModAction(
kind="delete_report",
@ -141,7 +141,7 @@ def remove_report_comment(v, cid, uid):
target_comment_id=cid
)
db.add(ma)
g.db.add(ma)
return {"message": "Report removed successfully!"}
def move_post(post:Submission, v:User, reason:str) -> Union[bool, str]:
@ -178,7 +178,7 @@ def move_post(post:Submission, v:User, reason:str) -> Union[bool, str]:
post.sub = sub_to
post.hole_pinned = None
db.add(post)
g.db.add(post)
if v.id != post.author_id:
if v.admin_level:
@ -192,7 +192,7 @@ def move_post(post:Submission, v:User, reason:str) -> Union[bool, str]:
target_submission_id=post.id,
_note=f'{sub_from_str}{sub_to_str}',
)
db.add(ma)
g.db.add(ma)
if sub_to == 'chudrama':
post.bannedfor = None
@ -203,7 +203,7 @@ def move_post(post:Submission, v:User, reason:str) -> Union[bool, str]:
user_id=v.id,
target_submission_id=post.id
)
db.add(ma)
g.db.add(ma)
if v.admin_level >= PERMS['POST_COMMENT_MODERATION']: position = 'a site admin'
else: position = f'a /h/{sub_from} mod'

View File

@ -26,9 +26,9 @@ def validate_formkey(u:User, formkey:Optional[str]) -> bool:
@cache.memoize()
def get_alt_graph_ids(uid:int) -> List[int]:
alt_graph_cte = db.query(literal(uid).label('user_id')).select_from(Alt).cte('alt_graph', recursive=True)
alt_graph_cte = g.db.query(literal(uid).label('user_id')).select_from(Alt).cte('alt_graph', recursive=True)
alt_graph_cte_inner = db.query(
alt_graph_cte_inner = g.db.query(
case(
(Alt.user1 == alt_graph_cte.c.user_id, Alt.user2),
(Alt.user2 == alt_graph_cte.c.user_id, Alt.user1),
@ -38,27 +38,27 @@ def get_alt_graph_ids(uid:int) -> List[int]:
)
alt_graph_cte = alt_graph_cte.union(alt_graph_cte_inner)
return set([x[0] for x in db.query(User.id).filter(User.id == alt_graph_cte.c.user_id, User.id != uid).all()])
return set([x[0] for x in g.db.query(User.id).filter(User.id == alt_graph_cte.c.user_id, User.id != uid).all()])
def get_alt_graph(uid:int) -> List[User]:
alt_ids = get_alt_graph_ids(uid)
return db.query(User).filter(User.id.in_(alt_ids)).order_by(User.username).all()
return g.db.query(User).filter(User.id.in_(alt_ids)).order_by(User.username).all()
def add_alt(user1:int, user2:int):
if AEVANN_ID in (user1, user2):
return
li = [user1, user2]
existing = db.query(Alt).filter(Alt.user1.in_(li), Alt.user2.in_(li)).one_or_none()
existing = g.db.query(Alt).filter(Alt.user1.in_(li), Alt.user2.in_(li)).one_or_none()
if not existing:
new_alt = Alt(user1=user1, user2=user2)
db.add(new_alt)
db.flush()
g.db.add(new_alt)
g.db.flush()
cache.delete_memoized(get_alt_graph_ids, user1)
cache.delete_memoized(get_alt_graph_ids, user2)
def check_for_alts(current:User, include_current_session=False):
current_id = current.id
ids = [x[0] for x in db.query(User.id).all()]
ids = [x[0] for x in g.db.query(User.id).all()]
past_accs = set(session.get("history", [])) if include_current_session else set()
for past_id in list(past_accs):
@ -70,7 +70,7 @@ def check_for_alts(current:User, include_current_session=False):
li = [past_id, current_id]
add_alt(past_id, current_id)
other_alts = db.query(Alt).filter(Alt.user1.in_(li), Alt.user2.in_(li)).all()
other_alts = g.db.query(Alt).filter(Alt.user1.in_(li), Alt.user2.in_(li)).all()
for a in other_alts:
if a.user1 != past_id: add_alt(a.user1, past_id)
if a.user1 != current_id: add_alt(a.user1, current_id)
@ -80,30 +80,30 @@ def check_for_alts(current:User, include_current_session=False):
past_accs.add(current_id)
if include_current_session:
session["history"] = list(past_accs)
db.flush()
g.db.flush()
for u in get_alt_graph(current.id):
if u.shadowbanned and not current.shadowbanned:
current.shadowbanned = u.shadowbanned
current.ban_reason = u.ban_reason
db.add(current)
g.db.add(current)
elif current.shadowbanned and not u.shadowbanned:
u.shadowbanned = current.shadowbanned
u.ban_reason = current.ban_reason
db.add(u)
g.db.add(u)
if u.is_muted and not current.is_muted:
current.is_muted = u.is_muted
db.add(current)
g.db.add(current)
elif current.is_muted and not u.is_muted:
u.is_muted = current.is_muted
db.add(u)
g.db.add(u)
if u.blacklisted_by and not current.blacklisted_by:
current.blacklisted_by = u.blacklisted_by
db.add(current)
g.db.add(current)
elif current.blacklisted_by and not u.blacklisted_by:
u.blacklisted_by = current.blacklisted_by
db.add(u)
g.db.add(u)
def execute_shadowban_viewers_and_voters(v:Optional[User], target:Union[Submission, Comment]):
if not v or not v.shadowbanned: return
@ -121,4 +121,4 @@ def execute_shadowban_viewers_and_voters(v:Optional[User], target:Union[Submissi
target.upvotes += amount
if isinstance(target, Submission):
target.views += amount*randint(3, 5)
db.add(target)
g.db.add(target)

View File

@ -61,7 +61,7 @@ def searchposts(v:User):
criteria=searchparse(query)
posts = db.query(Submission.id) \
posts = g.db.query(Submission.id) \
.join(Submission.author) \
.filter(Submission.author_id.notin_(v.userblocks))
@ -162,7 +162,7 @@ def searchposts(v:User):
posts = get_posts(ids, v=v, eager=True)
if v.client: return {"total":total, "data":[x.json for x in posts]}
if v.client: return {"total":total, "data":[x.json(g.db) for x in posts]}
return render_template("search.html",
v=v,
@ -192,7 +192,7 @@ def searchcomments(v:User):
criteria = searchparse(query)
comments = db.query(Comment.id).outerjoin(Comment.post) \
comments = g.db.query(Comment.id).outerjoin(Comment.post) \
.filter(
or_(Comment.parent_submission != None, Comment.wall_user_id != None),
Comment.author_id.notin_(v.userblocks),
@ -234,7 +234,7 @@ def searchcomments(v:User):
comments = apply_time_filter(t, comments, Comment)
if v.admin_level < PERMS['POST_COMMENT_MODERATION']:
private = [x[0] for x in db.query(Submission.id).filter(Submission.private == True).all()]
private = [x[0] for x in g.db.query(Submission.id).filter(Submission.private == True).all()]
comments = comments.filter(
Comment.is_banned==False,
@ -275,7 +275,7 @@ def searchcomments(v:User):
comments = get_comments(ids, v=v)
if v.client: return {"total":total, "data":[x.json for x in comments]}
if v.client: return {"total":total, "data":[x.json(db=g.db) for x in comments]}
return render_template("search_comments.html", v=v, query=query, total=total, page=page, comments=comments, sort=sort, t=t, next_exists=next_exists, standalone=True)
@ -300,7 +300,7 @@ def searchmessages(v:User):
if v.admin_level >= PERMS['VIEW_MODMAIL']:
dm_conditions.append(Comment.sentto == MODMAIL_ID),
comments = db.query(Comment.id) \
comments = g.db.query(Comment.id) \
.filter(
Comment.sentto != None,
Comment.parent_submission == None,
@ -366,7 +366,7 @@ def searchmessages(v:User):
comments = get_comments(ids, v=v)
if v.client: return {"total":total, "data":[x.json for x in comments]}
if v.client: return {"total":total, "data":[x.json(db=g.db) for x in comments]}
return render_template("search_comments.html", v=v, query=query, total=total, page=page, comments=comments, sort=sort, t=t, next_exists=next_exists, standalone=True)
@app.get("/search/users")
@ -381,7 +381,7 @@ def searchusers(v:User):
try: page = max(1, int(request.values.get("page", 1)))
except: abort(400, "Invalid page input!")
users = db.query(User)
users = g.db.query(User)
criteria = searchparse(query)

View File

@ -47,7 +47,7 @@ def remove_background(v):
if v.background.startswith('/images/'):
remove_media(v.background)
v.background = None
db.add(v)
g.db.add(v)
return {"message": "Background removed!"}
@app.post('/settings/custom_background')
@ -71,7 +71,7 @@ def upload_custom_background(v):
if v.background and v.background.startswith('/images/'):
remove_media(v.background)
v.background = background
db.add(v)
g.db.add(v)
return redirect('/settings/personal')
@ -93,7 +93,7 @@ def upload_profile_background(v):
if v.profile_background and path.isfile(v.profile_background):
remove_media(v.profile_background)
v.profile_background = background
db.add(v)
g.db.add(v)
badge_grant(badge_id=193, user=v)
return redirect(f'/@{v.username}')
@ -173,14 +173,14 @@ def settings_personal_post(v):
if isinstance(slur_filter_updated, bool):
updated = slur_filter_updated
else:
db.add(v)
g.db.add(v)
return slur_filter_updated
profanity_filter_updated = updated or update_potentially_permanent_flag("profanityreplacer", "profanityreplacer", "profanity replacer", 190)
if isinstance(profanity_filter_updated, bool):
updated = profanity_filter_updated
else:
db.add(v)
g.db.add(v)
return profanity_filter_updated
updated = updated or update_flag("hidevotedon", "hidevotedon")
@ -199,7 +199,7 @@ def settings_personal_post(v):
if v.spider: badge_grant(user=v, badge_id=179)
else:
badge = v.has_badge(179)
if badge: db.delete(badge)
if badge: g.db.delete(badge)
elif IS_FISTMAS() and not updated and request.values.get("event_music", v.event_music) != v.event_music and v.can_toggle_event_music:
updated = True
@ -208,25 +208,25 @@ def settings_personal_post(v):
elif not updated and request.values.get("bio") == "" and not request.files.get('file'):
v.bio = None
v.bio_html = None
db.add(v)
g.db.add(v)
return render_template("settings/personal.html", v=v, msg="Your bio has been updated!")
elif not updated and request.values.get("sig") == "":
v.sig = None
v.sig_html = None
db.add(v)
g.db.add(v)
return render_template("settings/personal.html", v=v, msg="Your sig has been updated!")
elif not updated and request.values.get("friends") == "":
v.friends = None
v.friends_html = None
db.add(v)
g.db.add(v)
return render_template("settings/personal.html", v=v, msg="Your friends list has been updated!")
elif not updated and request.values.get("enemies") == "":
v.enemies = None
v.enemies_html = None
db.add(v)
g.db.add(v)
return render_template("settings/personal.html", v=v, msg="Your enemies list has been updated!")
elif not updated and v.patron and request.values.get("sig"):
@ -239,7 +239,7 @@ def settings_personal_post(v):
v.sig = sig[:200]
v.sig_html=sig_html
db.add(v)
g.db.add(v)
return render_template("settings/personal.html",
v=v,
msg="Your sig has been updated.")
@ -269,7 +269,7 @@ def settings_personal_post(v):
v.friends = friends
v.friends_html=friends_html
db.add(v)
g.db.add(v)
return render_template("settings/personal.html",
v=v,
msg="Your friends list has been updated.")
@ -299,7 +299,7 @@ def settings_personal_post(v):
v.enemies = enemies
v.enemies_html=enemies_html
db.add(v)
g.db.add(v)
return render_template("settings/personal.html",
v=v,
msg="Your enemies list has been updated.")
@ -320,7 +320,7 @@ def settings_personal_post(v):
v.bio = bio[:BIO_FRIENDS_ENEMIES_LENGTH_LIMIT]
v.bio_html=bio_html
db.add(v)
g.db.add(v)
return render_template("settings/personal.html",
v=v,
msg="Your bio has been updated.")
@ -366,7 +366,7 @@ def settings_personal_post(v):
updated = True
if updated:
db.add(v)
g.db.add(v)
return {"message": "Your settings have been updated!"}
else:
abort(400, "You didn't change anything!")
@ -384,7 +384,7 @@ def filters(v:User):
return redirect("/settings/advanced?error=You didn't change anything!")
v.custom_filter_list=filters
db.add(v)
g.db.add(v)
return redirect("/settings/advanced?msg=Your custom filters have been updated!")
@ -397,7 +397,7 @@ def set_color(v:User, attr:str, color:Optional[str]):
return render_template("settings/personal.html", v=v, error="Invalid color hex code!")
if color and current != color:
setattr(v, attr, color)
db.add(v)
g.db.add(v)
return render_template("settings/personal.html", v=v, msg="Color successfully updated!")
@ -452,7 +452,7 @@ def settings_security_post(v):
v.passhash = hash_password(request.values.get("new_password"))
db.add(v)
g.db.add(v)
return render_template("settings/security.html", v=v, msg="Your password has been changed!")
if request.values.get("new_email"):
@ -492,7 +492,7 @@ def settings_security_post(v):
return render_template("settings/security.html", v=v, error="Invalid token!")
v.mfa_secret = secret
db.add(v)
g.db.add(v)
return render_template("settings/security.html", v=v, msg="Two-factor authentication enabled!")
if request.values.get("2fa_remove"):
@ -505,8 +505,8 @@ def settings_security_post(v):
return render_template("settings/security.html", v=v, error="Invalid token!")
v.mfa_secret = None
db.add(v)
db.flush()
g.db.add(v)
g.db.flush()
return render_template("settings/security.html", v=v, msg="Two-factor authentication disabled!")
@app.post("/settings/log_out_all_others")
@ -521,7 +521,7 @@ def settings_log_out_others(v):
v.login_nonce += 1
session["login_nonce"] = v.login_nonce
db.add(v)
g.db.add(v)
return redirect("/settings/security?msg=All other devices have been logged out!")
@ -556,7 +556,7 @@ def settings_images_profile(v):
v.highres = highres
v.profileurl = imageurl
db.add(v)
g.db.add(v)
cache.delete_memoized(get_profile_picture, v.id)
cache.delete_memoized(get_profile_picture, v.username)
@ -584,7 +584,7 @@ def settings_images_banner(v):
if v.bannerurl and '/images/' in v.bannerurl and path.isfile(v.bannerurl):
remove_media(v.bannerurl)
v.bannerurl = bannerurl
db.add(v)
g.db.add(v)
return redirect("/settings/personal?msg=Banner successfully updated!")
@ -604,7 +604,7 @@ def settings_css(v):
if v.agendaposter: abort(400, "Agendapostered users can't edit CSS!")
css = request.values.get("css", v.css).strip().replace('\\', '').strip()[:CSS_LENGTH_LIMIT]
v.css = css
db.add(v)
g.db.add(v)
return render_template("settings/css.html", v=v, msg="Custom CSS successfully updated!", profilecss=v.profilecss)
@ -619,7 +619,7 @@ def settings_profilecss(v):
if not valid:
return render_template("settings/css.html", error=error, v=v, profilecss=profilecss)
v.profilecss = profilecss
db.add(v)
g.db.add(v)
return redirect("/settings/css?msg=Profile CSS successfully updated!")
@app.get("/settings/security")
@ -654,7 +654,7 @@ def settings_block_user(v):
if v.has_blocked(user): abort(409, f"You have already blocked @{user.username}")
new_block = UserBlock(user_id=v.id, target_id=user.id)
db.add(new_block)
g.db.add(new_block)
if user.admin_level >= PERMS['USER_BLOCKS_VISIBLE']:
send_notification(user.id, f"@{v.username} has blocked you!")
@ -672,7 +672,7 @@ def settings_unblock_user(v):
user = get_user(request.values.get("username"))
x = v.has_blocked(user)
if not x: abort(409, "You can't unblock someone you haven't blocked")
db.delete(x)
g.db.delete(x)
if not v.shadowbanned and user.admin_level >= PERMS['USER_BLOCKS_VISIBLE']:
send_notification(user.id, f"@{v.username} has unblocked you!")
cache.delete_memoized(frontlist)
@ -712,7 +712,7 @@ def settings_name_change(v):
search_name = new_name.replace('\\', '').replace('_','\_').replace('%','')
x = db.query(User).filter(
x = g.db.query(User).filter(
or_(
User.username.ilike(search_name),
User.original_username.ilike(search_name)
@ -727,7 +727,7 @@ def settings_name_change(v):
v=get_account(v.id)
v.username=new_name
v.name_changed_utc=int(time.time())
db.add(v)
g.db.add(v)
return redirect("/settings/personal?msg=Name successfully changed!")
@ -752,16 +752,17 @@ def settings_song_change_mp3(v):
remove_media(name)
return redirect("/settings/personal?error=MP3 file must be smaller than 8MB")
if path.isfile(f"/songs/{v.song}.mp3") and db.query(User).filter_by(song=v.song).count() == 1:
if path.isfile(f"/songs/{v.song}.mp3") and g.db.query(User).filter_by(song=v.song).count() == 1:
remove_media(f"/songs/{v.song}.mp3")
v.song = song
db.add(v)
g.db.add(v)
return redirect("/settings/personal?msg=Profile Anthem successfully updated!")
def _change_song_youtube(vid, id):
db = db_session()
v = db.get(User, vid)
if v.song and path.isfile(f"/songs/{v.song}.mp3") and db.query(User).filter_by(song=v.song).count() == 1:
@ -805,10 +806,10 @@ def settings_song_change(v):
song=request.values.get("song").strip()
if song == "" and v.song:
if path.isfile(f"/songs/{v.song}.mp3") and db.query(User).filter_by(song=v.song).count() == 1:
if path.isfile(f"/songs/{v.song}.mp3") and g.db.query(User).filter_by(song=v.song).count() == 1:
remove_media(f"/songs/{v.song}.mp3")
v.song = None
db.add(v)
g.db.add(v)
return redirect("/settings/personal?msg=Profile Anthem successfully removed!")
song = song.replace("https://music.youtube.com", "https://youtube.com")
@ -826,7 +827,7 @@ def settings_song_change(v):
return redirect("/settings/personal?error=Not a YouTube link!"), 400
if path.isfile(f'/songs/{id}.mp3'):
v.song = id
db.add(v)
g.db.add(v)
return redirect("/settings/personal?msg=Profile Anthem successfully updated!")
@ -872,7 +873,7 @@ def settings_title_change(v):
v.customtitleplain = customtitleplain
v.customtitle = customtitle
db.add(v)
g.db.add(v)
return redirect("/settings/personal?msg=Flair successfully updated!")
@ -900,7 +901,7 @@ def settings_pronouns_change(v):
elif 'fag' in bare_pronouns: pronouns = 'cute/twink'
v.pronouns = pronouns
db.add(v)
g.db.add(v)
return redirect("/settings/personal?msg=Pronouns successfully updated!")
@ -916,7 +917,7 @@ def settings_checkmark_text(v):
if not new_name: abort(400)
if new_name == v.verified: return redirect("/settings/personal?error=You didn't change anything!")
v.verified = new_name
db.add(v)
g.db.add(v)
return redirect("/settings/personal?msg=Checkmark Text successfully updated!")
if IS_FISTMAS():
@ -927,5 +928,5 @@ if IS_FISTMAS():
@auth_required
def event_darkmode(v):
v.event_darkmode = not v.event_darkmode
db.add(v)
g.db.add(v)
return {"message": "Dark mode toggled successfully!"}

View File

@ -78,7 +78,7 @@ ORDER BY payout DESC, bets_won DESC, bets_total ASC;
@cache.memoize()
def _special_leaderboard_get():
result = db.execute(_special_leaderboard_query).all()
result = g.db.execute(_special_leaderboard_query).all()
return result
@app.get('/events/worldcup2022/leaderboard')

View File

@ -50,7 +50,7 @@ def marseys(v:User):
if SITE_NAME != 'rDrama':
abort(404)
marseys = get_marseys()
marseys = get_marseys(g.db)
authors = get_accounts_dict([m.author_id for m in marseys], v=v, graceful=True)
original = os.listdir("/asset_submissions/marseys/original")
for marsey in marseys:
@ -64,10 +64,10 @@ def marseys(v:User):
@app.get("/emojis")
@limiter.limit(DEFAULT_RATELIMIT)
def emoji_list():
return get_emojis()
return get_emojis(g.db)
@cache.cached(timeout=86400, key_prefix=MARSEYS_CACHE_KEY)
def get_marseys():
def get_marseys(db:scoped_session):
if not FEATURES['MARSEYS']: return []
marseys = []
for marsey, author in db.query(Marsey, User).join(User, Marsey.author_id == User.id).filter(Marsey.submitter_id == None).order_by(Marsey.count.desc()):
@ -77,8 +77,8 @@ def get_marseys():
return marseys
@cache.cached(timeout=600, key_prefix=EMOJIS_CACHE_KEY)
def get_emojis():
emojis = [m.json for m in get_marseys()]
def get_emojis(db:scoped_session):
emojis = [m.json() for m in get_marseys(db)]
for src in EMOJI_SRCS:
with open(src, "r", encoding="utf-8") as f:
emojis = emojis + json.load(f)
@ -125,7 +125,7 @@ def daily_chart(v:User):
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['VIEW_PATRONS'])
def patrons(v):
users = db.query(User).filter(User.patron > 0).order_by(User.patron.desc(), User.id).all()
users = g.db.query(User).filter(User.patron > 0).order_by(User.patron.desc(), User.id).all()
return render_template("admin/patrons.html", v=v, users=users, benefactor_def=AWARDS['benefactor'])
@ -135,7 +135,7 @@ def patrons(v):
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required
def admins(v:User):
admins = db.query(User).filter(User.admin_level >= PERMS['ADMIN_MOP_VISIBLE']).order_by(User.truescore.desc()).all()
admins = g.db.query(User).filter(User.admin_level >= PERMS['ADMIN_MOP_VISIBLE']).order_by(User.truescore.desc()).all()
return render_template("admins.html", v=v, admins=admins)
@app.get("/log")
@ -165,7 +165,7 @@ def log(v:User):
kind = None
actions = []
else:
actions = db.query(ModAction)
actions = g.db.query(ModAction)
if not (v and v.admin_level >= PERMS['USER_SHADOWBAN']):
actions = actions.filter(ModAction.kind.notin_(MODACTION_PRIVILEGED_TYPES))
if not (v and v.admin_level >= PERMS['PROGSTACK']):
@ -184,7 +184,7 @@ def log(v:User):
next_exists=len(actions) > PAGE_SIZE
actions=actions[:PAGE_SIZE]
admins = [x[0] for x in db.query(User.username).filter(User.admin_level >= PERMS['ADMIN_MOP_VISIBLE']).order_by(User.username).all()]
admins = [x[0] for x in g.db.query(User.username).filter(User.admin_level >= PERMS['ADMIN_MOP_VISIBLE']).order_by(User.username).all()]
return render_template("log.html", v=v, admins=admins, types=types, admin=admin, type=kind, actions=actions, next_exists=next_exists, page=page, single_user_url='admin')
@ -196,11 +196,11 @@ def log_item(id, v):
try: id = int(id)
except: abort(404)
action=db.get(ModAction, id)
action=g.db.get(ModAction, id)
if not action: abort(404)
admins = [x[0] for x in db.query(User.username).filter(User.admin_level >= PERMS['ADMIN_MOP_VISIBLE']).all()]
admins = [x[0] for x in g.db.query(User.username).filter(User.admin_level >= PERMS['ADMIN_MOP_VISIBLE']).all()]
if v and v.admin_level >= PERMS['USER_SHADOWBAN']:
if v and v.admin_level >= PERMS['PROGSTACK']:
@ -268,17 +268,17 @@ def submit_contact(v):
body_html=body_html,
sentto=MODMAIL_ID
)
db.add(new_comment)
db.flush()
g.db.add(new_comment)
g.db.flush()
execute_blackjack(v, new_comment, new_comment.body_html, 'modmail')
execute_under_siege(v, new_comment, new_comment.body_html, 'modmail')
new_comment.top_comment_id = new_comment.id
admin_ids = [x[0] for x in db.query(User.id).filter(User.admin_level >= PERMS['NOTIFICATIONS_MODMAIL']).all()]
admin_ids = [x[0] for x in g.db.query(User.id).filter(User.admin_level >= PERMS['NOTIFICATIONS_MODMAIL']).all()]
for admin_id in admin_ids:
notif = Notification(comment_id=new_comment.id, user_id=admin_id)
db.add(notif)
g.db.add(notif)
push_notif(admin_ids, f'New modmail from @{new_comment.author_name}', new_comment.body, f'{SITE_FULL}/notifications/modmail')
@ -293,9 +293,9 @@ no = (21,22,23,24,25,26,27)
@cache.memoize(timeout=3600)
def badge_list(site):
badges = db.query(BadgeDef).filter(BadgeDef.id.notin_(no)).order_by(BadgeDef.id).all()
counts_raw = db.query(Badge.badge_id, func.count()).group_by(Badge.badge_id).all()
users = db.query(User).count()
badges = g.db.query(BadgeDef).filter(BadgeDef.id.notin_(no)).order_by(BadgeDef.id).all()
counts_raw = g.db.query(Badge.badge_id, func.count()).group_by(Badge.badge_id).all()
users = g.db.query(User).count()
counts = {}
for c in counts_raw:
@ -317,7 +317,7 @@ def badges(v:User):
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['USER_BLOCKS_VISIBLE'])
def blocks(v):
blocks=db.query(UserBlock).all()
blocks=g.db.query(UserBlock).all()
users = []
targets = []
for x in blocks:
@ -358,7 +358,7 @@ def transfers_id(id, v):
try: id = int(id)
except: abort(404)
transfer = db.get(Comment, id)
transfer = g.db.get(Comment, id)
if not transfer: abort(404)
@ -370,7 +370,7 @@ def transfers_id(id, v):
@auth_required
def transfers(v:User):
comments = db.query(Comment).filter(Comment.author_id == AUTOJANNY_ID, Comment.parent_submission == None, Comment.body_html.like("%</a> has transferred %")).order_by(Comment.id.desc())
comments = g.db.query(Comment).filter(Comment.author_id == AUTOJANNY_ID, Comment.parent_submission == None, Comment.body_html.like("%</a> has transferred %")).order_by(Comment.id.desc())
try: page = max(int(request.values.get("page", 1)), 1)
except: page = 1
@ -380,7 +380,7 @@ def transfers(v:User):
comments = comments[:PAGE_SIZE]
if v.client:
return {"data": [x.json for x in comments]}
return {"data": [x.json(g.db) for x in comments]}
else:
return render_template("transfers.html", v=v, page=page, comments=comments, standalone=True, next_exists=next_exists)

View File

@ -26,7 +26,7 @@ def exile_post(v:User, pid):
if not u.exiled_from(sub):
exile = Exile(user_id=u.id, sub=sub, exiler_id=v.id)
db.add(exile)
g.db.add(exile)
send_notification(u.id, f"@{v.username} has exiled you from /h/{sub} for [{p.title}]({p.shortlink})")
@ -37,7 +37,7 @@ def exile_post(v:User, pid):
target_user_id=u.id,
_note=f'for <a href="{p.permalink}">{p.title_html}</a>'
)
db.add(ma)
g.db.add(ma)
return {"message": f"@{u.username} has been exiled from /h/{sub} successfully!"}
@ -60,7 +60,7 @@ def exile_comment(v:User, cid):
if not u.exiled_from(sub):
exile = Exile(user_id=u.id, sub=sub, exiler_id=v.id)
db.add(exile)
g.db.add(exile)
send_notification(u.id, f"@{v.username} has exiled you from /h/{sub} for [{c.permalink}]({c.shortlink})")
@ -71,7 +71,7 @@ def exile_comment(v:User, cid):
target_user_id=u.id,
_note=f'for <a href="/comment/{c.id}#context">comment</a>'
)
db.add(ma)
g.db.add(ma)
return {"message": f"@{u.username} has been exiled from /h/{sub} successfully!"}
@ -87,8 +87,8 @@ def unexile(v:User, sub, uid):
if v.shadowbanned: return redirect(f'/h/{sub}/exilees')
if u.exiled_from(sub):
exile = db.query(Exile).filter_by(user_id=u.id, sub=sub).one_or_none()
db.delete(exile)
exile = g.db.query(Exile).filter_by(user_id=u.id, sub=sub).one_or_none()
g.db.delete(exile)
send_notification(u.id, f"@{v.username} has revoked your exile from /h/{sub}")
@ -98,7 +98,7 @@ def unexile(v:User, sub, uid):
user_id=v.id,
target_user_id=u.id
)
db.add(ma)
g.db.add(ma)
if g.is_api_or_xhr:
return {"message": f"@{u.username} has been unexiled from /h/{sub} successfully!"}
@ -113,10 +113,10 @@ def unexile(v:User, sub, uid):
@auth_required
def block_sub(v:User, sub):
sub = get_sub_by_name(sub).name
existing = db.query(SubBlock).filter_by(user_id=v.id, sub=sub).one_or_none()
existing = g.db.query(SubBlock).filter_by(user_id=v.id, sub=sub).one_or_none()
if not existing:
block = SubBlock(user_id=v.id, sub=sub)
db.add(block)
g.db.add(block)
cache.delete_memoized(frontlist)
return {"message": f"/h/{sub} blocked successfully!"}
@ -130,10 +130,10 @@ def unblock_sub(v:User, sub):
if not User.can_see(v, sub):
abort(403)
block = db.query(SubBlock).filter_by(user_id=v.id, sub=sub.name).one_or_none()
block = g.db.query(SubBlock).filter_by(user_id=v.id, sub=sub.name).one_or_none()
if block:
db.delete(block)
g.db.delete(block)
cache.delete_memoized(frontlist)
return {"message": f"/h/{sub.name} unblocked successfully!"}
@ -145,10 +145,10 @@ def unblock_sub(v:User, sub):
@auth_required
def subscribe_sub(v:User, sub):
sub = get_sub_by_name(sub).name
existing = db.query(SubJoin).filter_by(user_id=v.id, sub=sub).one_or_none()
existing = g.db.query(SubJoin).filter_by(user_id=v.id, sub=sub).one_or_none()
if not existing:
subscribe = SubJoin(user_id=v.id, sub=sub)
db.add(subscribe)
g.db.add(subscribe)
cache.delete_memoized(frontlist)
return {"message": f"/h/{sub} unblocked successfully!"}
@ -159,9 +159,9 @@ def subscribe_sub(v:User, sub):
@auth_required
def unsubscribe_sub(v:User, sub):
sub = get_sub_by_name(sub).name
subscribe = db.query(SubJoin).filter_by(user_id=v.id, sub=sub).one_or_none()
subscribe = g.db.query(SubJoin).filter_by(user_id=v.id, sub=sub).one_or_none()
if subscribe:
db.delete(subscribe)
g.db.delete(subscribe)
cache.delete_memoized(frontlist)
return {"message": f"/h/{sub} blocked successfully!"}
@ -174,10 +174,10 @@ def follow_sub(v:User, sub):
sub = get_sub_by_name(sub)
if not User.can_see(v, sub):
abort(403)
existing = db.query(SubSubscription).filter_by(user_id=v.id, sub=sub.name).one_or_none()
existing = g.db.query(SubSubscription).filter_by(user_id=v.id, sub=sub.name).one_or_none()
if not existing:
subscription = SubSubscription(user_id=v.id, sub=sub.name)
db.add(subscription)
g.db.add(subscription)
cache.delete_memoized(frontlist)
return {"message": f"/h/{sub} followed successfully!"}
@ -189,9 +189,9 @@ def follow_sub(v:User, sub):
@auth_required
def unfollow_sub(v:User, sub):
sub = get_sub_by_name(sub)
subscription = db.query(SubSubscription).filter_by(user_id=v.id, sub=sub.name).one_or_none()
subscription = g.db.query(SubSubscription).filter_by(user_id=v.id, sub=sub.name).one_or_none()
if subscription:
db.delete(subscription)
g.db.delete(subscription)
cache.delete_memoized(frontlist)
return {"message": f"/h/{sub} unfollowed successfully!"}
@ -204,7 +204,7 @@ def mods(v:User, sub):
sub = get_sub_by_name(sub)
if not User.can_see(v, sub):
abort(403)
users = db.query(User, Mod).join(Mod).filter_by(sub=sub.name).order_by(Mod.created_utc).all()
users = g.db.query(User, Mod).join(Mod).filter_by(sub=sub.name).order_by(Mod.created_utc).all()
return render_template("sub/mods.html", v=v, sub=sub, users=users)
@ -217,7 +217,7 @@ def sub_exilees(v:User, sub):
sub = get_sub_by_name(sub)
if not User.can_see(v, sub):
abort(403)
users = db.query(User, Exile).join(Exile, Exile.user_id==User.id) \
users = g.db.query(User, Exile).join(Exile, Exile.user_id==User.id) \
.filter_by(sub=sub.name) \
.order_by(Exile.created_utc.desc(), User.username).all()
@ -232,7 +232,7 @@ def sub_blockers(v:User, sub):
sub = get_sub_by_name(sub)
if not User.can_see(v, sub):
abort(403)
users = db.query(User, SubBlock).join(SubBlock) \
users = g.db.query(User, SubBlock).join(SubBlock) \
.filter_by(sub=sub.name) \
.order_by(SubBlock.created_utc.desc(), User.username).all()
@ -248,7 +248,7 @@ def sub_followers(v:User, sub):
sub = get_sub_by_name(sub)
if not User.can_see(v, sub):
abort(403)
users = db.query(User, SubSubscription).join(SubSubscription) \
users = g.db.query(User, SubSubscription).join(SubSubscription) \
.filter_by(sub=sub.name) \
.order_by(SubSubscription.created_utc.desc(), User.username).all()
@ -276,11 +276,11 @@ def add_mod(v:User, sub):
if sub in {'furry','vampire','racist','femboy'} and not v.client and not user.house.lower().startswith(sub):
abort(403, f"@{user.username} needs to be a member of House {sub.capitalize()} to be added as a mod there!")
existing = db.query(Mod).filter_by(user_id=user.id, sub=sub).one_or_none()
existing = g.db.query(Mod).filter_by(user_id=user.id, sub=sub).one_or_none()
if not existing:
mod = Mod(user_id=user.id, sub=sub)
db.add(mod)
g.db.add(mod)
if v.id != user.id:
send_repeatable_notification(user.id, f"@{v.username} has added you as a mod to /h/{sub}")
@ -291,7 +291,7 @@ def add_mod(v:User, sub):
user_id=v.id,
target_user_id=user.id
)
db.add(ma)
g.db.add(ma)
return redirect(f'/h/{sub}/mods')
@ -317,12 +317,12 @@ def remove_mod(v:User, sub):
if not user: abort(404)
mod = db.query(Mod).filter_by(user_id=user.id, sub=sub).one_or_none()
mod = g.db.query(Mod).filter_by(user_id=user.id, sub=sub).one_or_none()
if not mod: abort(400)
if not (v.id == user.id or v.mod_date(sub) and v.mod_date(sub) < mod.created_utc): abort(403)
db.delete(mod)
g.db.delete(mod)
if v.id != user.id:
send_repeatable_notification(user.id, f"@{v.username} has removed you as a mod from /h/{sub}")
@ -333,7 +333,7 @@ def remove_mod(v:User, sub):
user_id=v.id,
target_user_id=user.id
)
db.add(ma)
g.db.add(ma)
return {"message": f"@{user.username} has been removed as a mod!"}
@ -371,16 +371,16 @@ def create_sub2(v):
if sub:
return redirect(f"/create_hole?error=/h/{sub} already exists!")
db.add(v)
g.db.add(v)
if v.shadowbanned: abort(500)
sub = Sub(name=name)
db.add(sub)
db.flush()
g.db.add(sub)
g.db.flush()
mod = Mod(user_id=v.id, sub=sub.name)
db.add(mod)
g.db.add(mod)
admins = [x[0] for x in db.query(User.id).filter(User.admin_level >= PERMS['NOTIFICATIONS_HOLE_CREATION'], User.id != v.id).all()]
admins = [x[0] for x in g.db.query(User.id).filter(User.admin_level >= PERMS['NOTIFICATIONS_HOLE_CREATION'], User.id != v.id).all()]
for admin in admins:
send_repeatable_notification(admin, f":!marseyparty: /h/{sub} has been created by @{v.username} :marseyparty:")
@ -408,13 +408,13 @@ def kick(v:User, pid):
user_id=v.id,
target_submission_id=post.id
)
db.add(ma)
g.db.add(ma)
if v.id != post.author_id:
message = f"@{v.username} (a /h/{old} mod) has moved [{post.title}]({post.shortlink}) from /h/{old} to the main feed!"
send_repeatable_notification(post.author_id, message)
db.add(post)
g.db.add(post)
cache.delete_memoized(frontlist)
@ -444,14 +444,14 @@ def post_sub_sidebar(v:User, sub):
sub.sidebar_html = sanitize(sub.sidebar, blackjack=f"/h/{sub} sidebar", showmore=False)
if len(sub.sidebar_html) > 20000: abort(400, "Sidebar is too big!")
db.add(sub)
g.db.add(sub)
ma = SubAction(
sub=sub.name,
kind='edit_sidebar',
user_id=v.id
)
db.add(ma)
g.db.add(ma)
return redirect(f'/h/{sub}/settings')
@ -478,21 +478,21 @@ def post_sub_css(v:User, sub):
return render_template('sub/settings.html', v=v, sidebar=sub.sidebar, sub=sub, error=error, css=css)
sub.css = css
db.add(sub)
g.db.add(sub)
ma = SubAction(
sub=sub.name,
kind='edit_css',
user_id=v.id
)
db.add(ma)
g.db.add(ma)
return redirect(f'/h/{sub}/settings')
@app.get("/h/<sub>/css")
@limiter.limit(DEFAULT_RATELIMIT)
def get_sub_css(sub):
sub = db.query(Sub.css).filter_by(name=sub.strip().lower()).one_or_none()
sub = g.db.query(Sub.css).filter_by(name=sub.strip().lower()).one_or_none()
if not sub: abort(404)
resp=make_response(sub.css or "")
resp.headers.add("Content-Type", "text/css")
@ -518,14 +518,14 @@ def upload_sub_banner(v:User, sub:str):
sub.bannerurls.append(bannerurl)
db.add(sub)
g.db.add(sub)
ma = SubAction(
sub=sub.name,
kind='upload_banner',
user_id=v.id
)
db.add(ma)
g.db.add(ma)
return redirect(f'/h/{sub}/settings')
@ -548,7 +548,7 @@ def delete_sub_banner(v:User, sub:str, index:int):
except FileNotFoundError:
pass
del sub.bannerurls[index]
db.add(sub)
g.db.add(sub)
ma = SubAction(
sub=sub.name,
@ -556,7 +556,7 @@ def delete_sub_banner(v:User, sub:str, index:int):
_note=index,
user_id=v.id
)
db.add(ma)
g.db.add(ma)
return {"message": f"Deleted banner {index} from /h/{sub} successfully"}
@ -574,7 +574,7 @@ def delete_all_sub_banners(v:User, sub:str):
except FileNotFoundError:
pass
sub.bannerurls = []
db.add(sub)
g.db.add(sub)
ma = SubAction(
sub=sub.name,
@ -582,7 +582,7 @@ def delete_all_sub_banners(v:User, sub:str):
_note='all',
user_id=v.id
)
db.add(ma)
g.db.add(ma)
return {"message": f"Deleted all banners from /h/{sub} successfully"}
@ -607,14 +607,14 @@ def sub_sidebar(v:User, sub):
if sub.sidebarurl:
remove_media(sub.sidebarurl)
sub.sidebarurl = sidebarurl
db.add(sub)
g.db.add(sub)
ma = SubAction(
sub=sub.name,
kind='change_sidebar_image',
user_id=v.id
)
db.add(ma)
g.db.add(ma)
return redirect(f'/h/{sub}/settings')
@ -639,14 +639,14 @@ def sub_marsey(v:User, sub):
if sub.marseyurl:
remove_media(sub.marseyurl)
sub.marseyurl = marseyurl
db.add(sub)
g.db.add(sub)
ma = SubAction(
sub=sub.name,
kind='change_marsey',
user_id=v.id
)
db.add(ma)
g.db.add(ma)
return redirect(f'/h/{sub}/settings')
@ -656,8 +656,8 @@ def sub_marsey(v:User, sub):
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required
def subs(v:User):
subs = db.query(Sub, func.count(Submission.sub)).outerjoin(Submission, Sub.name == Submission.sub).group_by(Sub.name).order_by(func.count(Submission.sub).desc()).all()
total_users = db.query(User).count()
subs = g.db.query(Sub, func.count(Submission.sub)).outerjoin(Submission, Sub.name == Submission.sub).group_by(Sub.name).order_by(func.count(Submission.sub).desc()).all()
total_users = g.db.query(User).count()
return render_template('sub/subs.html', v=v, subs=subs, total_users=total_users)
@app.post("/hole_pin/<int:pid>")
@ -677,7 +677,7 @@ def hole_pin(v:User, pid):
abort(403, f"You can only pin 2 posts to /h/{p.sub}")
p.hole_pinned = v.username
db.add(p)
g.db.add(p)
if v.id != p.author_id:
message = f"@{v.username} (a /h/{p.sub} mod) has pinned [{p.title}]({p.shortlink}) in /h/{p.sub}"
@ -689,7 +689,7 @@ def hole_pin(v:User, pid):
user_id=v.id,
target_submission_id=p.id
)
db.add(ma)
g.db.add(ma)
cache.delete_memoized(frontlist)
@ -708,7 +708,7 @@ def hole_unpin(v:User, pid):
if not v.mods(p.sub): abort(403)
p.hole_pinned = None
db.add(p)
g.db.add(p)
if v.id != p.author_id:
message = f"@{v.username} (a /h/{p.sub} mod) has unpinned [{p.title}]({p.shortlink}) in /h/{p.sub}"
@ -720,7 +720,7 @@ def hole_unpin(v:User, pid):
user_id=v.id,
target_submission_id=p.id
)
db.add(ma)
g.db.add(ma)
cache.delete_memoized(frontlist)
@ -739,7 +739,7 @@ def sub_stealth(v:User, sub):
if not v.mods(sub.name): abort(403)
sub.stealth = not sub.stealth
db.add(sub)
g.db.add(sub)
cache.delete_memoized(frontlist)
@ -749,7 +749,7 @@ def sub_stealth(v:User, sub):
kind='enable_stealth',
user_id=v.id
)
db.add(ma)
g.db.add(ma)
return {"message": f"Stealth mode has been enabled for /h/{sub} successfully!"}
else:
ma = SubAction(
@ -757,7 +757,7 @@ def sub_stealth(v:User, sub):
kind='disable_stealth',
user_id=v.id
)
db.add(ma)
g.db.add(ma)
return {"message": f"Stealth mode has been disabled for /h/{sub} successfully!"}
@ -776,7 +776,7 @@ def mod_pin(cid, v):
comment.stickied = v.username + " (Mod)"
db.add(comment)
g.db.add(comment)
ma = SubAction(
sub=comment.post.sub,
@ -784,7 +784,7 @@ def mod_pin(cid, v):
user_id=v.id,
target_comment_id=comment.id
)
db.add(ma)
g.db.add(ma)
if v.id != comment.author_id:
message = f"@{v.username} (a /h/{comment.post.sub} mod) has pinned your [comment]({comment.shortlink})"
@ -805,7 +805,7 @@ def mod_unpin(cid, v):
if not (comment.post.sub and v.mods(comment.post.sub)): abort(403)
comment.stickied = None
db.add(comment)
g.db.add(comment)
ma = SubAction(
sub=comment.post.sub,
@ -813,7 +813,7 @@ def mod_unpin(cid, v):
user_id=v.id,
target_comment_id=comment.id
)
db.add(ma)
g.db.add(ma)
if v.id != comment.author_id:
message = f"@{v.username} (a /h/{comment.post.sub} mod) has unpinned your [comment]({comment.shortlink})"
@ -845,7 +845,7 @@ def hole_log(v:User, sub):
kind = None
actions = []
else:
actions = db.query(SubAction).filter_by(sub=sub.name)
actions = g.db.query(SubAction).filter_by(sub=sub.name)
if mod_id:
actions = actions.filter_by(user_id=mod_id)
@ -860,8 +860,8 @@ def hole_log(v:User, sub):
next_exists=len(actions)>25
actions=actions[:25]
mods = [x[0] for x in db.query(Mod.user_id).filter_by(sub=sub.name).all()]
mods = [x[0] for x in db.query(User.username).filter(User.id.in_(mods)).order_by(User.username).all()]
mods = [x[0] for x in g.db.query(Mod.user_id).filter_by(sub=sub.name).all()]
mods = [x[0] for x in g.db.query(User.username).filter(User.id.in_(mods)).order_by(User.username).all()]
return render_template("log.html", v=v, admins=mods, types=types, admin=mod, type=kind, actions=actions, next_exists=next_exists, page=page, sub=sub, single_user_url='mod')
@ -876,12 +876,12 @@ def hole_log_item(id, v, sub):
try: id = int(id)
except: abort(404)
action=db.get(SubAction, id)
action=g.db.get(SubAction, id)
if not action: abort(404)
mods = [x[0] for x in db.query(Mod.user_id).filter_by(sub=sub.name).all()]
mods = [x[0] for x in db.query(User.username).filter(User.id.in_(mods)).order_by(User.username).all()]
mods = [x[0] for x in g.db.query(Mod.user_id).filter_by(sub=sub.name).all()]
mods = [x[0] for x in g.db.query(User.username).filter(User.id.in_(mods)).order_by(User.username).all()]
types = SUBACTION_TYPES

View File

@ -39,7 +39,7 @@ def upvoters_downvoters(v, username, uid, cls, vote_cls, vote_dir, template, sta
try: page = max(1, int(request.values.get("page", 1)))
except: abort(400, "Invalid page input!")
listing = db.query(cls).join(vote_cls).filter(cls.ghost == False, cls.is_banned == False, cls.deleted_utc == 0, vote_cls.vote_type==vote_dir, cls.author_id==id, vote_cls.user_id==uid).order_by(cls.created_utc.desc()).offset(PAGE_SIZE * (page - 1)).limit(PAGE_SIZE + 1).all()
listing = g.db.query(cls).join(vote_cls).filter(cls.ghost == False, cls.is_banned == False, cls.deleted_utc == 0, vote_cls.vote_type==vote_dir, cls.author_id==id, vote_cls.user_id==uid).order_by(cls.created_utc.desc()).offset(PAGE_SIZE * (page - 1)).limit(PAGE_SIZE + 1).all()
listing = [p.id for p in listing]
next_exists = len(listing) > PAGE_SIZE
@ -98,7 +98,7 @@ def upvoting_downvoting(v, username, uid, cls, vote_cls, vote_dir, template, sta
try: page = max(1, int(request.values.get("page", 1)))
except: abort(400, "Invalid page input!")
listing = db.query(cls).join(vote_cls).filter(cls.ghost == False, cls.is_banned == False, cls.deleted_utc == 0, vote_cls.vote_type==vote_dir, vote_cls.user_id==id, cls.author_id==uid).order_by(cls.created_utc.desc()).offset(PAGE_SIZE * (page - 1)).limit(PAGE_SIZE + 1).all()
listing = g.db.query(cls).join(vote_cls).filter(cls.ghost == False, cls.is_banned == False, cls.deleted_utc == 0, vote_cls.vote_type==vote_dir, vote_cls.user_id==id, cls.author_id==uid).order_by(cls.created_utc.desc()).offset(PAGE_SIZE * (page - 1)).limit(PAGE_SIZE + 1).all()
listing = [p.id for p in listing]
next_exists = len(listing) > PAGE_SIZE
@ -152,7 +152,7 @@ def user_voted(v, username, cls, vote_cls, template, standalone):
try: page = max(1, int(request.values.get("page", 1)))
except: abort(400, "Invalid page input!")
listing = db.query(cls).join(vote_cls).filter(
listing = g.db.query(cls).join(vote_cls).filter(
cls.ghost == False,
cls.is_banned == False,
cls.deleted_utc == 0,
@ -192,7 +192,7 @@ def user_voted_comments(v:User, username):
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required
def banned(v:User):
users = db.query(User).filter(
users = g.db.query(User).filter(
User.is_banned != None,
or_(User.unban_utc == 0, User.unban_utc > time.time()),
).order_by(User.ban_reason)
@ -205,7 +205,7 @@ def banned(v:User):
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required
def grassed(v:User):
users = db.query(User).filter(
users = g.db.query(User).filter(
User.ban_reason.like('grass award used by @%'),
User.unban_utc > time.time(),
)
@ -218,7 +218,7 @@ def grassed(v:User):
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required
def chuds(v:User):
users = db.query(User).filter(
users = g.db.query(User).filter(
or_(User.agendaposter == 1, User.agendaposter > time.time()),
)
if v.admin_level >= PERMS['VIEW_LAST_ACTIVE']:
@ -248,14 +248,14 @@ def all_upvoters_downvoters(v:User, username:str, vote_dir:int, is_who_simps_hat
votes = []
votes2 = []
if is_who_simps_hates:
votes = db.query(Submission.author_id, func.count(Submission.author_id)).join(Vote).filter(Submission.ghost == False, Submission.is_banned == False, Submission.deleted_utc == 0, Vote.vote_type==vote_dir, Vote.user_id==id).group_by(Submission.author_id).order_by(func.count(Submission.author_id).desc()).all()
votes2 = db.query(Comment.author_id, func.count(Comment.author_id)).join(CommentVote).filter(Comment.ghost == False, Comment.is_banned == False, Comment.deleted_utc == 0, CommentVote.vote_type==vote_dir, CommentVote.user_id==id).group_by(Comment.author_id).order_by(func.count(Comment.author_id).desc()).all()
votes = g.db.query(Submission.author_id, func.count(Submission.author_id)).join(Vote).filter(Submission.ghost == False, Submission.is_banned == False, Submission.deleted_utc == 0, Vote.vote_type==vote_dir, Vote.user_id==id).group_by(Submission.author_id).order_by(func.count(Submission.author_id).desc()).all()
votes2 = g.db.query(Comment.author_id, func.count(Comment.author_id)).join(CommentVote).filter(Comment.ghost == False, Comment.is_banned == False, Comment.deleted_utc == 0, CommentVote.vote_type==vote_dir, CommentVote.user_id==id).group_by(Comment.author_id).order_by(func.count(Comment.author_id).desc()).all()
else:
votes = db.query(Vote.user_id, func.count(Vote.user_id)).join(Submission).filter(Submission.ghost == False, Submission.is_banned == False, Submission.deleted_utc == 0, Vote.vote_type==vote_dir, Submission.author_id==id).group_by(Vote.user_id).order_by(func.count(Vote.user_id).desc()).all()
votes2 = db.query(CommentVote.user_id, func.count(CommentVote.user_id)).join(Comment).filter(Comment.ghost == False, Comment.is_banned == False, Comment.deleted_utc == 0, CommentVote.vote_type==vote_dir, Comment.author_id==id).group_by(CommentVote.user_id).order_by(func.count(CommentVote.user_id).desc()).all()
votes = g.db.query(Vote.user_id, func.count(Vote.user_id)).join(Submission).filter(Submission.ghost == False, Submission.is_banned == False, Submission.deleted_utc == 0, Vote.vote_type==vote_dir, Submission.author_id==id).group_by(Vote.user_id).order_by(func.count(Vote.user_id).desc()).all()
votes2 = g.db.query(CommentVote.user_id, func.count(CommentVote.user_id)).join(Comment).filter(Comment.ghost == False, Comment.is_banned == False, Comment.deleted_utc == 0, CommentVote.vote_type==vote_dir, Comment.author_id==id).group_by(CommentVote.user_id).order_by(func.count(CommentVote.user_id).desc()).all()
votes = Counter(dict(votes)) + Counter(dict(votes2))
total = sum(votes.values())
users = db.query(User).filter(User.id.in_(votes.keys()))
users = g.db.query(User).filter(User.id.in_(votes.keys()))
users2 = [(user, votes[user.id]) for user in users.all()]
users = sorted(users2, key=lambda x: x[1], reverse=True)
@ -364,10 +364,10 @@ def transfer_currency(v:User, username:str, currency_name:Literal['coins', 'mars
receiver.pay_account('coins', amount - tax)
else:
raise ValueError(f"Invalid currency '{currency_name}' got when transferring {amount} from {v.id} to {receiver.id}")
db.add(receiver)
g.db.add(receiver)
if GIFT_NOTIF_ID: send_repeatable_notification(GIFT_NOTIF_ID, log_message)
send_repeatable_notification(receiver.id, notif_text)
db.add(v)
g.db.add(v)
return {"message": f"{amount - tax} {currency_name} have been transferred to @{receiver.username}"}
@app.post("/@<username>/transfer_coins")
@ -392,27 +392,27 @@ def transfer_bux(v:User, username:str):
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required
def leaderboard(v:User):
users = db.query(User)
users = g.db.query(User)
coins = Leaderboard("Coins", "coins", "coins", "Coins", None, Leaderboard.get_simple_lb, User.coins, v, lambda u:u.coins, users)
subscribers = Leaderboard("Followers", "followers", "followers", "Followers", "followers", Leaderboard.get_simple_lb, User.stored_subscriber_count, v, lambda u:u.stored_subscriber_count, users)
posts = Leaderboard("Posts", "post count", "posts", "Posts", "posts", Leaderboard.get_simple_lb, User.post_count, v, lambda u:u.post_count, users)
comments = Leaderboard("Comments", "comment count", "comments", "Comments", "comments", Leaderboard.get_simple_lb, User.comment_count, v, lambda u:u.comment_count, users)
received_awards = Leaderboard("Awards", "received awards", "awards", "Awards", None, Leaderboard.get_simple_lb, User.received_award_count, v, lambda u:u.received_award_count, users)
coins_spent = Leaderboard("Spent in shop", "coins spent in shop", "spent", "Coins", None, Leaderboard.get_simple_lb, User.coins_spent, v, lambda u:u.coins_spent, users)
truescore = Leaderboard("Truescore", "truescore", "truescore", "Truescore", None, Leaderboard.get_simple_lb, User.truescore, v, lambda u:u.truescore, users)
coins = Leaderboard("Coins", "coins", "coins", "Coins", None, Leaderboard.get_simple_lb, User.coins, v, lambda u:u.coins, g.db, users)
subscribers = Leaderboard("Followers", "followers", "followers", "Followers", "followers", Leaderboard.get_simple_lb, User.stored_subscriber_count, v, lambda u:u.stored_subscriber_count, g.db, users)
posts = Leaderboard("Posts", "post count", "posts", "Posts", "posts", Leaderboard.get_simple_lb, User.post_count, v, lambda u:u.post_count, g.db, users)
comments = Leaderboard("Comments", "comment count", "comments", "Comments", "comments", Leaderboard.get_simple_lb, User.comment_count, v, lambda u:u.comment_count, g.db, users)
received_awards = Leaderboard("Awards", "received awards", "awards", "Awards", None, Leaderboard.get_simple_lb, User.received_award_count, v, lambda u:u.received_award_count, g.db, users)
coins_spent = Leaderboard("Spent in shop", "coins spent in shop", "spent", "Coins", None, Leaderboard.get_simple_lb, User.coins_spent, v, lambda u:u.coins_spent, g.db, users)
truescore = Leaderboard("Truescore", "truescore", "truescore", "Truescore", None, Leaderboard.get_simple_lb, User.truescore, v, lambda u:u.truescore, g.db, users)
badges = Leaderboard("Badges", "badges", "badges", "Badges", None, Leaderboard.get_badge_marsey_lb, Badge.user_id, v, None, None)
badges = Leaderboard("Badges", "badges", "badges", "Badges", None, Leaderboard.get_badge_marsey_lb, Badge.user_id, v, None, g.db, None)
blocks = Leaderboard("Blocked", "most blocked", "blocked", "Blocked By", "blockers", Leaderboard.get_blockers_lb, UserBlock.target_id, v, None, None)
blocks = Leaderboard("Blocked", "most blocked", "blocked", "Blocked By", "blockers", Leaderboard.get_blockers_lb, UserBlock.target_id, v, None, g.db, None)
owned_hats = Leaderboard("Owned hats", "owned hats", "owned-hats", "Owned Hats", None, Leaderboard.get_hat_lb, User.owned_hats, v, None, None)
owned_hats = Leaderboard("Owned hats", "owned hats", "owned-hats", "Owned Hats", None, Leaderboard.get_hat_lb, User.owned_hats, v, None, g.db, None)
leaderboards = [coins, coins_spent, truescore, subscribers, posts, comments, received_awards, badges, blocks, owned_hats]
if SITE == 'rdrama.net':
leaderboards.append(Leaderboard("Designed hats", "designed hats", "designed-hats", "Designed Hats", None, Leaderboard.get_hat_lb, User.designed_hats, v, None, None))
leaderboards.append(Leaderboard("Marseys", "Marseys made", "marseys", "Marseys", None, Leaderboard.get_badge_marsey_lb, Marsey.author_id, v, None, None))
leaderboards.append(Leaderboard("Designed hats", "designed hats", "designed-hats", "Designed Hats", None, Leaderboard.get_hat_lb, User.designed_hats, v, None, g.db, None))
leaderboards.append(Leaderboard("Marseys", "Marseys made", "marseys", "Marseys", None, Leaderboard.get_badge_marsey_lb, Marsey.author_id, v, None, g.db, None))
return render_template("leaderboard.html", v=v, leaderboards=leaderboards)
@ -422,7 +422,7 @@ def get_css(id):
try: id = int(id)
except: abort(404)
css, bg = db.query(User.css, User.background).filter_by(id=id).one_or_none()
css, bg = g.db.query(User.css, User.background).filter_by(id=id).one_or_none()
if bg:
if not css: css = ''
@ -446,7 +446,7 @@ def get_profilecss(id):
try: id = int(id)
except: abort(404)
css, bg = db.query(User.profilecss, User.profile_background).filter_by(id=id).one_or_none()
css, bg = g.db.query(User.profilecss, User.profile_background).filter_by(id=id).one_or_none()
if bg:
if not css: css = ''
@ -475,10 +475,10 @@ def usersong(username:str):
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required
def subscribe(v, post_id):
existing = db.query(Subscription).filter_by(user_id=v.id, submission_id=post_id).one_or_none()
existing = g.db.query(Subscription).filter_by(user_id=v.id, submission_id=post_id).one_or_none()
if not existing:
new_sub = Subscription(user_id=v.id, submission_id=post_id)
db.add(new_sub)
g.db.add(new_sub)
return {"message": "Subscribed to post successfully!"}
@app.post("/unsubscribe/<int:post_id>")
@ -487,9 +487,9 @@ def subscribe(v, post_id):
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required
def unsubscribe(v, post_id):
existing = db.query(Subscription).filter_by(user_id=v.id, submission_id=post_id).one_or_none()
existing = g.db.query(Subscription).filter_by(user_id=v.id, submission_id=post_id).one_or_none()
if existing:
db.delete(existing)
g.db.delete(existing)
return {"message": "Unsubscribed from post successfully!"}
@app.post("/@<username>/message")
@ -517,7 +517,7 @@ def message2(v:User, username:str):
body_html = sanitize(message)
existing = db.query(Comment.id).filter(
existing = g.db.query(Comment.id).filter(
Comment.author_id == v.id,
Comment.sentto == user.id,
Comment.body_html == body_html
@ -532,17 +532,17 @@ def message2(v:User, username:str):
body=message,
body_html=body_html
)
db.add(c)
db.flush()
g.db.add(c)
g.db.flush()
execute_blackjack(v, c, c.body_html, 'message')
execute_under_siege(v, c, c.body_html, 'message')
c.top_comment_id = c.id
if user.id not in bots:
notif = db.query(Notification).filter_by(comment_id=c.id, user_id=user.id).one_or_none()
notif = g.db.query(Notification).filter_by(comment_id=c.id, user_id=user.id).one_or_none()
if not notif:
notif = Notification(comment_id=c.id, user_id=user.id)
db.add(notif)
g.db.add(notif)
if not v.shadowbanned:
@ -605,16 +605,16 @@ def messagereply(v:User):
body=body,
body_html=body_html,
)
db.add(c)
db.flush()
g.db.add(c)
g.db.flush()
execute_blackjack(v, c, c.body_html, 'message')
execute_under_siege(v, c, c.body_html, 'message')
if user_id and user_id not in {v.id, MODMAIL_ID} | bots:
notif = db.query(Notification).filter_by(comment_id=c.id, user_id=user_id).one_or_none()
notif = g.db.query(Notification).filter_by(comment_id=c.id, user_id=user_id).one_or_none()
if not notif:
notif = Notification(comment_id=c.id, user_id=user_id)
db.add(notif)
g.db.add(notif)
if not v.shadowbanned:
title = f'New message from @{c.author_name}'
@ -626,7 +626,7 @@ def messagereply(v:User):
top_comment = c.top_comment
if top_comment.sentto == MODMAIL_ID:
admins = db.query(User.id).filter(User.admin_level >= PERMS['NOTIFICATIONS_MODMAIL'], User.id != v.id)
admins = g.db.query(User.id).filter(User.admin_level >= PERMS['NOTIFICATIONS_MODMAIL'], User.id != v.id)
if SITE == 'rdrama.net':
admins = admins.filter(User.id != AEVANN_ID)
@ -638,12 +638,12 @@ def messagereply(v:User):
for admin in admins:
notif = Notification(comment_id=c.id, user_id=admin)
db.add(notif)
g.db.add(notif)
ids = [top_comment.id] + [x.id for x in top_comment.replies(sort="old", v=v)]
notifications = db.query(Notification).filter(Notification.comment_id.in_(ids), Notification.user_id.in_(admins))
notifications = g.db.query(Notification).filter(Notification.comment_id.in_(ids), Notification.user_id.in_(admins))
for n in notifications:
db.delete(n)
g.db.delete(n)
return {"comment": render_template("comments.html", v=v, comments=[c])}
@ -679,7 +679,7 @@ def is_available(name:str):
name2 = name.replace('\\', '').replace('_','\_').replace('%','')
x = db.query(User).filter(
x = g.db.query(User).filter(
or_(
User.username.ilike(name2),
User.original_username.ilike(name2)
@ -717,7 +717,7 @@ def followers(v:User, username:str):
try: page = int(request.values.get("page", 1))
except: page = 1
users = db.query(Follow, User).join(Follow, Follow.target_id == u.id) \
users = g.db.query(Follow, User).join(Follow, Follow.target_id == u.id) \
.filter(Follow.user_id == User.id) \
.order_by(Follow.created_utc.desc()) \
.offset(PAGE_SIZE * (page - 1)).limit(PAGE_SIZE + 1).all()
@ -737,7 +737,7 @@ def blockers(v:User, username:str):
try: page = int(request.values.get("page", 1))
except: page = 1
users = db.query(UserBlock, User).join(UserBlock, UserBlock.target_id == u.id) \
users = g.db.query(UserBlock, User).join(UserBlock, UserBlock.target_id == u.id) \
.filter(UserBlock.user_id == User.id) \
.order_by(UserBlock.created_utc.desc()) \
.offset(PAGE_SIZE * (page - 1)).limit(PAGE_SIZE + 1).all()
@ -759,7 +759,7 @@ def following(v:User, username:str):
try: page = int(request.values.get("page", 1))
except: page = 1
users = db.query(User).join(Follow, Follow.user_id == u.id) \
users = g.db.query(User).join(Follow, Follow.user_id == u.id) \
.filter(Follow.target_id == User.id) \
.order_by(Follow.created_utc.desc()) \
.offset(PAGE_SIZE * (page - 1)).limit(PAGE_SIZE + 1).all()
@ -779,7 +779,7 @@ def visitors(v:User, username:str):
try: page = int(request.values.get("page", 1))
except: page = 1
views = db.query(ViewerRelationship).filter_by(user_id=u.id).order_by(ViewerRelationship.last_view_utc.desc()).offset(PAGE_SIZE * (page - 1)).limit(PAGE_SIZE + 1).all()
views = g.db.query(ViewerRelationship).filter_by(user_id=u.id).order_by(ViewerRelationship.last_view_utc.desc()).offset(PAGE_SIZE * (page - 1)).limit(PAGE_SIZE + 1).all()
next_exists = (len(views) > PAGE_SIZE)
views = views[:PAGE_SIZE]
@ -788,7 +788,7 @@ def visitors(v:User, username:str):
@cache.memoize()
def userpagelisting(user:User, site=None, v=None, page:int=1, sort="new", t="all"):
posts = db.query(Submission.id).filter_by(author_id=user.id, is_pinned=False)
posts = g.db.query(Submission.id).filter_by(author_id=user.id, is_pinned=False)
if not (v and (v.admin_level >= PERMS['POST_COMMENT_MODERATION'] or v.id == user.id)):
posts = posts.filter_by(is_banned=False, private=False, ghost=False, deleted_utc=0)
posts = apply_time_filter(t, posts, Submission)
@ -812,11 +812,10 @@ def u_username_wall(v:Optional[User], username:str):
is_following = v and u.has_follower(v)
if v and v.id != u.id and not v.admin_level:
view = db.query(ViewerRelationship).filter_by(viewer_id=v.id, user_id=u.id).one_or_none()
view = g.db.query(ViewerRelationship).filter_by(viewer_id=v.id, user_id=u.id).one_or_none()
if view: view.last_view_utc = int(time.time())
else: view = ViewerRelationship(viewer_id=v.id, user_id=u.id)
db.add(view)
db.flush()
g.db.add(view)
try: page = max(int(request.values.get("page", "1")), 1)
except: page = 1
@ -824,7 +823,7 @@ def u_username_wall(v:Optional[User], username:str):
if v:
comments, output = get_comments_v_properties(v, None, Comment.wall_user_id == u.id)
else:
comments = db.query(Comment).filter(Comment.wall_user_id == u.id)
comments = g.db.query(Comment).filter(Comment.wall_user_id == u.id)
comments = comments.filter(Comment.level == 1)
if not v or (v.id != u.id and v.admin_level < PERMS['POST_COMMENT_MODERATION']):
@ -843,7 +842,7 @@ def u_username_wall(v:Optional[User], username:str):
comments = comments[:PAGE_SIZE]
if v and v.client:
return {"data": [c.json for c in comments]}
return {"data": [c.json(g.db) for c in comments]}
return render_template("userpage/wall.html", u=u, v=v, listing=comments, page=page, next_exists=next_exists, is_following=is_following, standalone=True, render_replies=True, wall=True)
@ -866,18 +865,17 @@ def u_username_wall_comment(v:User, username:str, cid):
is_following = v and u.has_follower(v)
if v and v.id != u.id and not v.admin_level:
view = db.query(ViewerRelationship).filter_by(viewer_id=v.id, user_id=u.id).one_or_none()
view = g.db.query(ViewerRelationship).filter_by(viewer_id=v.id, user_id=u.id).one_or_none()
if view: view.last_view_utc = int(time.time())
else: view = ViewerRelationship(viewer_id=v.id, user_id=u.id)
db.add(view)
db.flush()
g.db.add(view)
if v and request.values.get("read"):
notif = db.query(Notification).filter_by(comment_id=cid, user_id=v.id, read=False).one_or_none()
notif = g.db.query(Notification).filter_by(comment_id=cid, user_id=v.id, read=False).one_or_none()
if notif:
notif.read = True
db.add(notif)
db.flush()
g.db.add(notif)
g.db.flush()
try: context = min(int(request.values.get("context", 8)), 8)
except: context = 8
@ -893,7 +891,7 @@ def u_username_wall_comment(v:User, username:str, cid):
# props won't save properly unless you put them in a list
output = get_comments_v_properties(v, None, Comment.top_comment_id == c.top_comment_id)[1]
if v and v.client: return top_comment.json
if v and v.client: return top_comment.json(db=g.db)
return render_template("userpage/wall.html", u=u, v=v, listing=[top_comment], page=1, is_following=is_following, standalone=True, render_replies=True, wall=True, comment_info=comment_info)
@ -919,11 +917,10 @@ def u_username(v:Optional[User], username:str):
return render_template("userpage/private.html", u=u, v=v, is_following=is_following), 403
if v and v.id != u.id and not v.admin_level:
view = db.query(ViewerRelationship).filter_by(viewer_id=v.id, user_id=u.id).one_or_none()
view = g.db.query(ViewerRelationship).filter_by(viewer_id=v.id, user_id=u.id).one_or_none()
if view: view.last_view_utc = int(time.time())
else: view = ViewerRelationship(viewer_id=v.id, user_id=u.id)
db.add(view)
db.flush()
g.db.add(view)
sort = request.values.get("sort", "new")
@ -938,7 +935,7 @@ def u_username(v:Optional[User], username:str):
if page == 1 and sort == 'new':
sticky = []
sticky = db.query(Submission).filter_by(is_pinned=True, author_id=u.id, is_banned=False).all()
sticky = g.db.query(Submission).filter_by(is_pinned=True, author_id=u.id, is_banned=False).all()
if sticky:
for p in sticky:
ids = [p.id] + ids
@ -947,7 +944,7 @@ def u_username(v:Optional[User], username:str):
if u.unban_utc:
if v and v.client:
return {"data": [x.json for x in listing]}
return {"data": [x.json(g.db) for x in listing]}
return render_template("userpage/submissions.html",
unban=u.unban_string,
@ -961,7 +958,7 @@ def u_username(v:Optional[User], username:str):
is_following=is_following)
if v and v.client:
return {"data": [x.json for x in listing]}
return {"data": [x.json(g.db) for x in listing]}
return render_template("userpage/submissions.html",
u=u,
@ -995,11 +992,10 @@ def u_username_comments(username, v=None):
return render_template("userpage/private.html", u=u, v=v, is_following=is_following), 403
if v and v.id != u.id and not v.admin_level:
view = db.query(ViewerRelationship).filter_by(viewer_id=v.id, user_id=u.id).one_or_none()
view = g.db.query(ViewerRelationship).filter_by(viewer_id=v.id, user_id=u.id).one_or_none()
if view: view.last_view_utc = int(time.time())
else: view = ViewerRelationship(viewer_id=v.id, user_id=u.id)
db.add(view)
db.flush()
g.db.add(view)
try: page = max(int(request.values.get("page", "1")), 1)
except: page = 1
@ -1008,7 +1004,7 @@ def u_username_comments(username, v=None):
t=request.values.get("t","all")
comment_post_author = aliased(User)
comments = db.query(Comment.id) \
comments = g.db.query(Comment.id) \
.outerjoin(Comment.post) \
.outerjoin(comment_post_author, Submission.author) \
.filter(
@ -1036,7 +1032,7 @@ def u_username_comments(username, v=None):
listing = get_comments(ids, v=v)
if v and v.client:
return {"data": [c.json for c in listing]}
return {"data": [c.json(g.db) for c in listing]}
return render_template("userpage/comments.html", u=u, v=v, listing=listing, page=page, sort=sort, t=t,next_exists=next_exists, is_following=is_following, standalone=True)
@ -1083,14 +1079,14 @@ def follow_user(username, v):
if target.id==v.id:
abort(400, "You can't follow yourself!")
if db.query(Follow).filter_by(user_id=v.id, target_id=target.id).one_or_none():
if g.db.query(Follow).filter_by(user_id=v.id, target_id=target.id).one_or_none():
return {"message": f"@{target.username} has been followed!"}
new_follow = Follow(user_id=v.id, target_id=target.id)
db.add(new_follow)
g.db.add(new_follow)
target.stored_subscriber_count = db.query(Follow).filter_by(target_id=target.id).count()
db.add(target)
target.stored_subscriber_count = g.db.query(Follow).filter_by(target_id=target.id).count()
g.db.add(target)
if not v.shadowbanned:
send_notification(target.id, f"@{v.username} has followed you!")
@ -1112,13 +1108,13 @@ def unfollow_user(username, v):
send_notification(target.id, f"@{v.username} has tried to unfollow you and failed because of your fish award!")
abort(400, f"You can't unfollow @{target.username}")
follow = db.query(Follow).filter_by(user_id=v.id, target_id=target.id).one_or_none()
follow = g.db.query(Follow).filter_by(user_id=v.id, target_id=target.id).one_or_none()
if follow:
db.delete(follow)
g.db.delete(follow)
target.stored_subscriber_count = db.query(Follow).filter_by(target_id=target.id).count()
db.add(target)
target.stored_subscriber_count = g.db.query(Follow).filter_by(target_id=target.id).count()
g.db.add(target)
if not v.shadowbanned:
send_notification(target.id, f"@{v.username} has unfollowed you!")
@ -1137,14 +1133,14 @@ def unfollow_user(username, v):
def remove_follow(username, v):
target = get_user(username)
follow = db.query(Follow).filter_by(user_id=target.id, target_id=v.id).one_or_none()
follow = g.db.query(Follow).filter_by(user_id=target.id, target_id=v.id).one_or_none()
if not follow: return {"message": f"@{target.username} has been removed as a follower!"}
db.delete(follow)
g.db.delete(follow)
v.stored_subscriber_count = db.query(Follow).filter_by(target_id=v.id).count()
db.add(v)
v.stored_subscriber_count = g.db.query(Follow).filter_by(target_id=v.id).count()
g.db.add(v)
send_repeatable_notification(target.id, f"@{v.username} has removed your follow!")
@ -1176,7 +1172,7 @@ def get_saves_and_subscribes(v, template, relationship_cls, page:int, standalone
cls = Comment
else:
raise TypeError("Relationships supported is SaveRelationship, Subscription, CommentSaveRelationship")
ids = [x[0] for x in db.query(query).join(join).filter(relationship_cls.user_id == v.id).order_by(cls.created_utc.desc()).offset(PAGE_SIZE * (page - 1)).limit(PAGE_SIZE + 1).all()]
ids = [x[0] for x in g.db.query(query).join(join).filter(relationship_cls.user_id == v.id).order_by(cls.created_utc.desc()).offset(PAGE_SIZE * (page - 1)).limit(PAGE_SIZE + 1).all()]
next_exists = len(ids) > PAGE_SIZE
ids = ids[:PAGE_SIZE]
@ -1191,7 +1187,7 @@ def get_saves_and_subscribes(v, template, relationship_cls, page:int, standalone
else:
raise TypeError("Only supports Submissions and Comments. This is probably the result of a bug with *this* function")
if v.client: return {"data": [x.json for x in listing]}
if v.client: return {"data": [x.json(g.db) for x in listing]}
return render_template(template, u=v, v=v, listing=listing, page=page, next_exists=next_exists, standalone=standalone)
@app.get("/@<username>/saved/posts")
@ -1234,22 +1230,22 @@ def fp(v:User, fp):
return '', 204
v.fp = fp
users = db.query(User).filter(User.fp == fp, User.id != v.id).all()
users = g.db.query(User).filter(User.fp == fp, User.id != v.id).all()
if users: print(f'{v.username}: fp', flush=True)
if v.email and v.is_activated:
alts = db.query(User).filter(User.email == v.email, User.is_activated, User.id != v.id).all()
alts = g.db.query(User).filter(User.email == v.email, User.is_activated, User.id != v.id).all()
if alts:
print(f'{v.username}: email', flush=True)
users += alts
for u in users:
li = [v.id, u.id]
existing = db.query(Alt).filter(Alt.user1.in_(li), Alt.user2.in_(li)).one_or_none()
existing = g.db.query(Alt).filter(Alt.user1.in_(li), Alt.user2.in_(li)).one_or_none()
if existing: continue
add_alt(user1=v.id, user2=u.id)
print(v.username + ' + ' + u.username, flush=True)
check_for_alts(v, include_current_session=True)
db.add(v)
g.db.add(v)
return '', 204
@app.get("/toggle_pins/<sort>")
@ -1292,7 +1288,7 @@ def bid_list(v:User, bid):
try: page = int(request.values.get("page", 1))
except: page = 1
users = db.query(User).join(User.badges).filter(Badge.badge_id==bid).offset(PAGE_SIZE * (page - 1)).limit(PAGE_SIZE + 1).all()
users = g.db.query(User).join(User.badges).filter(Badge.badge_id==bid).offset(PAGE_SIZE * (page - 1)).limit(PAGE_SIZE + 1).all()
next_exists = (len(users) > PAGE_SIZE)
users = users[:PAGE_SIZE]
@ -1321,7 +1317,7 @@ tiers={
marseybux_li = (0,2500,5000,10000,25000,50000,100000,250000)
def claim_rewards(v):
transactions = db.query(Transaction).filter_by(email=v.email, claimed=None).all()
transactions = g.db.query(Transaction).filter_by(email=v.email, claimed=None).all()
highest_tier = 0
marseybux = 0
@ -1335,28 +1331,28 @@ def claim_rewards(v):
if tier > highest_tier:
highest_tier = tier
transaction.claimed = True
db.add(transaction)
g.db.add(transaction)
if marseybux:
v.pay_account('marseybux', marseybux)
send_repeatable_notification(v.id, f"You have received {marseybux} Marseybux! You can use them to buy awards or hats in the [shop](/shop/awards) or gamble them in the [casino](/casino).")
db.add(v)
g.db.add(v)
v.patron_utc = time.time() + 2937600
if highest_tier > v.patron:
v.patron = highest_tier
for badge in db.query(Badge).filter(Badge.user_id == v.id, Badge.badge_id > 20, Badge.badge_id < 28).all():
db.delete(badge)
for badge in g.db.query(Badge).filter(Badge.user_id == v.id, Badge.badge_id > 20, Badge.badge_id < 28).all():
g.db.delete(badge)
badge_grant(badge_id=20+highest_tier, user=v)
print(f'@{v.username} rewards claimed successfully!', flush=True)
def claim_rewards_all_users():
emails = [x[0] for x in db.query(Transaction.email).filter_by(claimed=None).all()]
users = db.query(User).filter(User.email.in_(emails)).all()
emails = [x[0] for x in g.db.query(Transaction.email).filter_by(claimed=None).all()]
users = g.db.query(User).filter(User.email.in_(emails)).all()
for user in users:
claim_rewards(user)
@ -1388,7 +1384,7 @@ if KOFI_TOKEN:
email=email
)
db.add(transaction)
g.db.add(transaction)
claim_rewards_all_users()
@ -1420,7 +1416,7 @@ def gumroad():
email=email
)
db.add(transaction)
g.db.add(transaction)
claim_rewards_all_users()
@ -1438,7 +1434,7 @@ def settings_claim_rewards(v:User):
if not (v.email and v.is_activated):
abort(400, f"You must have a verified email to verify {patron} status and claim your rewards!")
transactions = db.query(Transaction).filter_by(email=v.email, claimed=None).all()
transactions = g.db.query(Transaction).filter_by(email=v.email, claimed=None).all()
if not transactions:
abort(400, f"{patron} rewards already claimed!")
@ -1456,7 +1452,7 @@ def users_list(v):
try: page = int(request.values.get("page", 1))
except: page = 1
users = db.query(User).order_by(User.id.desc()).offset(PAGE_SIZE * (page - 1)).limit(PAGE_SIZE + 1).all()
users = g.db.query(User).order_by(User.id.desc()).offset(PAGE_SIZE * (page - 1)).limit(PAGE_SIZE + 1).all()
next_exists = (len(users) > PAGE_SIZE)
users = users[:PAGE_SIZE]

View File

@ -25,7 +25,7 @@ def vote_info_get(v, link):
abort(500)
if isinstance(thing, Submission):
query = db.query(Vote).join(Vote.user).filter(
query = g.db.query(Vote).join(Vote.user).filter(
Vote.submission_id == thing.id,
).order_by(Vote.created_utc)
@ -33,7 +33,7 @@ def vote_info_get(v, link):
downs = query.filter(Vote.vote_type == -1).all()
elif isinstance(thing, Comment):
query = db.query(CommentVote).join(CommentVote.user).filter(
query = g.db.query(CommentVote).join(CommentVote.user).filter(
CommentVote.comment_id == thing.id,
).order_by(CommentVote.created_utc)
@ -76,7 +76,7 @@ def vote_post_comment(target_id, new, v, cls, vote_cls):
coin_mult = 1
existing = db.query(vote_cls).filter_by(user_id=v.id)
existing = g.db.query(vote_cls).filter_by(user_id=v.id)
if vote_cls == Vote:
existing = existing.filter_by(submission_id=target.id)
elif vote_cls == CommentVote:
@ -98,23 +98,23 @@ def vote_post_comment(target_id, new, v, cls, vote_cls):
if existing.vote_type == 0 and new != 0:
target.author.pay_account('coins', coin_value)
target.author.truescore += coin_delta
db.add(target.author)
g.db.add(target.author)
existing.vote_type = new
existing.coins = coin_value
db.add(existing)
g.db.add(existing)
elif existing.vote_type != 0 and new == 0:
target.author.charge_account('coins', existing.coins,
should_check_balance=False)
target.author.truescore -= coin_delta
db.add(target.author)
db.delete(existing)
g.db.add(target.author)
g.db.delete(existing)
else:
existing.vote_type = new
db.add(existing)
g.db.add(existing)
elif new != 0:
target.author.pay_account('coins', coin_value)
target.author.truescore += coin_delta
db.add(target.author)
g.db.add(target.author)
real = new == -1 or (not alt and v.is_votes_real)
vote = None
@ -134,12 +134,12 @@ def vote_post_comment(target_id, new, v, cls, vote_cls):
real=real,
coins=coin_value
)
db.add(vote)
db.flush()
g.db.add(vote)
g.db.flush()
# this is hacky but it works, we should probably do better later
def get_vote_count(dir, real_instead_of_dir):
votes = db.query(vote_cls)
votes = g.db.query(vote_cls)
if real_instead_of_dir:
votes = votes.filter(vote_cls.real == True)
else:
@ -182,7 +182,7 @@ def vote_post_comment(target_id, new, v, cls, vote_cls):
mul = min(mul, 2)
target.realupvotes = floor(target.realupvotes * mul)
db.add(target)
g.db.add(target)
return "", 204

View File

@ -1,6 +1,5 @@
import time
from flask import g, request, session
import secrets
from files.classes.clients import ClientAuth
from files.helpers.alerts import *
@ -9,7 +8,7 @@ from files.helpers.get import get_account
from files.helpers.logging import log_file
from files.helpers.settings import get_setting
from files.routes.routehelpers import validate_formkey
from files.__main__ import app, limiter
from files.__main__ import app, db_session, limiter
def rpath(n):
return request.path
@ -27,15 +26,12 @@ def get_ID():
def get_logged_in_user():
if hasattr(g, 'v') and g.v: return g.v
if not hasattr(g, 'nonce'):
g.nonce = secrets.token_urlsafe(31)
if not hasattr(g, 'db'): g.db = db_session()
g.desires_auth = True
v = None
token = request.headers.get("Authorization","").strip()
if token:
client = db.query(ClientAuth).filter(ClientAuth.access_token == token).one_or_none()
client = g.db.query(ClientAuth).filter(ClientAuth.access_token == token).one_or_none()
if client:
v = client.user
v.client = client
@ -72,7 +68,7 @@ def get_logged_in_user():
timestamp = int(time.time())
if (v.last_active + LOGGEDIN_ACTIVE_TIME) < timestamp:
v.last_active = timestamp
db.add(v)
g.db.add(v)
if SITE == 'rdrama.net' and request.headers.get("Cf-Ipcountry") == 'EG':
if v:

View File

@ -64,7 +64,7 @@
{% if SITE == 'rdrama.net' %}
<td>{% include "user_in_table.html" %}</td>
{% endif %}
<td><a href="/hat_owners/{{hat.id}}">{{hat.number_sold()}}</a></td>
<td><a href="/hat_owners/{{hat.id}}">{{hat.number_sold(g.db)}}</a></td>
<td>{{hat.price}}</td>
<td class="shop-table-actions" style="width:unset">
{% if hat.id not in owned_hat_ids and hat.is_purchasable %}

View File

@ -984,6 +984,7 @@ CREATE TABLE public.users (
titlecolor character varying(6) NOT NULL,
profileurl character varying(65),
bannerurl character varying(65),
hidevotedon boolean DEFAULT false NOT NULL,
newtab boolean DEFAULT false NOT NULL,
flairchanged integer,
defaultsortingcomments character varying(15) NOT NULL,