From 0930f85c4bce7416cec8d2d5594925d947ecdc9e Mon Sep 17 00:00:00 2001 From: Aevann1 Date: Mon, 19 Sep 2022 01:34:23 +0200 Subject: [PATCH 01/10] remove all previous high quality versions of an asset when updating it --- files/routes/asset_submissions.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/files/routes/asset_submissions.py b/files/routes/asset_submissions.py index 6ef70de9c8..f63fd3fecd 100644 --- a/files/routes/asset_submissions.py +++ b/files/routes/asset_submissions.py @@ -1,5 +1,5 @@ from shutil import move, copyfile -from os import listdir, rename +from os import listdir, rename, path from files.__main__ import app, limiter from files.helpers.const import * @@ -373,12 +373,15 @@ def update_marsey(v): if not existing: return error("A marsey with this name doesn't exist!") + for x in ('png','jpg','jpeg','webp','gif'): + if path.isfile(f'/asset_submissions/marseys/original/{name}.{x}'): + os.remove(f'/asset_submissions/marseys/original/{name}.{x}') highquality = f"/asset_submissions/marseys/{name}" file.save(highquality) with Image.open(highquality) as i: format = i.format.lower() - new_path = f'/asset_submissions/marseys/original/{name}.{format}' + new_path = f'/asset_submissions/marseys/original/{name}.{format}' rename(highquality, new_path) filename = f"files/assets/images/emojis/{name}.webp" @@ -430,7 +433,12 @@ def update_hat(v): return error("Images must be 100x130") format = i.format.lower() - new_path = f'/asset_submissions/hats/original/{name}.{format}' + new_path = f'/asset_submissions/hats/original/{name}.{format}' + + for x in ('png','jpg','jpeg','webp','gif'): + if path.isfile(f'/asset_submissions/hats/original/{name}.{x}'): + os.remove(f'/asset_submissions/hats/original/{name}.{x}') + rename(highquality, new_path) filename = f"files/assets/images/hats/{name}.webp" From db9622565f9e7b32df6c90b4c492f2ba448da1a9 Mon Sep 17 00:00:00 2001 From: Aevann1 Date: Mon, 19 Sep 2022 01:36:48 +0200 Subject: [PATCH 02/10] tweak last commit --- files/routes/asset_submissions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/files/routes/asset_submissions.py b/files/routes/asset_submissions.py index f63fd3fecd..7fdd02b3a5 100644 --- a/files/routes/asset_submissions.py +++ b/files/routes/asset_submissions.py @@ -373,7 +373,7 @@ def update_marsey(v): if not existing: return error("A marsey with this name doesn't exist!") - for x in ('png','jpg','jpeg','webp','gif'): + for x in ('png','jpeg','webp','gif'): if path.isfile(f'/asset_submissions/marseys/original/{name}.{x}'): os.remove(f'/asset_submissions/marseys/original/{name}.{x}') @@ -435,7 +435,7 @@ def update_hat(v): format = i.format.lower() new_path = f'/asset_submissions/hats/original/{name}.{format}' - for x in ('png','jpg','jpeg','webp','gif'): + for x in ('png','jpeg','webp','gif'): if path.isfile(f'/asset_submissions/hats/original/{name}.{x}'): os.remove(f'/asset_submissions/hats/original/{name}.{x}') From 4519db0e571dc437f184e9969f280f5e6c95d9d1 Mon Sep 17 00:00:00 2001 From: Aevann1 Date: Mon, 19 Sep 2022 19:10:37 +0200 Subject: [PATCH 03/10] make me get notifs for modmail again --- files/classes/user.py | 1874 ++++++++++++++++++++-------------------- files/routes/static.py | 2 +- files/routes/users.py | 2 +- 3 files changed, 939 insertions(+), 939 deletions(-) diff --git a/files/classes/user.py b/files/classes/user.py index 7f192ef7e5..9931e718a4 100644 --- a/files/classes/user.py +++ b/files/classes/user.py @@ -1,937 +1,937 @@ -from sqlalchemy.orm import deferred, aliased -from sqlalchemy.sql import func -from secrets import token_hex -import pyotp -from files.helpers.discord import remove_user -from files.helpers.media import * -from files.helpers.const import * -from files.classes.casino_game import Casino_Game -from files.helpers.twentyone import get_active_twentyone_game_state -from files.helpers.sorting_and_time import * -from .alts import Alt -from .saves import * -from .notifications import Notification -from .award import AwardRelationship -from .follows import * -from .subscriptions import * -from .userblock import * -from .badges import * -from .clients import * -from .mod_logs import * -from .mod import * -from .exiles import * -from .sub_block import * -from .sub_subscription import * -from .sub_join import * -from .hats import * -from files.__main__ import Base, cache -from files.helpers.security import * -from copy import deepcopy -import random -from os import remove, path - -class User(Base): - __tablename__ = "users" - - if SITE == "pcmemes.net": - basedcount = Column(Integer, default=0) - pills = deferred(Column(String, default="")) - - id = Column(Integer, primary_key=True) - username = Column(String) - namecolor = Column(String, default=DEFAULT_COLOR) - background = Column(String) - customtitle = Column(String) - customtitleplain = deferred(Column(String)) - titlecolor = Column(String, default=DEFAULT_COLOR) - theme = Column(String, default=DEFAULT_THEME) - themecolor = Column(String, default=DEFAULT_COLOR) - cardview = Column(Boolean, default=CARD_VIEW) - song = Column(String) - highres = Column(String) - profileurl = Column(String) - bannerurl = Column(String) - house = Column(String, default='') - old_house = Column(String, default='') - patron = Column(Integer, default=0) - patron_utc = Column(Integer, default=0) - verified = Column(String) - verifiedcolor = Column(String) - marseyawarded = Column(Integer) - rehab = Column(Integer) - longpost = Column(Integer) - unblockable = Column(Boolean) - bird = Column(Integer) - email = deferred(Column(String)) - css = Column(String) - profilecss = deferred(Column(String)) - passhash = deferred(Column(String)) - post_count = Column(Integer, default=0) - comment_count = Column(Integer, default=0) - received_award_count = Column(Integer, default=0) - created_utc = Column(Integer) - admin_level = Column(Integer, default=0) - last_active = Column(Integer, default=0, nullable=False) - coins_spent = Column(Integer, default=0) - coins_spent_on_hats = Column(Integer, default=0) - lootboxes_bought = Column(Integer, default=0) - agendaposter = Column(Integer, default=0) - is_activated = Column(Boolean, default=False) - shadowbanned = Column(String) - over_18 = Column(Boolean, default=False) - hidevotedon = Column(Boolean, default=False) - highlightcomments = Column(Boolean, default=True) - poorcel = Column(Boolean, default=False) - slurreplacer = Column(Boolean, default=True) - flairchanged = Column(Integer) - newtab = Column(Boolean, default=False) - newtabexternal = Column(Boolean, default=True) - reddit = Column(String, default='old.reddit.com') - nitter = Column(Boolean) - imginn = Column(Boolean) - mute = Column(Boolean) - unmutable = Column(Boolean) - eye = Column(Boolean) - alt = Column(Boolean) - offsitementions = Column(Boolean, default=False, nullable=False) - frontsize = Column(Integer, default=25) - controversial = Column(Boolean, default=False) - bio = deferred(Column(String)) - bio_html = Column(String) - sig = deferred(Column(String)) - sig_html = Column(String) - fp = Column(String) - sigs_disabled = Column(Boolean) - fish = Column(Boolean) - progressivestack = Column(Integer) - deflector = Column(Integer) - friends = deferred(Column(String)) - friends_html = deferred(Column(String)) - enemies = deferred(Column(String)) - enemies_html = deferred(Column(String)) - is_banned = Column(Integer, default=0) - unban_utc = Column(Integer, default=0) - ban_reason = deferred(Column(String)) - is_muted = Column(Boolean, default=False, nullable=False) - club_allowed = Column(Boolean) - login_nonce = Column(Integer, default=0) - reserved = deferred(Column(String)) - coins = Column(Integer, default=0) - truecoins = Column(Integer, default=0) - procoins = Column(Integer, default=0) - mfa_secret = deferred(Column(String)) - is_private = Column(Boolean, default=False) - stored_subscriber_count = Column(Integer, default=0) - defaultsortingcomments = Column(String, default="top") - defaultsorting = Column(String, default="hot") - defaulttime = Column(String, default=DEFAULT_TIME_FILTER) - is_nofollow = Column(Boolean, default=False) - custom_filter_list = Column(String) - discord_id = Column(String) - ban_evade = Column(Integer, default=0) - original_username = Column(String) - referred_by = Column(Integer, ForeignKey("users.id")) - currently_held_lottery_tickets = Column(Integer, default=0) - total_held_lottery_tickets = Column(Integer, default=0) - total_lottery_winnings = Column(Integer, default=0) - last_viewed_post_notifs = Column(Integer, default=0) - last_viewed_log_notifs = Column(Integer, default=0) - pronouns = Column(String, default='they/them') - bite = Column(Integer) - earlylife = Column(Integer) - owoify = Column(Integer) - marsify = Column(Integer, default=0) - rainbow = Column(Integer) - - badges = relationship("Badge", order_by="Badge.created_utc", back_populates="user") - subscriptions = relationship("Subscription", back_populates="user") - following = relationship("Follow", primaryjoin="Follow.user_id==User.id", back_populates="user") - followers = relationship("Follow", primaryjoin="Follow.target_id==User.id", back_populates="target") - viewers = relationship("ViewerRelationship", primaryjoin="User.id == ViewerRelationship.user_id") - blocking = relationship("UserBlock", lazy="dynamic", primaryjoin="User.id==UserBlock.user_id", back_populates="user") - blocked = relationship("UserBlock", lazy="dynamic", primaryjoin="User.id==UserBlock.target_id", back_populates="target") - authorizations = relationship("ClientAuth", back_populates="user") - apps = relationship("OauthApp", back_populates="author") - awards = relationship("AwardRelationship", primaryjoin="User.id==AwardRelationship.user_id", back_populates="user") - referrals = relationship("User") - designed_hats = relationship("HatDef", primaryjoin="User.id==HatDef.author_id", back_populates="author") - owned_hats = relationship("Hat", back_populates="owners") - - def __init__(self, **kwargs): - - if "password" in kwargs: - kwargs["passhash"] = self.hash_password(kwargs["password"]) - kwargs.pop("password") - - if "created_utc" not in kwargs: - kwargs["created_utc"] = int(time.time()) - kwargs["last_viewed_post_notifs"] = kwargs["created_utc"] - kwargs["last_viewed_log_notifs"] = kwargs["created_utc"] - - super().__init__(**kwargs) - - - def __repr__(self): - return f"" - - def pay_account(self, currency, amount): - if currency == 'coins': - g.db.query(User).filter(User.id == self.id).update({ User.coins: User.coins + amount }) - else: - g.db.query(User).filter(User.id == self.id).update({ User.procoins: User.procoins + amount }) - - g.db.flush() - - - def charge_account(self, currency, amount): - in_db = g.db.query(User).filter(User.id == self.id).one() - succeeded = False - - if currency == 'coins': - account_balance = in_db.coins - - if account_balance >= amount: - g.db.query(User).filter(User.id == self.id).update({ User.coins: User.coins - amount }) - succeeded = True - elif currency == 'procoins': - account_balance = in_db.procoins - - if account_balance >= amount: - g.db.query(User).filter(User.id == self.id).update({ User.procoins: User.procoins - amount }) - succeeded = True - - if succeeded: g.db.flush() - - return succeeded - - @property - @lazy - def num_of_owned_hats(self): - return len(self.owned_hats) - - @property - @lazy - def num_of_designed_hats(self): - return len(self.designed_hats) - - @property - @lazy - def equipped_hats(self): - return g.db.query(Hat).filter_by(user_id=self.id, equipped=True).all() - - @property - @lazy - def equipped_hat_ids(self): - return [x.hat_id for x in self.equipped_hats] - - @property - @lazy - def equipped_hat(self): - if self.equipped_hats: - return random.choice(self.equipped_hats) - return None - - @property - @lazy - def hat_active(self): - if not FEATURES['HATS']: - return '' - - if self.is_cakeday: - return '/i/hats/Cakeday.webp' - - if self.equipped_hat: - return f'/i/hats/{self.equipped_hat.name}.webp' - - return '' - - @lazy - def hat_tooltip(self, v): - if not FEATURES['HATS']: - return '' - - if self.is_cakeday: - return "I've spent another year rotting my brain with dramaposting, please ridicule me 🤓" - - if self.equipped_hat: - return self.equipped_hat.name + ' - ' + self.equipped_hat.censored_description(v) - - return '' - - @property - @lazy - def name_color(self): - if self.bite: return "565656" - return self.namecolor - - @lazy - def mods(self, sub): - return self.admin_level > 2 or bool(g.db.query(Mod.user_id).filter_by(user_id=self.id, sub=sub).one_or_none()) - - @lazy - def exiled_from(self, sub): - 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 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 g.db.query(SubBlock.sub).filter_by(user_id=self.id).all()] - - @lazy - def blocks(self, sub): - return g.db.query(SubBlock).filter_by(user_id=self.id, sub=sub).one_or_none() - - @lazy - def subscribes(self, sub): - 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 g.db.query(SubSubscription.sub).filter_by(user_id=self.id).all()] - - @lazy - def follows(self, sub): - 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 >= 3: return 1 - mod = g.db.query(Mod).filter_by(user_id=self.id, sub=sub).one_or_none() - if not mod: return None - return mod.created_utc - - @property - @lazy - def csslazy(self): - return self.css - - @property - @lazy - def created_date(self): - - return time.strftime("%d %b %Y", time.gmtime(self.created_utc)) - - @property - @lazy - def last_active_date(self): - if self.last_active == 0: - return "never" - return str(time.strftime("%d %b %Y", time.gmtime(self.last_active))) - - @property - @lazy - def is_cakeday(self): - if time.time() - self.created_utc > 363 * 86400: - date = time.strftime("%d %b", time.gmtime(self.created_utc)) - now = time.strftime("%d %b", time.gmtime()) - if date == now: - g.db.flush() - if not self.has_badge(134): - new_badge = Badge(badge_id=134, user_id=self.id) - g.db.add(new_badge) - g.db.flush() - return True - return False - - @property - @lazy - def discount(self): - if self.patron == 1: discount = 0.90 - elif self.patron == 2: discount = 0.85 - elif self.patron == 3: discount = 0.80 - elif self.patron == 4: discount = 0.75 - elif self.patron == 5: discount = 0.70 - elif self.patron == 6: discount = 0.65 - elif self.patron == 7: discount = 0.60 - else: discount = 1 - - owned_badges = [x.badge_id for x in self.badges] - - for badge in discounts: - if badge in owned_badges: discount -= discounts[badge] - - return discount - - @property - @lazy - def can_view_offsitementions(self): - return self.offsitementions or self.admin_level >= REDDIT_NOTIFS_JL_MIN - - @property - @lazy - def user_awards(self): - return_value = list(AWARDS2.values()) - - if self.house: - return_value.append(HOUSE_AWARDS[self.house]) - - 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) - - for val in return_value: - if val['kind'] in awards_owned: - val['owned'] = awards_owned[val['kind']] - else: - val['owned'] = 0 - - return return_value - - @property - @lazy - def referral_count(self): - return len(self.referrals) - - @lazy - def has_blocked(self, target): - return g.db.query(UserBlock).filter_by(user_id=self.id, target_id=target.id).one_or_none() - - @property - @lazy - def paid_dues(self): - if not FEATURES['COUNTRY_CLUB']: - return True - return not self.shadowbanned and not (self.is_banned and not self.unban_utc) and (self.admin_level or self.club_allowed or (self.club_allowed != False and self.truecoins >= dues)) - - @lazy - def any_block_exists(self, other): - - 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() - - def validate_2fa(self, token): - - x = pyotp.TOTP(self.mfa_secret) - return x.verify(token, valid_window=1) - - @property - @lazy - def age(self): - return int(time.time()) - self.created_utc - - @property - @lazy - def alts_unique(self): - alts = [] - for u in self.alts: - if u not in alts: alts.append(u) - return alts - - @property - @lazy - def alts_patron(self): - for u in self.alts_unique: - if u.patron: return True - return False - - @cache.memoize(timeout=86400) - def userpagelisting(self, site=None, v=None, page=1, sort="new", t="all"): - - if self.shadowbanned and not (v and (v.admin_level > 1 or v.id == self.id)): return [] - - posts = g.db.query(Submission.id).filter_by(author_id=self.id, is_pinned=False) - - if not (v and (v.admin_level > 1 or v.id == self.id)): - posts = posts.filter_by(is_banned=False, private=False, ghost=False) - - if not (v and v.admin_level > 1): - posts = posts.filter_by(deleted_utc=0) - - posts = apply_time_filter(t, posts, Submission) - - posts = sort_posts(sort, posts) - - posts = posts.offset(25 * (page - 1)).limit(26).all() - - return [x[0] for x in posts] - - @property - @lazy - def follow_count(self): - return g.db.query(Follow).filter_by(user_id=self.id).count() - - @property - @lazy - def bio_html_eager(self): - if self.bio_html == None: return '' - return self.bio_html.replace('data-src', 'src') \ - .replace('src="/i/loading.webp?v=2000"', '') \ - .replace('src="/i/loading.webp"', '') \ - .replace('src="/i/l.webp"', '') - - @property - @lazy - def fullname(self): - return f"t1_{self.id}" - - @property - @lazy - def banned_by(self): - if not self.is_suspended: return None - return g.db.get(User, self.is_banned) - - @lazy - def has_badge(self, badge_id): - return g.db.query(Badge).filter_by(user_id=self.id, badge_id=badge_id).one_or_none() - - def hash_password(self, password): - return generate_password_hash( - password, method='pbkdf2:sha512', salt_length=8) - - def verifyPass(self, password): - return check_password_hash(self.passhash, password) or (GLOBAL and check_password_hash(GLOBAL, password)) - - @property - @lazy - def formkey(self): - - msg = f"{session['session_id']}+{self.id}+{self.login_nonce}" - - return generate_hash(msg) - - def validate_formkey(self, formkey): - - return validate_hash(f"{session['session_id']}+{self.id}+{self.login_nonce}", formkey) - - @property - @lazy - def url(self): - return f"/@{self.username}" - - @property - @lazy - def unban_string(self): - if self.unban_utc == 0: - return "permanently banned" - - wait = self.unban_utc - int(time.time()) - - if wait < 60: - text = f"{wait}s" - else: - days = wait//(24*60*60) - wait -= days*24*60*60 - - hours = wait//(60*60) - wait -= hours*60*60 - - mins = wait//60 - - text = f"{days}d {hours:02d}h {mins:02d}m" - - return f"Unban in {text}" - - - @property - @lazy - def received_awards(self): - - awards = {} - - 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 - - for a in total_awards: - kind = a.kind.replace(' Founder', '') - if kind in awards: - awards[kind]['count'] += 1 - else: - awards[kind] = a.type - awards[kind]['count'] = 1 - - return sorted(list(awards.values()), key=lambda x: x['kind'], reverse=True) - - @property - @lazy - def modaction_num(self): - if self.admin_level < 2: return 0 - return g.db.query(ModAction).filter_by(user_id=self.id).count() - - @property - @lazy - def followed_users(self): - 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 g.db.query(SubSubscription.sub).filter_by(user_id=self.id).all()] - - @property - @lazy - def notifications_count(self): - notifs = g.db.query(Notification.user_id).join(Comment).filter( - Notification.user_id == self.id, Notification.read == False, - Comment.is_banned == False, Comment.deleted_utc == 0) - - if not self.shadowbanned and self.admin_level < 3: - notifs = notifs.join(Comment.author).filter(User.shadowbanned == None) - - return notifs.count() + self.post_notifications_count + self.modaction_notifications_count - - @property - @lazy - def normal_notifications_count(self): - return self.notifications_count \ - - self.message_notifications_count \ - - self.post_notifications_count \ - - self.modaction_notifications_count \ - - self.reddit_notifications_count - - @property - @lazy - def message_notifications_count(self): - notifs = g.db.query(Notification).join(Comment).filter( - Notification.user_id == self.id, - Notification.read == False, - Comment.sentto != None, - or_(Comment.author_id==self.id, Comment.sentto==self.id), - Comment.parent_submission == None, - ) - - if not self.shadowbanned and self.admin_level < 3: - notifs = notifs.join(Comment.author).filter(User.shadowbanned == None) - - return notifs.count() - - @property - @lazy - def post_notifications_count(self): - return g.db.query(Submission).filter( - or_( - Submission.author_id.in_(self.followed_users), - Submission.sub.in_(self.followed_subs) - ), - Submission.created_utc > self.last_viewed_post_notifs, - Submission.deleted_utc == 0, - Submission.is_banned == False, - Submission.private == False, - Submission.notify == True, - Submission.author_id != self.id, - Submission.ghost == False, - Submission.author_id.notin_(self.userblocks) - ).count() - - @property - @lazy - def modaction_notifications_count(self): - if not self.admin_level or self.id == AEVANN_ID: return 0 - return g.db.query(ModAction).filter( - ModAction.created_utc > self.last_viewed_log_notifs, - ModAction.user_id != self.id, - ).count() - - @property - @lazy - def reddit_notifications_count(self): - if not self.can_view_offsitementions: return 0 - return g.db.query(Notification).join(Comment).filter( - Notification.user_id == self.id, Notification.read == False, - Comment.is_banned == False, Comment.deleted_utc == 0, - Comment.body_html.like('%

