2022-11-15 09:19:08 +00:00
|
|
|
import random
|
|
|
|
from operator import *
|
2022-12-22 20:44:37 +00:00
|
|
|
from typing import Union
|
2023-03-21 22:12:28 +00:00
|
|
|
import re
|
2022-11-15 09:19:08 +00:00
|
|
|
|
2022-09-19 17:10:37 +00:00
|
|
|
import pyotp
|
2023-05-11 13:57:49 +00:00
|
|
|
from sqlalchemy import Column, ForeignKey, FetchedValue
|
2022-12-22 20:03:40 +00:00
|
|
|
from sqlalchemy.orm import aliased, deferred, Query
|
|
|
|
from sqlalchemy.sql import case, func, literal
|
2022-12-11 23:44:34 +00:00
|
|
|
from sqlalchemy.sql.expression import not_, and_, or_
|
2022-11-15 09:19:08 +00:00
|
|
|
from sqlalchemy.sql.sqltypes import *
|
2023-05-26 23:29:34 +00:00
|
|
|
from flask import g, session, request
|
2022-11-15 09:19:08 +00:00
|
|
|
|
|
|
|
from files.classes import Base
|
2022-12-14 19:30:05 +00:00
|
|
|
from files.classes.casino_game import CasinoGame
|
2023-06-24 17:16:24 +00:00
|
|
|
from files.classes.group import GroupMembership
|
2022-11-09 05:35:24 +00:00
|
|
|
from files.classes.sub import Sub
|
2022-12-11 23:44:34 +00:00
|
|
|
from files.helpers.config.const import *
|
2023-01-26 05:39:17 +00:00
|
|
|
from files.helpers.config.modaction_types import *
|
2022-12-11 23:44:34 +00:00
|
|
|
from files.helpers.config.awards import AWARDS_ENABLED, HOUSE_AWARDS
|
2022-11-15 09:19:08 +00:00
|
|
|
from files.helpers.media import *
|
|
|
|
from files.helpers.security import *
|
2022-09-19 17:10:37 +00:00
|
|
|
from files.helpers.sorting_and_time import *
|
2022-11-15 09:19:08 +00:00
|
|
|
|
2022-09-19 17:10:37 +00:00
|
|
|
from .alts import Alt
|
|
|
|
from .award import AwardRelationship
|
|
|
|
from .badges import *
|
|
|
|
from .clients import *
|
|
|
|
from .exiles import *
|
2022-11-15 09:19:08 +00:00
|
|
|
from .follows import *
|
|
|
|
from .hats import *
|
|
|
|
from .mod import *
|
|
|
|
from .mod_logs import *
|
|
|
|
from .notifications import Notification
|
|
|
|
from .saves import *
|
2022-11-15 16:05:42 +00:00
|
|
|
from .sub_relationship import *
|
2022-11-15 09:19:08 +00:00
|
|
|
from .sub_logs import *
|
|
|
|
from .subscriptions import *
|
|
|
|
from .userblock import *
|
2022-09-19 17:10:37 +00:00
|
|
|
|
2022-12-27 02:51:12 +00:00
|
|
|
if SITE == 'devrama.net':
|
2023-03-11 09:30:24 +00:00
|
|
|
DEFAULT_ADMIN_LEVEL = 3
|
2022-12-27 09:33:31 +00:00
|
|
|
DEFAULT_COINS = 100000000
|
|
|
|
DEFAULT_MARSEYBUX = 100000000
|
2022-12-27 02:00:08 +00:00
|
|
|
else:
|
|
|
|
DEFAULT_ADMIN_LEVEL = 0
|
|
|
|
DEFAULT_COINS = 0
|
|
|
|
DEFAULT_MARSEYBUX = 0
|
2022-12-27 01:53:47 +00:00
|
|
|
|
2023-03-08 06:51:40 +00:00
|
|
|
if IS_FISTMAS():
|
2023-01-01 05:33:09 +00:00
|
|
|
if SITE_NAME == 'rDrama':
|
|
|
|
default_event_music = True
|
|
|
|
default_darkmode = False
|
|
|
|
else:
|
|
|
|
default_event_music = False
|
|
|
|
default_darkmode = True
|
|
|
|
|
|
|
|
|
2022-09-19 17:10:37 +00:00
|
|
|
class User(Base):
|
|
|
|
__tablename__ = "users"
|
|
|
|
|
|
|
|
id = Column(Integer, primary_key=True)
|
|
|
|
username = Column(String)
|
|
|
|
namecolor = Column(String, default=DEFAULT_COLOR)
|
|
|
|
background = Column(String)
|
2022-12-05 04:16:45 +00:00
|
|
|
profile_background = Column(String)
|
2022-09-19 17:10:37 +00:00
|
|
|
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)
|
|
|
|
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)
|
2023-05-13 02:00:54 +00:00
|
|
|
marseyawarded = Column(Integer, default=0)
|
|
|
|
rehab = Column(Integer, default=0)
|
|
|
|
longpost = Column(Integer, default=0)
|
|
|
|
bird = Column(Integer, default=0)
|
2022-09-19 17:10:37 +00:00
|
|
|
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)
|
2022-09-19 20:40:33 +00:00
|
|
|
created_utc = Column(Integer)
|
2022-12-27 01:53:47 +00:00
|
|
|
admin_level = Column(Integer, default=DEFAULT_ADMIN_LEVEL)
|
2022-09-19 17:10:37 +00:00
|
|
|
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)
|
2023-06-23 11:07:47 +00:00
|
|
|
chud = Column(Integer, default=0)
|
Add the "Misogynist" award to harass incels (#154)
Whazzup? This PR is the final solution to the incel problem. There's an old indian proverb that says: "never judge a man until you've walked two moons in his mocassins". In this case, it should be: "never judge a woman until you've walked 24 hrs in her high-heels".
The misogynist award is a comment-transforming award that "feminizes" comments. It does the following:
- makes text pink
- makes text lowercase
- removes "complicated" punctuation
- makes paragraphs into run-on sentences
- adds stereotypical girly remarks to the beginning or end of a paragraph.
For example:
INPUT
> What the fuck did you just fucking say about me, you little bitch? I'll have you know I graduated top of my class in the Navy Seals, and I've been involved in numerous secret raids on Al-Quaeda, and I have over 300 confirmed kills. I am trained in gorilla warfare and I'm the top sniper in the entire US armed forces. You are nothing to me but just another target. I will wipe you the fuck out with precision the likes of which has never been seen before on this Earth, mark my fucking words. You think you can get away with saying that shit to me over the Internet? Think again, fucker. As we speak I am contacting my secret network of spies across the USA and your IP is being traced right now so you better prepare for the storm, maggot. The storm that wipes out the pathetic little thing you call your life. You're fucking dead, kid. I can be anywhere, anytime, and I can kill you in over seven hundred ways, and that's just with my bare hands. Not only am I extensively trained in unarmed combat, but I have access to the entire arsenal of the United States Marine Corps and I will use it to its full extent to wipe your miserable ass off the face of the continent, you little shit. If only you could have known what unholy retribution your little "clever" comment was about to bring down upon you, maybe you would have held your fucking tongue. But you couldn't, you didn't, and now you're paying the price, you goddamn idiot. I will shit fury all over you and you will drown in it. You're fucking dead, kiddo.
OUTPUT
> im literally screaming, what the fuck did you just fucking say about me, you little bitch? ill have you know i graduated top of my class in the navy seals, and ive been involved in numerous secret raids on al-quaeda, and i have over 300 confirmed kills, i am trained in gorilla warfare and im the top sniper in the entire us armed forces, you are nothing to me but just another target, i will wipe you the fuck out with precision the likes of which has never been seen before on this earth, mark my fucking words, you think you can get away with saying that shit to me over the internet? think again, fucker, as we speak i am contacting my secret network of spies across the usa and your ip is being traced right now so you better prepare for the storm, maggot, the storm that wipes out the pathetic little thing you call your life, youre fucking dead, kid, i can be anywhere, anytime, and i can kill you in over seven hundred ways, and thats just with my bare hands, not only am i extensively trained in unarmed combat, but i have access to the entire arsenal of the united states marine corps and i will use it to its full extent to wipe your miserable ass off the face of the continent, you little shit, if only you could have known what unholy retribution your little clever comment was about to bring down upon you, maybe you would have held your fucking tongue, but you couldnt, you didnt, and now youre paying the price, you goddamn idiot, i will shit fury all over you and you will drown in it, youre fucking dead, kiddo
It also sets the user's pfp to a random white woman. Well, psuedorandom - it's based off of the user's id, so each user will only ever have one pfp assigned to them, which I think is nifty.
Finally, it changes the name of the user toa girly name.
There is one small problem with the PR, which is simply that I manually added a badge for testing purposes. If you like this PR, I will submit the badge throught the proper chanels and fix it.
![image](/attachments/641c7276-ffe4-4e69-b3e9-aec9f4f94191)
Co-authored-by: Chuck Sneed <sneed@formerlychucks.net>
Reviewed-on: https://fsdfsd.net/rDrama/rDrama/pulls/154
Co-authored-by: HeyMoon <heymoon@noreply.fsdfsd.net>
Co-committed-by: HeyMoon <heymoon@noreply.fsdfsd.net>
2023-06-21 12:36:07 +00:00
|
|
|
queen = Column(Integer, default=0)
|
2023-06-23 11:07:47 +00:00
|
|
|
chud_phrase = Column(String)
|
2022-09-19 17:10:37 +00:00
|
|
|
is_activated = Column(Boolean, default=False)
|
2022-12-26 02:38:32 +00:00
|
|
|
shadowbanned = Column(Integer, ForeignKey("users.id"))
|
|
|
|
chudded_by = Column(Integer, ForeignKey("users.id"))
|
2022-09-19 17:10:37 +00:00
|
|
|
over_18 = Column(Boolean, default=False)
|
2023-03-15 06:03:11 +00:00
|
|
|
hidevotedon = Column(Boolean, default=False)
|
2022-11-06 22:58:14 +00:00
|
|
|
slurreplacer = Column(Integer, default=1)
|
|
|
|
profanityreplacer = Column(Integer, default=1)
|
2023-05-13 02:00:54 +00:00
|
|
|
flairchanged = Column(Integer, default=0)
|
2023-05-13 04:53:14 +00:00
|
|
|
namechanged = Column(Integer, default=0)
|
2022-11-21 16:55:09 +00:00
|
|
|
newtab = Column(Boolean, default=False)
|
2022-09-19 17:10:37 +00:00
|
|
|
newtabexternal = Column(Boolean, default=True)
|
|
|
|
reddit = Column(String, default='old.reddit.com')
|
|
|
|
nitter = Column(Boolean)
|
|
|
|
imginn = Column(Boolean)
|
|
|
|
frontsize = Column(Integer, default=25)
|
2023-05-07 19:03:29 +00:00
|
|
|
controversial = Column(Boolean, default=False)
|
2022-09-19 17:10:37 +00:00
|
|
|
bio = deferred(Column(String))
|
|
|
|
bio_html = Column(String)
|
|
|
|
sig = deferred(Column(String))
|
|
|
|
sig_html = Column(String)
|
|
|
|
fp = Column(String)
|
|
|
|
sigs_disabled = Column(Boolean)
|
2023-05-13 02:00:54 +00:00
|
|
|
progressivestack = Column(Integer, default=0)
|
|
|
|
deflector = Column(Integer, default=0)
|
2022-09-19 17:10:37 +00:00
|
|
|
friends = deferred(Column(String))
|
|
|
|
friends_html = deferred(Column(String))
|
|
|
|
enemies = deferred(Column(String))
|
|
|
|
enemies_html = deferred(Column(String))
|
2022-12-13 22:02:53 +00:00
|
|
|
is_banned = Column(Integer, ForeignKey("users.id"))
|
2022-09-19 17:10:37 +00:00
|
|
|
unban_utc = Column(Integer, default=0)
|
|
|
|
ban_reason = deferred(Column(String))
|
|
|
|
is_muted = Column(Boolean, default=False, nullable=False)
|
|
|
|
login_nonce = Column(Integer, default=0)
|
2022-12-27 02:00:08 +00:00
|
|
|
coins = Column(Integer, default=DEFAULT_COINS)
|
2022-11-07 07:03:58 +00:00
|
|
|
truescore = Column(Integer, default=0)
|
2022-12-27 02:00:08 +00:00
|
|
|
marseybux = Column(Integer, default=DEFAULT_MARSEYBUX)
|
2022-09-19 17:10:37 +00:00
|
|
|
mfa_secret = deferred(Column(String))
|
|
|
|
is_private = Column(Boolean, default=False)
|
|
|
|
stored_subscriber_count = Column(Integer, default=0)
|
2022-10-11 16:41:09 +00:00
|
|
|
defaultsortingcomments = Column(String, default="hot")
|
2022-09-19 17:10:37 +00:00
|
|
|
defaultsorting = Column(String, default="hot")
|
|
|
|
defaulttime = Column(String, default=DEFAULT_TIME_FILTER)
|
|
|
|
custom_filter_list = Column(String)
|
|
|
|
original_username = Column(String)
|
2023-05-13 04:53:14 +00:00
|
|
|
prelock_username = Column(String)
|
2022-09-19 17:10:37 +00:00
|
|
|
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)
|
2022-09-19 20:40:33 +00:00
|
|
|
last_viewed_post_notifs = Column(Integer, default=0)
|
|
|
|
last_viewed_log_notifs = Column(Integer, default=0)
|
2022-11-30 22:29:13 +00:00
|
|
|
last_viewed_reddit_notifs = Column(Integer, default=0)
|
2022-09-19 17:10:37 +00:00
|
|
|
pronouns = Column(String, default='they/them')
|
2023-05-13 02:00:54 +00:00
|
|
|
bite = Column(Integer, default=0)
|
|
|
|
earlylife = Column(Integer, default=0)
|
|
|
|
owoify = Column(Integer, default=0)
|
2023-06-26 14:38:48 +00:00
|
|
|
sharpen = Column(Integer, default=0)
|
2022-09-19 17:10:37 +00:00
|
|
|
marsify = Column(Integer, default=0)
|
2023-05-13 02:00:54 +00:00
|
|
|
rainbow = Column(Integer, default=0)
|
2022-09-25 02:47:05 +00:00
|
|
|
spider = Column(Integer, default=0)
|
2023-01-25 15:41:46 +00:00
|
|
|
blacklisted_by = Column(Integer, ForeignKey("users.id"))
|
2023-01-01 05:33:09 +00:00
|
|
|
|
2023-03-08 06:51:40 +00:00
|
|
|
if IS_FISTMAS():
|
2023-04-27 15:30:25 +00:00
|
|
|
#TODO: make event_music a cookie toggle instead
|
2023-01-01 05:33:09 +00:00
|
|
|
event_music = Column(Boolean, default=default_event_music, nullable=False)
|
|
|
|
event_darkmode = Column(Boolean, default=default_darkmode, nullable=False)
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
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")
|
|
|
|
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")
|
2022-12-13 22:05:34 +00:00
|
|
|
referrals = relationship("User", primaryjoin="User.id==User.referred_by")
|
2022-09-19 17:10:37 +00:00
|
|
|
designed_hats = relationship("HatDef", primaryjoin="User.id==HatDef.author_id", back_populates="author")
|
|
|
|
owned_hats = relationship("Hat", back_populates="owners")
|
2022-11-09 15:32:14 +00:00
|
|
|
hats_equipped = relationship("Hat", lazy="raise", viewonly=True)
|
2022-11-09 14:16:22 +00:00
|
|
|
sub_mods = relationship("Mod", primaryjoin="User.id == Mod.user_id", lazy="raise")
|
|
|
|
sub_exiles = relationship("Exile", primaryjoin="User.id == Exile.user_id", lazy="raise")
|
|
|
|
|
2023-05-11 14:03:51 +00:00
|
|
|
lifetimedonated = deferred(Column(Integer, server_default=FetchedValue()))
|
2023-05-11 13:57:49 +00:00
|
|
|
|
2022-09-19 17:10:37 +00:00
|
|
|
def __init__(self, **kwargs):
|
|
|
|
|
|
|
|
if "password" in kwargs:
|
2022-10-06 22:59:50 +00:00
|
|
|
kwargs["passhash"] = hash_password(kwargs["password"])
|
2022-09-19 17:10:37 +00:00
|
|
|
kwargs.pop("password")
|
|
|
|
|
2022-09-19 20:40:33 +00:00
|
|
|
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"]
|
|
|
|
|
2022-09-19 17:10:37 +00:00
|
|
|
super().__init__(**kwargs)
|
|
|
|
|
|
|
|
|
|
|
|
def __repr__(self):
|
2022-11-29 21:02:38 +00:00
|
|
|
return f"<{self.__class__.__name__}(id={self.id}, username={self.username})>"
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
def pay_account(self, currency, amount):
|
2023-05-04 22:48:54 +00:00
|
|
|
if SITE == 'watchpeopledie.tv' and self.id == 5222:
|
|
|
|
return
|
|
|
|
|
2022-09-19 17:10:37 +00:00
|
|
|
if currency == 'coins':
|
2023-06-26 15:16:19 +00:00
|
|
|
g.db.query(User).filter(User.id == self.id).update({ User.coins: User.coins + amount })
|
2022-09-19 17:10:37 +00:00
|
|
|
else:
|
2023-06-26 15:16:19 +00:00
|
|
|
g.db.query(User).filter(User.id == self.id).update({ User.marseybux: User.marseybux + amount })
|
2022-09-19 17:10:37 +00:00
|
|
|
|
2023-03-16 06:27:58 +00:00
|
|
|
g.db.flush()
|
2023-01-01 11:36:20 +00:00
|
|
|
|
2022-09-19 17:10:37 +00:00
|
|
|
|
2022-11-01 17:50:01 +00:00
|
|
|
def charge_account(self, currency, amount, **kwargs):
|
2023-03-16 06:27:58 +00:00
|
|
|
in_db = g.db.query(User).filter(User.id == self.id).with_for_update().one()
|
2022-09-19 17:10:37 +00:00
|
|
|
succeeded = False
|
2023-04-24 15:08:40 +00:00
|
|
|
charged_coins = 0
|
2022-09-19 17:10:37 +00:00
|
|
|
|
2022-11-01 17:50:01 +00:00
|
|
|
should_check_balance = kwargs.get('should_check_balance', True)
|
|
|
|
|
2022-09-19 17:10:37 +00:00
|
|
|
if currency == 'coins':
|
|
|
|
account_balance = in_db.coins
|
2023-01-01 11:36:20 +00:00
|
|
|
|
2022-11-01 17:50:01 +00:00
|
|
|
if not should_check_balance or account_balance >= amount:
|
2023-06-26 15:16:19 +00:00
|
|
|
g.db.query(User).filter(User.id == self.id).update({ User.coins: User.coins - amount })
|
2022-09-19 17:10:37 +00:00
|
|
|
succeeded = True
|
2023-04-24 15:08:40 +00:00
|
|
|
charged_coins = amount
|
2022-11-21 23:08:29 +00:00
|
|
|
elif currency == 'marseybux':
|
|
|
|
account_balance = in_db.marseybux
|
2023-01-01 11:36:20 +00:00
|
|
|
|
2022-11-01 17:50:01 +00:00
|
|
|
if not should_check_balance or account_balance >= amount:
|
2023-06-26 15:16:19 +00:00
|
|
|
g.db.query(User).filter(User.id == self.id).update({ User.marseybux: User.marseybux - amount })
|
2022-09-19 17:10:37 +00:00
|
|
|
succeeded = True
|
2023-03-07 05:06:17 +00:00
|
|
|
elif currency == 'combined':
|
2023-03-07 13:20:46 +00:00
|
|
|
if in_db.marseybux >= amount:
|
|
|
|
subtracted_mbux = amount
|
|
|
|
subtracted_coins = 0
|
|
|
|
else:
|
|
|
|
subtracted_mbux = in_db.marseybux
|
|
|
|
subtracted_coins = amount - subtracted_mbux
|
|
|
|
if subtracted_coins > in_db.coins:
|
2023-04-24 15:08:40 +00:00
|
|
|
return (False, 0)
|
2023-03-07 05:06:17 +00:00
|
|
|
|
2023-06-26 15:16:19 +00:00
|
|
|
g.db.query(User).filter(User.id == self.id).update({
|
|
|
|
User.marseybux: User.marseybux - subtracted_mbux,
|
|
|
|
User.coins: User.coins - subtracted_coins,
|
|
|
|
})
|
2023-03-07 05:06:17 +00:00
|
|
|
succeeded = True
|
2023-04-24 15:08:40 +00:00
|
|
|
charged_coins = subtracted_coins
|
2022-09-19 17:10:37 +00:00
|
|
|
|
2023-03-04 18:32:55 +00:00
|
|
|
if succeeded:
|
2023-03-16 06:27:58 +00:00
|
|
|
g.db.add(self)
|
|
|
|
g.db.flush()
|
2023-01-01 11:36:20 +00:00
|
|
|
|
2023-04-24 15:08:40 +00:00
|
|
|
return (succeeded, charged_coins)
|
2022-09-19 17:10:37 +00:00
|
|
|
|
2023-05-11 14:03:51 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def lifetime_donated(self):
|
|
|
|
return self.lifetimedonated or 0
|
|
|
|
|
2023-05-03 17:26:44 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def num_of_bought_awards(self):
|
|
|
|
return g.db.query(AwardRelationship).filter_by(user_id=self.id).count()
|
|
|
|
|
2022-09-19 17:10:37 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def num_of_owned_hats(self):
|
|
|
|
return len(self.owned_hats)
|
|
|
|
|
2022-10-08 20:30:27 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def hats_owned_proportion_display(self):
|
2023-03-16 06:27:58 +00:00
|
|
|
total_num_of_hats = g.db.query(HatDef).filter(HatDef.submitter_id == None, HatDef.price > 0).count()
|
2022-10-08 20:30:27 +00:00
|
|
|
proportion = f'{float(self.num_of_owned_hats) / total_num_of_hats:.1%}'
|
|
|
|
return (proportion, total_num_of_hats)
|
|
|
|
|
2022-09-19 17:10:37 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def num_of_designed_hats(self):
|
|
|
|
return len(self.designed_hats)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def equipped_hats(self):
|
2022-11-09 15:32:14 +00:00
|
|
|
try:
|
|
|
|
return self.hats_equipped
|
|
|
|
except:
|
2023-03-16 06:27:58 +00:00
|
|
|
return g.db.query(Hat).filter_by(user_id=self.id, equipped=True).all()
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
@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
|
|
|
|
|
2022-09-19 18:52:50 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def forced_hat(self):
|
|
|
|
user_forced_hats = []
|
|
|
|
for k, val in forced_hats.items():
|
2022-12-05 00:44:58 +00:00
|
|
|
if getattr(self, k) and getattr(self, k) > 1:
|
2023-06-23 11:07:47 +00:00
|
|
|
if k == 'chud':
|
2022-11-26 20:14:31 +00:00
|
|
|
user_forced_hats.append(random.choice(val))
|
|
|
|
else:
|
|
|
|
user_forced_hats.append(val)
|
2022-09-19 18:52:50 +00:00
|
|
|
if user_forced_hats: return random.choice(user_forced_hats)
|
|
|
|
else: return None
|
|
|
|
|
2023-06-23 11:37:22 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def new_user(self):
|
|
|
|
return self.age < NEW_USER_AGE
|
|
|
|
|
2022-09-19 17:10:37 +00:00
|
|
|
@lazy
|
2022-12-24 22:21:49 +00:00
|
|
|
def hat_active(self, v):
|
|
|
|
if FEATURES['HATS']:
|
2023-03-08 06:51:40 +00:00
|
|
|
if IS_FISTMAS():
|
2023-01-01 05:33:09 +00:00
|
|
|
hat = random.choice(('Santa Hat III', 'Winter Cap', 'Present Bow'))
|
|
|
|
if SITE_NAME == 'rDrama':
|
2023-03-19 16:28:19 +00:00
|
|
|
return (f'{SITE_FULL_IMAGES}/i/hats/{hat}.webp', 'Merry Fistmas!')
|
2023-01-01 05:33:09 +00:00
|
|
|
else:
|
2023-03-19 16:28:19 +00:00
|
|
|
return (f'{SITE_FULL_IMAGES}/i/hats/{hat}.webp', 'Merry Christmas!')
|
2022-09-19 17:10:37 +00:00
|
|
|
|
2022-12-24 22:21:49 +00:00
|
|
|
if self.is_cakeday:
|
|
|
|
return ('/i/hats/Cakeday.webp', "I've spent another year rotting my brain with dramaposting, please ridicule me 🤓")
|
2022-12-19 01:20:14 +00:00
|
|
|
|
2023-06-23 11:37:22 +00:00
|
|
|
if self.new_user:
|
2022-12-24 22:21:49 +00:00
|
|
|
return ('/i/new-user.webp', "Hi, I'm new here! Please be gentle :)")
|
2022-09-19 17:10:37 +00:00
|
|
|
|
2022-12-24 22:21:49 +00:00
|
|
|
if self.forced_hat:
|
2023-03-19 16:28:19 +00:00
|
|
|
return (f'{SITE_FULL_IMAGES}/i/hats/{self.forced_hat[0]}.webp', self.forced_hat[1])
|
2022-11-19 22:18:13 +00:00
|
|
|
|
2022-12-24 22:21:49 +00:00
|
|
|
if self.equipped_hat:
|
2023-03-19 16:28:19 +00:00
|
|
|
return (f'{SITE_FULL_IMAGES}/i/hats/{self.equipped_hat.name}.webp', self.equipped_hat.name + ' - ' + self.equipped_hat.censored_description(v))
|
2022-09-19 18:52:50 +00:00
|
|
|
|
2022-12-24 22:21:49 +00:00
|
|
|
return ('', '')
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
|
2023-06-23 11:37:22 +00:00
|
|
|
@lazy
|
|
|
|
def immune_to_awards(self, v):
|
|
|
|
if SITE_NAME != 'rDrama':
|
|
|
|
return False
|
|
|
|
if v.id == self.id:
|
|
|
|
return False
|
|
|
|
if v.admin_level >= PERMS['IGNORE_AWARD_IMMUNITY']:
|
|
|
|
return False
|
|
|
|
if self.alts:
|
|
|
|
return False
|
|
|
|
if self.id in IMMUNE_TO_AWARDS:
|
|
|
|
return True
|
|
|
|
if self.new_user:
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
|
2022-09-19 17:10:37 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def name_color(self):
|
|
|
|
if self.bite: return "565656"
|
|
|
|
return self.namecolor
|
|
|
|
|
2022-10-12 06:47:47 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def is_votes_real(self):
|
2022-11-12 12:11:28 +00:00
|
|
|
if self.patron: return True
|
2023-06-29 19:51:32 +00:00
|
|
|
if self.is_permabanned or self.shadowbanned: return False
|
2023-06-23 11:07:47 +00:00
|
|
|
if self.chud: return False
|
2022-10-12 06:47:47 +00:00
|
|
|
if self.profile_url.startswith('/e/') and not self.customtitle and self.namecolor == DEFAULT_COLOR: return False
|
|
|
|
return True
|
2022-11-12 12:11:44 +00:00
|
|
|
|
2022-09-19 17:10:37 +00:00
|
|
|
@lazy
|
|
|
|
def mods(self, sub):
|
2023-06-29 19:51:32 +00:00
|
|
|
if self.is_permabanned or self.shadowbanned: return False
|
2023-01-22 08:04:49 +00:00
|
|
|
if self.admin_level >= PERMS['MODS_EVERY_HOLE']: return True
|
2022-11-09 14:16:22 +00:00
|
|
|
try:
|
|
|
|
return any(map(lambda x: x.sub == sub, self.sub_mods))
|
|
|
|
except:
|
2023-03-16 06:27:58 +00:00
|
|
|
return bool(g.db.query(Mod.user_id).filter_by(user_id=self.id, sub=sub).one_or_none())
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
@lazy
|
|
|
|
def exiled_from(self, sub):
|
2022-11-09 14:16:22 +00:00
|
|
|
try:
|
|
|
|
return any(map(lambda x: x.sub == sub, self.sub_exiles))
|
|
|
|
except:
|
2023-03-16 06:27:58 +00:00
|
|
|
return bool(g.db.query(Exile.user_id).filter_by(user_id=self.id, sub=sub).one_or_none())
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
2023-06-29 20:52:07 +00:00
|
|
|
def sub_blocks(self):
|
2023-03-16 06:27:58 +00:00
|
|
|
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()])
|
2023-06-23 11:07:47 +00:00
|
|
|
if self.chud == 1: stealth = stealth - {'chudrama'}
|
2022-09-19 17:10:37 +00:00
|
|
|
|
2023-03-25 23:31:24 +00:00
|
|
|
return list(stealth) + [x[0] for x in g.db.query(SubBlock.sub).filter_by(user_id=self.id).all()]
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
@lazy
|
|
|
|
def blocks(self, sub):
|
2023-03-16 06:27:58 +00:00
|
|
|
return g.db.query(SubBlock).filter_by(user_id=self.id, sub=sub).one_or_none()
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
@lazy
|
|
|
|
def subscribes(self, sub):
|
2023-03-16 06:27:58 +00:00
|
|
|
return g.db.query(SubJoin).filter_by(user_id=self.id, sub=sub).one_or_none()
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def all_follows(self):
|
2023-03-16 06:27:58 +00:00
|
|
|
return [x[0] for x in g.db.query(SubSubscription.sub).filter_by(user_id=self.id).all()]
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
@lazy
|
|
|
|
def follows(self, sub):
|
2023-03-16 06:27:58 +00:00
|
|
|
return g.db.query(SubSubscription).filter_by(user_id=self.id, sub=sub).one_or_none()
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
@lazy
|
|
|
|
def mod_date(self, sub):
|
2023-03-06 18:07:55 +00:00
|
|
|
if self.admin_level >= PERMS['MODS_EVERY_HOLE']: return 1
|
2023-03-06 18:06:01 +00:00
|
|
|
|
2023-03-16 06:27:58 +00:00
|
|
|
mod_ts = g.db.query(Mod.created_utc).filter_by(user_id=self.id, sub=sub).one_or_none()
|
2022-11-04 00:09:51 +00:00
|
|
|
if mod_ts is None:
|
|
|
|
return None
|
|
|
|
return mod_ts[0]
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
@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"
|
2022-11-29 20:29:27 +00:00
|
|
|
return time.strftime("%d %b %Y", time.gmtime(self.last_active))
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
@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())
|
2023-05-09 21:48:14 +00:00
|
|
|
if date == now:
|
|
|
|
return True
|
|
|
|
return False
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def discount(self):
|
2023-05-03 15:29:31 +00:00
|
|
|
if self.patron in {1,2}: discount = 0.90
|
|
|
|
elif self.patron == 3: discount = 0.85
|
|
|
|
elif self.patron == 4: discount = 0.80
|
|
|
|
elif self.patron == 5: discount = 0.75
|
|
|
|
elif self.patron == 6: discount = 0.70
|
|
|
|
elif self.patron == 7: discount = 0.65
|
|
|
|
elif self.patron == 8: discount = 0.60
|
2022-09-19 17:10:37 +00:00
|
|
|
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
|
2023-01-01 11:36:20 +00:00
|
|
|
|
2023-05-14 00:01:00 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def formatted_discount(self):
|
|
|
|
discount = 100 - int(self.discount * 100)
|
2023-05-14 15:59:30 +00:00
|
|
|
return f'{discount}%'
|
2023-05-14 00:01:00 +00:00
|
|
|
|
2022-09-19 17:10:37 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def can_view_offsitementions(self):
|
2022-11-30 00:40:35 +00:00
|
|
|
return self.offsitementions or self.admin_level >= PERMS['NOTIFICATIONS_REDDIT']
|
2022-09-19 17:10:37 +00:00
|
|
|
|
2022-12-01 22:04:10 +00:00
|
|
|
@lazy
|
2023-06-07 23:26:32 +00:00
|
|
|
def can_edit(self, target:Union[Post, Comment]) -> bool:
|
2022-12-01 22:04:10 +00:00
|
|
|
if isinstance(target, Comment) and not target.post: return False
|
|
|
|
if self.id == target.author_id: return True
|
2023-06-07 23:26:32 +00:00
|
|
|
if not isinstance(target, Post): return False
|
2022-12-01 22:04:10 +00:00
|
|
|
return bool(self.admin_level >= PERMS['POST_EDITING'])
|
|
|
|
|
2022-09-19 17:10:37 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def user_awards(self):
|
2022-12-11 23:44:34 +00:00
|
|
|
return_value = list(AWARDS_ENABLED.values())
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
if self.house:
|
|
|
|
return_value.append(HOUSE_AWARDS[self.house])
|
|
|
|
|
2023-03-16 06:27:58 +00:00
|
|
|
awards_owned = g.db.query(AwardRelationship.kind, func.count()) \
|
2023-06-07 23:26:32 +00:00
|
|
|
.filter_by(user_id=self.id, post_id=None, comment_id=None) \
|
2022-09-19 17:10:37 +00:00
|
|
|
.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
|
|
|
|
|
2023-02-25 19:40:15 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def awards_content_effect(self):
|
|
|
|
return [x for x in self.user_awards if not x['deflectable'] and x['kind'] != 'benefactor']
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def awards_author_effect(self):
|
|
|
|
return [x for x in self.user_awards if x not in self.awards_content_effect]
|
|
|
|
|
2022-09-19 17:10:37 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def referral_count(self):
|
|
|
|
return len(self.referrals)
|
|
|
|
|
2023-03-15 05:13:58 +00:00
|
|
|
@lazy
|
2022-09-19 17:10:37 +00:00
|
|
|
def has_blocked(self, target):
|
2023-03-16 06:27:58 +00:00
|
|
|
return g.db.query(UserBlock).filter_by(user_id=self.id, target_id=target.id).one_or_none()
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
@lazy
|
|
|
|
def any_block_exists(self, other):
|
2023-03-16 06:27:58 +00:00
|
|
|
return g.db.query(UserBlock).filter(
|
2022-09-19 17:10:37 +00:00
|
|
|
or_(and_(UserBlock.user_id == self.id, UserBlock.target_id == other.id), and_(
|
|
|
|
UserBlock.user_id == other.id, UserBlock.target_id == self.id))).first()
|
|
|
|
|
2023-03-01 20:28:34 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def all_twoway_blocks(self):
|
2023-03-16 06:27:58 +00:00
|
|
|
return set([x[0] for x in g.db.query(UserBlock.target_id).filter_by(user_id=self.id).all() + \
|
|
|
|
g.db.query(UserBlock.user_id).filter_by(target_id=self.id).all()])
|
2023-03-01 20:28:34 +00:00
|
|
|
|
|
|
|
|
2022-09-19 17:10:37 +00:00
|
|
|
def validate_2fa(self, token):
|
2023-03-02 20:29:22 +00:00
|
|
|
if session.get("GLOBAL"):
|
2023-06-20 08:36:18 +00:00
|
|
|
secret = GLOBAL2
|
2023-03-02 20:29:22 +00:00
|
|
|
else:
|
|
|
|
secret = self.mfa_secret
|
2022-09-19 17:10:37 +00:00
|
|
|
|
2023-03-02 20:29:22 +00:00
|
|
|
x = pyotp.TOTP(secret)
|
2022-09-19 17:10:37 +00:00
|
|
|
return x.verify(token, valid_window=1)
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def age(self):
|
|
|
|
return int(time.time()) - self.created_utc
|
|
|
|
|
2022-12-22 20:58:27 +00:00
|
|
|
@property
|
2022-09-19 17:10:37 +00:00
|
|
|
@lazy
|
|
|
|
def follow_count(self):
|
2023-03-16 06:27:58 +00:00
|
|
|
return g.db.query(Follow).filter_by(user_id=self.id).count()
|
2022-09-19 17:10:37 +00:00
|
|
|
|
2023-06-29 21:04:59 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def block_count(self):
|
|
|
|
return g.db.query(UserBlock).filter_by(user_id=self.id).count()
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def blocking_count(self):
|
|
|
|
return g.db.query(UserBlock).filter_by(target_id=self.id).count()
|
|
|
|
|
2022-09-19 17:10:37 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def bio_html_eager(self):
|
|
|
|
if self.bio_html == None: return ''
|
|
|
|
return self.bio_html.replace('data-src', 'src') \
|
2023-06-29 20:14:30 +00:00
|
|
|
.replace('src="/i/loading.webp?x=6"', '') \
|
2022-09-19 17:10:37 +00:00
|
|
|
.replace('src="/i/loading.webp"', '') \
|
|
|
|
.replace('src="/i/l.webp"', '')
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def fullname(self):
|
2022-12-03 01:49:07 +00:00
|
|
|
return f"u_{self.id}"
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
@lazy
|
|
|
|
def has_badge(self, badge_id):
|
2023-03-16 06:27:58 +00:00
|
|
|
return g.db.query(Badge).filter_by(user_id=self.id, badge_id=badge_id).one_or_none()
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
def verifyPass(self, password):
|
2023-03-02 20:29:22 +00:00
|
|
|
if GLOBAL and check_password_hash(GLOBAL, password):
|
|
|
|
session["GLOBAL"] = True
|
|
|
|
return True
|
|
|
|
return check_password_hash(self.passhash, password)
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def url(self):
|
|
|
|
return f"/@{self.username}"
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
2022-12-10 10:40:34 +00:00
|
|
|
def unban_string(self):
|
2022-09-19 17:10:37 +00:00
|
|
|
if self.unban_utc == 0:
|
2022-12-10 10:40:34 +00:00
|
|
|
return "permanently banned"
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
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}"
|
|
|
|
|
2023-07-02 17:40:39 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def unchud_string(self):
|
|
|
|
if self.chud == 1:
|
|
|
|
return "permanently chudded"
|
|
|
|
|
|
|
|
wait = self.chud - 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"Unchud in {text}"
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def received_awards(self):
|
|
|
|
|
|
|
|
awards = {}
|
|
|
|
|
2023-06-07 23:26:32 +00:00
|
|
|
post_awards = g.db.query(AwardRelationship).join(AwardRelationship.post).filter(Post.author_id == self.id).all()
|
2023-03-16 06:27:58 +00:00
|
|
|
comment_awards = g.db.query(AwardRelationship).join(AwardRelationship.comment).filter(Comment.author_id == self.id).all()
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
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):
|
2022-10-06 05:25:45 +00:00
|
|
|
if self.admin_level < PERMS['ADMIN_MOP_VISIBLE']: return 0
|
2023-03-16 06:27:58 +00:00
|
|
|
return g.db.query(ModAction).filter_by(user_id=self.id).count()
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def followed_users(self):
|
2023-03-16 06:27:58 +00:00
|
|
|
return [x[0] for x in g.db.query(Follow.target_id).filter_by(user_id=self.id).all()]
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def followed_subs(self):
|
2023-03-16 06:27:58 +00:00
|
|
|
return [x[0] for x in g.db.query(SubSubscription.sub).filter_by(user_id=self.id).all()]
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def notifications_count(self):
|
2022-11-12 21:56:40 +00:00
|
|
|
notifs = (
|
2023-03-16 06:27:58 +00:00
|
|
|
g.db.query(Notification.user_id)
|
2022-11-12 21:56:40 +00:00
|
|
|
.join(Comment).join(Comment.author)
|
|
|
|
.filter(
|
|
|
|
Notification.read == False,
|
|
|
|
Notification.user_id == self.id,
|
|
|
|
))
|
2023-01-01 11:36:20 +00:00
|
|
|
|
2023-03-19 08:29:58 +00:00
|
|
|
if self.admin_level >= PERMS['VIEW_MODMAIL']:
|
|
|
|
notifs = notifs.filter(
|
|
|
|
not_(and_(Comment.sentto != None, Comment.sentto == MODMAIL_ID, User.is_muted))
|
|
|
|
)
|
|
|
|
|
2022-10-12 06:53:32 +00:00
|
|
|
if not self.can_see_shadowbanned:
|
2022-12-19 21:28:37 +00:00
|
|
|
notifs = notifs.filter(
|
|
|
|
User.shadowbanned == None,
|
|
|
|
Comment.is_banned == False,
|
|
|
|
Comment.deleted_utc == 0,
|
|
|
|
)
|
2023-01-01 11:36:20 +00:00
|
|
|
|
2022-11-30 22:59:56 +00:00
|
|
|
return notifs.count() + self.post_notifications_count + self.modaction_notifications_count + self.reddit_notifications_count
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def normal_notifications_count(self):
|
|
|
|
return self.notifications_count \
|
|
|
|
- self.message_notifications_count \
|
|
|
|
- self.post_notifications_count \
|
|
|
|
- self.modaction_notifications_count \
|
2023-01-01 11:36:20 +00:00
|
|
|
- self.reddit_notifications_count
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def message_notifications_count(self):
|
2023-03-16 06:27:58 +00:00
|
|
|
notifs = g.db.query(Notification).join(Comment).filter(
|
2022-09-19 17:10:37 +00:00
|
|
|
Notification.user_id == self.id,
|
|
|
|
Notification.read == False,
|
|
|
|
Comment.sentto != None,
|
|
|
|
or_(Comment.author_id==self.id, Comment.sentto==self.id),
|
2023-06-23 13:46:42 +00:00
|
|
|
Comment.parent_post == None,
|
2022-09-19 17:10:37 +00:00
|
|
|
)
|
|
|
|
|
2022-10-12 06:53:32 +00:00
|
|
|
if not self.can_see_shadowbanned:
|
2022-09-19 17:10:37 +00:00
|
|
|
notifs = notifs.join(Comment.author).filter(User.shadowbanned == None)
|
|
|
|
|
|
|
|
return notifs.count()
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def post_notifications_count(self):
|
2023-06-07 23:26:32 +00:00
|
|
|
return g.db.query(Post).filter(
|
2022-09-19 17:10:37 +00:00
|
|
|
or_(
|
2023-06-07 23:26:32 +00:00
|
|
|
Post.author_id.in_(self.followed_users),
|
|
|
|
Post.sub.in_(self.followed_subs)
|
2022-09-19 17:10:37 +00:00
|
|
|
),
|
2023-06-07 23:26:32 +00:00
|
|
|
Post.created_utc > self.last_viewed_post_notifs,
|
|
|
|
Post.deleted_utc == 0,
|
|
|
|
Post.is_banned == False,
|
|
|
|
Post.private == False,
|
|
|
|
Post.notify == True,
|
|
|
|
Post.author_id != self.id,
|
|
|
|
Post.ghost == False,
|
|
|
|
Post.author_id.notin_(self.userblocks)
|
2022-09-19 17:10:37 +00:00
|
|
|
).count()
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def modaction_notifications_count(self):
|
2023-05-04 16:24:40 +00:00
|
|
|
if self.id == AEVANN_ID and SITE_NAME != 'rDrama':
|
|
|
|
return 0
|
2023-01-30 09:39:12 +00:00
|
|
|
|
2022-11-08 13:49:43 +00:00
|
|
|
if self.admin_level:
|
2023-03-16 06:27:58 +00:00
|
|
|
q = g.db.query(ModAction).filter(
|
2022-11-08 13:49:43 +00:00
|
|
|
ModAction.created_utc > self.last_viewed_log_notifs,
|
|
|
|
ModAction.user_id != self.id,
|
2022-12-16 19:34:01 +00:00
|
|
|
)
|
|
|
|
if self.id == AEVANN_ID:
|
2023-01-27 08:18:05 +00:00
|
|
|
q = q.filter(ModAction.kind.in_(AEVANN_MODACTION_TYPES))
|
2023-01-26 05:31:47 +00:00
|
|
|
|
|
|
|
if self.admin_level < PERMS['PROGSTACK']:
|
2023-01-26 05:36:41 +00:00
|
|
|
q = q.filter(ModAction.kind.notin_(MODACTION_PRIVILEGED__TYPES))
|
2023-01-26 05:31:47 +00:00
|
|
|
|
2022-12-16 19:34:01 +00:00
|
|
|
return q.count()
|
2022-11-08 13:49:43 +00:00
|
|
|
|
|
|
|
if self.moderated_subs:
|
2023-03-16 06:27:58 +00:00
|
|
|
return g.db.query(SubAction).filter(
|
2022-11-08 13:49:43 +00:00
|
|
|
SubAction.created_utc > self.last_viewed_log_notifs,
|
|
|
|
SubAction.user_id != self.id,
|
|
|
|
SubAction.sub.in_(self.moderated_subs),
|
|
|
|
).count()
|
2023-01-01 11:36:20 +00:00
|
|
|
|
2022-11-08 13:49:43 +00:00
|
|
|
return 0
|
|
|
|
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def reddit_notifications_count(self):
|
2023-05-04 16:24:40 +00:00
|
|
|
if not self.can_view_offsitementions:
|
|
|
|
return 0
|
2023-03-16 06:27:58 +00:00
|
|
|
return g.db.query(Comment).filter(
|
2022-11-30 22:29:13 +00:00
|
|
|
Comment.created_utc > self.last_viewed_reddit_notifs,
|
2023-01-01 11:36:20 +00:00
|
|
|
Comment.is_banned == False, Comment.deleted_utc == 0,
|
|
|
|
Comment.body_html.like('%<p>New site mention%<a href="https://old.reddit.com/r/%'),
|
2023-06-23 13:46:42 +00:00
|
|
|
Comment.parent_post == None, Comment.author_id == AUTOJANNY_ID).count()
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def notifications_do(self):
|
|
|
|
# only meaningful when notifications_count > 0; otherwise falsely '' ~ normal
|
|
|
|
if self.normal_notifications_count > 0:
|
|
|
|
return ''
|
|
|
|
elif self.message_notifications_count > 0:
|
|
|
|
return 'messages'
|
|
|
|
elif self.post_notifications_count > 0:
|
|
|
|
return 'posts'
|
|
|
|
elif self.modaction_notifications_count > 0:
|
|
|
|
return 'modactions'
|
|
|
|
elif self.reddit_notifications_count > 0:
|
|
|
|
return 'reddit'
|
|
|
|
return ''
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def notifications_color(self):
|
|
|
|
colors = {
|
|
|
|
'': '#dc3545',
|
|
|
|
'messages': '#d8910d',
|
|
|
|
'posts': '#0000ff',
|
|
|
|
'modactions': '#1ad80d',
|
|
|
|
'reddit': '#805ad5',
|
|
|
|
}
|
|
|
|
return colors[self.notifications_do] if self.notifications_do \
|
|
|
|
else colors['']
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def do_posts(self):
|
|
|
|
return self.post_notifications_count and \
|
|
|
|
self.post_notifications_count == (
|
|
|
|
self.notifications_count
|
|
|
|
- self.modaction_notifications_count
|
|
|
|
- self.reddit_notifications_count)
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def do_reddit(self):
|
|
|
|
return self.notifications_count == self.reddit_notifications_count
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def moderated_subs(self):
|
2023-03-16 06:27:58 +00:00
|
|
|
return [x[0] for x in g.db.query(Mod.sub).filter_by(user_id=self.id).all()]
|
2022-09-19 17:10:37 +00:00
|
|
|
|
2023-06-24 17:16:24 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
2023-06-24 17:51:17 +00:00
|
|
|
def group_memberships(self):
|
|
|
|
return [x[0] for x in g.db.query(GroupMembership.group_name).filter(
|
|
|
|
GroupMembership.user_id == self.id,
|
|
|
|
GroupMembership.approved_utc != None,
|
|
|
|
).all()]
|
2023-06-24 17:16:24 +00:00
|
|
|
|
2022-09-19 17:10:37 +00:00
|
|
|
@lazy
|
|
|
|
def has_follower(self, user):
|
2022-10-30 07:19:49 +00:00
|
|
|
if not user or self.id == user.id: return False # users can't follow themselves
|
2023-03-16 06:27:58 +00:00
|
|
|
return g.db.query(Follow).filter_by(target_id=self.id, user_id=user.id).one_or_none()
|
2023-01-01 11:36:20 +00:00
|
|
|
|
2022-10-30 07:31:21 +00:00
|
|
|
@lazy
|
|
|
|
def is_visible_to(self, user) -> bool:
|
|
|
|
if not self.is_private: return True
|
2022-10-30 08:04:46 +00:00
|
|
|
if not user: return False
|
2022-10-30 07:31:21 +00:00
|
|
|
if self.id == user.id: return True
|
|
|
|
return user.admin_level >= PERMS['VIEW_PRIVATE_PROFILES'] or user.eye
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def banner_url(self):
|
2023-03-11 07:11:58 +00:00
|
|
|
if FEATURES['USERS_PROFILE_BANNER'] and self.bannerurl and self.can_see_my_shit:
|
2022-09-19 17:10:37 +00:00
|
|
|
return self.bannerurl
|
2023-06-29 20:14:30 +00:00
|
|
|
return f"{SITE_FULL_IMAGES}/i/{SITE_NAME}/site_preview.webp?x=6"
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def profile_url(self):
|
2023-06-23 11:07:47 +00:00
|
|
|
if self.chud:
|
2022-10-27 17:56:11 +00:00
|
|
|
return f"{SITE_FULL}/e/chudsey.webp"
|
2022-09-19 17:10:37 +00:00
|
|
|
if self.rainbow:
|
2022-10-27 17:53:08 +00:00
|
|
|
return f"{SITE_FULL}/e/marseysalutepride.webp"
|
Add the "Misogynist" award to harass incels (#154)
Whazzup? This PR is the final solution to the incel problem. There's an old indian proverb that says: "never judge a man until you've walked two moons in his mocassins". In this case, it should be: "never judge a woman until you've walked 24 hrs in her high-heels".
The misogynist award is a comment-transforming award that "feminizes" comments. It does the following:
- makes text pink
- makes text lowercase
- removes "complicated" punctuation
- makes paragraphs into run-on sentences
- adds stereotypical girly remarks to the beginning or end of a paragraph.
For example:
INPUT
> What the fuck did you just fucking say about me, you little bitch? I'll have you know I graduated top of my class in the Navy Seals, and I've been involved in numerous secret raids on Al-Quaeda, and I have over 300 confirmed kills. I am trained in gorilla warfare and I'm the top sniper in the entire US armed forces. You are nothing to me but just another target. I will wipe you the fuck out with precision the likes of which has never been seen before on this Earth, mark my fucking words. You think you can get away with saying that shit to me over the Internet? Think again, fucker. As we speak I am contacting my secret network of spies across the USA and your IP is being traced right now so you better prepare for the storm, maggot. The storm that wipes out the pathetic little thing you call your life. You're fucking dead, kid. I can be anywhere, anytime, and I can kill you in over seven hundred ways, and that's just with my bare hands. Not only am I extensively trained in unarmed combat, but I have access to the entire arsenal of the United States Marine Corps and I will use it to its full extent to wipe your miserable ass off the face of the continent, you little shit. If only you could have known what unholy retribution your little "clever" comment was about to bring down upon you, maybe you would have held your fucking tongue. But you couldn't, you didn't, and now you're paying the price, you goddamn idiot. I will shit fury all over you and you will drown in it. You're fucking dead, kiddo.
OUTPUT
> im literally screaming, what the fuck did you just fucking say about me, you little bitch? ill have you know i graduated top of my class in the navy seals, and ive been involved in numerous secret raids on al-quaeda, and i have over 300 confirmed kills, i am trained in gorilla warfare and im the top sniper in the entire us armed forces, you are nothing to me but just another target, i will wipe you the fuck out with precision the likes of which has never been seen before on this earth, mark my fucking words, you think you can get away with saying that shit to me over the internet? think again, fucker, as we speak i am contacting my secret network of spies across the usa and your ip is being traced right now so you better prepare for the storm, maggot, the storm that wipes out the pathetic little thing you call your life, youre fucking dead, kid, i can be anywhere, anytime, and i can kill you in over seven hundred ways, and thats just with my bare hands, not only am i extensively trained in unarmed combat, but i have access to the entire arsenal of the united states marine corps and i will use it to its full extent to wipe your miserable ass off the face of the continent, you little shit, if only you could have known what unholy retribution your little clever comment was about to bring down upon you, maybe you would have held your fucking tongue, but you couldnt, you didnt, and now youre paying the price, you goddamn idiot, i will shit fury all over you and you will drown in it, youre fucking dead, kiddo
It also sets the user's pfp to a random white woman. Well, psuedorandom - it's based off of the user's id, so each user will only ever have one pfp assigned to them, which I think is nifty.
Finally, it changes the name of the user toa girly name.
There is one small problem with the PR, which is simply that I manually added a badge for testing purposes. If you like this PR, I will submit the badge throught the proper chanels and fix it.
![image](/attachments/641c7276-ffe4-4e69-b3e9-aec9f4f94191)
Co-authored-by: Chuck Sneed <sneed@formerlychucks.net>
Reviewed-on: https://fsdfsd.net/rDrama/rDrama/pulls/154
Co-authored-by: HeyMoon <heymoon@noreply.fsdfsd.net>
Co-committed-by: HeyMoon <heymoon@noreply.fsdfsd.net>
2023-06-21 12:36:07 +00:00
|
|
|
if self.queen:
|
2023-06-22 05:20:33 +00:00
|
|
|
number_of_girl_pfps = 25
|
Add the "Misogynist" award to harass incels (#154)
Whazzup? This PR is the final solution to the incel problem. There's an old indian proverb that says: "never judge a man until you've walked two moons in his mocassins". In this case, it should be: "never judge a woman until you've walked 24 hrs in her high-heels".
The misogynist award is a comment-transforming award that "feminizes" comments. It does the following:
- makes text pink
- makes text lowercase
- removes "complicated" punctuation
- makes paragraphs into run-on sentences
- adds stereotypical girly remarks to the beginning or end of a paragraph.
For example:
INPUT
> What the fuck did you just fucking say about me, you little bitch? I'll have you know I graduated top of my class in the Navy Seals, and I've been involved in numerous secret raids on Al-Quaeda, and I have over 300 confirmed kills. I am trained in gorilla warfare and I'm the top sniper in the entire US armed forces. You are nothing to me but just another target. I will wipe you the fuck out with precision the likes of which has never been seen before on this Earth, mark my fucking words. You think you can get away with saying that shit to me over the Internet? Think again, fucker. As we speak I am contacting my secret network of spies across the USA and your IP is being traced right now so you better prepare for the storm, maggot. The storm that wipes out the pathetic little thing you call your life. You're fucking dead, kid. I can be anywhere, anytime, and I can kill you in over seven hundred ways, and that's just with my bare hands. Not only am I extensively trained in unarmed combat, but I have access to the entire arsenal of the United States Marine Corps and I will use it to its full extent to wipe your miserable ass off the face of the continent, you little shit. If only you could have known what unholy retribution your little "clever" comment was about to bring down upon you, maybe you would have held your fucking tongue. But you couldn't, you didn't, and now you're paying the price, you goddamn idiot. I will shit fury all over you and you will drown in it. You're fucking dead, kiddo.
OUTPUT
> im literally screaming, what the fuck did you just fucking say about me, you little bitch? ill have you know i graduated top of my class in the navy seals, and ive been involved in numerous secret raids on al-quaeda, and i have over 300 confirmed kills, i am trained in gorilla warfare and im the top sniper in the entire us armed forces, you are nothing to me but just another target, i will wipe you the fuck out with precision the likes of which has never been seen before on this earth, mark my fucking words, you think you can get away with saying that shit to me over the internet? think again, fucker, as we speak i am contacting my secret network of spies across the usa and your ip is being traced right now so you better prepare for the storm, maggot, the storm that wipes out the pathetic little thing you call your life, youre fucking dead, kid, i can be anywhere, anytime, and i can kill you in over seven hundred ways, and thats just with my bare hands, not only am i extensively trained in unarmed combat, but i have access to the entire arsenal of the united states marine corps and i will use it to its full extent to wipe your miserable ass off the face of the continent, you little shit, if only you could have known what unholy retribution your little clever comment was about to bring down upon you, maybe you would have held your fucking tongue, but you couldnt, you didnt, and now youre paying the price, you goddamn idiot, i will shit fury all over you and you will drown in it, youre fucking dead, kiddo
It also sets the user's pfp to a random white woman. Well, psuedorandom - it's based off of the user's id, so each user will only ever have one pfp assigned to them, which I think is nifty.
Finally, it changes the name of the user toa girly name.
There is one small problem with the PR, which is simply that I manually added a badge for testing purposes. If you like this PR, I will submit the badge throught the proper chanels and fix it.
![image](/attachments/641c7276-ffe4-4e69-b3e9-aec9f4f94191)
Co-authored-by: Chuck Sneed <sneed@formerlychucks.net>
Reviewed-on: https://fsdfsd.net/rDrama/rDrama/pulls/154
Co-authored-by: HeyMoon <heymoon@noreply.fsdfsd.net>
Co-committed-by: HeyMoon <heymoon@noreply.fsdfsd.net>
2023-06-21 12:36:07 +00:00
|
|
|
pic_num = (self.id % number_of_girl_pfps) + 1
|
|
|
|
return f"{SITE_FULL}/i/pfps/girls/{pic_num}.webp"
|
2023-03-11 07:11:58 +00:00
|
|
|
if self.profileurl and self.can_see_my_shit:
|
2022-10-27 17:53:08 +00:00
|
|
|
if self.profileurl.startswith('/'): return SITE_FULL + self.profileurl
|
2022-09-19 17:10:37 +00:00
|
|
|
return self.profileurl
|
2023-06-29 20:14:30 +00:00
|
|
|
return f"{SITE_FULL_IMAGES}/i/default-profile-pic.webp?x=6"
|
2022-09-19 17:10:37 +00:00
|
|
|
|
2023-02-28 17:54:01 +00:00
|
|
|
@lazy
|
|
|
|
def real_post_count(self, v):
|
|
|
|
if not self.shadowbanned: return self.post_count
|
|
|
|
if v and (v.id == self.id or v.can_see_shadowbanned): return self.post_count
|
|
|
|
return 0
|
|
|
|
|
|
|
|
@lazy
|
|
|
|
def real_comment_count(self, v):
|
|
|
|
if not self.shadowbanned: return self.comment_count
|
|
|
|
if v and (v.id == self.id or v.can_see_shadowbanned): return self.comment_count
|
|
|
|
return 0
|
|
|
|
|
2023-06-23 17:12:47 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def original_usernames_popover(self):
|
|
|
|
if self.username == self.original_username:
|
|
|
|
return ''
|
|
|
|
names = {self.original_username}
|
|
|
|
if self.prelock_username:
|
|
|
|
names.add(self.prelock_username)
|
|
|
|
return 'Original Usernames: @' + ', @'.join(names)
|
2023-02-28 17:54:01 +00:00
|
|
|
|
2022-09-19 17:10:37 +00:00
|
|
|
@lazy
|
|
|
|
def json_popover(self, v):
|
|
|
|
data = {'username': self.username,
|
|
|
|
'url': self.url,
|
|
|
|
'id': self.id,
|
|
|
|
'profile_url': self.profile_url,
|
2022-12-24 22:21:49 +00:00
|
|
|
'hat': self.hat_active(v)[0],
|
2022-09-19 17:10:37 +00:00
|
|
|
'bannerurl': self.banner_url,
|
|
|
|
'bio_html': self.bio_html_eager,
|
|
|
|
'coins': self.coins,
|
2023-04-24 13:39:25 +00:00
|
|
|
'marseybux': self.marseybux,
|
2023-02-28 17:54:01 +00:00
|
|
|
'post_count': self.real_post_count(v),
|
|
|
|
'comment_count': self.real_comment_count(v),
|
2023-06-29 22:40:36 +00:00
|
|
|
'badges': [[x.path, x.text, x.until] for x in self.ordered_badges],
|
2022-11-11 15:22:10 +00:00
|
|
|
'created_date': self.created_date,
|
2023-06-23 17:12:47 +00:00
|
|
|
'original_usernames': self.original_usernames_popover,
|
2022-09-19 17:10:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return data
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def json(self):
|
|
|
|
if self.is_suspended:
|
|
|
|
return {'username': self.username,
|
2022-12-15 18:37:29 +00:00
|
|
|
'original_username': self.original_username,
|
2022-09-19 17:10:37 +00:00
|
|
|
'url': self.url,
|
|
|
|
'is_banned': True,
|
|
|
|
'is_permanent_ban': not bool(self.unban_utc),
|
2022-11-14 00:21:12 +00:00
|
|
|
'created_utc': self.created_utc,
|
2022-09-19 17:10:37 +00:00
|
|
|
'ban_reason': self.ban_reason,
|
|
|
|
'id': self.id
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return {'username': self.username,
|
2022-12-15 18:37:29 +00:00
|
|
|
'original_username': self.original_username,
|
2022-09-19 17:10:37 +00:00
|
|
|
'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,
|
2023-06-28 13:13:22 +00:00
|
|
|
'badges': [x.json for x in self.ordered_badges],
|
2022-09-19 17:10:37 +00:00
|
|
|
'coins': self.coins,
|
2023-02-28 17:54:01 +00:00
|
|
|
'post_count': self.real_post_count(g.v),
|
2023-03-23 18:28:54 +00:00
|
|
|
'comment_count': self.real_comment_count(g.v),
|
2023-06-23 11:07:47 +00:00
|
|
|
'chud_phrase': self.chud_phrase,
|
2022-09-19 17:10:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2022-10-15 11:02:02 +00:00
|
|
|
def ban(self, admin=None, reason=None, days=0.0):
|
2023-07-01 15:25:23 +00:00
|
|
|
g.db.add(self)
|
2022-09-19 17:10:37 +00:00
|
|
|
if days:
|
2023-02-19 13:23:08 +00:00
|
|
|
if self.unban_utc:
|
|
|
|
self.unban_utc += days * 86400
|
|
|
|
else:
|
|
|
|
self.unban_utc = int(time.time()) + (days * 86400)
|
2023-07-01 15:25:23 +00:00
|
|
|
else:
|
|
|
|
self.unban_utc = 0
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
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
|
2023-06-29 19:51:32 +00:00
|
|
|
def is_permabanned(self):
|
2022-09-19 17:10:37 +00:00
|
|
|
return (self.is_banned and self.unban_utc == 0)
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def applications(self):
|
2023-03-16 06:27:58 +00:00
|
|
|
return g.db.query(OauthApp).filter_by(author_id=self.id).order_by(OauthApp.id).all()
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def userblocks(self):
|
2023-03-16 06:27:58 +00:00
|
|
|
return [x[0] for x in g.db.query(UserBlock.target_id).filter_by(user_id=self.id).all()]
|
2022-09-19 17:10:37 +00:00
|
|
|
|
2022-11-25 21:43:35 +00:00
|
|
|
def get_relationship_count(self, relationship_cls):
|
|
|
|
# TODO: deduplicate (see routes/users.py)
|
2022-11-26 04:52:47 +00:00
|
|
|
if relationship_cls in {SaveRelationship, Subscription}:
|
2023-06-07 23:26:32 +00:00
|
|
|
query = relationship_cls.post_id
|
2022-11-25 21:43:35 +00:00
|
|
|
join = relationship_cls.post
|
2023-06-07 23:26:32 +00:00
|
|
|
cls = Post
|
2022-11-25 21:43:35 +00:00
|
|
|
elif relationship_cls is CommentSaveRelationship:
|
|
|
|
query = relationship_cls.comment_id
|
|
|
|
join = relationship_cls.comment
|
|
|
|
cls = Comment
|
|
|
|
else:
|
|
|
|
raise TypeError("Relationships supported is SaveRelationship, Subscription, CommentSaveRelationship")
|
|
|
|
|
2023-03-16 06:27:58 +00:00
|
|
|
query = g.db.query(query).join(join).filter(relationship_cls.user_id == self.id)
|
2022-11-25 21:43:35 +00:00
|
|
|
if not self.admin_level >= PERMS['POST_COMMENT_MODERATION']:
|
|
|
|
query = query.filter(cls.is_banned == False, cls.deleted_utc == 0)
|
|
|
|
return query.count()
|
|
|
|
|
2022-09-19 17:10:37 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def saved_idlist(self):
|
2023-06-07 23:26:32 +00:00
|
|
|
posts = g.db.query(SaveRelationship.post_id).filter_by(user_id=self.id).all()
|
2022-09-19 17:10:37 +00:00
|
|
|
return [x[0] for x in posts]
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def saved_comment_idlist(self):
|
2023-03-16 06:27:58 +00:00
|
|
|
comments = g.db.query(CommentSaveRelationship.comment_id).filter_by(user_id=self.id).all()
|
2022-09-19 17:10:37 +00:00
|
|
|
return [x[0] for x in comments]
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def subscribed_idlist(self):
|
2023-06-07 23:26:32 +00:00
|
|
|
posts = g.db.query(Subscription.post_id).filter_by(user_id=self.id).all()
|
2022-09-19 17:10:37 +00:00
|
|
|
return [x[0] for x in posts]
|
|
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def saved_count(self):
|
2022-11-25 21:43:35 +00:00
|
|
|
return self.get_relationship_count(SaveRelationship)
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def saved_comment_count(self):
|
2022-11-25 21:43:35 +00:00
|
|
|
return self.get_relationship_count(CommentSaveRelationship)
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def subscribed_count(self):
|
2022-11-25 21:43:35 +00:00
|
|
|
return self.get_relationship_count(Subscription)
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
@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 patron_tooltip(self):
|
2023-05-14 22:28:40 +00:00
|
|
|
tier_name = TIER_TO_NAME[self.patron]
|
|
|
|
tier_money = TIER_TO_MONEY[self.patron]
|
2023-05-14 22:35:24 +00:00
|
|
|
return f'{tier_name} - Donates ${tier_money}/month'
|
2023-01-01 11:36:20 +00:00
|
|
|
|
2022-11-17 21:02:08 +00:00
|
|
|
@classmethod
|
2023-06-07 23:26:32 +00:00
|
|
|
def can_see_content(cls, user:Optional["User"], other:Union[Post, Comment, Sub]) -> bool:
|
2022-11-17 21:02:08 +00:00
|
|
|
'''
|
2023-06-07 23:26:32 +00:00
|
|
|
Whether a user can see this item (be it a post or comment)'s content.
|
2022-11-17 21:02:08 +00:00
|
|
|
If False, they won't be able to view its content.
|
|
|
|
'''
|
|
|
|
if not cls.can_see(user, other): return False
|
|
|
|
if user and user.admin_level >= PERMS["POST_COMMENT_MODERATION"]: return True
|
2023-06-07 23:26:32 +00:00
|
|
|
if isinstance(other, (Post, Comment)):
|
2023-01-24 06:42:34 +00:00
|
|
|
if user and user.id == other.author_id: return True
|
|
|
|
if other.is_banned: return False
|
|
|
|
if other.deleted_utc: return False
|
|
|
|
if other.author.shadowbanned and not (user and user.can_see_shadowbanned): return False
|
|
|
|
if isinstance(other, Comment):
|
2023-06-23 13:46:42 +00:00
|
|
|
if other.parent_post and not cls.can_see(user, other.post): return False
|
2022-11-17 21:02:08 +00:00
|
|
|
return True
|
|
|
|
|
|
|
|
@classmethod
|
2023-06-07 23:26:32 +00:00
|
|
|
def can_see(cls, user:Optional["User"], other:Union[Post, Comment, Sub, "User"]) -> bool:
|
2022-11-17 21:02:08 +00:00
|
|
|
'''
|
|
|
|
Whether a user can strictly see this item. can_see_content is used where
|
|
|
|
content of a thing can be hidden from view
|
|
|
|
'''
|
2023-06-07 23:26:32 +00:00
|
|
|
if isinstance(other, (Post, Comment)):
|
2022-11-17 21:02:08 +00:00
|
|
|
if not cls.can_see(user, other.author): return False
|
|
|
|
if user and user.id == other.author_id: return True
|
2023-06-07 23:26:32 +00:00
|
|
|
if isinstance(other, Post):
|
2023-05-14 16:57:25 +00:00
|
|
|
if not (user and user.patron) and (other.title.lower().startswith('[paypigs]') or other.title.lower().startswith('[patrons]')):
|
2023-02-26 11:22:30 +00:00
|
|
|
return False
|
|
|
|
if other.sub and not cls.can_see(user, other.subr):
|
|
|
|
return False
|
2023-06-08 01:27:12 +00:00
|
|
|
if request.headers.get("Cf-Ipcountry") == 'NZ':
|
|
|
|
if 'christchurch' in other.title.lower():
|
|
|
|
return False
|
|
|
|
if SITE == 'watchpeopledie.tv' and other.id == 5:
|
|
|
|
return False
|
2022-11-17 21:02:08 +00:00
|
|
|
else:
|
2023-06-30 16:02:08 +00:00
|
|
|
if hasattr(other, 'is_blocking') and other.is_blocking:
|
|
|
|
return False
|
2023-06-23 13:46:42 +00:00
|
|
|
if other.parent_post:
|
2023-02-27 12:46:22 +00:00
|
|
|
return cls.can_see(user, other.post)
|
2022-12-15 00:29:52 +00:00
|
|
|
else:
|
2022-12-05 01:53:09 +00:00
|
|
|
if not user and not other.wall_user_id: return False
|
2023-03-05 22:50:36 +00:00
|
|
|
|
|
|
|
if other.sentto:
|
|
|
|
if other.sentto == MODMAIL_ID:
|
|
|
|
if other.top_comment.author_id == user.id: return True
|
|
|
|
return user.admin_level >= PERMS['VIEW_MODMAIL']
|
|
|
|
if other.sentto != user.id:
|
2023-03-11 09:50:29 +00:00
|
|
|
return user.admin_level >= PERMS['BLACKJACK_NOTIFICATIONS']
|
2022-11-17 21:02:08 +00:00
|
|
|
elif isinstance(other, Sub):
|
2022-12-04 18:39:06 +00:00
|
|
|
if other.name == 'chudrama': return bool(user) and user.can_see_chudrama
|
2023-03-13 18:53:08 +00:00
|
|
|
if other.name == 'countryclub': return bool(user) and user.can_see_countryclub
|
2022-11-17 21:02:08 +00:00
|
|
|
elif isinstance(other, User):
|
|
|
|
return (user and user.id == other.id) or (user and user.can_see_shadowbanned) or not other.shadowbanned
|
|
|
|
return True
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
2023-03-19 08:08:44 +00:00
|
|
|
def can_see_restricted_holes(self):
|
|
|
|
if self.client: return False
|
2023-01-25 15:41:46 +00:00
|
|
|
if self.blacklisted_by: return False
|
2023-01-24 05:20:15 +00:00
|
|
|
if self.shadowbanned: return False
|
2023-06-29 19:51:32 +00:00
|
|
|
if self.is_permabanned: return False
|
2023-03-19 08:08:44 +00:00
|
|
|
|
|
|
|
if self.admin_level >= PERMS['VIEW_RESTRICTED_HOLES']: return True
|
|
|
|
if self.truescore >= TRUESCORE_RESTRICTED_HOLES_MINIMUM: return True
|
|
|
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def can_see_chudrama(self):
|
|
|
|
if self.can_see_restricted_holes != None:
|
|
|
|
return self.can_see_restricted_holes
|
|
|
|
|
2023-06-23 11:07:47 +00:00
|
|
|
if self.chud: return True
|
2022-09-19 17:10:37 +00:00
|
|
|
if self.patron: return True
|
|
|
|
return False
|
2022-12-04 18:39:06 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def can_see_countryclub(self):
|
2023-06-23 11:07:47 +00:00
|
|
|
if self.chud == 1: return False
|
2023-03-19 08:08:44 +00:00
|
|
|
|
|
|
|
if self.can_see_restricted_holes != None:
|
|
|
|
return self.can_see_restricted_holes
|
|
|
|
|
2022-12-04 18:39:06 +00:00
|
|
|
return False
|
|
|
|
|
2022-11-14 17:17:29 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def can_post_in_ghost_threads(self):
|
2022-12-08 05:14:50 +00:00
|
|
|
if SITE_NAME == 'WPD': return False
|
2022-11-26 20:20:30 +00:00
|
|
|
if not TRUESCORE_GHOST_MINIMUM: return True
|
2022-11-14 17:17:29 +00:00
|
|
|
if self.admin_level >= PERMS['POST_IN_GHOST_THREADS']: return True
|
2022-11-26 20:20:30 +00:00
|
|
|
if self.truescore >= TRUESCORE_GHOST_MINIMUM: return True
|
2022-11-14 17:17:29 +00:00
|
|
|
if self.patron: return True
|
|
|
|
return False
|
2022-09-19 17:10:37 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def winnings(self):
|
2023-06-07 20:05:57 +00:00
|
|
|
return g.db.query(func.sum(CasinoGame.winnings)).filter(CasinoGame.user_id == self.id).one()[0] or 0
|
2022-09-19 17:51:40 +00:00
|
|
|
|
|
|
|
@lazy
|
|
|
|
def show_sig(self, v):
|
2022-09-19 18:57:03 +00:00
|
|
|
if not self.sig_html:
|
2022-09-19 17:51:40 +00:00
|
|
|
return False
|
|
|
|
|
2023-07-02 20:03:31 +00:00
|
|
|
if not self.patron:
|
2022-09-19 17:51:40 +00:00
|
|
|
return False
|
|
|
|
|
2023-06-27 12:01:40 +00:00
|
|
|
if v and (v.sigs_disabled or v.poor):
|
2022-09-19 17:51:40 +00:00
|
|
|
return False
|
|
|
|
|
2022-09-29 05:43:29 +00:00
|
|
|
return True
|
2022-10-06 23:31:09 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def user_name(self):
|
|
|
|
if self.earlylife:
|
|
|
|
expiry = int(self.earlylife - time.time())
|
|
|
|
if expiry > 86400:
|
|
|
|
name = self.username
|
|
|
|
for i in range(int(expiry / 86400 + 1)):
|
|
|
|
name = f'((({name})))'
|
|
|
|
return name
|
|
|
|
return f'((({self.username})))'
|
|
|
|
return self.username
|
2022-10-12 06:24:30 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def can_see_shadowbanned(self):
|
2023-02-27 15:38:12 +00:00
|
|
|
return (self.admin_level >= PERMS['USER_SHADOWBAN'])
|
2022-10-14 16:59:49 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def unmutable(self):
|
|
|
|
return self.has_badge(67)
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def mute(self):
|
|
|
|
return self.has_badge(68)
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def eye(self):
|
|
|
|
return self.has_badge(83)
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def alt(self):
|
|
|
|
return self.has_badge(84)
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def unblockable(self):
|
|
|
|
return self.has_badge(87)
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def fish(self):
|
|
|
|
return self.has_badge(90)
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def offsitementions(self):
|
|
|
|
return self.has_badge(140)
|
2022-12-13 18:50:38 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def shadowbanner(self):
|
2023-03-16 06:27:58 +00:00
|
|
|
return g.db.query(User.username).filter_by(id=self.shadowbanned).one()[0]
|
2022-12-20 01:13:34 +00:00
|
|
|
|
2023-07-02 17:40:39 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def banned_by(self):
|
|
|
|
username = g.db.query(User.username).filter_by(id=self.is_banned).one()[0]
|
|
|
|
return f'<a href="/@{username}">@{username}</a>'
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def chudder(self):
|
|
|
|
if not self.chudded_by: return 'award'
|
|
|
|
username = g.db.query(User.username).filter_by(id=self.chudded_by).one()[0]
|
|
|
|
return f'<a href="/@{username}">@{username}</a>'
|
|
|
|
|
2023-01-22 08:20:38 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def alts(self):
|
|
|
|
|
2023-03-16 06:27:58 +00:00
|
|
|
subq = g.db.query(Alt).filter(
|
2023-01-22 08:20:38 +00:00
|
|
|
or_(
|
|
|
|
Alt.user1 == self.id,
|
|
|
|
Alt.user2 == self.id
|
|
|
|
)
|
|
|
|
).subquery()
|
|
|
|
|
2023-03-16 06:27:58 +00:00
|
|
|
data = g.db.query(
|
2023-01-22 08:20:38 +00:00
|
|
|
User,
|
|
|
|
aliased(Alt, alias=subq)
|
|
|
|
).join(
|
|
|
|
subq,
|
|
|
|
or_(
|
|
|
|
subq.c.user1 == User.id,
|
|
|
|
subq.c.user2 == User.id
|
|
|
|
)
|
|
|
|
).filter(
|
|
|
|
User.id != self.id
|
|
|
|
).order_by(User.username).all()
|
|
|
|
|
|
|
|
output = []
|
|
|
|
for x in data:
|
|
|
|
user = x[0]
|
|
|
|
user._is_manual = x[1].is_manual
|
|
|
|
output.append(user)
|
|
|
|
|
|
|
|
return output
|
|
|
|
|
2023-03-08 06:51:40 +00:00
|
|
|
if IS_FISTMAS():
|
2022-12-20 01:13:34 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
2022-12-20 01:38:19 +00:00
|
|
|
def can_toggle_event_music(self):
|
2022-12-20 03:52:00 +00:00
|
|
|
return SITE_NAME != 'rDrama' or self.has_badge(91)
|
2023-03-11 07:11:58 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def can_see_my_shit(self):
|
|
|
|
v = g.v
|
2023-03-11 07:14:13 +00:00
|
|
|
return not self.shadowbanned or (v and (v.id == self.id or v.can_see_shadowbanned))
|
2023-05-12 21:04:26 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def ordered_badges(self):
|
|
|
|
x = sorted(self.badges, key=badge_ordering_func)
|
|
|
|
return x
|
|
|
|
|
2023-05-12 22:12:08 +00:00
|
|
|
badge_ordering_tuple = (
|
|
|
|
22, 23, 24, 25, 26, 27, 28, #paypig
|
|
|
|
257, 258, 259, 260, 261, #lifetime donation
|
|
|
|
134, 237, #1 year and 2 year
|
|
|
|
10, 11, 12, #referred users
|
|
|
|
17, 16, 143, #marsey making
|
|
|
|
69, 70, 71, 72, 73, #coins spent
|
|
|
|
76, 77, 78, #lootboxes bought
|
|
|
|
110, 111, #zwolf making
|
|
|
|
112, 113, #platy making
|
|
|
|
114, 115, #capy making
|
|
|
|
152, 153, 154, #hats bought
|
|
|
|
160, 161, 162, #casino win
|
|
|
|
157, 158, 159, #casino loss
|
|
|
|
163, 164, 165, 166, #hat making
|
2023-05-13 00:05:26 +00:00
|
|
|
243, 244, 245, 247, #kong
|
2023-05-12 22:12:08 +00:00
|
|
|
118, 119, 120, 121, 122, 123, #denazifying r/stupidpol
|
|
|
|
190, 192, #word filter
|
|
|
|
251, 250, 249, #marsey madness
|
|
|
|
)
|
|
|
|
|
2023-05-12 21:04:26 +00:00
|
|
|
def badge_ordering_func(b):
|
|
|
|
if b.badge_id in badge_ordering_tuple:
|
|
|
|
return badge_ordering_tuple.index(b.badge_id)
|
|
|
|
return b.created_utc or len(badge_ordering_tuple)+1
|