2021-11-07 20:34:12 +00:00
|
|
|
from sqlalchemy.orm import deferred, aliased
|
2021-10-15 14:08:27 +00:00
|
|
|
from secrets import token_hex
|
|
|
|
import pyotp
|
|
|
|
from files.helpers.discord import remove_user
|
|
|
|
from files.helpers.images import *
|
|
|
|
from files.helpers.const import *
|
|
|
|
from .alts import Alt
|
|
|
|
from .submission import SaveRelationship
|
|
|
|
from .comment import Notification
|
|
|
|
from .award import AwardRelationship
|
|
|
|
from .subscriptions import *
|
|
|
|
from .userblock import *
|
|
|
|
from .badges import *
|
|
|
|
from .clients import *
|
2021-12-26 03:18:28 +00:00
|
|
|
from .mod_logs import *
|
2022-02-05 21:09:17 +00:00
|
|
|
from .mod import *
|
2021-10-15 14:08:27 +00:00
|
|
|
from files.__main__ import Base, cache
|
|
|
|
from files.helpers.security import *
|
|
|
|
import random
|
2021-12-03 19:20:52 +00:00
|
|
|
from os import environ, remove, path
|
2021-10-15 14:08:27 +00:00
|
|
|
|
|
|
|
defaulttheme = environ.get("DEFAULT_THEME", "midnight").strip()
|
2022-01-13 02:59:17 +00:00
|
|
|
defaulttimefilter = environ.get("DEFAULT_TIME_FILTER", "all").strip()
|
2021-10-15 14:08:27 +00:00
|
|
|
cardview = bool(int(environ.get("CARD_VIEW", 1)))
|
|
|
|
|
|
|
|
class User(Base):
|
|
|
|
__tablename__ = "users"
|
|
|
|
|
2022-01-19 09:07:16 +00:00
|
|
|
if SITE == "pcmemes.net":
|
2021-10-15 14:08:27 +00:00
|
|
|
quadrant = Column(String)
|
|
|
|
basedcount = Column(Integer, default=0)
|
|
|
|
pills = deferred(Column(String, default=""))
|
|
|
|
|
|
|
|
id = Column(Integer, primary_key=True)
|
|
|
|
username = Column(String)
|
2022-02-05 11:31:05 +00:00
|
|
|
namecolor = Column(String, default=DEFAULT_COLOR)
|
2021-10-15 14:08:27 +00:00
|
|
|
background = Column(String)
|
|
|
|
customtitle = Column(String)
|
2021-11-06 17:30:39 +00:00
|
|
|
customtitleplain = deferred(Column(String))
|
2022-02-05 11:31:05 +00:00
|
|
|
titlecolor = Column(String, default=DEFAULT_COLOR)
|
2021-10-15 14:08:27 +00:00
|
|
|
theme = Column(String, default=defaulttheme)
|
2022-02-05 11:31:05 +00:00
|
|
|
themecolor = Column(String, default=DEFAULT_COLOR)
|
2021-10-15 14:08:27 +00:00
|
|
|
cardview = Column(Boolean, default=cardview)
|
|
|
|
song = Column(String)
|
|
|
|
highres = Column(String)
|
|
|
|
profileurl = Column(String)
|
|
|
|
bannerurl = Column(String)
|
2022-02-04 11:13:59 +00:00
|
|
|
house = Column(String)
|
2021-10-15 14:08:27 +00:00
|
|
|
patron = Column(Integer, default=0)
|
2022-01-29 02:48:34 +00:00
|
|
|
patron_utc = Column(Integer, default=0)
|
2021-10-15 14:08:27 +00:00
|
|
|
verified = Column(String)
|
2021-10-27 00:37:34 +00:00
|
|
|
verifiedcolor = Column(String)
|
2021-10-27 20:12:16 +00:00
|
|
|
marseyawarded = Column(Integer)
|
2022-01-31 01:41:04 +00:00
|
|
|
rehab = Column(Integer)
|
2021-11-18 20:50:03 +00:00
|
|
|
longpost = Column(Integer)
|
2022-01-25 01:59:58 +00:00
|
|
|
winnings = Column(Integer, default=0)
|
2021-11-26 21:24:47 +00:00
|
|
|
unblockable = Column(Boolean)
|
2021-11-23 22:36:38 +00:00
|
|
|
bird = Column(Integer)
|
2021-11-06 17:30:39 +00:00
|
|
|
email = deferred(Column(String))
|
2021-10-15 14:08:27 +00:00
|
|
|
css = deferred(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, default=0)
|
|
|
|
suicide_utc = Column(Integer, default=0)
|
|
|
|
rent_utc = Column(Integer, default=0)
|
|
|
|
steal_utc = Column(Integer, default=0)
|
|
|
|
fail_utc = Column(Integer, default=0)
|
|
|
|
fail2_utc = Column(Integer, default=0)
|
|
|
|
admin_level = Column(Integer, default=0)
|
2021-10-21 19:25:58 +00:00
|
|
|
coins_spent = Column(Integer, default=0)
|
2021-12-14 22:06:54 +00:00
|
|
|
lootboxes_bought = Column(Integer, default=0)
|
2021-10-15 14:08:27 +00:00
|
|
|
agendaposter = Column(Boolean, default=False)
|
|
|
|
agendaposter_expires_utc = Column(Integer, default=0)
|
|
|
|
changelogsub = Column(Boolean, default=False)
|
|
|
|
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)
|
|
|
|
slurreplacer = Column(Boolean, default=True)
|
2021-10-21 20:50:00 +00:00
|
|
|
flairchanged = Column(Integer)
|
2021-10-15 14:08:27 +00:00
|
|
|
newtab = Column(Boolean, default=False)
|
|
|
|
newtabexternal = Column(Boolean, default=True)
|
|
|
|
oldreddit = Column(Boolean, default=True)
|
2021-11-26 21:24:47 +00:00
|
|
|
teddit = Column(Boolean)
|
|
|
|
nitter = Column(Boolean)
|
|
|
|
mute = Column(Boolean)
|
|
|
|
unmutable = Column(Boolean)
|
|
|
|
eye = Column(Boolean)
|
|
|
|
alt = Column(Boolean)
|
2021-10-15 14:08:27 +00:00
|
|
|
frontsize = Column(Integer, default=25)
|
|
|
|
controversial = Column(Boolean, default=False)
|
2021-11-06 17:30:39 +00:00
|
|
|
bio = deferred(Column(String))
|
2021-11-04 17:02:21 +00:00
|
|
|
bio_html = Column(String)
|
2021-11-06 17:30:39 +00:00
|
|
|
sig = deferred(Column(String))
|
2021-11-04 15:12:17 +00:00
|
|
|
sig_html = Column(String)
|
2021-11-18 16:04:52 +00:00
|
|
|
fp = Column(String)
|
2021-11-26 21:24:47 +00:00
|
|
|
sigs_disabled = Column(Boolean)
|
2021-12-10 04:58:55 +00:00
|
|
|
fish = Column(Boolean)
|
2021-12-31 23:45:27 +00:00
|
|
|
progressivestack = Column(Integer)
|
2021-11-06 17:30:39 +00:00
|
|
|
friends = deferred(Column(String))
|
|
|
|
friends_html = deferred(Column(String))
|
|
|
|
enemies = deferred(Column(String))
|
|
|
|
enemies_html = deferred(Column(String))
|
2021-10-15 14:08:27 +00:00
|
|
|
is_banned = Column(Integer, default=0)
|
|
|
|
unban_utc = Column(Integer, default=0)
|
2021-11-06 17:30:39 +00:00
|
|
|
ban_reason = deferred(Column(String))
|
2021-10-15 14:08:27 +00:00
|
|
|
club_allowed = Column(Boolean, default=False)
|
|
|
|
login_nonce = Column(Integer, default=0)
|
2021-11-06 17:30:39 +00:00
|
|
|
reserved = deferred(Column(String))
|
2021-10-15 14:08:27 +00:00
|
|
|
coins = Column(Integer, default=0)
|
|
|
|
truecoins = Column(Integer, default=0)
|
2021-10-21 22:55:48 +00:00
|
|
|
procoins = Column(Integer, default=0)
|
2021-10-15 14:08:27 +00:00
|
|
|
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=defaulttimefilter)
|
|
|
|
is_nofollow = Column(Boolean, default=False)
|
|
|
|
custom_filter_list = Column(String)
|
|
|
|
discord_id = Column(String)
|
|
|
|
ban_evade = Column(Integer, default=0)
|
|
|
|
original_username = deferred(Column(String))
|
|
|
|
referred_by = Column(Integer, ForeignKey("users.id"))
|
2022-02-01 04:20:31 +00:00
|
|
|
nwordpass = Column(Boolean)
|
|
|
|
|
2021-11-05 21:30:54 +00:00
|
|
|
badges = relationship("Badge", viewonly=True)
|
2021-10-15 14:08:27 +00:00
|
|
|
subscriptions = relationship("Subscription", viewonly=True)
|
|
|
|
following = relationship("Follow", primaryjoin="Follow.user_id==User.id", viewonly=True)
|
|
|
|
followers = relationship("Follow", primaryjoin="Follow.target_id==User.id", viewonly=True)
|
|
|
|
viewers = relationship("ViewerRelationship", primaryjoin="User.id == ViewerRelationship.user_id", viewonly=True)
|
|
|
|
blocking = relationship("UserBlock", lazy="dynamic", primaryjoin="User.id==UserBlock.user_id", viewonly=True)
|
|
|
|
blocked = relationship("UserBlock", lazy="dynamic", primaryjoin="User.id==UserBlock.target_id", viewonly=True)
|
2021-11-05 21:30:54 +00:00
|
|
|
authorizations = relationship("ClientAuth", viewonly=True)
|
|
|
|
awards = relationship("AwardRelationship", primaryjoin="User.id==AwardRelationship.user_id", viewonly=True)
|
2021-10-15 14:08:27 +00:00
|
|
|
referrals = relationship("User", viewonly=True)
|
|
|
|
|
|
|
|
def __init__(self, **kwargs):
|
|
|
|
|
|
|
|
if "password" in kwargs:
|
|
|
|
kwargs["passhash"] = self.hash_password(kwargs["password"])
|
|
|
|
kwargs.pop("password")
|
|
|
|
|
|
|
|
kwargs["created_utc"] = int(time.time())
|
|
|
|
|
|
|
|
super().__init__(**kwargs)
|
|
|
|
|
|
|
|
|
2022-02-05 21:09:17 +00:00
|
|
|
@lazy
|
|
|
|
def mods(self, sub):
|
|
|
|
return g.db.query(Mod.user_id).filter_by(user_id=self.id, sub=sub).one_or_none()
|
|
|
|
|
2021-11-06 18:20:34 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def csslazy(self):
|
|
|
|
return self.css
|
|
|
|
|
2021-11-05 21:30:54 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def notifications(self):
|
2021-11-06 15:52:48 +00:00
|
|
|
return g.db.query(Notification).filter_by(user_id=self.id)
|
2021-11-05 21:30:54 +00:00
|
|
|
|
2021-10-15 14:08:27 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def created_date(self):
|
|
|
|
|
|
|
|
return time.strftime("%d %b %Y", time.gmtime(self.created_utc))
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
2021-11-05 21:30:54 +00:00
|
|
|
def user_awards(self):
|
2021-10-15 14:08:27 +00:00
|
|
|
|
2021-11-02 21:29:53 +00:00
|
|
|
return_value = list(AWARDS2.values())
|
2021-10-15 14:08:27 +00:00
|
|
|
|
2021-11-06 15:52:48 +00:00
|
|
|
user_awards = g.db.query(AwardRelationship).filter_by(user_id=self.id)
|
2021-10-15 14:08:27 +00:00
|
|
|
|
|
|
|
for val in return_value: val['owned'] = user_awards.filter_by(kind=val['kind'], submission_id=None, comment_id=None).count()
|
|
|
|
|
|
|
|
return return_value
|
|
|
|
|
|
|
|
@property
|
|
|
|
def referral_count(self):
|
|
|
|
return len(self.referrals)
|
|
|
|
|
2021-11-29 23:07:57 +00:00
|
|
|
def is_blocking(self, target):
|
2022-01-02 00:06:46 +00:00
|
|
|
return g.db.query(UserBlock).filter_by(user_id=self.id, target_id=target.id).one_or_none()
|
2021-10-15 14:08:27 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def paid_dues(self):
|
2021-12-21 15:07:28 +00:00
|
|
|
return self.admin_level > 1 or self.club_allowed or self.truecoins > int(environ.get("DUES").strip()) and self.club_allowed != False
|
2021-10-15 14:08:27 +00:00
|
|
|
|
|
|
|
def any_block_exists(self, other):
|
|
|
|
|
2021-11-06 15:52:48 +00:00
|
|
|
return g.db.query(UserBlock).filter(
|
2021-10-15 14:08:27 +00:00
|
|
|
or_(and_(UserBlock.user_id == self.id, UserBlock.target_id == other.id), and_(
|
2022-01-02 00:06:46 +00:00
|
|
|
UserBlock.user_id == other.id, UserBlock.target_id == self.id))).one_or_none()
|
2021-10-15 14:08:27 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
|
2021-11-24 15:33:41 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def ban_reason_link(self):
|
2021-11-24 16:20:57 +00:00
|
|
|
if self.ban_reason:
|
2021-11-24 16:28:17 +00:00
|
|
|
if self.ban_reason.startswith("/post/"): return self.ban_reason.split(None, 1)[0]
|
2022-01-30 13:40:11 +00:00
|
|
|
if self.ban_reason.startswith("/comment/"): return self.ban_reason.split(None, 1)[0] + "?context=8#context"
|
2021-11-24 15:33:41 +00:00
|
|
|
|
2021-10-15 14:08:27 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def alts_unique(self):
|
|
|
|
alts = []
|
|
|
|
for u in self.alts:
|
|
|
|
if u not in alts: alts.append(u)
|
|
|
|
return alts
|
|
|
|
|
2022-01-02 18:03:51 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def alts_patron(self):
|
|
|
|
for u in self.alts_unique:
|
|
|
|
if u.patron: return True
|
|
|
|
return False
|
|
|
|
|
2021-10-15 14:08:27 +00:00
|
|
|
@cache.memoize(timeout=86400)
|
|
|
|
def userpagelisting(self, v=None, page=1, sort="new", t="all"):
|
|
|
|
|
2021-12-29 06:43:20 +00:00
|
|
|
if self.shadowbanned and not (v and (v.admin_level > 1 or v.id == self.id)): return []
|
2021-10-15 14:08:27 +00:00
|
|
|
|
2021-11-06 15:52:48 +00:00
|
|
|
posts = g.db.query(Submission.id).filter_by(author_id=self.id, is_pinned=False)
|
2021-10-15 14:08:27 +00:00
|
|
|
|
2021-11-15 22:19:59 +00:00
|
|
|
if not (v and (v.admin_level > 1 or v.id == self.id)):
|
2022-01-22 16:37:58 +00:00
|
|
|
posts = posts.filter_by(deleted_utc=0, is_banned=False, private=False, ghost=None)
|
2021-10-15 14:08:27 +00:00
|
|
|
|
|
|
|
now = int(time.time())
|
|
|
|
if t == 'hour':
|
|
|
|
cutoff = now - 3600
|
|
|
|
elif t == 'day':
|
|
|
|
cutoff = now - 86400
|
|
|
|
elif t == 'week':
|
|
|
|
cutoff = now - 604800
|
|
|
|
elif t == 'month':
|
|
|
|
cutoff = now - 2592000
|
|
|
|
elif t == 'year':
|
|
|
|
cutoff = now - 31536000
|
|
|
|
else:
|
|
|
|
cutoff = 0
|
|
|
|
posts = posts.filter(Submission.created_utc >= cutoff)
|
|
|
|
|
|
|
|
if sort == "new":
|
|
|
|
posts = posts.order_by(Submission.created_utc.desc())
|
|
|
|
elif sort == "old":
|
|
|
|
posts = posts.order_by(Submission.created_utc.asc())
|
|
|
|
elif sort == "controversial":
|
2021-11-30 23:21:29 +00:00
|
|
|
posts = posts.order_by(-1 * Submission.upvotes * Submission.downvotes * Submission.downvotes)
|
2021-10-15 14:08:27 +00:00
|
|
|
elif sort == "top":
|
2021-11-30 23:21:29 +00:00
|
|
|
posts = posts.order_by(Submission.downvotes - Submission.upvotes)
|
2021-10-15 14:08:27 +00:00
|
|
|
elif sort == "bottom":
|
2021-11-30 23:21:29 +00:00
|
|
|
posts = posts.order_by(Submission.upvotes - Submission.downvotes)
|
2021-10-15 14:08:27 +00:00
|
|
|
elif sort == "comments":
|
|
|
|
posts = posts.order_by(Submission.comment_count.desc())
|
|
|
|
|
|
|
|
posts = posts.offset(25 * (page - 1)).limit(26).all()
|
|
|
|
|
|
|
|
return [x[0] for x in posts]
|
|
|
|
|
2022-01-02 00:05:22 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def follow_count(self):
|
|
|
|
return g.db.query(Follow.id).filter_by(user_id=self.id).count()
|
|
|
|
|
2021-10-25 02:44:54 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def bio_html_eager(self):
|
2021-12-10 22:49:39 +00:00
|
|
|
if self.bio_html == None: return ''
|
2021-12-24 23:00:09 +00:00
|
|
|
return self.bio_html.replace('data-src', 'src').replace('src="/static/assets/images/loading.webp"', '')
|
2021-10-25 02:44:54 +00:00
|
|
|
|
2021-10-15 14:08:27 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def fullname(self):
|
|
|
|
return f"t1_{self.id}"
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def banned_by(self):
|
|
|
|
if not self.is_suspended: return None
|
2022-01-02 00:06:46 +00:00
|
|
|
return g.db.query(User).filter_by(id=self.is_banned).one_or_none()
|
2021-10-15 14:08:27 +00:00
|
|
|
|
2021-11-21 17:40:47 +00:00
|
|
|
def has_badge(self, badge_id):
|
2022-01-02 00:06:46 +00:00
|
|
|
return g.db.query(Badge).filter_by(user_id=self.id, badge_id=badge_id).one_or_none()
|
2021-10-15 14:08:27 +00:00
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
@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):
|
2022-01-28 20:02:35 +00:00
|
|
|
return f"{SITE_FULL}/@{self.username}"
|
2021-10-15 14:08:27 +00:00
|
|
|
|
|
|
|
def __repr__(self):
|
2022-01-21 11:55:53 +00:00
|
|
|
return f"<User(id={self.id})>"
|
2021-10-15 14:08:27 +00:00
|
|
|
|
|
|
|
@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 = {}
|
|
|
|
|
2021-11-06 15:52:48 +00:00
|
|
|
posts_idlist = [x[0] for x in g.db.query(Submission.id).filter_by(author_id=self.id).all()]
|
|
|
|
comments_idlist = [x[0] for x in g.db.query(Comment.id).filter_by(author_id=self.id).all()]
|
2021-10-15 14:08:27 +00:00
|
|
|
|
2021-11-06 15:52:48 +00:00
|
|
|
post_awards = g.db.query(AwardRelationship).filter(AwardRelationship.submission_id.in_(posts_idlist)).all()
|
|
|
|
comment_awards = g.db.query(AwardRelationship).filter(AwardRelationship.comment_id.in_(comments_idlist)).all()
|
2021-10-15 14:08:27 +00:00
|
|
|
|
|
|
|
total_awards = post_awards + comment_awards
|
|
|
|
|
|
|
|
for a in total_awards:
|
|
|
|
if a.kind in awards:
|
|
|
|
awards[a.kind]['count'] += 1
|
|
|
|
else:
|
|
|
|
awards[a.kind] = a.type
|
|
|
|
awards[a.kind]['count'] = 1
|
|
|
|
|
|
|
|
return sorted(list(awards.values()), key=lambda x: x['kind'], reverse=True)
|
|
|
|
|
2021-12-26 03:18:28 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def modaction_num(self):
|
|
|
|
if self.admin_level < 2: return 0
|
|
|
|
return g.db.query(ModAction.id).filter_by(user_id=self.id).count()
|
|
|
|
|
2021-10-15 14:08:27 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def notifications_count(self):
|
2021-11-06 15:52:48 +00:00
|
|
|
return g.db.query(Notification.id).join(Comment).filter(Notification.user_id == self.id, Notification.read == False, Comment.is_banned == False, Comment.deleted_utc == 0).count()
|
2021-11-05 17:55:23 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def post_notifications_count(self):
|
2021-11-18 14:21:19 +00:00
|
|
|
return g.db.query(Notification.id).join(Comment).filter(Notification.user_id == self.id, Notification.read == False, Comment.author_id == AUTOJANNY_ID).count()
|
2021-10-15 14:08:27 +00:00
|
|
|
|
2021-12-20 23:50:02 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def not_post_notifications_count(self):
|
|
|
|
return self.notifications_count - self.post_notifications_count
|
2021-10-15 14:08:27 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def alts(self):
|
|
|
|
|
2021-11-06 15:52:48 +00:00
|
|
|
subq = g.db.query(Alt).filter(
|
2021-10-15 14:08:27 +00:00
|
|
|
or_(
|
|
|
|
Alt.user1 == self.id,
|
|
|
|
Alt.user2 == self.id
|
|
|
|
)
|
|
|
|
).subquery()
|
|
|
|
|
|
|
|
data = g.db.query(
|
|
|
|
User,
|
2021-11-07 20:34:12 +00:00
|
|
|
aliased(Alt, alias=subq)
|
2021-11-06 15:52:48 +00:00
|
|
|
).join(
|
2021-10-15 14:08:27 +00:00
|
|
|
subq,
|
|
|
|
or_(
|
2021-11-07 20:34:12 +00:00
|
|
|
subq.c.user1 == User.id,
|
|
|
|
subq.c.user2 == User.id
|
2021-10-15 14:08:27 +00:00
|
|
|
)
|
|
|
|
).filter(
|
|
|
|
User.id != self.id
|
|
|
|
).order_by(User.username.asc()).all()
|
|
|
|
|
|
|
|
data = [x for x in data]
|
|
|
|
output = []
|
|
|
|
for x in data:
|
|
|
|
user = x[0]
|
|
|
|
user._is_manual = x[1].is_manual
|
|
|
|
output.append(user)
|
|
|
|
|
|
|
|
return output
|
|
|
|
|
|
|
|
def has_follower(self, user):
|
|
|
|
|
2022-01-02 00:06:46 +00:00
|
|
|
return g.db.query(Follow).filter_by(target_id=self.id, user_id=user.id).one_or_none()
|
2021-10-15 14:08:27 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def banner_url(self):
|
|
|
|
if self.bannerurl: return self.bannerurl
|
2022-02-05 10:25:36 +00:00
|
|
|
else: return f"{SITE_FULL}/static/assets/images/{SITE_NAME}/site_preview.webp?a=1009"
|
2021-10-15 14:08:27 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def profile_url(self):
|
2022-01-24 16:44:54 +00:00
|
|
|
if self.agendaposter: return f"{SITE_FULL}/static/assets/images/defaultpictures/agendaposter/{random.randint(1, 51)}.webp?a=1008"
|
2022-01-24 21:38:03 +00:00
|
|
|
if self.profileurl:
|
|
|
|
if self.profileurl.startswith('/'): return SITE_FULL + self.profileurl
|
|
|
|
return self.profileurl
|
2022-02-01 04:20:31 +00:00
|
|
|
if SITE_NAME == 'Drama': return f"{SITE_FULL}/static/assets/images/defaultpictures/bhm/{random.randint(1, 25)}.webp?a=1008"
|
2022-01-24 16:44:54 +00:00
|
|
|
return f"{SITE_FULL}/static/assets/images/default-profile-pic.webp?a=1008"
|
2021-10-15 14:08:27 +00:00
|
|
|
|
2021-12-10 23:29:35 +00:00
|
|
|
@lazy
|
2021-12-17 05:08:40 +00:00
|
|
|
def json_popover(self, v):
|
2021-12-10 23:29:35 +00:00
|
|
|
data = {'username': self.username,
|
|
|
|
'url': self.url,
|
2022-01-03 01:54:13 +00:00
|
|
|
'id': self.id,
|
2021-12-10 23:29:35 +00:00
|
|
|
'profile_url': self.profile_url,
|
|
|
|
'bannerurl': self.banner_url,
|
|
|
|
'bio_html': self.bio_html_eager,
|
|
|
|
'coins': self.coins,
|
2021-12-17 05:08:40 +00:00
|
|
|
'post_count': 0 if self.shadowbanned and not (v and (v.shadowbanned or v.admin_level)) else self.post_count,
|
|
|
|
'comment_count': 0 if self.shadowbanned and not (v and (v.shadowbanned or v.admin_level)) else self.comment_count,
|
2021-12-11 00:53:16 +00:00
|
|
|
'badges': [x.path for x in self.badges],
|
2021-12-10 23:29:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return data
|
|
|
|
|
2021-10-15 14:08:27 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def json_raw(self):
|
|
|
|
data = {'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,
|
2022-01-28 21:42:09 +00:00
|
|
|
'profile_url': self.profile_url,
|
2021-12-10 22:52:13 +00:00
|
|
|
'bannerurl': self.banner_url,
|
2021-10-15 14:08:27 +00:00
|
|
|
'bio': self.bio,
|
2021-12-10 22:49:39 +00:00
|
|
|
'bio_html': self.bio_html_eager,
|
2021-10-15 14:08:27 +00:00
|
|
|
'flair': self.customtitle
|
|
|
|
}
|
|
|
|
|
|
|
|
return data
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def json_core(self):
|
|
|
|
|
|
|
|
now = int(time.time())
|
2022-01-06 16:46:09 +00:00
|
|
|
if self.is_suspended:
|
2021-10-15 14:08:27 +00:00
|
|
|
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 self.json_raw
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def json(self):
|
|
|
|
data = self.json_core
|
|
|
|
|
2021-12-12 19:20:57 +00:00
|
|
|
data["badges"] = [x.json for x in self.badges]
|
2021-12-10 23:29:35 +00:00
|
|
|
data['coins'] = self.coins
|
2021-10-15 14:08:27 +00:00
|
|
|
data['post_count'] = self.post_count
|
|
|
|
data['comment_count'] = self.comment_count
|
|
|
|
|
|
|
|
return data
|
|
|
|
|
2021-12-03 19:20:52 +00:00
|
|
|
def deletepfp(self):
|
|
|
|
if self.highres and '/images/' in self.highres:
|
|
|
|
image = '/images/' + self.highres.split('/images/')[1]
|
|
|
|
if path.exists(image): remove(image)
|
|
|
|
if self.profileurl and '/images/' in self.profileurl:
|
|
|
|
image = '/images/' + self.profileurl.split('/images/')[1]
|
|
|
|
if path.exists(image): remove(image)
|
|
|
|
self.highres = None
|
|
|
|
self.profileurl = None
|
|
|
|
|
|
|
|
def deletebanner(self):
|
|
|
|
if self.bannerurl and '/images/' in self.bannerurl:
|
|
|
|
image = '/images/' + self.bannerurl.split('/images/')[1]
|
|
|
|
if path.exists(image): remove(image)
|
|
|
|
self.bannerurl = None
|
2021-10-15 14:08:27 +00:00
|
|
|
|
2021-12-03 19:20:52 +00:00
|
|
|
def ban(self, admin=None, reason=None, days=0):
|
2022-01-16 01:04:31 +00:00
|
|
|
if days:
|
|
|
|
self.unban_utc = int(time.time()) + (days * 86400)
|
|
|
|
g.db.add(self)
|
2022-01-16 00:54:04 +00:00
|
|
|
elif self.discord_id: remove_user(self)
|
2021-10-15 14:08:27 +00:00
|
|
|
|
2021-11-18 14:21:19 +00:00
|
|
|
self.is_banned = admin.id if admin else AUTOJANNY_ID
|
2021-10-15 14:08:27 +00:00
|
|
|
if reason: self.ban_reason = reason
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
def is_suspended(self):
|
2022-01-06 16:46:09 +00:00
|
|
|
return (self.is_banned and (self.unban_utc == 0 or self.unban_utc > time.time()))
|
2021-10-15 14:08:27 +00:00
|
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def applications(self):
|
2022-01-06 20:30:08 +00:00
|
|
|
return g.db.query(OauthApp).filter_by(author_id=self.id).order_by(OauthApp.id)
|
2021-10-15 14:08:27 +00:00
|
|
|
|
2022-01-13 23:29:15 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def created_datetime(self):
|
|
|
|
return str(time.strftime("%d/%B/%Y %H:%M:%S UTC", time.gmtime(self.created_utc)))
|
|
|
|
|
2021-10-15 14:08:27 +00:00
|
|
|
@lazy
|
|
|
|
def subscribed_idlist(self, page=1):
|
2021-11-06 15:52:48 +00:00
|
|
|
posts = g.db.query(Subscription.submission_id).filter_by(user_id=self.id).all()
|
2021-10-15 14:08:27 +00:00
|
|
|
return [x[0] for x in posts]
|
|
|
|
|
|
|
|
@lazy
|
|
|
|
def saved_idlist(self, page=1):
|
|
|
|
|
2021-11-06 15:52:48 +00:00
|
|
|
saved = [x[0] for x in g.db.query(SaveRelationship.submission_id).filter(SaveRelationship.user_id == self.id).all()]
|
2022-01-29 13:53:45 +00:00
|
|
|
posts = g.db.query(Submission.id).filter(Submission.id.in_(saved), Submission.is_banned == False, Submission.deleted_utc == 0)
|
2021-10-15 14:08:27 +00:00
|
|
|
|
|
|
|
if self.admin_level == 0:
|
|
|
|
blocking = [x[0] for x in g.db.query(
|
2021-11-06 15:52:48 +00:00
|
|
|
UserBlock.target_id).filter_by(
|
2021-10-15 14:08:27 +00:00
|
|
|
user_id=self.id).all()]
|
|
|
|
blocked = [x[0] for x in g.db.query(
|
2021-11-06 15:52:48 +00:00
|
|
|
UserBlock.user_id).filter_by(
|
2021-10-15 14:08:27 +00:00
|
|
|
target_id=self.id).all()]
|
|
|
|
|
|
|
|
posts = posts.filter(
|
|
|
|
Submission.author_id.notin_(blocking),
|
|
|
|
Submission.author_id.notin_(blocked)
|
|
|
|
)
|
|
|
|
|
2022-01-29 13:53:45 +00:00
|
|
|
return [x[0] for x in posts.order_by(Submission.created_utc.desc()).offset(25 * (page - 1)).all()]
|
2021-10-15 14:08:27 +00:00
|
|
|
|
|
|
|
@lazy
|
2022-01-29 13:57:55 +00:00
|
|
|
def saved_comment_idlist(self, page=1):
|
2021-10-15 14:08:27 +00:00
|
|
|
|
2021-11-06 15:52:48 +00:00
|
|
|
try: saved = [x[0] for x in g.db.query(SaveRelationship.comment_id).filter(SaveRelationship.user_id == self.id).all()]
|
2021-10-15 14:08:27 +00:00
|
|
|
except: return []
|
2022-01-29 13:53:45 +00:00
|
|
|
comments = g.db.query(Comment.id).filter(Comment.id.in_(saved), Comment.is_banned == False, Comment.deleted_utc == 0)
|
2021-10-15 14:08:27 +00:00
|
|
|
|
|
|
|
if self.admin_level == 0:
|
|
|
|
blocking = [x[0] for x in g.db.query(
|
2021-11-06 15:52:48 +00:00
|
|
|
UserBlock.target_id).filter_by(
|
2021-10-15 14:08:27 +00:00
|
|
|
user_id=self.id).all()]
|
|
|
|
blocked = [x[0] for x in g.db.query(
|
2021-11-06 15:52:48 +00:00
|
|
|
UserBlock.user_id).filter_by(
|
2021-10-15 14:08:27 +00:00
|
|
|
target_id=self.id).all()]
|
|
|
|
|
|
|
|
comments = comments.filter(
|
|
|
|
Comment.author_id.notin_(blocking),
|
|
|
|
Comment.author_id.notin_(blocked)
|
|
|
|
)
|
|
|
|
|
2022-01-29 13:57:55 +00:00
|
|
|
return [x[0] for x in comments.order_by(Comment.created_utc.desc()).offset(25 * (page - 1)).all()]
|
2021-10-15 14:08:27 +00:00
|
|
|
|
2022-01-29 13:53:45 +00:00
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def saved_count(self):
|
|
|
|
return len(self.saved_idlist())
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def saved_comment_count(self):
|
|
|
|
return len(self.saved_comment_idlist())
|
|
|
|
|
2021-10-15 14:08:27 +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
|
|
|
|
|
|
|
|
|
|
|
|
class ViewerRelationship(Base):
|
|
|
|
|
|
|
|
__tablename__ = "viewers"
|
|
|
|
|
|
|
|
id = Column(Integer, Sequence('viewers_id_seq'), primary_key=True)
|
|
|
|
user_id = Column(Integer, ForeignKey('users.id'))
|
|
|
|
viewer_id = Column(Integer, ForeignKey('users.id'))
|
|
|
|
last_view_utc = Column(Integer)
|
|
|
|
|
|
|
|
viewer = relationship("User", primaryjoin="ViewerRelationship.viewer_id == User.id", viewonly=True)
|
|
|
|
|
|
|
|
def __init__(self, **kwargs):
|
|
|
|
|
|
|
|
if 'last_view_utc' not in kwargs:
|
|
|
|
kwargs['last_view_utc'] = int(time.time())
|
|
|
|
|
|
|
|
super().__init__(**kwargs)
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def last_view_since(self):
|
|
|
|
|
|
|
|
return int(time.time()) - self.last_view_utc
|
|
|
|
|
|
|
|
@property
|
|
|
|
@lazy
|
|
|
|
def last_view_string(self):
|
|
|
|
|
|
|
|
age = self.last_view_since
|
|
|
|
|
|
|
|
if age < 60:
|
|
|
|
return "just now"
|
|
|
|
elif age < 3600:
|
|
|
|
minutes = int(age / 60)
|
|
|
|
return f"{minutes}m ago"
|
|
|
|
elif age < 86400:
|
|
|
|
hours = int(age / 3600)
|
|
|
|
return f"{hours}hr ago"
|
|
|
|
elif age < 2678400:
|
|
|
|
days = int(age / 86400)
|
|
|
|
return f"{days}d ago"
|
|
|
|
|
|
|
|
now = time.gmtime()
|
|
|
|
ctd = time.gmtime(self.created_utc)
|
|
|
|
|
|
|
|
months = now.tm_mon - ctd.tm_mon + 12 * (now.tm_year - ctd.tm_year)
|
|
|
|
if now.tm_mday < ctd.tm_mday:
|
|
|
|
months -= 1
|
|
|
|
|
|
|
|
if months < 12:
|
|
|
|
return f"{months}mo ago"
|
|
|
|
else:
|
|
|
|
years = int(months / 12)
|
2022-02-01 04:20:31 +00:00
|
|
|
return f"{years}yr ago"
|