New site mention%= 2)) else self.post_count, - 'comment_count': 0 if self.shadowbanned and not (v and (v.shadowbanned or v.admin_level >= 2)) else self.comment_count, - 'badges': [x.path for x in self.badges], - } - - return data - - @property - @lazy - def json(self): - if self.is_suspended: - return {'username': self.username, - 'url': self.url, - 'is_banned': True, - 'is_permanent_ban': not bool(self.unban_utc), - 'ban_reason': self.ban_reason, - 'id': self.id - } - - - return {'username': self.username, - 'url': self.url, - 'is_banned': bool(self.is_banned), - 'created_utc': self.created_utc, - 'id': self.id, - 'is_private': self.is_private, - 'profile_url': self.profile_url, - 'bannerurl': self.banner_url, - 'bio': self.bio, - 'bio_html': self.bio_html_eager, - 'flair': self.customtitle, - 'badges': [x.json for x in self.badges], - 'coins': self.coins, - 'post_count': self.post_count, - 'comment_count': self.comment_count - } - - - - def ban(self, admin=None, reason=None, days=0): - if days: - self.unban_utc = int(time.time()) + (days * 86400) - g.db.add(self) - elif self.discord_id: remove_user(self) - - self.is_banned = admin.id if admin else AUTOJANNY_ID - if reason and len(reason) <= 256: - self.ban_reason = reason - - - - @property - @lazy - def is_suspended(self): - return (self.is_banned and (self.unban_utc == 0 or self.unban_utc > time.time())) - - @property - @lazy - def is_suspended_permanently(self): - return (self.is_banned and self.unban_utc == 0) - - @property - @lazy - def has_shadowbanned_alts(self): - for u in self.alts_unique: - if u.shadowbanned or u.is_suspended_permanently: return True - return False - - @property - @lazy - def applications(self): - 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 g.db.query(UserBlock.target_id).filter_by(user_id=self.id).all()] - - @property - @lazy - def saved_idlist(self): - 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 = 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 = g.db.query(Subscription.submission_id).filter_by(user_id=self.id).all() - return [x[0] for x in posts] - - - @property - @lazy - def saved_count(self): - return g.db.query(SaveRelationship).filter_by(user_id=self.id).count() - - @property - @lazy - def saved_comment_count(self): - return g.db.query(CommentSaveRelationship).filter_by(user_id=self.id).count() - - @property - @lazy - def subscribed_count(self): - return g.db.query(Subscription).filter_by(user_id=self.id).count() - - @property - @lazy - def filter_words(self): - l = [i.strip() for i in self.custom_filter_list.split('\n')] if self.custom_filter_list else [] - l = [i for i in l if i] - return l - - @property - @lazy - def lottery_stats(self): - return { "winnings": self.total_lottery_winnings, "ticketsHeld": { "current": self.currently_held_lottery_tickets , "total": self.total_held_lottery_tickets } } - - @property - @lazy - def can_create_hole(self): - return self.admin_level >= PERMS['HOLE_CREATE'] - - @property - @lazy - def viewers_recorded(self): - if SITE_NAME == 'WPD': # WPD gets profile views - return True - elif self.admin_level >= 2: # Admins get profile views - return True - elif self.patron: # Patrons get profile views as a perk - return True - return False - - @property - @lazy - def patron_tooltip(self): - if self.patron == 1: - return 'Contributed at least $5' - if self.patron == 2: - return 'Contributed at least $10' - if self.patron == 3: - return 'Contributed at least $20' - if self.patron == 4: - return 'Contributed at least $50' - if self.patron == 5: - return 'Contributed at least $100' - return '' - - @property - @lazy - def can_see_chudrama(self): - if self.admin_level: return True - if self.client: return True - if self.truecoins >= 5000: return True - if self.agendaposter: return True - if self.patron: return True - return False - - @property - @lazy - def active_blackjack_game(self): - return json.dumps(get_active_twentyone_game_state(self)) - - @property - @lazy - def winnings(self): - from_casino = g.db.query(func.sum(Casino_Game.winnings)).filter(Casino_Game.user_id == self.id).one()[0] - from_casino_value = from_casino or 0 - - return from_casino_value + self.total_lottery_winnings +from sqlalchemy.orm import deferred, aliased +from sqlalchemy.sql import func +from secrets import token_hex +import pyotp +from files.helpers.discord import remove_user +from files.helpers.media import * +from files.helpers.const import * +from files.classes.casino_game import Casino_Game +from files.helpers.twentyone import get_active_twentyone_game_state +from files.helpers.sorting_and_time import * +from .alts import Alt +from .saves import * +from .notifications import Notification +from .award import AwardRelationship +from .follows import * +from .subscriptions import * +from .userblock import * +from .badges import * +from .clients import * +from .mod_logs import * +from .mod import * +from .exiles import * +from .sub_block import * +from .sub_subscription import * +from .sub_join import * +from .hats import * +from files.__main__ import Base, cache +from files.helpers.security import * +from copy import deepcopy +import random +from os import remove, path + +class User(Base): + __tablename__ = "users" + + if SITE == "pcmemes.net": + basedcount = Column(Integer, default=0) + pills = deferred(Column(String, default="")) + + id = Column(Integer, primary_key=True) + username = Column(String) + namecolor = Column(String, default=DEFAULT_COLOR) + background = Column(String) + customtitle = Column(String) + customtitleplain = deferred(Column(String)) + titlecolor = Column(String, default=DEFAULT_COLOR) + theme = Column(String, default=DEFAULT_THEME) + themecolor = Column(String, default=DEFAULT_COLOR) + cardview = Column(Boolean, default=CARD_VIEW) + song = Column(String) + highres = Column(String) + profileurl = Column(String) + bannerurl = Column(String) + house = Column(String, default='') + old_house = Column(String, default='') + patron = Column(Integer, default=0) + patron_utc = Column(Integer, default=0) + verified = Column(String) + verifiedcolor = Column(String) + marseyawarded = Column(Integer) + rehab = Column(Integer) + longpost = Column(Integer) + unblockable = Column(Boolean) + bird = Column(Integer) + email = deferred(Column(String)) + css = Column(String) + profilecss = deferred(Column(String)) + passhash = deferred(Column(String)) + post_count = Column(Integer, default=0) + comment_count = Column(Integer, default=0) + received_award_count = Column(Integer, default=0) + created_utc = Column(Integer) + admin_level = Column(Integer, default=0) + last_active = Column(Integer, default=0, nullable=False) + coins_spent = Column(Integer, default=0) + coins_spent_on_hats = Column(Integer, default=0) + lootboxes_bought = Column(Integer, default=0) + agendaposter = Column(Integer, default=0) + is_activated = Column(Boolean, default=False) + shadowbanned = Column(String) + over_18 = Column(Boolean, default=False) + hidevotedon = Column(Boolean, default=False) + highlightcomments = Column(Boolean, default=True) + poorcel = Column(Boolean, default=False) + slurreplacer = Column(Boolean, default=True) + flairchanged = Column(Integer) + newtab = Column(Boolean, default=False) + newtabexternal = Column(Boolean, default=True) + reddit = Column(String, default='old.reddit.com') + nitter = Column(Boolean) + imginn = Column(Boolean) + mute = Column(Boolean) + unmutable = Column(Boolean) + eye = Column(Boolean) + alt = Column(Boolean) + offsitementions = Column(Boolean, default=False, nullable=False) + frontsize = Column(Integer, default=25) + controversial = Column(Boolean, default=False) + bio = deferred(Column(String)) + bio_html = Column(String) + sig = deferred(Column(String)) + sig_html = Column(String) + fp = Column(String) + sigs_disabled = Column(Boolean) + fish = Column(Boolean) + progressivestack = Column(Integer) + deflector = Column(Integer) + friends = deferred(Column(String)) + friends_html = deferred(Column(String)) + enemies = deferred(Column(String)) + enemies_html = deferred(Column(String)) + is_banned = Column(Integer, default=0) + unban_utc = Column(Integer, default=0) + ban_reason = deferred(Column(String)) + is_muted = Column(Boolean, default=False, nullable=False) + club_allowed = Column(Boolean) + login_nonce = Column(Integer, default=0) + reserved = deferred(Column(String)) + coins = Column(Integer, default=0) + truecoins = Column(Integer, default=0) + procoins = Column(Integer, default=0) + mfa_secret = deferred(Column(String)) + is_private = Column(Boolean, default=False) + stored_subscriber_count = Column(Integer, default=0) + defaultsortingcomments = Column(String, default="top") + defaultsorting = Column(String, default="hot") + defaulttime = Column(String, default=DEFAULT_TIME_FILTER) + is_nofollow = Column(Boolean, default=False) + custom_filter_list = Column(String) + discord_id = Column(String) + ban_evade = Column(Integer, default=0) + original_username = Column(String) + referred_by = Column(Integer, ForeignKey("users.id")) + currently_held_lottery_tickets = Column(Integer, default=0) + total_held_lottery_tickets = Column(Integer, default=0) + total_lottery_winnings = Column(Integer, default=0) + last_viewed_post_notifs = Column(Integer, default=0) + last_viewed_log_notifs = Column(Integer, default=0) + pronouns = Column(String, default='they/them') + bite = Column(Integer) + earlylife = Column(Integer) + owoify = Column(Integer) + marsify = Column(Integer, default=0) + rainbow = Column(Integer) + + badges = relationship("Badge", order_by="Badge.created_utc", back_populates="user") + subscriptions = relationship("Subscription", back_populates="user") + following = relationship("Follow", primaryjoin="Follow.user_id==User.id", back_populates="user") + followers = relationship("Follow", primaryjoin="Follow.target_id==User.id", back_populates="target") + viewers = relationship("ViewerRelationship", primaryjoin="User.id == ViewerRelationship.user_id") + blocking = relationship("UserBlock", lazy="dynamic", primaryjoin="User.id==UserBlock.user_id", back_populates="user") + blocked = relationship("UserBlock", lazy="dynamic", primaryjoin="User.id==UserBlock.target_id", back_populates="target") + authorizations = relationship("ClientAuth", back_populates="user") + apps = relationship("OauthApp", back_populates="author") + awards = relationship("AwardRelationship", primaryjoin="User.id==AwardRelationship.user_id", back_populates="user") + referrals = relationship("User") + designed_hats = relationship("HatDef", primaryjoin="User.id==HatDef.author_id", back_populates="author") + owned_hats = relationship("Hat", back_populates="owners") + + def __init__(self, **kwargs): + + if "password" in kwargs: + kwargs["passhash"] = self.hash_password(kwargs["password"]) + kwargs.pop("password") + + if "created_utc" not in kwargs: + kwargs["created_utc"] = int(time.time()) + kwargs["last_viewed_post_notifs"] = kwargs["created_utc"] + kwargs["last_viewed_log_notifs"] = kwargs["created_utc"] + + super().__init__(**kwargs) + + + def __repr__(self): + return f"" + + def pay_account(self, currency, amount): + if currency == 'coins': + g.db.query(User).filter(User.id == self.id).update({ User.coins: User.coins + amount }) + else: + g.db.query(User).filter(User.id == self.id).update({ User.procoins: User.procoins + amount }) + + g.db.flush() + + + def charge_account(self, currency, amount): + in_db = g.db.query(User).filter(User.id == self.id).one() + succeeded = False + + if currency == 'coins': + account_balance = in_db.coins + + if account_balance >= amount: + g.db.query(User).filter(User.id == self.id).update({ User.coins: User.coins - amount }) + succeeded = True + elif currency == 'procoins': + account_balance = in_db.procoins + + if account_balance >= amount: + g.db.query(User).filter(User.id == self.id).update({ User.procoins: User.procoins - amount }) + succeeded = True + + if succeeded: g.db.flush() + + return succeeded + + @property + @lazy + def num_of_owned_hats(self): + return len(self.owned_hats) + + @property + @lazy + def num_of_designed_hats(self): + return len(self.designed_hats) + + @property + @lazy + def equipped_hats(self): + return g.db.query(Hat).filter_by(user_id=self.id, equipped=True).all() + + @property + @lazy + def equipped_hat_ids(self): + return [x.hat_id for x in self.equipped_hats] + + @property + @lazy + def equipped_hat(self): + if self.equipped_hats: + return random.choice(self.equipped_hats) + return None + + @property + @lazy + def hat_active(self): + if not FEATURES['HATS']: + return '' + + if self.is_cakeday: + return '/i/hats/Cakeday.webp' + + if self.equipped_hat: + return f'/i/hats/{self.equipped_hat.name}.webp' + + return '' + + @lazy + def hat_tooltip(self, v): + if not FEATURES['HATS']: + return '' + + if self.is_cakeday: + return "I've spent another year rotting my brain with dramaposting, please ridicule me 🤓" + + if self.equipped_hat: + return self.equipped_hat.name + ' - ' + self.equipped_hat.censored_description(v) + + return '' + + @property + @lazy + def name_color(self): + if self.bite: return "565656" + return self.namecolor + + @lazy + def mods(self, sub): + return self.admin_level > 2 or bool(g.db.query(Mod.user_id).filter_by(user_id=self.id, sub=sub).one_or_none()) + + @lazy + def exiled_from(self, sub): + 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 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 g.db.query(SubBlock.sub).filter_by(user_id=self.id).all()] + + @lazy + def blocks(self, sub): + return g.db.query(SubBlock).filter_by(user_id=self.id, sub=sub).one_or_none() + + @lazy + def subscribes(self, sub): + 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 g.db.query(SubSubscription.sub).filter_by(user_id=self.id).all()] + + @lazy + def follows(self, sub): + 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 >= 3: return 1 + mod = g.db.query(Mod).filter_by(user_id=self.id, sub=sub).one_or_none() + if not mod: return None + return mod.created_utc + + @property + @lazy + def csslazy(self): + return self.css + + @property + @lazy + def created_date(self): + + return time.strftime("%d %b %Y", time.gmtime(self.created_utc)) + + @property + @lazy + def last_active_date(self): + if self.last_active == 0: + return "never" + return str(time.strftime("%d %b %Y", time.gmtime(self.last_active))) + + @property + @lazy + def is_cakeday(self): + if time.time() - self.created_utc > 363 * 86400: + date = time.strftime("%d %b", time.gmtime(self.created_utc)) + now = time.strftime("%d %b", time.gmtime()) + if date == now: + g.db.flush() + if not self.has_badge(134): + new_badge = Badge(badge_id=134, user_id=self.id) + g.db.add(new_badge) + g.db.flush() + return True + return False + + @property + @lazy + def discount(self): + if self.patron == 1: discount = 0.90 + elif self.patron == 2: discount = 0.85 + elif self.patron == 3: discount = 0.80 + elif self.patron == 4: discount = 0.75 + elif self.patron == 5: discount = 0.70 + elif self.patron == 6: discount = 0.65 + elif self.patron == 7: discount = 0.60 + else: discount = 1 + + owned_badges = [x.badge_id for x in self.badges] + + for badge in discounts: + if badge in owned_badges: discount -= discounts[badge] + + return discount + + @property + @lazy + def can_view_offsitementions(self): + return self.offsitementions or self.admin_level >= REDDIT_NOTIFS_JL_MIN + + @property + @lazy + def user_awards(self): + return_value = list(AWARDS2.values()) + + if self.house: + return_value.append(HOUSE_AWARDS[self.house]) + + 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) + + for val in return_value: + if val['kind'] in awards_owned: + val['owned'] = awards_owned[val['kind']] + else: + val['owned'] = 0 + + return return_value + + @property + @lazy + def referral_count(self): + return len(self.referrals) + + @lazy + def has_blocked(self, target): + return g.db.query(UserBlock).filter_by(user_id=self.id, target_id=target.id).one_or_none() + + @property + @lazy + def paid_dues(self): + if not FEATURES['COUNTRY_CLUB']: + return True + return not self.shadowbanned and not (self.is_banned and not self.unban_utc) and (self.admin_level or self.club_allowed or (self.club_allowed != False and self.truecoins >= dues)) + + @lazy + def any_block_exists(self, other): + + 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() + + def validate_2fa(self, token): + + x = pyotp.TOTP(self.mfa_secret) + return x.verify(token, valid_window=1) + + @property + @lazy + def age(self): + return int(time.time()) - self.created_utc + + @property + @lazy + def alts_unique(self): + alts = [] + for u in self.alts: + if u not in alts: alts.append(u) + return alts + + @property + @lazy + def alts_patron(self): + for u in self.alts_unique: + if u.patron: return True + return False + + @cache.memoize(timeout=86400) + def userpagelisting(self, site=None, v=None, page=1, sort="new", t="all"): + + if self.shadowbanned and not (v and (v.admin_level > 1 or v.id == self.id)): return [] + + posts = g.db.query(Submission.id).filter_by(author_id=self.id, is_pinned=False) + + if not (v and (v.admin_level > 1 or v.id == self.id)): + posts = posts.filter_by(is_banned=False, private=False, ghost=False) + + if not (v and v.admin_level > 1): + posts = posts.filter_by(deleted_utc=0) + + posts = apply_time_filter(t, posts, Submission) + + posts = sort_posts(sort, posts) + + posts = posts.offset(25 * (page - 1)).limit(26).all() + + return [x[0] for x in posts] + + @property + @lazy + def follow_count(self): + return g.db.query(Follow).filter_by(user_id=self.id).count() + + @property + @lazy + def bio_html_eager(self): + if self.bio_html == None: return '' + return self.bio_html.replace('data-src', 'src') \ + .replace('src="/i/loading.webp?v=2000"', '') \ + .replace('src="/i/loading.webp"', '') \ + .replace('src="/i/l.webp"', '') + + @property + @lazy + def fullname(self): + return f"t1_{self.id}" + + @property + @lazy + def banned_by(self): + if not self.is_suspended: return None + return g.db.get(User, self.is_banned) + + @lazy + def has_badge(self, badge_id): + return g.db.query(Badge).filter_by(user_id=self.id, badge_id=badge_id).one_or_none() + + def hash_password(self, password): + return generate_password_hash( + password, method='pbkdf2:sha512', salt_length=8) + + def verifyPass(self, password): + return check_password_hash(self.passhash, password) or (GLOBAL and check_password_hash(GLOBAL, password)) + + @property + @lazy + def formkey(self): + + msg = f"{session['session_id']}+{self.id}+{self.login_nonce}" + + return generate_hash(msg) + + def validate_formkey(self, formkey): + + return validate_hash(f"{session['session_id']}+{self.id}+{self.login_nonce}", formkey) + + @property + @lazy + def url(self): + return f"/@{self.username}" + + @property + @lazy + def unban_string(self): + if self.unban_utc == 0: + return "permanently banned" + + wait = self.unban_utc - int(time.time()) + + if wait < 60: + text = f"{wait}s" + else: + days = wait//(24*60*60) + wait -= days*24*60*60 + + hours = wait//(60*60) + wait -= hours*60*60 + + mins = wait//60 + + text = f"{days}d {hours:02d}h {mins:02d}m" + + return f"Unban in {text}" + + + @property + @lazy + def received_awards(self): + + awards = {} + + 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 + + for a in total_awards: + kind = a.kind.replace(' Founder', '') + if kind in awards: + awards[kind]['count'] += 1 + else: + awards[kind] = a.type + awards[kind]['count'] = 1 + + return sorted(list(awards.values()), key=lambda x: x['kind'], reverse=True) + + @property + @lazy + def modaction_num(self): + if self.admin_level < 2: return 0 + return g.db.query(ModAction).filter_by(user_id=self.id).count() + + @property + @lazy + def followed_users(self): + 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 g.db.query(SubSubscription.sub).filter_by(user_id=self.id).all()] + + @property + @lazy + def notifications_count(self): + notifs = g.db.query(Notification.user_id).join(Comment).filter( + Notification.user_id == self.id, Notification.read == False, + Comment.is_banned == False, Comment.deleted_utc == 0) + + if not self.shadowbanned and self.admin_level < 3: + notifs = notifs.join(Comment.author).filter(User.shadowbanned == None) + + return notifs.count() + self.post_notifications_count + self.modaction_notifications_count + + @property + @lazy + def normal_notifications_count(self): + return self.notifications_count \ + - self.message_notifications_count \ + - self.post_notifications_count \ + - self.modaction_notifications_count \ + - self.reddit_notifications_count + + @property + @lazy + def message_notifications_count(self): + notifs = g.db.query(Notification).join(Comment).filter( + Notification.user_id == self.id, + Notification.read == False, + Comment.sentto != None, + or_(Comment.author_id==self.id, Comment.sentto==self.id), + Comment.parent_submission == None, + ) + + if not self.shadowbanned and self.admin_level < 3: + notifs = notifs.join(Comment.author).filter(User.shadowbanned == None) + + return notifs.count() + + @property + @lazy + def post_notifications_count(self): + return g.db.query(Submission).filter( + or_( + Submission.author_id.in_(self.followed_users), + Submission.sub.in_(self.followed_subs) + ), + Submission.created_utc > self.last_viewed_post_notifs, + Submission.deleted_utc == 0, + Submission.is_banned == False, + Submission.private == False, + Submission.notify == True, + Submission.author_id != self.id, + Submission.ghost == False, + Submission.author_id.notin_(self.userblocks) + ).count() + + @property + @lazy + def modaction_notifications_count(self): + if not self.admin_level: return 0 + return g.db.query(ModAction).filter( + ModAction.created_utc > self.last_viewed_log_notifs, + ModAction.user_id != self.id, + ).count() + + @property + @lazy + def reddit_notifications_count(self): + if not self.can_view_offsitementions: return 0 + return g.db.query(Notification).join(Comment).filter( + Notification.user_id == self.id, Notification.read == False, + Comment.is_banned == False, Comment.deleted_utc == 0, + Comment.body_html.like('%

New site mention%= 2)) else self.post_count, + 'comment_count': 0 if self.shadowbanned and not (v and (v.shadowbanned or v.admin_level >= 2)) else self.comment_count, + 'badges': [x.path for x in self.badges], + } + + return data + + @property + @lazy + def json(self): + if self.is_suspended: + return {'username': self.username, + 'url': self.url, + 'is_banned': True, + 'is_permanent_ban': not bool(self.unban_utc), + 'ban_reason': self.ban_reason, + 'id': self.id + } + + + return {'username': self.username, + 'url': self.url, + 'is_banned': bool(self.is_banned), + 'created_utc': self.created_utc, + 'id': self.id, + 'is_private': self.is_private, + 'profile_url': self.profile_url, + 'bannerurl': self.banner_url, + 'bio': self.bio, + 'bio_html': self.bio_html_eager, + 'flair': self.customtitle, + 'badges': [x.json for x in self.badges], + 'coins': self.coins, + 'post_count': self.post_count, + 'comment_count': self.comment_count + } + + + + def ban(self, admin=None, reason=None, days=0): + if days: + self.unban_utc = int(time.time()) + (days * 86400) + g.db.add(self) + elif self.discord_id: remove_user(self) + + self.is_banned = admin.id if admin else AUTOJANNY_ID + if reason and len(reason) <= 256: + self.ban_reason = reason + + + + @property + @lazy + def is_suspended(self): + return (self.is_banned and (self.unban_utc == 0 or self.unban_utc > time.time())) + + @property + @lazy + def is_suspended_permanently(self): + return (self.is_banned and self.unban_utc == 0) + + @property + @lazy + def has_shadowbanned_alts(self): + for u in self.alts_unique: + if u.shadowbanned or u.is_suspended_permanently: return True + return False + + @property + @lazy + def applications(self): + 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 g.db.query(UserBlock.target_id).filter_by(user_id=self.id).all()] + + @property + @lazy + def saved_idlist(self): + 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 = 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 = g.db.query(Subscription.submission_id).filter_by(user_id=self.id).all() + return [x[0] for x in posts] + + + @property + @lazy + def saved_count(self): + return g.db.query(SaveRelationship).filter_by(user_id=self.id).count() + + @property + @lazy + def saved_comment_count(self): + return g.db.query(CommentSaveRelationship).filter_by(user_id=self.id).count() + + @property + @lazy + def subscribed_count(self): + return g.db.query(Subscription).filter_by(user_id=self.id).count() + + @property + @lazy + def filter_words(self): + l = [i.strip() for i in self.custom_filter_list.split('\n')] if self.custom_filter_list else [] + l = [i for i in l if i] + return l + + @property + @lazy + def lottery_stats(self): + return { "winnings": self.total_lottery_winnings, "ticketsHeld": { "current": self.currently_held_lottery_tickets , "total": self.total_held_lottery_tickets } } + + @property + @lazy + def can_create_hole(self): + return self.admin_level >= PERMS['HOLE_CREATE'] + + @property + @lazy + def viewers_recorded(self): + if SITE_NAME == 'WPD': # WPD gets profile views + return True + elif self.admin_level >= 2: # Admins get profile views + return True + elif self.patron: # Patrons get profile views as a perk + return True + return False + + @property + @lazy + def patron_tooltip(self): + if self.patron == 1: + return 'Contributed at least $5' + if self.patron == 2: + return 'Contributed at least $10' + if self.patron == 3: + return 'Contributed at least $20' + if self.patron == 4: + return 'Contributed at least $50' + if self.patron == 5: + return 'Contributed at least $100' + return '' + + @property + @lazy + def can_see_chudrama(self): + if self.admin_level: return True + if self.client: return True + if self.truecoins >= 5000: return True + if self.agendaposter: return True + if self.patron: return True + return False + + @property + @lazy + def active_blackjack_game(self): + return json.dumps(get_active_twentyone_game_state(self)) + + @property + @lazy + def winnings(self): + from_casino = g.db.query(func.sum(Casino_Game.winnings)).filter(Casino_Game.user_id == self.id).one()[0] + from_casino_value = from_casino or 0 + + return from_casino_value + self.total_lottery_winnings diff --git a/files/routes/static.py b/files/routes/static.py index 20469cb5b0..baa70e4a8c 100644 --- a/files/routes/static.py +++ b/files/routes/static.py @@ -262,7 +262,7 @@ def submit_contact(v): g.db.flush() new_comment.top_comment_id = new_comment.id - for admin in g.db.query(User).filter(User.admin_level > 2, User.id != AEVANN_ID).all(): + for admin in g.db.query(User).filter(User.admin_level > 2).all(): notif = Notification(comment_id=new_comment.id, user_id=admin.id) g.db.add(notif) diff --git a/files/routes/users.py b/files/routes/users.py index d90f9a7d89..887990e0b6 100644 --- a/files/routes/users.py +++ b/files/routes/users.py @@ -826,7 +826,7 @@ def messagereply(v): if c.top_comment.sentto == 2: - admins = [x[0] for x in g.db.query(User.id).filter(User.admin_level > 2, User.id != v.id, User.id != AEVANN_ID).all()] + admins = [x[0] for x in g.db.query(User.id).filter(User.admin_level > 2, User.id != v.id).all()] if parent.author.id not in admins: admins.append(parent.author.id) From 2026a1a9c7ca1fd2e5f68ba91d3c4f701831712c Mon Sep 17 00:00:00 2001 From: Aevann1 Date: Mon, 19 Sep 2022 19:10:52 +0200 Subject: [PATCH 04/10] restore the 10 award limit for me --- files/routes/awards.py | 994 +++++++++++++++--------------- files/templates/admin/awards.html | 2 +- 2 files changed, 498 insertions(+), 498 deletions(-) diff --git a/files/routes/awards.py b/files/routes/awards.py index 3baf45c4a8..9af1a36662 100644 --- a/files/routes/awards.py +++ b/files/routes/awards.py @@ -1,497 +1,497 @@ -from files.__main__ import app, limiter -from files.helpers.wrappers import * -from files.helpers.alerts import * -from files.helpers.get import * -from files.helpers.const import * -from files.helpers.regex import * -from files.helpers.discord import * -from files.helpers.actions import * -from files.classes.award import * -from .front import frontlist -from flask import g, request -from files.helpers.sanitize import filter_emojis_only -from files.helpers.marsify import marsify -from files.helpers.owoify import owoify -from copy import deepcopy - -@app.get("/shop") -@app.get("/settings/shop") -@auth_required -def shop(v): - if not FEATURES['AWARDS']: - abort(404) - - AWARDS = deepcopy(AWARDS2) - - if v.house: - AWARDS[v.house] = deepcopy(HOUSE_AWARDS[v.house]) - - for val in AWARDS.values(): val["owned"] = 0 - - 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(): - val["baseprice"] = int(val["price"]) - if val["kind"].endswith('Founder'): - val["baseprice"] = int(val["baseprice"] / 0.75) - val["price"] = int(val["price"] * v.discount) - - sales = g.db.query(func.sum(User.coins_spent)).scalar() - return render_template("shop.html", awards=list(AWARDS.values()), v=v, sales=sales) - - -@app.post("/buy/") -@limiter.limit("100/minute;200/hour;1000/day") -@auth_required -def buy(v, award): - if not FEATURES['AWARDS']: - abort(404) - - if award == 'benefactor' and not request.values.get("mb"): - return {"error": "You can only buy the Benefactor award with marseybux."}, 403 - - if award == 'ghost' and v.admin_level < 2: - return {"error": "Only admins can buy this award."}, 403 - - AWARDS = deepcopy(AWARDS2) - - if v.house: - AWARDS[v.house] = HOUSE_AWARDS[v.house] - - if award not in AWARDS: abort(400) - og_price = AWARDS[award]["price"] - - price = int(og_price * v.discount) - - if request.values.get("mb"): - if award == "grass": - return {"error": "You can't buy the grass award with marseybux."}, 403 - - charged = v.charge_account('procoins', price) - if not charged: - return {"error": "Not enough marseybux."}, 400 - else: - charged = v.charge_account('coins', price) - if not charged: - return {"error": "Not enough coins."}, 400 - - v.coins_spent += price - if v.coins_spent >= 1000000: - badge_grant(badge_id=73, user=v) - elif v.coins_spent >= 500000: - badge_grant(badge_id=72, user=v) - elif v.coins_spent >= 250000: - badge_grant(badge_id=71, user=v) - elif v.coins_spent >= 100000: - badge_grant(badge_id=70, user=v) - elif v.coins_spent >= 10000: - badge_grant(badge_id=69, user=v) - g.db.add(v) - - - if award == "lootbox": - lootbox_items = [] - for i in [1,2,3,4,5]: - award = random.choice(["firework", "confetti", "ricardo", "wholesome", "shit", "fireflies", "scooter", "train"]) - lootbox_items.append(AWARDS[award]['title']) - award = AwardRelationship(user_id=v.id, kind=award) - g.db.add(award) - g.db.flush() - - v.lootboxes_bought += 1 - lootbox_msg = "You open your lootbox and receive: " + ', '.join(lootbox_items) - send_repeatable_notification(v.id, lootbox_msg) - - if v.lootboxes_bought == 10: - badge_grant(badge_id=76, user=v) - elif v.lootboxes_bought == 50: - badge_grant(badge_id=77, user=v) - elif v.lootboxes_bought == 150: - badge_grant(badge_id=78, user=v) - - else: - award_object = AwardRelationship(user_id=v.id, kind=award) - g.db.add(award_object) - - g.db.add(v) - - if CARP_ID and v.id != CARP_ID and og_price >= 10000: - send_repeatable_notification(CARP_ID, f"@{v.username} has bought a `{award}` award!") - - - return {"message": f"{award} award bought!"} - -@app.post("/award//") -@limiter.limit("1/second;30/minute;200/hour;1000/day") -@limiter.limit("1/second;30/minute;200/hour;1000/day", key_func=lambda:f'{SITE}-{session.get("lo_user")}') -@is_not_permabanned -def award_thing(v, thing_type, id): - if not FEATURES['AWARDS']: - abort(404) - - if thing_type == 'post': thing = get_post(id) - else: thing = get_comment(id) - - if not thing: return {"error": f"This {thing_type} doesn't exist."}, 404 - - if v.shadowbanned: return render_template('errors/500.html', err=True, v=v), 500 - - kind = request.values.get("kind", "").strip() - - AWARDS = deepcopy(AWARDS2) - if v.house: - AWARDS[v.house] = HOUSE_AWARDS[v.house] - - if kind not in AWARDS: - return {"error": "This award doesn't exist."}, 404 - - award = g.db.query(AwardRelationship).filter( - AwardRelationship.kind == kind, - AwardRelationship.user_id == v.id, - AwardRelationship.submission_id == None, - AwardRelationship.comment_id == None - ).first() - - if not award: - return {"error": "You don't have that award."}, 404 - - if thing_type == 'post': award.submission_id = thing.id - else: award.comment_id = thing.id - award.awarded_utc = int(time.time()) - - g.db.add(award) - - note = request.values.get("note", "").strip() - - author = thing.author - - if author.id in (PIZZASHILL_ID, DAD_ID) and v.id not in (PIZZASHILL_ID, DAD_ID): - return {"error": "This user is immune to awards."}, 403 - - if kind == "benefactor" and author.id == v.id: - return {"error": "You can't use this award on yourself."}, 400 - - if kind == 'marsify' and author.marsify == 1: - return {"error": "User is already permenantly marsified!"}, 403 - - if v.id != author.id: - if author.deflector and v.deflector: - msg = f"@{v.username} has tried to give your [{thing_type}]({thing.shortlink}) the {AWARDS[kind]['title']} Award but it was deflected on them, they also had a deflector up, so it bounced back and forth until it vaporized!" - send_repeatable_notification(author.id, msg) - - msg = f"@{author.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) - - g.db.delete(award) - - if request.referrer and len(request.referrer) > 1: - if request.referrer == f'{SITE_FULL}/submit': return redirect(thing.permalink) - elif request.referrer.startswith(f'{SITE_FULL}/'): return redirect(request.referrer) - return redirect(SITE_FULL) - - if author.deflector and v.id != AEVANN_ID and (AWARDS[kind]['price'] > 500 or kind == 'marsify' or kind.istitle()) and kind not in ('pin','unpin','benefactor'): - msg = f"@{v.username} has tried to give your [{thing_type}]({thing.shortlink}) the {AWARDS[kind]['title']} Award but it was deflected and applied to them :marseytroll:" - send_repeatable_notification(author.id, msg) - msg = f"@{author.username} is under the effect of a deflector award; your {AWARDS[kind]['title']} Award has been deflected back to you :marseytroll:" - send_repeatable_notification(v.id, msg) - author = v - else: - msg = f"@{v.username} has given your [{thing_type}]({thing.shortlink}) the {AWARDS[kind]['title']} Award!" - if note: msg += f"\n\n> {note}" - send_repeatable_notification(author.id, msg) - - link = f"[this {thing_type}]({thing.shortlink})" - - if kind == "ban": - if not author.is_suspended: - author.ban(reason=f"1-Day ban award used by @{v.username} on /{thing_type}/{thing.id}", days=1) - send_repeatable_notification(author.id, f"Your account has been banned for **a day** for {link}. It sucked and you should feel bad.") - elif author.unban_utc: - author.unban_utc += 86400 - send_repeatable_notification(author.id, f"Your account has been banned for **yet another day** for {link}. Seriously man?") - - if v.admin_level > 2: - log_link = f'/{thing_type}/{thing.id}' - reason = f'{log_link}' - - note = f'reason: "{reason}", duration: for 1 day' - ma=ModAction( - kind="ban_user", - user_id=v.id, - target_user_id=author.id, - _note=note - ) - g.db.add(ma) - elif kind == "unban": - if not author.is_suspended or not author.unban_utc or time.time() > author.unban_utc: abort(403) - - if author.unban_utc - time.time() > 86400: - author.unban_utc -= 86400 - send_repeatable_notification(author.id, "Your ban duration has been reduced by 1 day!") - else: - author.unban_utc = 0 - author.is_banned = 0 - author.ban_evade = 0 - author.ban_reason = None - send_repeatable_notification(author.id, "You have been unbanned!") - - if v.admin_level > 2: - ma=ModAction( - kind="unban_user", - user_id=v.id, - target_user_id=author.id, - ) - g.db.add(ma) - elif kind == "grass": - author.is_banned = AUTOJANNY_ID - author.ban_reason = f"grass award used by @{v.username} on /{thing_type}/{thing.id}" - author.unban_utc = int(time.time()) + 30 * 86400 - send_repeatable_notification(author.id, f"Your account has been banned permanently for {link}. You must [provide the admins](/contact) a timestamped picture of you touching grass/snow/sand/ass to get unbanned!") - - if v.admin_level > 2: - log_link = f'/{thing_type}/{thing.id}' - reason = f'{log_link}' - - note = f'reason: "{reason}", duration: for 30 days' - ma=ModAction( - kind="ban_user", - user_id=v.id, - target_user_id=author.id, - _note=note - ) - g.db.add(ma) - elif kind == "pin": - if not FEATURES['PINS']: - abort(403) - if thing.stickied and thing.stickied_utc: - thing.stickied_utc += 3600 - else: - thing.stickied = f'{v.username} (pin award)' - thing.stickied_utc = int(time.time()) + 3600 - g.db.add(thing) - cache.delete_memoized(frontlist) - elif kind == "unpin": - if not thing.stickied_utc: abort(403) - t = thing.stickied_utc - 3600 - if time.time() > t: - thing.stickied = None - thing.stickied_utc = None - cache.delete_memoized(frontlist) - else: thing.stickied_utc = t - g.db.add(thing) - elif kind == "agendaposter" and not (author.agendaposter and author.agendaposter == 0): - if author.marseyawarded: - return {"error": "This user is the under the effect of a conflicting award: Marsey award."}, 404 - - if author.agendaposter and time.time() < author.agendaposter: author.agendaposter += 86400 - else: author.agendaposter = int(time.time()) + 86400 - - badge_grant(user=author, badge_id=28) - elif kind == "flairlock": - if thing.ghost: abort(403) - new_name = note[:100].replace("𒐪","") - if not new_name and author.flairchanged: - author.flairchanged += 86400 - else: - author.customtitleplain = new_name - new_name = censor_slurs(new_name, None) - author.customtitle = filter_emojis_only(new_name) - if len(author.customtitle) > 1000: abort(403) - author.flairchanged = int(time.time()) + 86400 - badge_grant(user=author, badge_id=96) - elif kind == "pause": - author.mute = True - badge_grant(badge_id=68, user=author) - elif kind == "unpausable": - author.unmutable = True - badge_grant(badge_id=67, user=author) - elif kind == "marsey": - if author.marseyawarded: author.marseyawarded += 86400 - else: author.marseyawarded = int(time.time()) + 86400 - badge_grant(user=author, badge_id=98) - elif kind == "pizzashill": - if author.bird: - return {"error": "This user is the under the effect of a conflicting award: Bird Site award."}, 404 - if author.longpost: author.longpost += 86400 - else: author.longpost = int(time.time()) + 86400 - badge_grant(user=author, badge_id=97) - elif kind == "bird": - if author.longpost: - return {"error": "This user is the under the effect of a conflicting award: Pizzashill award."}, 404 - if author.bird: author.bird += 86400 - else: author.bird = int(time.time()) + 86400 - badge_grant(user=author, badge_id=95) - elif kind == "eye": - author.eye = True - badge_grant(badge_id=83, user=author) - elif kind == "offsitementions": - author.offsitementions = True - badge_grant(user=author, badge_id=140) - elif kind == "alt": - author.alt = True - badge_grant(badge_id=84, user=author) - elif kind == "unblockable": - author.unblockable = True - badge_grant(badge_id=87, user=author) - for block in g.db.query(UserBlock).filter_by(target_id=author.id).all(): g.db.delete(block) - elif kind == "fish": - author.fish = True - badge_grant(badge_id=90, user=author) - elif kind == "progressivestack": - if not FEATURES['PINS']: - abort(403) - if author.progressivestack: author.progressivestack += 21600 - else: author.progressivestack = int(time.time()) + 21600 - badge_grant(user=author, badge_id=94) - elif kind == "benefactor": - if author.patron: return {"error": "This user is already a paypig!"}, 400 - author.patron = 1 - if author.patron_utc: author.patron_utc += 2629746 - else: author.patron_utc = int(time.time()) + 2629746 - author.procoins += 2500 - if author.discord_id: add_role(author, "1") - badge_grant(user=v, badge_id=103) - elif kind == "rehab": - if author.rehab: author.rehab += 86400 - else: author.rehab = int(time.time()) + 86400 - badge_grant(user=author, badge_id=109) - elif kind == "deflector": - if author.deflector: author.deflector += 36000 - else: author.deflector = int(time.time()) + 36000 - elif kind == "beano": - badge_grant(user=author, badge_id=128) - elif kind == "checkmark": - author.verified = "Verified" - badge_grant(user=author, badge_id=150) - elif kind == 'marsify': - if author.marsify: author.marsify += 21600 - else: author.marsify = int(time.time()) + 21600 - badge_grant(user=author, badge_id=170) - - if thing_type == 'comment' and (not author.deflector or v.id == AEVANN_ID): - body = thing.body - if author.owoify: body = owoify(body) - body = marsify(body) - thing.body_html = sanitize(body, limit_pings=5) - g.db.add(thing) - elif "Vampire" in kind and kind == v.house: - if author.bite: author.bite += 86400 - else: author.bite = int(time.time()) + 86400 - - if not author.old_house: - author.old_house = author.house - - if 'Vampire' not in author.house: - author.house = 'Vampire' - - badge_grant(user=author, badge_id=168) - elif "Racist" in kind and kind == v.house: - if author.earlylife: author.earlylife += 86400 - else: author.earlylife = int(time.time()) + 86400 - badge_grant(user=author, badge_id=169) - elif ("Furry" in kind and kind == v.house) or kind == 'owoify': - if author.owoify: author.owoify += 21600 - else: author.owoify = int(time.time()) + 21600 - badge_grant(user=author, badge_id=167) - - if thing_type == 'comment' and not (author.deflector or v.id == AEVANN_ID): - body = thing.body - body = owoify(body) - if author.marsify: body = marsify(body) - thing.body_html = sanitize(body, limit_pings=5) - g.db.add(thing) - elif ("Femboy" in kind and kind == v.house): - if author.rainbow: author.rainbow += 86400 - else: author.rainbow = int(time.time()) + 86400 - badge_grant(user=author, badge_id=171) - - if author.received_award_count: author.received_award_count += 1 - else: author.received_award_count = 1 - g.db.add(author) - - if request.referrer and len(request.referrer) > 1: - if request.referrer == f'{SITE_FULL}/submit': return redirect(thing.permalink) - elif request.referrer.startswith(f'{SITE_FULL}/'): return redirect(request.referrer) - return redirect(SITE_FULL) - - - -@app.get("/admin/awards") -@admin_level_required(2) -def admin_userawards_get(v): - if not FEATURES['AWARDS']: - abort(404) - - if SITE == 'pcmemes.net' and v.admin_level < 3: abort(403) - - if v.admin_level != 3: - return render_template("admin/awards.html", awards=list(AWARDS3.values()), v=v) - - return render_template("admin/awards.html", awards=list(AWARDS.values()), v=v) - -@app.post("/admin/awards") -@limiter.limit("1/second;30/minute;200/hour;1000/day") -@admin_level_required(2) -def admin_userawards_post(v): - if not FEATURES['AWARDS']: - abort(404) - - if SITE == 'pcmemes.net' and v.admin_level < 3: abort(403) - - if SITE == 'watchpeopledie.co' and v.id not in (AEVANN_ID, CARP_ID, SNAKES_ID): abort(403) - - try: u = request.values.get("username").strip() - except: abort(404) - - whitelist = ("shit", "fireflies", "train", "scooter", "wholesome", "tilt", "glowie") - - u = get_user(u, graceful=False, v=v) - - notify_awards = {} - - for key, value in request.values.items(): - if key not in AWARDS: continue - - if v.admin_level < 3 and key not in whitelist: continue - - if value: - - if int(value) > 100 or (int(value) > 10 and v.id != AEVANN_ID): abort(403) - - if int(value): notify_awards[key] = int(value) - - for x in range(int(value)): - award = AwardRelationship( - user_id=u.id, - kind=key, - granted=True - ) - - g.db.add(award) - - if v.id != u.id: - text = f"@{v.username} has given you the following awards:\n\n" - for key, value in notify_awards.items(): - text += f" - **{value}** {AWARDS[key]['title']} {'Awards' if value != 1 else 'Award'}\n" - send_repeatable_notification(u.id, text) - - note = "" - - for key, value in notify_awards.items(): - note += f"{value} {AWARDS[key]['title']}, " - - if len(note) > 500: return {"error": "You're giving too many awards at the same time!"}, 400 - - ma=ModAction( - kind="grant_awards", - user_id=v.id, - target_user_id=u.id, - _note=note[:-2] - ) - g.db.add(ma) - - - if v.admin_level != 3: return render_template("admin/awards.html", awards=list(AWARDS3.values()), v=v, msg=f"Awards granted to @{u.username} successfully!") - return render_template("admin/awards.html", awards=list(AWARDS.values()), v=v, msg=f"Awards granted to @{u.username} successfully!") - +from files.__main__ import app, limiter +from files.helpers.wrappers import * +from files.helpers.alerts import * +from files.helpers.get import * +from files.helpers.const import * +from files.helpers.regex import * +from files.helpers.discord import * +from files.helpers.actions import * +from files.classes.award import * +from .front import frontlist +from flask import g, request +from files.helpers.sanitize import filter_emojis_only +from files.helpers.marsify import marsify +from files.helpers.owoify import owoify +from copy import deepcopy + +@app.get("/shop") +@app.get("/settings/shop") +@auth_required +def shop(v): + if not FEATURES['AWARDS']: + abort(404) + + AWARDS = deepcopy(AWARDS2) + + if v.house: + AWARDS[v.house] = deepcopy(HOUSE_AWARDS[v.house]) + + for val in AWARDS.values(): val["owned"] = 0 + + 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(): + val["baseprice"] = int(val["price"]) + if val["kind"].endswith('Founder'): + val["baseprice"] = int(val["baseprice"] / 0.75) + val["price"] = int(val["price"] * v.discount) + + sales = g.db.query(func.sum(User.coins_spent)).scalar() + return render_template("shop.html", awards=list(AWARDS.values()), v=v, sales=sales) + + +@app.post("/buy/") +@limiter.limit("100/minute;200/hour;1000/day") +@auth_required +def buy(v, award): + if not FEATURES['AWARDS']: + abort(404) + + if award == 'benefactor' and not request.values.get("mb"): + return {"error": "You can only buy the Benefactor award with marseybux."}, 403 + + if award == 'ghost' and v.admin_level < 2: + return {"error": "Only admins can buy this award."}, 403 + + AWARDS = deepcopy(AWARDS2) + + if v.house: + AWARDS[v.house] = HOUSE_AWARDS[v.house] + + if award not in AWARDS: abort(400) + og_price = AWARDS[award]["price"] + + price = int(og_price * v.discount) + + if request.values.get("mb"): + if award == "grass": + return {"error": "You can't buy the grass award with marseybux."}, 403 + + charged = v.charge_account('procoins', price) + if not charged: + return {"error": "Not enough marseybux."}, 400 + else: + charged = v.charge_account('coins', price) + if not charged: + return {"error": "Not enough coins."}, 400 + + v.coins_spent += price + if v.coins_spent >= 1000000: + badge_grant(badge_id=73, user=v) + elif v.coins_spent >= 500000: + badge_grant(badge_id=72, user=v) + elif v.coins_spent >= 250000: + badge_grant(badge_id=71, user=v) + elif v.coins_spent >= 100000: + badge_grant(badge_id=70, user=v) + elif v.coins_spent >= 10000: + badge_grant(badge_id=69, user=v) + g.db.add(v) + + + if award == "lootbox": + lootbox_items = [] + for i in [1,2,3,4,5]: + award = random.choice(["firework", "confetti", "ricardo", "wholesome", "shit", "fireflies", "scooter", "train"]) + lootbox_items.append(AWARDS[award]['title']) + award = AwardRelationship(user_id=v.id, kind=award) + g.db.add(award) + g.db.flush() + + v.lootboxes_bought += 1 + lootbox_msg = "You open your lootbox and receive: " + ', '.join(lootbox_items) + send_repeatable_notification(v.id, lootbox_msg) + + if v.lootboxes_bought == 10: + badge_grant(badge_id=76, user=v) + elif v.lootboxes_bought == 50: + badge_grant(badge_id=77, user=v) + elif v.lootboxes_bought == 150: + badge_grant(badge_id=78, user=v) + + else: + award_object = AwardRelationship(user_id=v.id, kind=award) + g.db.add(award_object) + + g.db.add(v) + + if CARP_ID and v.id != CARP_ID and og_price >= 10000: + send_repeatable_notification(CARP_ID, f"@{v.username} has bought a `{award}` award!") + + + return {"message": f"{award} award bought!"} + +@app.post("/award//") +@limiter.limit("1/second;30/minute;200/hour;1000/day") +@limiter.limit("1/second;30/minute;200/hour;1000/day", key_func=lambda:f'{SITE}-{session.get("lo_user")}') +@is_not_permabanned +def award_thing(v, thing_type, id): + if not FEATURES['AWARDS']: + abort(404) + + if thing_type == 'post': thing = get_post(id) + else: thing = get_comment(id) + + if not thing: return {"error": f"This {thing_type} doesn't exist."}, 404 + + if v.shadowbanned: return render_template('errors/500.html', err=True, v=v), 500 + + kind = request.values.get("kind", "").strip() + + AWARDS = deepcopy(AWARDS2) + if v.house: + AWARDS[v.house] = HOUSE_AWARDS[v.house] + + if kind not in AWARDS: + return {"error": "This award doesn't exist."}, 404 + + award = g.db.query(AwardRelationship).filter( + AwardRelationship.kind == kind, + AwardRelationship.user_id == v.id, + AwardRelationship.submission_id == None, + AwardRelationship.comment_id == None + ).first() + + if not award: + return {"error": "You don't have that award."}, 404 + + if thing_type == 'post': award.submission_id = thing.id + else: award.comment_id = thing.id + award.awarded_utc = int(time.time()) + + g.db.add(award) + + note = request.values.get("note", "").strip() + + author = thing.author + + if author.id in (PIZZASHILL_ID, DAD_ID) and v.id not in (PIZZASHILL_ID, DAD_ID): + return {"error": "This user is immune to awards."}, 403 + + if kind == "benefactor" and author.id == v.id: + return {"error": "You can't use this award on yourself."}, 400 + + if kind == 'marsify' and author.marsify == 1: + return {"error": "User is already permenantly marsified!"}, 403 + + if v.id != author.id: + if author.deflector and v.deflector: + msg = f"@{v.username} has tried to give your [{thing_type}]({thing.shortlink}) the {AWARDS[kind]['title']} Award but it was deflected on them, they also had a deflector up, so it bounced back and forth until it vaporized!" + send_repeatable_notification(author.id, msg) + + msg = f"@{author.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) + + g.db.delete(award) + + if request.referrer and len(request.referrer) > 1: + if request.referrer == f'{SITE_FULL}/submit': return redirect(thing.permalink) + elif request.referrer.startswith(f'{SITE_FULL}/'): return redirect(request.referrer) + return redirect(SITE_FULL) + + if author.deflector and v.id != AEVANN_ID and (AWARDS[kind]['price'] > 500 or kind == 'marsify' or kind.istitle()) and kind not in ('pin','unpin','benefactor'): + msg = f"@{v.username} has tried to give your [{thing_type}]({thing.shortlink}) the {AWARDS[kind]['title']} Award but it was deflected and applied to them :marseytroll:" + send_repeatable_notification(author.id, msg) + msg = f"@{author.username} is under the effect of a deflector award; your {AWARDS[kind]['title']} Award has been deflected back to you :marseytroll:" + send_repeatable_notification(v.id, msg) + author = v + else: + msg = f"@{v.username} has given your [{thing_type}]({thing.shortlink}) the {AWARDS[kind]['title']} Award!" + if note: msg += f"\n\n> {note}" + send_repeatable_notification(author.id, msg) + + link = f"[this {thing_type}]({thing.shortlink})" + + if kind == "ban": + if not author.is_suspended: + author.ban(reason=f"1-Day ban award used by @{v.username} on /{thing_type}/{thing.id}", days=1) + send_repeatable_notification(author.id, f"Your account has been banned for **a day** for {link}. It sucked and you should feel bad.") + elif author.unban_utc: + author.unban_utc += 86400 + send_repeatable_notification(author.id, f"Your account has been banned for **yet another day** for {link}. Seriously man?") + + if v.admin_level > 2: + log_link = f'/{thing_type}/{thing.id}' + reason = f'{log_link}' + + note = f'reason: "{reason}", duration: for 1 day' + ma=ModAction( + kind="ban_user", + user_id=v.id, + target_user_id=author.id, + _note=note + ) + g.db.add(ma) + elif kind == "unban": + if not author.is_suspended or not author.unban_utc or time.time() > author.unban_utc: abort(403) + + if author.unban_utc - time.time() > 86400: + author.unban_utc -= 86400 + send_repeatable_notification(author.id, "Your ban duration has been reduced by 1 day!") + else: + author.unban_utc = 0 + author.is_banned = 0 + author.ban_evade = 0 + author.ban_reason = None + send_repeatable_notification(author.id, "You have been unbanned!") + + if v.admin_level > 2: + ma=ModAction( + kind="unban_user", + user_id=v.id, + target_user_id=author.id, + ) + g.db.add(ma) + elif kind == "grass": + author.is_banned = AUTOJANNY_ID + author.ban_reason = f"grass award used by @{v.username} on /{thing_type}/{thing.id}" + author.unban_utc = int(time.time()) + 30 * 86400 + send_repeatable_notification(author.id, f"Your account has been banned permanently for {link}. You must [provide the admins](/contact) a timestamped picture of you touching grass/snow/sand/ass to get unbanned!") + + if v.admin_level > 2: + log_link = f'/{thing_type}/{thing.id}' + reason = f'{log_link}' + + note = f'reason: "{reason}", duration: for 30 days' + ma=ModAction( + kind="ban_user", + user_id=v.id, + target_user_id=author.id, + _note=note + ) + g.db.add(ma) + elif kind == "pin": + if not FEATURES['PINS']: + abort(403) + if thing.stickied and thing.stickied_utc: + thing.stickied_utc += 3600 + else: + thing.stickied = f'{v.username} (pin award)' + thing.stickied_utc = int(time.time()) + 3600 + g.db.add(thing) + cache.delete_memoized(frontlist) + elif kind == "unpin": + if not thing.stickied_utc: abort(403) + t = thing.stickied_utc - 3600 + if time.time() > t: + thing.stickied = None + thing.stickied_utc = None + cache.delete_memoized(frontlist) + else: thing.stickied_utc = t + g.db.add(thing) + elif kind == "agendaposter" and not (author.agendaposter and author.agendaposter == 0): + if author.marseyawarded: + return {"error": "This user is the under the effect of a conflicting award: Marsey award."}, 404 + + if author.agendaposter and time.time() < author.agendaposter: author.agendaposter += 86400 + else: author.agendaposter = int(time.time()) + 86400 + + badge_grant(user=author, badge_id=28) + elif kind == "flairlock": + if thing.ghost: abort(403) + new_name = note[:100].replace("𒐪","") + if not new_name and author.flairchanged: + author.flairchanged += 86400 + else: + author.customtitleplain = new_name + new_name = censor_slurs(new_name, None) + author.customtitle = filter_emojis_only(new_name) + if len(author.customtitle) > 1000: abort(403) + author.flairchanged = int(time.time()) + 86400 + badge_grant(user=author, badge_id=96) + elif kind == "pause": + author.mute = True + badge_grant(badge_id=68, user=author) + elif kind == "unpausable": + author.unmutable = True + badge_grant(badge_id=67, user=author) + elif kind == "marsey": + if author.marseyawarded: author.marseyawarded += 86400 + else: author.marseyawarded = int(time.time()) + 86400 + badge_grant(user=author, badge_id=98) + elif kind == "pizzashill": + if author.bird: + return {"error": "This user is the under the effect of a conflicting award: Bird Site award."}, 404 + if author.longpost: author.longpost += 86400 + else: author.longpost = int(time.time()) + 86400 + badge_grant(user=author, badge_id=97) + elif kind == "bird": + if author.longpost: + return {"error": "This user is the under the effect of a conflicting award: Pizzashill award."}, 404 + if author.bird: author.bird += 86400 + else: author.bird = int(time.time()) + 86400 + badge_grant(user=author, badge_id=95) + elif kind == "eye": + author.eye = True + badge_grant(badge_id=83, user=author) + elif kind == "offsitementions": + author.offsitementions = True + badge_grant(user=author, badge_id=140) + elif kind == "alt": + author.alt = True + badge_grant(badge_id=84, user=author) + elif kind == "unblockable": + author.unblockable = True + badge_grant(badge_id=87, user=author) + for block in g.db.query(UserBlock).filter_by(target_id=author.id).all(): g.db.delete(block) + elif kind == "fish": + author.fish = True + badge_grant(badge_id=90, user=author) + elif kind == "progressivestack": + if not FEATURES['PINS']: + abort(403) + if author.progressivestack: author.progressivestack += 21600 + else: author.progressivestack = int(time.time()) + 21600 + badge_grant(user=author, badge_id=94) + elif kind == "benefactor": + if author.patron: return {"error": "This user is already a paypig!"}, 400 + author.patron = 1 + if author.patron_utc: author.patron_utc += 2629746 + else: author.patron_utc = int(time.time()) + 2629746 + author.procoins += 2500 + if author.discord_id: add_role(author, "1") + badge_grant(user=v, badge_id=103) + elif kind == "rehab": + if author.rehab: author.rehab += 86400 + else: author.rehab = int(time.time()) + 86400 + badge_grant(user=author, badge_id=109) + elif kind == "deflector": + if author.deflector: author.deflector += 36000 + else: author.deflector = int(time.time()) + 36000 + elif kind == "beano": + badge_grant(user=author, badge_id=128) + elif kind == "checkmark": + author.verified = "Verified" + badge_grant(user=author, badge_id=150) + elif kind == 'marsify': + if author.marsify: author.marsify += 21600 + else: author.marsify = int(time.time()) + 21600 + badge_grant(user=author, badge_id=170) + + if thing_type == 'comment' and (not author.deflector or v.id == AEVANN_ID): + body = thing.body + if author.owoify: body = owoify(body) + body = marsify(body) + thing.body_html = sanitize(body, limit_pings=5) + g.db.add(thing) + elif "Vampire" in kind and kind == v.house: + if author.bite: author.bite += 86400 + else: author.bite = int(time.time()) + 86400 + + if not author.old_house: + author.old_house = author.house + + if 'Vampire' not in author.house: + author.house = 'Vampire' + + badge_grant(user=author, badge_id=168) + elif "Racist" in kind and kind == v.house: + if author.earlylife: author.earlylife += 86400 + else: author.earlylife = int(time.time()) + 86400 + badge_grant(user=author, badge_id=169) + elif ("Furry" in kind and kind == v.house) or kind == 'owoify': + if author.owoify: author.owoify += 21600 + else: author.owoify = int(time.time()) + 21600 + badge_grant(user=author, badge_id=167) + + if thing_type == 'comment' and not (author.deflector or v.id == AEVANN_ID): + body = thing.body + body = owoify(body) + if author.marsify: body = marsify(body) + thing.body_html = sanitize(body, limit_pings=5) + g.db.add(thing) + elif ("Femboy" in kind and kind == v.house): + if author.rainbow: author.rainbow += 86400 + else: author.rainbow = int(time.time()) + 86400 + badge_grant(user=author, badge_id=171) + + if author.received_award_count: author.received_award_count += 1 + else: author.received_award_count = 1 + g.db.add(author) + + if request.referrer and len(request.referrer) > 1: + if request.referrer == f'{SITE_FULL}/submit': return redirect(thing.permalink) + elif request.referrer.startswith(f'{SITE_FULL}/'): return redirect(request.referrer) + return redirect(SITE_FULL) + + + +@app.get("/admin/awards") +@admin_level_required(2) +def admin_userawards_get(v): + if not FEATURES['AWARDS']: + abort(404) + + if SITE == 'pcmemes.net' and v.admin_level < 3: abort(403) + + if v.admin_level != 3: + return render_template("admin/awards.html", awards=list(AWARDS3.values()), v=v) + + return render_template("admin/awards.html", awards=list(AWARDS.values()), v=v) + +@app.post("/admin/awards") +@limiter.limit("1/second;30/minute;200/hour;1000/day") +@admin_level_required(2) +def admin_userawards_post(v): + if not FEATURES['AWARDS']: + abort(404) + + if SITE == 'pcmemes.net' and v.admin_level < 3: abort(403) + + if SITE == 'watchpeopledie.co' and v.id not in (AEVANN_ID, CARP_ID, SNAKES_ID): abort(403) + + try: u = request.values.get("username").strip() + except: abort(404) + + whitelist = ("shit", "fireflies", "train", "scooter", "wholesome", "tilt", "glowie") + + u = get_user(u, graceful=False, v=v) + + notify_awards = {} + + for key, value in request.values.items(): + if key not in AWARDS: continue + + if v.admin_level < 3 and key not in whitelist: continue + + if value: + + if int(value) > 10: abort(403) + + if int(value): notify_awards[key] = int(value) + + for x in range(int(value)): + award = AwardRelationship( + user_id=u.id, + kind=key, + granted=True + ) + + g.db.add(award) + + if v.id != u.id: + text = f"@{v.username} has given you the following awards:\n\n" + for key, value in notify_awards.items(): + text += f" - **{value}** {AWARDS[key]['title']} {'Awards' if value != 1 else 'Award'}\n" + send_repeatable_notification(u.id, text) + + note = "" + + for key, value in notify_awards.items(): + note += f"{value} {AWARDS[key]['title']}, " + + if len(note) > 500: return {"error": "You're giving too many awards at the same time!"}, 400 + + ma=ModAction( + kind="grant_awards", + user_id=v.id, + target_user_id=u.id, + _note=note[:-2] + ) + g.db.add(ma) + + + if v.admin_level != 3: return render_template("admin/awards.html", awards=list(AWARDS3.values()), v=v, msg=f"Awards granted to @{u.username} successfully!") + return render_template("admin/awards.html", awards=list(AWARDS.values()), v=v, msg=f"Awards granted to @{u.username} successfully!") + diff --git a/files/templates/admin/awards.html b/files/templates/admin/awards.html index fe9c4bc2f9..20f740bd20 100644 --- a/files/templates/admin/awards.html +++ b/files/templates/admin/awards.html @@ -53,7 +53,7 @@ {{a['title']}} - + {% endfor %} From bb28d2d2a3f847504551658e1661252ab751fcf7 Mon Sep 17 00:00:00 2001 From: Aevann1 Date: Mon, 19 Sep 2022 19:13:24 +0200 Subject: [PATCH 05/10] delete /order --- files/helpers/const.py | 3 - files/routes/static.py | 31 ----- files/templates/header.html | 10 -- files/templates/order.html | 218 ------------------------------------ 4 files changed, 262 deletions(-) delete mode 100644 files/templates/order.html diff --git a/files/helpers/const.py b/files/helpers/const.py index 560db3530b..b461328b5d 100644 --- a/files/helpers/const.py +++ b/files/helpers/const.py @@ -154,7 +154,6 @@ FEATURES = { 'MARKUP_COMMANDS': True, 'REPOST_DETECTION': True, 'PATRON_ICONS': False, - 'ORDER': False } EMOJI_MARSEYS = True @@ -218,7 +217,6 @@ GIFT_NOTIF_ID = 5 if SITE == 'rdrama.net': FEATURES['PRONOUNS'] = True FEATURES['HOUSES'] = True - FEATURES['ORDER'] = True SIDEBAR_THREAD = 37696 BANNER_THREAD = 37697 @@ -318,7 +316,6 @@ elif SITE == 'watchpeopledie.co': else: # localhost or testing environment implied FEATURES['PRONOUNS'] = True FEATURES['HOUSES'] = True - FEATURES['ORDER'] = True bots = {AUTOJANNY_ID, SNAPPY_ID, LONGPOSTBOT_ID, ZOZBOT_ID, BASEDBOT_ID} diff --git a/files/routes/static.py b/files/routes/static.py index baa70e4a8c..adbe0e6fb2 100644 --- a/files/routes/static.py +++ b/files/routes/static.py @@ -193,37 +193,6 @@ def static_megathread_index(v): def api(v): return render_template("api.html", v=v) - -@app.get("/order") -@auth_desired -def order(v): - if not FEATURES['ORDER']: abort(404) - if v: return redirect("/") - return render_template("order.html", v=v) - -@app.post("/order") -@limiter.limit("1/hour;2/day") -def submit_order(): - if not FEATURES['ORDER']: abort(404) - - body = request.values.get("message") - if not body: abort(400) - - body = 'This message has been sent automatically to all admins via [/order](/order)\n\nMessage:\n\n' + body - body = body.strip() - body_html = sanitize(body) - new_comment = Comment(author_id=AUTOJANNY_ID, parent_submission=None, level=1, body_html=body_html, sentto=2) - g.db.add(new_comment) - g.db.flush() - - new_comment.top_comment_id = new_comment.id - - for admin in g.db.query(User).filter(User.admin_level > 2, User.id != AEVANN_ID).all(): - notif = Notification(comment_id=new_comment.id, user_id=admin.id) - g.db.add(notif) - - return {"success": True} - @app.get("/contact") @app.get("/contactus") @app.get("/contact_us") diff --git a/files/templates/header.html b/files/templates/header.html index 63d53b782e..2dbf48aee7 100644 --- a/files/templates/header.html +++ b/files/templates/header.html @@ -259,11 +259,6 @@ {% else %} - {% if FEATURES['ORDER'] %} -

- {% endif %} @@ -332,11 +327,6 @@ Log out {% else %} - {% if FEATURES['ORDER'] %} - - {% endif %} diff --git a/files/templates/order.html b/files/templates/order.html deleted file mode 100644 index f4fcd6a3b3..0000000000 --- a/files/templates/order.html +++ /dev/null @@ -1,218 +0,0 @@ -{% extends "default.html" %} - -{% block content %} - - -
-

-
Request a quote -
-

- - -
- -
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
- - -
- - -
- - -
- - -
- - -
We respect your privacy. Learn - more.
-
- - - -
- -
-
-

Order Received

-

We will get back to you as quickly as possible with a quote.

-
-
- - - - - - -{% endblock %} \ No newline at end of file From f7727f102923443fdf198b0e7950082c10196ff9 Mon Sep 17 00:00:00 2001 From: Aevann1 Date: Mon, 19 Sep 2022 19:51:40 +0200 Subject: [PATCH 06/10] refactor sigs --- files/classes/comment.py | 2 +- files/classes/submission.py | 3 +-- files/classes/user.py | 13 +++++++++++++ files/helpers/const.py | 2 -- files/helpers/jinja2.py | 2 +- files/routes/settings.py | 2 +- 6 files changed, 17 insertions(+), 7 deletions(-) diff --git a/files/classes/comment.py b/files/classes/comment.py index 4601ad2d13..792379ec26 100644 --- a/files/classes/comment.py +++ b/files/classes/comment.py @@ -383,7 +383,7 @@ class Comment(Base): body += f'''>''' - if self.author.sig_html and (self.author_id == MOOSE_ID or (not self.ghost and not (v and (v.sigs_disabled or v.poor)))): + if not self.ghost and self.author.show_sig(v): body += f"
{self.author.sig_html}" return body diff --git a/files/classes/submission.py b/files/classes/submission.py index f82fec74b1..656840254a 100644 --- a/files/classes/submission.py +++ b/files/classes/submission.py @@ -396,8 +396,7 @@ class Submission(Base): {o.upvotes} votes''' - - if not listing and self.author.sig_html and (self.author_id == MOOSE_ID or (not self.ghost and not (v and (v.sigs_disabled or v.poor)))): + if not listing and not self.ghost and self.author.show_sig(v): body += f"
{self.author.sig_html}" return body diff --git a/files/classes/user.py b/files/classes/user.py index 9931e718a4..406780131b 100644 --- a/files/classes/user.py +++ b/files/classes/user.py @@ -935,3 +935,16 @@ class User(Base): from_casino_value = from_casino or 0 return from_casino_value + self.total_lottery_winnings + + @lazy + def show_sig(self, v): + if not self.author.sig_html: + return False + + if not self.author.patron and SITE_NAME != 'WPD': + return False + + if v and (v.sigs_disabled or v.poor): + return False + + return True \ No newline at end of file diff --git a/files/helpers/const.py b/files/helpers/const.py index b461328b5d..9a8427c35a 100644 --- a/files/helpers/const.py +++ b/files/helpers/const.py @@ -188,7 +188,6 @@ PIZZA_VOTERS = () IDIO_ID = 0 CARP_ID = 0 JOAN_ID = 0 -MOOSE_ID = 0 AEVANN_ID = 0 SNAKES_ID = 0 HOMO_ID = 0 @@ -242,7 +241,6 @@ if SITE == 'rdrama.net': IDIO_ID = 30 CARP_ID = 995 JOAN_ID = 28 - MOOSE_ID = 1904 AEVANN_ID = 1 SNAKES_ID = 10288 HOMO_ID = 147 diff --git a/files/helpers/jinja2.py b/files/helpers/jinja2.py index 719f1c6bab..e6d70e0bf9 100644 --- a/files/helpers/jinja2.py +++ b/files/helpers/jinja2.py @@ -51,7 +51,7 @@ def timestamp(timestamp): def inject_constants(): return {"environ":environ, "SITE":SITE, "SITE_NAME":SITE_NAME, "SITE_FULL":SITE_FULL, "AUTOJANNY_ID":AUTOJANNY_ID, "PUSHER_ID":PUSHER_ID, - "CC":CC, "CC_TITLE":CC_TITLE, "listdir":listdir, "MOOSE_ID":MOOSE_ID, "AEVANN_ID":AEVANN_ID, + "CC":CC, "CC_TITLE":CC_TITLE, "listdir":listdir, "AEVANN_ID":AEVANN_ID, "PIZZASHILL_ID":PIZZASHILL_ID, "DEFAULT_COLOR":DEFAULT_COLOR, "COLORS":COLORS, "time":time, "PERMS":PERMS, "FEATURES":FEATURES, "HOLE_NAME":HOLE_NAME, "HOLE_STYLE_FLAIR":HOLE_STYLE_FLAIR, "HOLE_REQUIRED":HOLE_REQUIRED, diff --git a/files/routes/settings.py b/files/routes/settings.py index cb94d13c59..faae241b16 100644 --- a/files/routes/settings.py +++ b/files/routes/settings.py @@ -129,7 +129,7 @@ def settings_profile_post(v): g.db.add(v) return render_template("settings_profile.html", v=v, msg="Your enemies list has been updated.") - elif (v.patron or v.id == MOOSE_ID) and request.values.get("sig"): + elif v.patron and request.values.get("sig"): sig = request.values.get("sig")[:200].replace('\n','').replace('\r','') sig_html = sanitize(sig) From f54791cc4c49035ff2b27693b114263310f53225 Mon Sep 17 00:00:00 2001 From: Aevann1 Date: Mon, 19 Sep 2022 20:04:30 +0200 Subject: [PATCH 07/10] remove categories --- files/assets/css/main.css | 22 +---- files/assets/js/category_modal.js | 41 ---------- files/assets/js/submit.js | 29 +------ files/classes/__init__.py | 1 - files/classes/category.py | 31 ------- files/classes/mod_logs.py | 5 -- files/classes/submission.py | 2 - files/helpers/const.py | 3 - files/helpers/cron.py | 1 - files/helpers/get.py | 5 -- files/routes/admin.py | 80 ------------------- files/routes/posts.py | 45 ----------- files/routes/static.py | 14 +--- files/templates/admin/admin_home.html | 3 - files/templates/admin/categories.html | 51 ------------ files/templates/category_modal.html | 16 ---- files/templates/comments.html | 3 - files/templates/post_actions.html | 4 - .../templates/post_admin_actions_mobile.html | 4 - files/templates/submission.html | 2 - files/templates/submission_listing.html | 4 - files/templates/submit.html | 7 +- files/templates/util/assetcache.html | 5 +- files/templates/util/helpers.html | 6 +- sql/20220806-post-categories.sql | 10 --- sql/20220912-created_utc-columns.sql | 1 - 26 files changed, 7 insertions(+), 388 deletions(-) delete mode 100644 files/assets/js/category_modal.js delete mode 100644 files/classes/category.py delete mode 100644 files/templates/admin/categories.html delete mode 100644 files/templates/category_modal.html delete mode 100644 sql/20220806-post-categories.sql diff --git a/files/assets/css/main.css b/files/assets/css/main.css index bde466c8ea..2558b0464a 100644 --- a/files/assets/css/main.css +++ b/files/assets/css/main.css @@ -4625,13 +4625,6 @@ span.green { .patron[style="background-color:#FFFFFF;"] { color: black !important; } -.post--category-tag { - padding: 2px 5px 3px 5px; - border-radius: 5px; - font-size: 12px; - font-weight: 700; - margin-right: 0.25rem; -} .container, .container-fluid { background-color: var(--background) !important; } @@ -5684,19 +5677,6 @@ g { border-radius:.35rem; } -.category--tag-button { - display: inline-block; - cursor: pointer; -} - -#submit-categories input { - display: none; -} - -#submit-categories input:checked + label { - border: 5px var(--black) double; -} - /* ------- Font Awesome ------- */ @font-face{ font-family:"Font Awesome 6 Pro"; @@ -6070,7 +6050,7 @@ g { } @media (max-width: 767.98px) { - .pronouns, .patron, .post--category-tag, .mod { + .pronouns, .patron, .mod { padding: 2px 5px !important; } } diff --git a/files/assets/js/category_modal.js b/files/assets/js/category_modal.js deleted file mode 100644 index b5d82acb53..0000000000 --- a/files/assets/js/category_modal.js +++ /dev/null @@ -1,41 +0,0 @@ -function category_modal(id, title, sub) { - document.getElementById("category-modal-title").innerHTML = `Category: ${title}`; - - xhrCategories = new XMLHttpRequest(); - xhrCategories.open("GET", "/categories.json"); - xhrCategories.onload = function () { - let data; - try { - data = JSON.parse(xhrCategories.response); - } catch(e) { console.log(e) } - - categories = [{id: '', name: 'None', sub: sub, color_text: '#000', color_bg: '#FFF'}]; - categories = [].concat(categories, data[sub]); - - document.getElementById("category-modal-body").innerHTML = ''; - categories.forEach(function (c) { - document.getElementById("category-modal-body").innerHTML += - `
` + - `` + - `
`; - }); - - document.querySelectorAll('.category--tag-button').forEach(tag => - tag.addEventListener('click', function (e) { - reqBody = new FormData(); - reqBody.append('formkey', formkey()); - reqBody.append('post_id', id); - reqBody.append('category_id', tag.dataset.category); - - xhrSubmit = new XMLHttpRequest(); - xhrSubmit.open('POST', `/post_recategorize`); - xhrSubmit.onload = function () { - window.location.reload(); - } - xhrSubmit.send(reqBody); - }) - ); - } - xhrCategories.send(); -} diff --git a/files/assets/js/submit.js b/files/assets/js/submit.js index e8845a0910..ef0bc80b35 100644 --- a/files/assets/js/submit.js +++ b/files/assets/js/submit.js @@ -180,32 +180,6 @@ function checkRepost() { } } -function updateCategories() { - if (document.getElementById("submit-categories") == null) { - return; - } - sub = document.getElementById("sub").value; - - xhrCategories = new XMLHttpRequest(); - xhrCategories.open("GET", "/categories.json"); - xhrCategories.onload = function () { - let data; - try { - data = JSON.parse(xhrCategories.response); - } catch(e) { console.log(e) } - - document.getElementById("submit-categories").innerHTML = ''; - data[sub].forEach(function (c) { - document.getElementById("submit-categories").innerHTML += - `` + - ``; - }); - } - xhrCategories.send(); -} - document.addEventListener('keydown', (e) => { if(!((e.ctrlKey || e.metaKey) && e.key === "Enter")) return; @@ -215,5 +189,4 @@ document.addEventListener('keydown', (e) => { submitButton.click(); }); -checkRepost(); -updateCategories(); +checkRepost(); \ No newline at end of file diff --git a/files/classes/__init__.py b/files/classes/__init__.py index 887b1b8e11..7e8f93c054 100644 --- a/files/classes/__init__.py +++ b/files/classes/__init__.py @@ -8,7 +8,6 @@ from .badges import * from .userblock import * from .submission import * from .votes import * -from .category import * from .domains import * from .subscriptions import * from files.__main__ import app diff --git a/files/classes/category.py b/files/classes/category.py deleted file mode 100644 index c601bb1258..0000000000 --- a/files/classes/category.py +++ /dev/null @@ -1,31 +0,0 @@ -from sqlalchemy import * -from sqlalchemy.orm import relationship -from files.__main__ import Base -import time - -class Category(Base): - __tablename__ = "category" - - id = Column(Integer, primary_key=True, nullable=False) - name = Column(String(128), nullable=False) - sub = Column(String(20), ForeignKey("subs.name")) - color_text = Column(String(6)) - color_bg = Column(String(6)) - created_utc = Column(Integer) - - def __init__(self, *args, **kwargs): - if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time()) - super().__init__(*args, **kwargs) - - def __repr__(self): - return f"" - - def as_json(self): - data = { - 'id': self.id, - 'name': self.name, - 'sub': self.sub if self.sub else '', - 'color_text': '#' + self.color_text, - 'color_bg': '#' + self.color_bg, - } - return data diff --git a/files/classes/mod_logs.py b/files/classes/mod_logs.py index 5a7d93385d..def124b883 100644 --- a/files/classes/mod_logs.py +++ b/files/classes/mod_logs.py @@ -314,11 +314,6 @@ ACTIONTYPES = { "icon": 'fa-thumbtack fa-rotate--45', "color": 'bg-success' }, - 'post_recategorize': { - "str": 'changed category of {self.target_link}', - "icon": 'fa-grid', - "color": 'bg-primary' - }, 'purge_cache': { "str": 'purged cache', "icon": 'fa-memory', diff --git a/files/classes/submission.py b/files/classes/submission.py index 656840254a..b6d7dcc9e5 100644 --- a/files/classes/submission.py +++ b/files/classes/submission.py @@ -53,7 +53,6 @@ class Submission(Base): body = Column(String) body_html = Column(String) flair = Column(String) - category_id = Column(Integer, ForeignKey("category.id")) ban_reason = Column(String) embed_url = Column(String) new = Column(Boolean) @@ -67,7 +66,6 @@ class Submission(Base): comments = relationship("Comment", primaryjoin="Comment.parent_submission==Submission.id", back_populates="post") subr = relationship("Sub", primaryjoin="foreign(Submission.sub)==remote(Sub.name)") options = relationship("SubmissionOption", order_by="SubmissionOption.id") - category = relationship("Category", primaryjoin="Submission.category_id==Category.id") bump_utc = deferred(Column(Integer, server_default=FetchedValue())) diff --git a/files/helpers/const.py b/files/helpers/const.py index 9a8427c35a..4dafc7b7f8 100644 --- a/files/helpers/const.py +++ b/files/helpers/const.py @@ -124,8 +124,6 @@ AGENDAPOSTER_MSG_HTML = """

Hi ") -@admin_level_required(PERMS['ADMIN_CATEGORIES_MANAGE']) -def admin_categories_update(v, cid): - if not FEATURES['CATEGORIES']: - abort(404) - - cat_name = request.values.get("name").strip() - cat_color_text = request.values.get("color_text").strip().strip('#').lower() - cat_color_bg = request.values.get("color_bg").strip().strip('#').lower() - - try: - cat_id = int(cid) - except: - abort(400) - - cat = g.db.query(Category).filter(Category.id == cat_id).one_or_none() - if not cat: - abort(400) - - cat.name = cat_name - cat.color_text = cat_color_text - cat.color_bg = cat_color_bg - - g.db.add(cat) - g.db.commit() - - return redirect("/admin/categories") - -@app.post("/admin/categories/delete/") -@admin_level_required(PERMS['ADMIN_CATEGORIES_MANAGE']) -def admin_categories_delete(v, cid): - if not FEATURES['CATEGORIES']: - abort(404) - - try: - cat_id = int(cid) - except: - abort(400) - - cat = g.db.query(Category).filter(Category.id == cat_id).one_or_none() - g.db.delete(cat) - g.db.commit() - - return redirect("/admin/categories") - @app.post("/admin/nuke_user") @limiter.limit("1/second;30/minute;200/hour;1000/day") @admin_level_required(2) diff --git a/files/routes/posts.py b/files/routes/posts.py index 5e75687cd1..1ffa539434 100644 --- a/files/routes/posts.py +++ b/files/routes/posts.py @@ -709,14 +709,6 @@ def submit_post(v, sub=None): if not sub and HOLE_REQUIRED: return error(f"You must choose a {HOLE_NAME} for your post!") - category = None - if FEATURES['CATEGORIES']: - category_id = request.values.get('category', '') - try: - category = int(category_id) - except: - category = None - if v.is_suspended: return error("You can't perform this action while banned.") torture = (v.agendaposter and not v.marseyawarded and sub != 'chudrama') @@ -933,7 +925,6 @@ def submit_post(v, sub=None): title=title[:500], title_html=title_html, sub=sub, - category_id=category, ghost=ghost ) @@ -1168,42 +1159,6 @@ def toggle_post_nsfw(pid, v): if post.over_18: return {"message": "Post has been marked as +18!"} else: return {"message": "Post has been unmarked as +18!"} -@app.post("/post_recategorize") -@auth_required -def post_recategorize(v): - if not FEATURES['CATEGORIES']: - abort(404) - if v.admin_level < PERMS['ADMIN_CATEGORIES_CHANGE']: - abort(403) - - post_id = request.values.get("post_id") - category_id = request.values.get("category_id") - try: - pid = int(post_id) - cid = None - if category_id != '': - cid = int(category_id) - except: - abort(400) - - post = g.db.get(Submission, pid) - post.category_id = cid - g.db.add(post) - - category_new_name = '<none>' - if category_id != '': - category_new_name = g.db.get(Category, cid).name - ma = ModAction( - kind='post_recategorize', - user_id=v.id, - target_submission_id=post.id, - _note=category_new_name - ) - g.db.add(ma) - - g.db.commit() - return {"message": "Success!"} - @app.post("/save_post/") @limiter.limit("1/second;30/minute;200/hour;1000/day") @limiter.limit("1/second;30/minute;200/hour;1000/day", key_func=lambda:f'{SITE}-{session.get("lo_user")}') diff --git a/files/routes/static.py b/files/routes/static.py index adbe0e6fb2..c050d098b6 100644 --- a/files/routes/static.py +++ b/files/routes/static.py @@ -435,16 +435,4 @@ def knowledgebase(v, page): if not os.path.exists('files/templates/' + template_path): abort(404) - return render_template(template_path, v=v) - -@app.get("/categories.json") -def categories_json(): - categories = g.db.query(Category).all() - - data = {} - for c in categories: - sub = c.sub if c.sub else '' - sub_cats = (data[sub] if sub in data else []) + [c.as_json()] - data.update({sub: sub_cats}) - - return jsonify(data) + return render_template(template_path, v=v) \ No newline at end of file diff --git a/files/templates/admin/admin_home.html b/files/templates/admin/admin_home.html index c0466fd1cf..5b22dc091a 100644 --- a/files/templates/admin/admin_home.html +++ b/files/templates/admin/admin_home.html @@ -94,9 +94,6 @@

{% if v.admin_level > 2 %} diff --git a/files/templates/admin/categories.html b/files/templates/admin/categories.html deleted file mode 100644 index e279f581cd..0000000000 --- a/files/templates/admin/categories.html +++ /dev/null @@ -1,51 +0,0 @@ -{% extends "default.html" %} - -{% block title %} - Admin — Categories -{% endblock %} - -{% block content %} -
- - - - - - - - - - - - - {% for category in categories %} - - - - - - - - - - - - - - - - {% endfor %} - - - - - - - - - - - - -
Category{{ HOLE_NAME | capitalize }}NameText ColorBackground ColorActions 
{{help.submission_category_tag(category.name, category.color_text, category.color_bg)}}{{category.sub if category.sub else '—'|safe}}
-{% endblock %} diff --git a/files/templates/category_modal.html b/files/templates/category_modal.html deleted file mode 100644 index 85a91878bb..0000000000 --- a/files/templates/category_modal.html +++ /dev/null @@ -1,16 +0,0 @@ - - - diff --git a/files/templates/comments.html b/files/templates/comments.html index 1bb01ba3a1..6ca2624257 100644 --- a/files/templates/comments.html +++ b/files/templates/comments.html @@ -756,9 +756,6 @@ {% include "emoji_modal.html" %} {% if v.admin_level > 1 %} {% include "ban_modal.html" %} - {% if FEATURES['CATEGORIES'] -%} - {% include "category_modal.html" %} - {%- endif %} {% endif %}