diff --git a/env b/env
index 4d8b5c95fd..f3f82e5d57 100644
--- a/env
+++ b/env
@@ -26,7 +26,6 @@ export GUMROAD_LINK="blahblahblah"
export GUMROAD_ID="blahblahblah"
export CARD_VIEW="0"
export DISABLE_DOWNVOTES="0"
-export DUES="0"
export DEFAULT_THEME="midnight"
export DEFAULT_COLOR="805ad5"
export EMAIL="blahblahblah@gmail.com"
diff --git a/files/assets/css/main.css b/files/assets/css/main.css
index e0409f3c7c..02b8d154c5 100644
--- a/files/assets/css/main.css
+++ b/files/assets/css/main.css
@@ -5953,7 +5953,6 @@ g {
.fa-gift:before{content:"\f06b"}
.fa-gingerbread-man:before{content:"\f79d"}
.fa-globe:before{content:"\f0ac"}
-.fa-golf-club:before{content:"\f451"}
.fa-home-alt:before{content:"\f015"}
.fa-id-badge:before{content:"\f2c1"}
.fa-id-card:before{content:"\f2c2"}
@@ -6065,7 +6064,6 @@ g {
.fa-trees:before{content:"\f724"}
.fa-flashlight:before{content:"\f8b8"}
.fa-candy-corn:before{content:"\f6bd"}
-.fa-club:before{content:"\f327"}
.fa-shirt:before{content:"\f553"}
.fa-bone:before{content:"\f5d7"}
.fa-jack-o-lantern:before{content:"\f30e"}
diff --git a/files/assets/js/submit.js b/files/assets/js/submit.js
index 26b3416c1c..38c3b1a199 100644
--- a/files/assets/js/submit.js
+++ b/files/assets/js/submit.js
@@ -6,7 +6,6 @@ document.getElementById('post-notify').checked = localStorage.getItem("post-noti
document.getElementById('post-new').checked = localStorage.getItem("post-new") == 'true'
document.getElementById('post-nsfw').checked = localStorage.getItem("post-nsfw") == 'true'
document.getElementById('post-private').checked = localStorage.getItem("post-private") == 'true'
-document.getElementById('post-club').checked = localStorage.getItem("post-club") == 'true'
document.getElementById('post-ghost').checked = localStorage.getItem("post-ghost") == 'true'
markdown(document.getElementById("post-text"));
@@ -121,7 +120,6 @@ function savetext() {
localStorage.setItem("post-new", document.getElementById('post-new').checked)
localStorage.setItem("post-nsfw", document.getElementById('post-nsfw').checked)
localStorage.setItem("post-private", document.getElementById('post-private').checked)
- localStorage.setItem("post-club", document.getElementById('post-club').checked)
localStorage.setItem("post-ghost", document.getElementById('post-ghost').checked)
}
diff --git a/files/classes/comment.py b/files/classes/comment.py
index 1555a5516c..41f037cb05 100644
--- a/files/classes/comment.py
+++ b/files/classes/comment.py
@@ -243,8 +243,6 @@ class Comment(Base):
@lazy
def realbody(self, v):
- if self.post and self.post.club and not (v and (v.paid_dues or v.id in {self.author_id, self.post.author_id} or (self.parent_comment and v.id == self.parent_comment.author_id))):
- return f"
{CC} ONLY
"
if self.deleted_utc != 0 and not (v and (v.admin_level >= PERMS['POST_COMMENT_MODERATION'] or v.id == self.author.id)): return "[Deleted by user]"
if self.is_banned and not (v and v.admin_level >= PERMS['POST_COMMENT_MODERATION']) and not (v and v.id == self.author.id): return ""
@@ -301,8 +299,6 @@ class Comment(Base):
@lazy
def plainbody(self, v):
- if self.post and self.post.club and not (v and (v.paid_dues or v.id in {self.author_id, self.post.author_id} or (self.parent_comment and v.id == self.parent_comment.author_id))):
- return f"{CC} ONLY"
if self.deleted_utc != 0 and not (v and (v.admin_level >= PERMS['POST_COMMENT_MODERATION'] or v.id == self.author.id)): return "[Deleted by user]"
if self.is_banned and not (v and v.admin_level >= PERMS['POST_COMMENT_MODERATION']) and not (v and v.id == self.author.id): return ""
diff --git a/files/classes/mod_logs.py b/files/classes/mod_logs.py
index 089c44cc77..889c73570f 100644
--- a/files/classes/mod_logs.py
+++ b/files/classes/mod_logs.py
@@ -50,7 +50,7 @@ class ModAction(Base):
@property
@lazy
def string(self):
- output = ACTIONTYPES[self.kind]["str"].format(self=self, cc=CC_TITLE)
+ output = ACTIONTYPES[self.kind]["str"].format(self=self)
if self.note: output += f" ({self.note})"
return output
@@ -59,7 +59,6 @@ class ModAction(Base):
def target_link(self):
if self.target_user: return f'{self.target_user.username}'
elif self.target_post:
- if self.target_post.club: return f'{CC} ONLY'
return censor_slurs(f'{self.target_post.title_html}', None)
elif self.target_comment_id: return f'comment'
@@ -119,16 +118,6 @@ ACTIONTYPES = {
"icon": 'fa-user-slash',
"color": 'bg-danger'
},
- 'club_allow': {
- "str": 'allowed user {self.target_link} into the {cc}',
- "icon": 'fa-golf-club',
- "color": 'bg-success'
- },
- 'club_ban': {
- "str": 'disallowed user {self.target_link} from the {cc}',
- "icon": 'fa-golf-club',
- "color": 'bg-danger'
- },
'delete_report': {
"str": 'deleted report on {self.target_link}',
"icon": 'fa-flag',
@@ -409,16 +398,6 @@ ACTIONTYPES = {
"icon": 'fa-cat',
"color": 'bg-success'
},
- 'club_post': {
- "str": 'moved post {self.target_link} to the {cc}',
- "icon": 'fa-club',
- "color": 'bg-success'
- },
- 'unclub_post': {
- "str": 'removed post {self.target_link} from the {cc}',
- "icon": 'fa-club',
- "color": 'bg-muted'
- },
}
ACTIONTYPES2 = deepcopy(ACTIONTYPES)
diff --git a/files/classes/sub_logs.py b/files/classes/sub_logs.py
index 649c4cccac..6ed27e9de0 100644
--- a/files/classes/sub_logs.py
+++ b/files/classes/sub_logs.py
@@ -41,7 +41,7 @@ class SubAction(Base):
@property
@lazy
def string(self):
- output = ACTIONTYPES[self.kind]["str"].format(self=self, cc=CC_TITLE)
+ output = ACTIONTYPES[self.kind]["str"].format(self=self)
if self._note: output += f" ({self._note})"
return output
@@ -50,7 +50,6 @@ class SubAction(Base):
def target_link(self):
if self.target_user: return f'{self.target_user.username}'
elif self.target_post:
- if self.target_post.club: return f'{CC} ONLY'
return censor_slurs(f'{self.target_post.title_html}', None)
elif self.target_comment_id: return f'comment'
diff --git a/files/classes/submission.py b/files/classes/submission.py
index 22307759ee..7623e19115 100644
--- a/files/classes/submission.py
+++ b/files/classes/submission.py
@@ -38,7 +38,6 @@ class Submission(Base):
sub = Column(String, ForeignKey("subs.name"))
is_pinned = Column(Boolean, default=False)
private = Column(Boolean, default=False)
- club = Column(Boolean, default=False)
comment_count = Column(Integer, default=0)
is_approved = Column(Integer, ForeignKey("users.id"))
over_18 = Column(Boolean, default=False)
@@ -113,8 +112,6 @@ class Submission(Base):
link = f"/post/{self.id}"
if self.sub: link = f"/h/{self.sub}{link}"
- if self.club: return link + '/-'
-
output = title_regex.sub('', self.title.lower())
output = output.split()[:6]
output = '-'.join(output)
@@ -210,7 +207,6 @@ class Submission(Base):
'distinguish_level': self.distinguish_level,
'voted': self.voted if hasattr(self, 'voted') else 0,
'flags': flags,
- 'club': self.club,
'author': '👻' if self.ghost else self.author.json,
'comment_count': self.comment_count
}
@@ -270,7 +266,6 @@ class Submission(Base):
@lazy
def realbody(self, v, listing=False):
- if self.club and not (v and (v.paid_dues or v.id == self.author_id)): return f"
{CC} ONLY
"
if self.deleted_utc != 0 and not (v and (v.admin_level >= PERMS['POST_COMMENT_MODERATION'] or v.id == self.author.id)): return "[Deleted by user]"
if self.is_banned and not (v and v.admin_level >= PERMS['POST_COMMENT_MODERATION']) and not (v and v.id == self.author.id): return ""
@@ -333,7 +328,6 @@ class Submission(Base):
def plainbody(self, v):
if self.deleted_utc != 0 and not (v and (v.admin_level >= PERMS['POST_COMMENT_MODERATION'] or v.id == self.author.id)): return "[Deleted by user]"
if self.is_banned and not (v and v.admin_level >= PERMS['POST_COMMENT_MODERATION']) and not (v and v.id == self.author.id): return ""
- if self.club and not (v and (v.paid_dues or v.id == self.author_id)): return f"
{CC} ONLY
"
body = self.body
if not body: return ""
@@ -348,12 +342,7 @@ class Submission(Base):
@lazy
def realtitle(self, v):
- if self.club and not (v and (v.paid_dues or v.id == self.author_id)):
- if v: return random.choice(TROLLTITLES).format(username=v.username)
- elif DUES == -2: return f'Please make an account to see this post'
- else: return f'{CC} MEMBERS ONLY'
- elif self.title_html: title = self.title_html
- else: title = self.title
+ title = self.title_html
title = censor_slurs(title, v)
@@ -364,10 +353,7 @@ class Submission(Base):
@lazy
def plaintitle(self, v):
- if self.club and not (v and (v.paid_dues or v.id == self.author_id)):
- if v: return random.choice(TROLLTITLES).format(username=v.username)
- else: return f'{CC} MEMBERS ONLY'
- else: title = self.title
+ title = self.title
title = censor_slurs(title, v).replace('', ':marseytrain:')
diff --git a/files/classes/user.py b/files/classes/user.py
index 6f3fb05b78..0149235c9c 100644
--- a/files/classes/user.py
+++ b/files/classes/user.py
@@ -109,7 +109,6 @@ class User(Base):
unban_utc = Column(Integer, default=0)
ban_reason = deferred(Column(String))
is_muted = Column(Boolean, default=False, nullable=False)
- club_allowed = Column(Boolean)
login_nonce = Column(Integer, default=0)
coins = Column(Integer, default=0)
truescore = Column(Integer, default=0)
@@ -451,14 +450,6 @@ class User(Base):
def has_blocked(self, target):
return g.db.query(UserBlock).filter_by(user_id=self.id, target_id=target.id).one_or_none()
- @property
- @lazy
- def paid_dues(self):
- if not FEATURES['COUNTRY_CLUB']: return True
- if self.shadowbanned: return False
- if self.is_suspended_permanently: return False
- return self.admin_level >= PERMS['VIEW_CLUB'] or self.club_allowed or (self.club_allowed != False and self.truescore >= DUES)
-
@lazy
def any_block_exists(self, other):
@@ -1015,11 +1006,8 @@ class User(Base):
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, Submission):
- if other.club and not (user and user.paid_dues): return False
- if other.sub == 'chudrama' and not (user and user.can_see_chudrama): return False
- else:
- if other.parent_submission and not cls.can_see_content(user, other.post): return False
+ if isinstance(other, Comment):
+ if other.parent_submission and not cls.can_see(user, other.post): return False
return True
@classmethod
@@ -1045,7 +1033,9 @@ class User(Base):
if other.parent_submission and other.post.sub and not cls.can_see(user, other.post.subr): return False
# if other.parent_submission and not cls.can_see(user, other.post): return False
elif isinstance(other, Sub):
- return other.name != 'chudrama' or (user and user.can_see_chudrama)
+ if other.name == 'chudrama': return bool(user) and user.can_see_chudrama
+ if other.name == 'countryclub': return bool(user) and user.can_see_countryclub
+ if other.name == 'masterbaiters': return bool(user) and user.can_see_masterbaiters
elif isinstance(other, User):
return (user and user.id == other.id) or (user and user.can_see_shadowbanned) or not other.shadowbanned
return True
@@ -1055,17 +1045,33 @@ class User(Base):
def can_see_chudrama(self):
if self.admin_level >= PERMS['VIEW_CHUDRAMA']: return True
if self.client: return True
- if self.truescore >= 5000: return True
+ if self.truescore >= TRUESCORE_CHUDRAMA_MINIMUM: return True
if self.agendaposter: return True
if self.patron: return True
return False
-
+
+ @property
+ @lazy
+ def can_see_countryclub(self):
+ if self.shadowbanned: return False
+ if self.is_suspended_permanently: return False
+ if self.agendaposter == 1: return False
+ if self.admin_level >= PERMS['VIEW_CLUB']: return True
+ if self.truescore >= TRUESCORE_CLUB_MINIMUM: return True
+ return False
+
+ @property
+ @lazy
+ def can_see_masterbaiters(self):
+ if self.shadowbanned: return False
+ if self.is_suspended_permanently: return False
+ return True
+
@property
@lazy
def can_post_in_ghost_threads(self):
if not TRUESCORE_GHOST_MINIMUM: return True
if self.admin_level >= PERMS['POST_IN_GHOST_THREADS']: return True
- if self.club_allowed: return True
if self.truescore >= TRUESCORE_GHOST_MINIMUM: return True
if self.patron: return True
return False
diff --git a/files/helpers/const.py b/files/helpers/const.py
index c6be9c9315..5b2e003192 100644
--- a/files/helpers/const.py
+++ b/files/helpers/const.py
@@ -29,7 +29,6 @@ GUMROAD_TOKEN = environ.get("GUMROAD_TOKEN", DEFAULT_CONFIG_VALUE).strip()
GUMROAD_LINK = environ.get("GUMROAD_LINK", DEFAULT_CONFIG_VALUE).strip()
GUMROAD_ID = environ.get("GUMROAD_ID", DEFAULT_CONFIG_VALUE).strip()
DISABLE_DOWNVOTES = bool(int(environ.get("DISABLE_DOWNVOTES", "0").strip()))
-DUES = int(environ.get("DUES", "0").strip())
DEFAULT_THEME = environ.get("DEFAULT_THEME", "midnight").strip()
DEFAULT_COLOR = environ.get("DEFAULT_COLOR", "805ad5").strip()
CARD_VIEW = bool(int(environ.get("CARD_VIEW", "0").strip()))
@@ -69,10 +68,6 @@ REDDIT_NOTIFS_CACHE_KEY = "reddit_notifications"
MARSEYS_CACHE_KEY = "marseys"
EMOJIS_CACHE_KEY = "emojis"
-if SITE_NAME == 'PCM': CC = "SPLASH MOUNTAIN"
-else: CC = "COUNTRY CLUB"
-CC_TITLE = CC.title()
-
CASINO_RELEASE_DAY = 1662825600
if SITE_NAME == 'rDrama': patron = 'Paypig'
@@ -241,7 +236,6 @@ PERMS = { # Minimum admin_level to perform action.
'USER_BAN': 2,
'USER_SHADOWBAN': 2,
'USER_AGENDAPOSTER': 2,
- 'USER_CLUB_ALLOW_BAN': 2,
'USER_LINK': 2,
'USER_MERGE': 3, # note: extra check for Aevann
'USER_TITLE_CHANGE': 2,
@@ -300,7 +294,6 @@ FEATURES = {
'AWARDS': True,
'CHAT': True,
'PINS': True,
- 'COUNTRY_CLUB': True,
'PRONOUNS': False,
'BADGES': True,
'HATS': True,
@@ -403,6 +396,8 @@ COSMETIC_AWARD_COIN_AWARD_PCT = 0.10
TRUESCORE_CHAT_MINIMUM = 0
TRUESCORE_DONATE_MINIMUM = 100
TRUESCORE_GHOST_MINIMUM = 0
+TRUESCORE_CHUDRAMA_MINIMUM = 5000
+TRUESCORE_CLUB_MINIMUM = 1000
CHAT_DISPLAY_USER_COUNT_MINIMUM = 0
LOGGEDIN_ACTIVE_TIME = 15 * 60
diff --git a/files/routes/admin.py b/files/routes/admin.py
index e68d343b7c..995409e06c 100644
--- a/files/routes/admin.py
+++ b/files/routes/admin.py
@@ -295,58 +295,6 @@ def revert_actions(v, username):
return {"message": f"@{user.username}'s admin actions have been reverted!"}
-@app.post("/@/club_allow")
-@limiter.limit(DEFAULT_RATELIMIT_SLOWER)
-@admin_level_required(PERMS['USER_CLUB_ALLOW_BAN'])
-def club_allow(v, username):
- u = get_user(username, v=v)
-
- if u.admin_level >= v.admin_level: abort(403, 'noob')
-
- u.club_allowed = True
- g.db.add(u)
-
- for x in u.alts_unique:
- x.club_allowed = True
- g.db.add(x)
-
- ma = ModAction(
- kind="club_allow",
- user_id=v.id,
- target_user_id=u.id
- )
- g.db.add(ma)
-
- send_repeatable_notification(u.id, f"@{v.username} (Admin) has inducted you into the {CC_TITLE}!")
-
- return {"message": f"@{u.username} has been allowed into the {CC_TITLE}!"}
-
-@app.post("/@/club_ban")
-@limiter.limit(DEFAULT_RATELIMIT_SLOWER)
-@admin_level_required(PERMS['USER_CLUB_ALLOW_BAN'])
-def club_ban(v, username):
- u = get_user(username, v=v)
-
- if u.admin_level >= v.admin_level: abort(403, 'noob')
-
- u.club_allowed = False
-
- for x in u.alts_unique:
- u.club_allowed = False
- g.db.add(x)
-
- ma = ModAction(
- kind="club_ban",
- user_id=v.id,
- target_user_id=u.id
- )
- g.db.add(ma)
-
- send_repeatable_notification(u.id, f"@{v.username} (Admin) has disallowed you from the {CC_TITLE}!")
-
- return {"message": f"@{u.username} has been disallowed from the {CC_TITLE}. Deserved."}
-
-
@app.get("/admin/shadowbanned")
@admin_level_required(PERMS['USER_SHADOWBAN'])
def shadowbanned(v):
diff --git a/files/routes/chat.py b/files/routes/chat.py
index 399d47ded0..d3b0bd1f0d 100644
--- a/files/routes/chat.py
+++ b/files/routes/chat.py
@@ -39,7 +39,7 @@ user_ids_to_socket_ids = {}
@app.get("/chat")
@is_not_permabanned
def chat(v):
- if TRUESCORE_CHAT_MINIMUM and v.truescore < TRUESCORE_CHAT_MINIMUM and not v.club_allowed:
+ if TRUESCORE_CHAT_MINIMUM and v.truescore < TRUESCORE_CHAT_MINIMUM:
abort(403, f"Need at least {TRUESCORE_CHAT_MINIMUM} truescore for access to chat.")
return render_template("chat.html", v=v, messages=messages)
@@ -51,7 +51,8 @@ def chat(v):
def speak(data, v):
limiter.check()
if v.is_banned: return '', 403
- if TRUESCORE_CHAT_MINIMUM and v.truescore < TRUESCORE_CHAT_MINIMUM and not v.club_allowed: return '', 403
+ if TRUESCORE_CHAT_MINIMUM and v.truescore < TRUESCORE_CHAT_MINIMUM:
+ return '', 403
vname = v.username.lower()
if vname in muted and not v.admin_level >= PERMS['CHAT_BYPASS_MUTE']:
diff --git a/files/routes/comments.py b/files/routes/comments.py
index 64ed6b8a3c..aee3f96490 100644
--- a/files/routes/comments.py
+++ b/files/routes/comments.py
@@ -33,7 +33,6 @@ WORDLE_COLOR_MAPPINGS = {-1: "🟥", 0: "🟨", 1: "🟩"}
def post_pid_comment_cid(cid, pid=None, anything=None, v=None, sub=None):
comment = get_comment(cid, v=v)
if not User.can_see(v, comment): abort(404)
- if comment.post and comment.post.club and not User.can_see_content(v, comment): abort(403)
if v and request.values.get("read"):
notif = g.db.query(Notification).filter_by(comment_id=cid, user_id=v.id, read=False).one_or_none()
@@ -112,8 +111,6 @@ def comment(v):
if sub in ('furry','vampire','racist','femboy') and not v.client and not v.house.lower().startswith(sub):
abort(403, f"You need to be a member of House {sub.capitalize()} to comment in /h/{sub}")
- if parent_post.club and not (v and (v.paid_dues or v.id == parent_post.author_id)): abort(403)
-
if not User.can_see(v, parent): abort(404)
if parent.deleted_utc != 0: abort(404)
diff --git a/files/routes/front.py b/files/routes/front.py
index fa11d9fcb8..ec2656c7b5 100644
--- a/files/routes/front.py
+++ b/files/routes/front.py
@@ -18,7 +18,8 @@ from files.__main__ import app, cache, limiter
def front_all(v, sub=None, subdomain=None):
if sub:
sub = get_sub_by_name(sub, graceful=True)
- if sub and not User.can_see(v, sub): abort(403, "You need 5000 truescore to be able to see /h/chudrama")
+ if sub and not User.can_see(v, sub):
+ abort(403)
if (request.path.startswith('/h/') or request.path.startswith('/s/')) and not sub: abort(404)
@@ -220,9 +221,6 @@ def comment_idlist(v=None, page=1, sort="new", t="all", gt=0, lt=0, site=None):
Comment.author_id.notin_(v.userblocks),
)
- if not v.paid_dues:
- comments = comments.filter(Submission.club == False)
-
if gt: comments = comments.filter(Comment.created_utc > gt)
if lt: comments = comments.filter(Comment.created_utc < lt)
diff --git a/files/routes/jinja2.py b/files/routes/jinja2.py
index 4b8afed067..066a37510f 100644
--- a/files/routes/jinja2.py
+++ b/files/routes/jinja2.py
@@ -77,13 +77,13 @@ def calc_users():
def inject_constants():
return {"environ":environ, "SITE":SITE, "SITE_NAME":SITE_NAME, "SITE_FULL":SITE_FULL,
"AUTOJANNY_ID":AUTOJANNY_ID, "MODMAIL_ID":MODMAIL_ID, "VAPID_PUBLIC_KEY":VAPID_PUBLIC_KEY,
- "CC":CC, "CC_TITLE":CC_TITLE, "listdir":listdir, "os_path":path, "AEVANN_ID":AEVANN_ID,
+ "listdir":listdir, "os_path":path, "AEVANN_ID":AEVANN_ID,
"PIZZASHILL_ID":PIZZASHILL_ID, "DEFAULT_COLOR":DEFAULT_COLOR,
"COLORS":COLORS, "time":time, "PERMS":PERMS, "FEATURES":FEATURES,
"HOLE_NAME":HOLE_NAME, "HOLE_STYLE_FLAIR":HOLE_STYLE_FLAIR, "HOLE_REQUIRED":HOLE_REQUIRED,
"GUMROAD_LINK":GUMROAD_LINK, "DEFAULT_THEME":DEFAULT_THEME, "DESCRIPTION":DESCRIPTION,
"has_sidebar":has_sidebar, "has_logo":has_logo,
- "FP":FP, "CHAT_DISPLAY_USER_COUNT_MINIMUM":CHAT_DISPLAY_USER_COUNT_MINIMUM, "patron":patron, "DUES":DUES,
+ "FP":FP, "CHAT_DISPLAY_USER_COUNT_MINIMUM":CHAT_DISPLAY_USER_COUNT_MINIMUM, "patron":patron,
"SIDEBAR_THREAD":SIDEBAR_THREAD, "BANNER_THREAD":BANNER_THREAD,
"BADGE_THREAD":BADGE_THREAD, "SNAPPY_THREAD":SNAPPY_THREAD,
"KOFI_TOKEN":KOFI_TOKEN, "KOFI_LINK":KOFI_LINK,
diff --git a/files/routes/posts.py b/files/routes/posts.py
index a609a85665..770a7f1a09 100644
--- a/files/routes/posts.py
+++ b/files/routes/posts.py
@@ -33,55 +33,6 @@ from files.__main__ import app, limiter
titleheaders = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.72 Safari/537.36"}
-@app.post("/club_post/")
-@feature_required('COUNTRY_CLUB')
-@auth_required
-def club_post(pid, v):
- post = get_post(pid)
- if post.author_id != v.id and v.admin_level < PERMS['POST_COMMENT_MODERATION']: abort(403)
-
- if not post.club:
- post.club = True
- g.db.add(post)
-
- if post.author_id != v.id:
- ma = ModAction(
- kind = "club_post",
- user_id = v.id,
- target_submission_id = post.id,
- )
- g.db.add(ma)
-
- message = f"@{v.username} (Admin) has marked [{post.title}]({post.shortlink}) as {CC_TITLE}!"
- send_repeatable_notification(post.author_id, message)
-
- return {"message": f"Post has been marked as {CC_TITLE}!"}
-
-@app.post("/unclub_post/")
-@feature_required('COUNTRY_CLUB')
-@auth_required
-def unclub_post(pid, v):
- post = get_post(pid)
- if post.author_id != v.id and v.admin_level < PERMS['POST_COMMENT_MODERATION']: abort(403)
-
- if post.club:
- post.club = False
- g.db.add(post)
-
- if post.author_id != v.id:
- ma = ModAction(
- kind = "unclub_post",
- user_id = v.id,
- target_submission_id = post.id,
- )
- g.db.add(ma)
-
- message = f"@{v.username} (Admin) has unmarked [{post.title}]({post.shortlink}) as {CC_TITLE}!"
- send_repeatable_notification(post.author_id, message)
-
- return {"message": f"Post has been unmarked as {CC_TITLE}!"}
-
-
@app.post("/publish/")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER)
@auth_required
@@ -139,7 +90,6 @@ def submit_get(v:User, sub=None):
def post_id(pid, anything=None, v=None, sub=None):
post = get_post(pid, v=v)
if not User.can_see(v, post): abort(403)
- if not User.can_see_content(v, post) and post.club: abort(403)
if post.over_18 and not (v and v.over_18) and session.get('over_18', 0) < int(time.time()):
if g.is_api_or_xhr: return {"error":"Must be 18+ to view"}, 451
@@ -234,7 +184,6 @@ def post_id(pid, anything=None, v=None, sub=None):
@auth_desired_with_logingate
def viewmore(v, pid, sort, offset):
post = get_post(pid, v=v)
- if post.club and not (v and (v.paid_dues or v.id == post.author_id)): abort(403)
try:
offset = int(offset)
except: abort(400)
@@ -783,7 +732,6 @@ def submit_post(v:User, sub=None):
flag_new = request.values.get("new", False, bool) or 'megathread' in title.lower()
flag_over_18 = request.values.get("over_18", False, bool)
flag_private = request.values.get("private", False, bool)
- flag_club = (request.values.get("club", False, bool) and FEATURES['COUNTRY_CLUB'])
flag_ghost = request.values.get("ghost", False, bool) and v.can_post_in_ghost_threads
if embed and len(embed) > 1500: embed = None
@@ -795,7 +743,6 @@ def submit_post(v:User, sub=None):
post = Submission(
private=flag_private,
notify=flag_notify,
- club=flag_club,
author_id=v.id,
over_18=flag_over_18,
new=flag_new,
diff --git a/files/routes/search.py b/files/routes/search.py
index 7515357aa3..6bee4b7a5b 100644
--- a/files/routes/search.py
+++ b/files/routes/search.py
@@ -19,7 +19,6 @@ valid_params = [
'before',
'after',
'title',
- 'cc',
search_operator_hole,
]
@@ -61,9 +60,6 @@ def searchposts(v:User):
.join(Submission.author) \
.filter(Submission.author_id.notin_(v.userblocks))
- if not v.paid_dues:
- posts = posts.filter(Submission.club == False)
-
if v.admin_level < PERMS['POST_COMMENT_MODERATION']:
posts = posts.filter(
Submission.deleted_utc == 0,
@@ -143,13 +139,6 @@ def searchposts(v:User):
except: abort(400)
posts = posts.filter(Submission.created_utc < before)
- if 'cc' in criteria:
- cc = criteria['cc'].lower().strip()
- if cc == 'true': cc = True
- elif cc == 'false': cc = False
- else: abort(400)
- posts = posts.filter(Submission.club == cc)
-
posts = apply_time_filter(t, posts, Submission)
posts = sort_objects(sort, posts, Submission,
@@ -236,10 +225,6 @@ def searchcomments(v:User):
comments = comments.filter(Comment.is_banned==False, Comment.deleted_utc == 0, Comment.parent_submission.notin_(private))
- if not v.paid_dues:
- club = [x[0] for x in g.db.query(Submission.id).filter(Submission.club == True).all()]
- comments = comments.filter(Comment.parent_submission.notin_(club))
-
if 'after' in criteria:
after = criteria['after']
try: after = int(after)
diff --git a/files/routes/subs.py b/files/routes/subs.py
index c0edb68a2a..c3090159d1 100644
--- a/files/routes/subs.py
+++ b/files/routes/subs.py
@@ -122,15 +122,17 @@ def block_sub(v:User, sub):
@app.post("/h//unblock")
@auth_required
def unblock_sub(v:User, sub):
- sub = get_sub_by_name(sub).name
- if sub == "chudrama" and not v.can_see_chudrama: abort(403)
- block = g.db.query(SubBlock).filter_by(user_id=v.id, sub=sub).one_or_none()
+ sub = get_sub_by_name(sub)
+ if not User.can_see(v, sub):
+ abort(403)
+
+ block = g.db.query(SubBlock).filter_by(user_id=v.id, sub=sub.name).one_or_none()
if block:
g.db.delete(block)
cache.delete_memoized(frontlist)
- return {"message": f"/h/{sub} unblocked successfully!"}
+ return {"message": f"/h/{sub.name} unblocked successfully!"}
@app.post("/h//subscribe")
@@ -162,7 +164,8 @@ def unsubscribe_sub(v:User, sub):
@auth_required
def follow_sub(v:User, sub):
sub = get_sub_by_name(sub)
- if sub.name == "chudrama" and not v.can_see_chudrama: abort(403)
+ if not User.can_see(v, sub):
+ abort(403)
existing = g.db.query(SubSubscription).filter_by(user_id=v.id, sub=sub.name).one_or_none()
if not existing:
subscription = SubSubscription(user_id=v.id, sub=sub.name)
@@ -186,7 +189,8 @@ def unfollow_sub(v:User, sub):
@auth_required
def mods(v:User, sub):
sub = get_sub_by_name(sub)
- if sub.name == "chudrama" and not v.can_see_chudrama: abort(403)
+ if not User.can_see(v, sub):
+ abort(403)
users = g.db.query(User, Mod).join(Mod).filter_by(sub=sub.name).order_by(Mod.created_utc).all()
return render_template("sub/mods.html", v=v, sub=sub, users=users)
@@ -196,7 +200,8 @@ def mods(v:User, sub):
@auth_required
def sub_exilees(v:User, sub):
sub = get_sub_by_name(sub)
- if sub.name == "chudrama" and not v.can_see_chudrama: abort(403)
+ if not User.can_see(v, sub):
+ abort(403)
users = g.db.query(User, Exile).join(Exile, Exile.user_id==User.id) \
.filter_by(sub=sub.name) \
.order_by(nullslast(Exile.created_utc.desc()), User.username).all()
@@ -208,7 +213,8 @@ def sub_exilees(v:User, sub):
@auth_required
def sub_blockers(v:User, sub):
sub = get_sub_by_name(sub)
- if sub.name == "chudrama" and not v.can_see_chudrama: abort(403)
+ if not User.can_see(v, sub):
+ abort(403)
users = g.db.query(User, SubBlock).join(SubBlock) \
.filter_by(sub=sub.name) \
.order_by(nullslast(SubBlock.created_utc.desc()), User.username).all()
@@ -221,7 +227,8 @@ def sub_blockers(v:User, sub):
@auth_required
def sub_followers(v:User, sub):
sub = get_sub_by_name(sub)
- if sub.name == "chudrama" and not v.can_see_chudrama: abort(403)
+ if not User.can_see(v, sub):
+ abort(403)
users = g.db.query(User, SubSubscription).join(SubSubscription) \
.filter_by(sub=sub.name) \
.order_by(nullslast(SubSubscription.created_utc.desc()), User.username).all()
@@ -701,7 +708,8 @@ def mod_unpin(cid, v):
@auth_required
def hole_log(v:User, sub):
sub = get_sub_by_name(sub)
- if sub.name == "chudrama" and not v.can_see_chudrama: abort(403)
+ if not User.can_see(v, sub):
+ abort(403)
try: page = max(int(request.values.get("page", 1)), 1)
except: page = 1
@@ -741,7 +749,8 @@ def hole_log(v:User, sub):
@auth_required
def hole_log_item(id, v, sub):
sub = get_sub_by_name(sub)
- if sub.name == "chudrama" and not v.can_see_chudrama: abort(403)
+ if not User.can_see(v, sub):
+ abort(403)
try: id = int(id)
except: abort(404)
diff --git a/files/templates/comments.html b/files/templates/comments.html
index 5d16b65eb0..814a701fe6 100644
--- a/files/templates/comments.html
+++ b/files/templates/comments.html
@@ -508,7 +508,7 @@
{% endif %}
- {% if v and v.id != c.author_id and c.body and not (c.post and c.post.club and not v.paid_dues) %}
+ {% if v and v.id != c.author_id and c.body %}
{{c.body.strip()}}
{% endif %}
diff --git a/files/templates/post_actions.html b/files/templates/post_actions.html
index eb49f845cf..80647b9d3b 100644
--- a/files/templates/post_actions.html
+++ b/files/templates/post_actions.html
@@ -57,10 +57,6 @@
{% endif %}
- {% if FEATURES['COUNTRY_CLUB'] and (v.admin_level >= PERMS['POST_COMMENT_MODERATION'] or v.id == p.author_id) %}
-
-
- {% endif %}
{% if v.admin_level >= PERMS['POST_COMMENT_MODERATION'] %}
diff --git a/files/templates/post_actions_mobile.html b/files/templates/post_actions_mobile.html
index de5a95b621..8fa7f8eddb 100644
--- a/files/templates/post_actions_mobile.html
+++ b/files/templates/post_actions_mobile.html
@@ -42,12 +42,6 @@
-
-
- {% if FEATURES['COUNTRY_CLUB'] -%}
-
-
- {%- endif %}
{% else %}
{% if not p.ghost %}
diff --git a/files/templates/post_admin_actions_mobile.html b/files/templates/post_admin_actions_mobile.html
index c42af5a873..b78eca81eb 100644
--- a/files/templates/post_admin_actions_mobile.html
+++ b/files/templates/post_admin_actions_mobile.html
@@ -17,10 +17,6 @@
{% endif %}
- {% if FEATURES['COUNTRY_CLUB'] -%}
-
-
- {%- endif %}
{% if v.can_edit(p) %}
diff --git a/files/templates/search.html b/files/templates/search.html
index a5d4d3854f..297e1d9a2b 100644
--- a/files/templates/search.html
+++ b/files/templates/search.html
@@ -68,10 +68,6 @@
Post Title Only:
-
-
Country Club:
-
-
{% endif %}
diff --git a/files/templates/submission.html b/files/templates/submission.html
index 38bdcc20b3..392a1c00af 100644
--- a/files/templates/submission.html
+++ b/files/templates/submission.html
@@ -64,12 +64,6 @@
{% block content %}
-{% if SITE == 'pcmemes.net' %}
- {% set cc='SPLASH MOUNTAIN' %}
-{% else %}
- {% set cc='COUNTRY CLUB' %}
-{% endif %}
-
@@ -101,14 +95,12 @@
{% if p.realurl(v) and not v_forbid_deleted %}
@@ -237,7 +228,7 @@
{% endif %}
-{% if (not p.club or v and (v.paid_dues or v.id == p.author_id)) and not v_forbid_deleted %}
+{% if not v_forbid_deleted %}
{% if p.realbody(v, listing=True) %}
{% if v.can_post_in_ghost_threads %}
diff --git a/files/templates/userpage/admintools.html b/files/templates/userpage/admintools.html
index 0bc7e5c396..243be53769 100644
--- a/files/templates/userpage/admintools.html
+++ b/files/templates/userpage/admintools.html
@@ -101,10 +101,6 @@
{% endif %}
- {% if FEATURES['COUNTRY_CLUB'] and v and v.admin_level >= PERMS['USER_CLUB_ALLOW_BAN'] %}
-
-
- {% endif %}
{% endif %}
diff --git a/migrations/20220702-poll-rework.sql b/migrations/20220702-poll-rework.sql
new file mode 100644
index 0000000000..fb7524cd07
--- /dev/null
+++ b/migrations/20220702-poll-rework.sql
@@ -0,0 +1,109 @@
+CREATE TABLE public.submission_options (
+ id integer PRIMARY KEY,
+ submission_id integer NOT NULL,
+ body_html character varying(500) NOT NULL,
+ exclusive boolean NOT NULL
+);
+
+CREATE INDEX option_submission ON public.submission_options USING btree (submission_id);
+
+ALTER TABLE ONLY public.submission_options
+ ADD CONSTRAINT option_submission_fkey FOREIGN KEY (submission_id) REFERENCES public.submissions(id) MATCH FULL;
+
+
+
+CREATE SEQUENCE public.submission_option_id_seq
+ AS integer
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER TABLE ONLY public.submission_options ALTER COLUMN id SET DEFAULT nextval('public.submission_option_id_seq'::regclass);
+
+
+
+CREATE TABLE public.submission_option_votes (
+ option_id integer NOT NULL,
+ user_id integer NOT NULL,
+ created_utc integer NOT NULL,
+ submission_id integer
+);
+
+
+
+ALTER TABLE ONLY public.submission_option_votes
+ ADD CONSTRAINT submission_option_votes_pkey PRIMARY KEY (option_id, user_id);
+
+
+ALTER TABLE ONLY public.submission_option_votes
+ ADD CONSTRAINT vote_option_fkey FOREIGN KEY (option_id) REFERENCES public.submission_options(id) MATCH FULL;
+
+ALTER TABLE ONLY public.submission_option_votes
+ ADD CONSTRAINT vote_user_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) MATCH FULL;
+
+ALTER TABLE ONLY public.submission_option_votes
+ ADD CONSTRAINT vote_submission_fkey FOREIGN KEY (submission_id) REFERENCES public.submissions(id) MATCH FULL;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+CREATE TABLE public.comment_options (
+ id integer PRIMARY KEY,
+ comment_id integer NOT NULL,
+ body_html character varying(500) NOT NULL,
+ exclusive boolean NOT NULL
+);
+
+CREATE INDEX option_comment ON public.comment_options USING btree (comment_id);
+
+ALTER TABLE ONLY public.comment_options
+ ADD CONSTRAINT option_comment_fkey FOREIGN KEY (comment_id) REFERENCES public.comments(id) MATCH FULL;
+
+
+
+CREATE SEQUENCE public.comment_option_id_seq
+ AS integer
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER TABLE ONLY public.comment_options ALTER COLUMN id SET DEFAULT nextval('public.comment_option_id_seq'::regclass);
+
+
+
+CREATE TABLE public.comment_option_votes (
+ option_id integer NOT NULL,
+ user_id integer NOT NULL,
+ created_utc integer NOT NULL,
+ comment_id integer
+);
+
+
+
+ALTER TABLE ONLY public.comment_option_votes
+ ADD CONSTRAINT comment_option_votes_pkey PRIMARY KEY (option_id, user_id);
+
+
+ALTER TABLE ONLY public.comment_option_votes
+ ADD CONSTRAINT vote_option_fkey FOREIGN KEY (option_id) REFERENCES public.comment_options(id) MATCH FULL;
+
+ALTER TABLE ONLY public.comment_option_votes
+ ADD CONSTRAINT vote_user_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) MATCH FULL;
+
+ALTER TABLE ONLY public.comment_option_votes
+ ADD CONSTRAINT vote_comment_fkey FOREIGN KEY (comment_id) REFERENCES public.comments(id) MATCH FULL;
diff --git a/migrations/20220708-notification-rework.sql b/migrations/20220708-notification-rework.sql
new file mode 100644
index 0000000000..e03129c58e
--- /dev/null
+++ b/migrations/20220708-notification-rework.sql
@@ -0,0 +1,2 @@
+alter table users add column last_viewed_post_notifs int not null default 0;
+alter table users alter column last_viewed_post_notifs drop default;
diff --git a/migrations/20220711-pronouns.sql b/migrations/20220711-pronouns.sql
new file mode 100644
index 0000000000..22d3d68f58
--- /dev/null
+++ b/migrations/20220711-pronouns.sql
@@ -0,0 +1,2 @@
+alter table users add column pronouns varchar(11) not null default 'they/them';
+alter table users alter column pronouns drop default;
diff --git a/migrations/20220805-modaction-notifs-rework.sql b/migrations/20220805-modaction-notifs-rework.sql
new file mode 100644
index 0000000000..d9998ecb67
--- /dev/null
+++ b/migrations/20220805-modaction-notifs-rework.sql
@@ -0,0 +1,2 @@
+alter table users add column last_viewed_log_notifs int not null default 0;
+alter table users alter column last_viewed_log_notifs drop default;
diff --git a/migrations/20220831-casino-feature.sql b/migrations/20220831-casino-feature.sql
new file mode 100644
index 0000000000..f3dfd87cd6
--- /dev/null
+++ b/migrations/20220831-casino-feature.sql
@@ -0,0 +1,15 @@
+CREATE TYPE casino_game_kind AS ENUM ('blackjack', 'slots');
+
+CREATE TYPE casino_game_currency AS ENUM ('coins', 'procoins');
+
+CREATE TABLE casino_games (
+ id SERIAL PRIMARY KEY,
+ user_id integer NOT NULL REFERENCES users(id),
+ created_utc integer NOT NULL,
+ active boolean NOT NULL DEFAULT true,
+ currency casino_game_currency NOT NULL,
+ wager integer NOT NULL,
+ winnings integer NOT NULL,
+ kind casino_game_kind NOT NULL,
+ game_state jsonb NOT NULL
+);
diff --git a/migrations/20220903-hats.sql b/migrations/20220903-hats.sql
new file mode 100644
index 0000000000..895305f6f1
--- /dev/null
+++ b/migrations/20220903-hats.sql
@@ -0,0 +1,249 @@
+CREATE TABLE public.hat_defs (
+ id integer PRIMARY KEY,
+ name character varying(50) NOT NULL UNIQUE,
+ description character varying(300) NOT NULL,
+ author_id integer NOT NULL,
+ price integer NOT NULL
+);
+
+CREATE SEQUENCE public.hat_defs_id_seq
+ AS integer
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE public.hat_defs_id_seq OWNED BY public.hat_defs.id;
+
+ALTER TABLE ONLY public.hat_defs ALTER COLUMN id SET DEFAULT nextval('public.hat_defs_id_seq'::regclass);
+
+ALTER TABLE ONLY public.hat_defs
+ ADD CONSTRAINT hat_defs_author_id_fkey FOREIGN KEY (author_id) REFERENCES public.users(id);
+
+
+
+
+
+CREATE TABLE public.hats (
+ hat_id integer NOT NULL,
+ user_id integer NOT NULL
+);
+
+ALTER TABLE ONLY public.hats
+ ADD CONSTRAINT hats_pkey PRIMARY KEY (user_id, hat_id);
+
+ALTER TABLE ONLY public.hats
+ ADD CONSTRAINT hats_hat_id_fkey FOREIGN KEY (hat_id) REFERENCES public.hat_defs(id);
+
+ALTER TABLE ONLY public.hats
+ ADD CONSTRAINT hats_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id);
+
+alter table users add column coins_spent_on_hats integer DEFAULT 0 NOT NULL;
+alter table users add column equipped_hat_id integer;
+ALTER TABLE ONLY public.users
+ ADD CONSTRAINT users_equipped_hat_id_fkey FOREIGN KEY (equipped_hat_id) REFERENCES public.hat_defs(id);
+
+insert into hat_defs (name, description, author_id, price) values
+('Ushanka', 'The People''s Hat', 2, 500),
+('Fur Hat', 'The first step on your path to fursuit ownership', 2, 500),
+('Cat Ears I', 'Mew :3', 2, 500),
+('Cat Ears II', 'Meow :3', 2, 500),
+('Playboy Bunny', 'Will this bring daddy back?', 2, 500),
+('Macaroni', 'Get it? Like the song lol', 2, 500),
+('Pirate', 'BUTT pirate', 2, 500),
+('Pirate Captain', 'Like a regular butt pirate, but for tops only', 2, 500),
+('Dreads', 'Finally, an excuse for poor hygiene', 2, 500),
+('The XXXTentacion', 'Pay homage to your favorite dead criminal!', 2, 500),
+('the 6ix9ine', 'The finest piece of snitch couture on the market', 2, 500),
+('The Elvis', 'Remember when this dude nailed a 13-year-old?', 2, 500),
+('Gussy Hat', 'Let everyone know that you''re NOT a rapist. Honest.', 2, 500),
+('Riveter', 'Can you do it? Really?', 2, 500),
+('Top Hat (leprechaun)', 'LLM but Irish', 2, 500),
+('Drinky Beer Hat', 'I actually didn''t know these were real things until I made this', 2, 500),
+('Viking', 'Rape, pillage, never bathe. Live the dream.', 2, 500),
+('Nonspecific Military Officer Hat', '[removed]', 2, 500),
+('Soviet Officer I', 'OUR hat', 2, 500),
+('Nonspecific Military Officer Hat II', '[removed]', 2, 500),
+('Soviet Officer II', 'High fashion war criminal chic', 2, 500),
+('Southern Gentleman', 'Slaveowner? Fried chicken chain founder? You decide!', 2, 500),
+('Cowboy I', 'Make him wish he could quit you', 2, 500),
+('Cowboy II', 'You''re my favorite deputy!', 2, 500),
+('Halo', 'Dramamine criticized this one and now I''m too self-conscious about it to write a description', 2, 500),
+('Fedora I', 'M''arsey', 2, 500),
+('Bowler', 'Why would you need a hat to go bowling?', 2, 500),
+('Du Rag (black)', 'Shitty bandana 1/6', 2, 500),
+('Du Rag (red)', 'Shitty bandana 2/6', 2, 500),
+('Du Rag (blue)', 'Shitty bandana 3/6', 2, 500),
+('Du Rag (purple)', 'Shitty bandana 4/6', 2, 500),
+('Du Rag (green)', 'Shitty bandana 5/6', 2, 500),
+('Du Rag (yellow)', 'Shitty bandana 6/6', 2, 500),
+('Ash Ketchum', 'You''re not so different, you and he', 2, 500),
+('The Hotep', 'Traditional kangwear. POC ONLY.', 2, 500),
+('Roman', 'Reddit delenda est', 2, 500),
+('Confederate Soldier Cap', 'Basically the Gryffindor of American history', 2, 500),
+('Northern Aggressor Soldier Cap', 'Slytherin irl', 2, 500),
+('Rhodesian Light Infantry Beret', 'Rhodesians never die. Immortality guaranteed!', 2, 500),
+('Magyar Headdress', 'Channel your inner QuadNarca and join Orban''s elite cavalry', 2, 500),
+('The Senator Warren', 'heya heya heya heya heya heya heya heya heya heya heya', 2, 500),
+('Please Be Patient I Have Autism', 'The OFFICIAL hat of rDrama.net', 2, 500),
+('Samurai Helmet', 'Never be mistaken for a baka gaijin again', 2, 500),
+('Watermelmet', 'Hydration and head protection all rolled into one stylish headpiece', 2, 500),
+('Frankenstein', 'Akshually, Frankenstein was the scientist. The monster didn''t have a name.', 2, 500),
+('The Drumpf', 'Orange hair bad', 2, 500),
+('Tinfoil Hat', 'Keep Bill Gates'' 5G vaccine OUT of your precious brain!', 2, 500),
+('Fez', 'Isn''t it CUTE?', 2, 500),
+('Ching Chong', 'Me Chinese Me No Dumb Me Stick Finger In Daddy''s Bum', 2, 500),
+('Octopus Friend', 'Awwwwwww!', 2, 500),
+('In The Navy', 'It''s not gay', 2, 500),
+('Seaman', 'semen lol', 2, 500),
+('Flower Crown I', 'oh god i have to write descriptions for 15 flower crowns', 2, 500),
+('Flower Crown II', 'A very cute flower crown', 2, 500),
+('Flower Crown III', 'A super cute flower crown', 2, 500),
+('Flower Crown IV', 'A really cute flower crown', 2, 500),
+('Flower Crown V', 'The cutest flower crown?', 2, 500),
+('Flower Crown VI', 'An extremely cute flower crown', 2, 500),
+('Flower Crown VII', 'A flower crown that''s just so cute', 2, 500),
+('Flower Crown VIII', 'A majorly cute flower crown', 2, 500),
+('Flower Crown IX', 'A mega cute flower crown', 2, 500),
+('Flower Crown X', 'An ultra cute flower crown', 2, 500),
+('Flower Crown XI', 'Definitely the cutest flower crown', 2, 500),
+('Flower Crown XII', 'A hella cute flower crown', 2, 500),
+('Flower Crown XIII', 'An experimental anti-gravity cute flower crown', 2, 500),
+('Flower Crown XIV', 'An adorably cute flower crown', 2, 500),
+('Flower Crown XV', 'The final cute flower crown', 2, 500),
+('Bow', 'What a cute little bow omg', 2, 500),
+('BIPOCsmoke', 'It''s a Newport. You know it''s a Newport.', 2, 500),
+('Gigachin', 'Aw yeah, this user definitely supports trans rights', 2, 500),
+('Queensguard', 'A bear died for this', 2, 500),
+('Queen Crown', 'Don''t be a drag', 2, 500),
+('King Crown', 'King is like the n word, only racists and black people should be allowed to say it', 2, 500),
+('Pope Hat', 'Matthew 16:18', 2, 500),
+('Heebhead', 'Do NOT google the Lavon Affair', 2, 500),
+('Zoomie Zoom Zoom', 'Underage user, do not interact', 2, 500),
+('Sombrero I', 'El Autistico', 2, 500),
+('Sombrero II', 'El Autistico Grandisimo', 2, 500),
+('Crypto Billionaire', 'Sorry about the ice cream machine', 2, 500),
+('Burger King Crown', 'I''m gonna say it', 2, 500),
+('Burger King', 'You can have it your way and you still chose this', 2, 500),
+('Wendys', 'Sassy social media intern', 2, 500),
+('KFC', 'Popeyes is too far away', 2, 500),
+('In-N-Out', 'Kill the commiefornian', 2, 500),
+('Carls Jr', 'Purveyor of literally the finest food in the world', 2, 500),
+('Whataburger', 'Texans don''t know any better', 2, 500),
+('Five Guys', 'I love having 5 guys in my mouth', 2, 500),
+('Taco Bell', 'Enabler of drunken mistakes', 2, 500),
+('Marsey-In-A-Box', 'Awww you''re playing make-believe!', 2, 500),
+('Orthodox Hood', 'User is a schismatic lunatic', 2, 500),
+('Afro', 'Pool''s closed motherlover', 2, 500),
+('Top Hat (black)', 'Traditional. Classy. Elegant.', 2, 500),
+('Wizard I', 'Three decades a KHHV', 2, 500),
+('Wizard II', 'Avada kedavra ✨', 2, 500),
+('Witch I', 'Hex the patriarchy', 2, 500),
+('Witch II', 'Bardfinn cosplay gear', 2, 500),
+('Sun Hat', 'Tradwife simplicity', 2, 500),
+('Obey Snapback', 'The timeless classic', 2, 500),
+('Thug Life Snapback', 'User confirmed mayo', 2, 500),
+('Supreme Snapback', 'Drip so hard omg', 2, 500),
+('Make America Great Again', 'The official headgear of stochastic terrorists everywhere', 2, 500),
+('Born To Feel', 'Do you pee standing up?', 2, 500),
+('Fortunate Son', 'BORN TO SHIT FORCED TO WIPE', 2, 500),
+('WWI', 'How is this supposed to offer any meaningful protection??', 2, 500),
+('Pickelhaube', 'Inarguably the most fashionable of all contemporary military headgear ', 2, 500),
+('Wehrmacht', 'What a cool helmet, I bet the people who wore it were real classy folks ', 2, 500),
+('Chair Force', 'Yeah I''m a combat veteran, I''ve seen shit you wouldn''t believe. One time the wifi was out for almost an hour. ', 2, 500),
+('Helmet w Dog Tags', 'More like dog fags lol', 2, 500),
+('Urban Camo Helmet', 'Man urban camo is cool', 2, 500),
+('Nightvision Helmet', 'Four-eyed freak', 2, 500),
+('Helmet w Mesh', 'Sexy fishnet stocking helmet', 2, 500),
+('Tojo Helmet', 'Artifact from Weeb War II', 2, 500),
+('Officers Cap', 'Get fragged bozo', 2, 500),
+('Jailbird Cap', 'The apex of prison fashion. Why did we stop using this?', 2, 500),
+('P-Hat (green)', 'Zezima fanboy', 2, 500),
+('P-Hat (red)', 'おれはPigAmericanですおれはばか i am average american man i enjoy bad game runescape', 2, 500),
+('P-Hat (yellow)', 'PISS HAT PISS HAT', 2, 500),
+('P-Hat (blue)', 'Ughhhh coming up with different descriptions for RuneScape party hats', 2, 500),
+('P-Hat (pink)', 'It''s pink.', 2, 500),
+('P-Hat (rainbow)', 'LGBTscape 😍', 2, 500),
+('Newsboy', 'Or newsgirl. It''s okay, the hat is actually gender-neutral.', 2, 500),
+('Whirly Tard Hat I', 'Wouldn''t it be neat if they could make one that like uses body heat or whatever to keep the propeller in a state of constant motion', 2, 500),
+('Dunce Cap', 'You retard. Imbecile. Utter buffoon. Oaf. Nincompoop. Idiot. Moron. CLOWN.', 2, 500),
+('Beret', 'Literally the most basic possible hat choice. Please do better. ', 2, 500),
+('Mario', 'BING BING WAHOO ', 2, 500),
+('Luigi', 'LING LING LAHOO', 2, 500),
+('Wing Cap', 'If the hat''s wings are what provide the thrust necessary for flight then how does it stay on and let YOU fly with it huh', 2, 500),
+('Metal Mario', 'Mario hat but with yelling and lots of double bass and distorted guitars and shit heck yeah', 2, 500),
+('Cappy', 'A sentient hat-creature that''s actually a pretty horrifying parasite if you think about it', 2, 500),
+('Wario', 'For the fat, yellow, extremely flatulent dramautist (in loving memory of Bidpots)', 2, 500),
+('Waluigi', 'Coming soon to Smash for sure', 2, 500),
+('Top Hat (kek)', 'Technically a top hat, shut up', 2, 500),
+('Top Hat (white)', 'Oh, how dignified', 2, 500),
+('Top Hat (striped)', 'Tim Burton''s take on the top hat', 2, 500),
+('Top Hat (checkered)', 'Actually chessed, but that''s not really a word.', 2, 500),
+('Top Hat (march hare)', 'April hare, May hare, June hare, July hare,', 2, 500),
+('Top Hat (mad hatter)', 'Hatters mad [x24]', 2, 500),
+('Top Hat (red)', 'Top hat, menstrual edition', 2, 500),
+('Top Hat (uncle sam)', 'THIS HAT WAS FACT-CHECKED BY TRUE AMERICAN PATRIOTS', 2, 500),
+('Fireperson I', 'In loving memory of r/HateForFirefighters', 2, 500),
+('Constable', 'Useless bong cop nonsense', 2, 500),
+('NYPD Officer', 'This user is authorized to stop, frisk and cavity search you at any time for any reason', 2, 500),
+('Crossing Guard', 'We love Officer Marsey!', 2, 500),
+('Paper Sailor', 'As idle as a paper ship, upon a paper ocean. Paper, paper, everywhere.', 2, 500),
+('FBI', 'Federal Bussy Inspector', 2, 500),
+('CIA', 'Cisgender Incineration Agency', 2, 500),
+('ATF', 'Ass-Tickling Faggot. HIDE YOUR DOG!', 2, 500),
+('Graduate', 'This hat signifies that the bearer has completed four (4) years of pan-african gender studies coursework', 2, 500),
+('Nurse', 'Minor TikTok celebrity, OnlyFans top 91%', 2, 500),
+('Farmer', 'Feed & Seed shopper', 2, 500),
+('Farmette', 'Feed & Seed shoppette', 2, 500),
+('Kung Lao', 'Why did I make a Kung Lao hat', 2, 500),
+('Top Hat (steampunk)', 'Like a regular top hat but with goggles and gears', 2, 500),
+('Brain Hat', 'Peter Griffin''s dog', 2, 500),
+('The TED_SIMP', 'Wear this hat to express your undying adoration for carp', 2, 500),
+('The Brandon', 'Listen here fat', 2, 500),
+('The Brandon II', 'LISTEN HERE FAT', 2, 500),
+('The King George', 'Proto-drag if you think about it', 2, 500),
+('The Mao', 'Our hair!', 2, 500),
+('The Young Stalin', 'Pockmarks not included', 2, 500),
+('The Ripe Stalin', 'An homage to the #1 most prolific killer of commies in world history', 2, 500),
+('The Austrian Painter', 'For aficionados of mid-20th century fine artists slash authors', 2, 500),
+('Kenny I', 'User''s life insurance claim was rejected', 2, 500),
+('Modern Major General', 'For my military knowledge, though I''m plucky and adventury / Has only been brought down to the beginning of the century / But still, in matters vegetable, animal, and mineral / I am the very model of a modern Major-General', 2, 500),
+('Red Star Cap', 'Cannon fodder', 2, 500),
+('Cartman', 'Fat antisemite - the archetypal rDrama user', 2, 500),
+('Cheesehead', 'For fans of the Green Gay Fudge Packers', 2, 500),
+('Kyle', 'ngl I don''t watch South Park so idk the difference between this and Stan', 2, 500),
+('Stan', 'ngl I don''t watch South Park so idk the difference between this and Kyle', 2, 500),
+('Kenny II', 'Like Kenny I except it shows more of your ugly face', 2, 500),
+('The Cleopatra', 'Did you know she was actually white?', 2, 500),
+('Pimp Hat I', 'Women are objects', 2, 500),
+('Devil Horns', 'Satan is so cool and quirky!!!', 2, 500),
+('Nooticer', 'THIS USER IS ENGAGED IN THOUGHTCRIME. DO NOT INTERACT.', 2, 500),
+('Airpods', 'oh god oh fuck he cant hear us', 2, 500),
+('Maskmaxxer', 'Why aren''t there two? Are you trying to kill us?', 2, 500),
+('The Tupac', 'dead nigger storage', 2, 500),
+('Media Executive', 'despite making up just 2% of the population,', 2, 500),
+('Surgeon', 'Lobotomize me daddy', 2, 500),
+('Mouseketeer', 'please don''t sue please don''t sue please don''t sue please don''t sue please don''t sue', 2, 500),
+('Karen', 'Let me speak to your manager', 2, 500),
+('Badass Fighter Ace', ' Top Gun™ Maverick® Now Showing In Theaters!', 2, 500),
+('Taqiyah', 'It''s not a yarmulke I swear', 2, 500),
+('Cock', 'DM me yours!', 2, 500),
+('Nervous, Sweating', '>mfw', 2, 500),
+('The Cat', 'does this really need a description', 2, 500),
+('Noose', 'Cope or rope', 2, 500),
+('The Penny', 'This shower cap bonnet is perfect for hiding nappy, alopecia-ridden hair', 2, 500),
+('Hard Hat (yellow)', 'A rock hard, throbbing, veiny hat. Check out the girth on this thing', 2, 500),
+('Hard Hat (white)', 'The mayo variant of the hard hat, used to signify someone of importance, or a visitor, at a job site', 2, 500),
+('Beret (TF2)', 'Stylish vidya-variant of the beret', 2, 500),
+('Texas Ten Gallon', 'Yeehaw!', 2, 500),
+('Demoman', 'KaBOOM', 2, 500),
+('Fireperson II', 'For extinguishing hot threads', 2, 500),
+('Miners Hat', 'Please don''t touch minors', 2, 500),
+('Old Man Hat', 'AKA the Wizdumb', 2, 500),
+('Pimp Hat II', 'Women are people and they deserve respect just kidding they should suck my penis', 2, 500),
+('Whirly Tard Hat II', 'Propeller go brrrrrrrrrr', 2, 500),
+('Family Man Free Hat', 'It''s a good show!', 2, 500),
+('Engineer', 'Choo choo!', 2, 500),
+('Vexillaurius Helmet', 'Degenerates like you belong on rDrama', 2, 500),
+('Astronaut Helmet', 'See you, space marsey', 2, 500);
diff --git a/migrations/20220909-marsey-submissin-ui.sql b/migrations/20220909-marsey-submissin-ui.sql
new file mode 100644
index 0000000000..7321779aad
--- /dev/null
+++ b/migrations/20220909-marsey-submissin-ui.sql
@@ -0,0 +1,6 @@
+alter table marseys add column submitter_id int;
+
+ALTER TABLE ONLY public.marseys
+ ADD CONSTRAINT marsey_submitter_fkey FOREIGN KEY (submitter_id) REFERENCES public.users(id);
+
+CREATE INDEX marseys_idx4 ON public.marseys USING btree (submitter_id);
diff --git a/migrations/20220910-hat-submissin-ui.sql b/migrations/20220910-hat-submissin-ui.sql
new file mode 100644
index 0000000000..6d65079240
--- /dev/null
+++ b/migrations/20220910-hat-submissin-ui.sql
@@ -0,0 +1,6 @@
+alter table hat_defs add column submitter_id int;
+
+ALTER TABLE ONLY public.hat_defs
+ ADD CONSTRAINT hat_def_submitter_fkey FOREIGN KEY (submitter_id) REFERENCES public.users(id);
+
+CREATE INDEX hat_defs_submitter_id_idx ON public.hat_defs USING btree (submitter_id);
diff --git a/migrations/20220910-notify-followers.sql b/migrations/20220910-notify-followers.sql
new file mode 100644
index 0000000000..908a72169a
--- /dev/null
+++ b/migrations/20220910-notify-followers.sql
@@ -0,0 +1,2 @@
+alter table submissions add column notify bool not null default true;
+alter table submissions alter column notify drop default;
diff --git a/migrations/20220911-add-roulette.sql b/migrations/20220911-add-roulette.sql
new file mode 100644
index 0000000000..a7f49f11c1
--- /dev/null
+++ b/migrations/20220911-add-roulette.sql
@@ -0,0 +1 @@
+ALTER TYPE casino_game_kind ADD VALUE 'roulette';
diff --git a/migrations/20220912-created_utc-columns.sql b/migrations/20220912-created_utc-columns.sql
new file mode 100644
index 0000000000..62f51f4cb1
--- /dev/null
+++ b/migrations/20220912-created_utc-columns.sql
@@ -0,0 +1,22 @@
+alter table alts add column created_utc int;
+alter table award_relationships add column created_utc int;
+alter table badge_defs add column created_utc int;
+alter table oauth_apps add column created_utc int;
+alter table client_auths add column created_utc int;
+alter table banneddomains add column created_utc int;
+alter table exiles add column created_utc int;
+alter table hat_defs add column created_utc int;
+alter table hats add column created_utc int;
+alter table lotteries add column created_utc int;
+alter table marseys add column created_utc int;
+alter table submission_options add column created_utc int;
+alter table comment_options add column created_utc int;
+alter table save_relationship add column created_utc int;
+alter table comment_save_relationship add column created_utc int;
+alter table sub_blocks add column created_utc int;
+alter table sub_joins add column created_utc int;
+alter table sub_subscriptions add column created_utc int;
+alter table subs add column created_utc int;
+alter table subscriptions add column created_utc int;
+alter table userblocks add column created_utc int;
+alter table viewers add column created_utc int;
diff --git a/migrations/20220913-transactions.sql b/migrations/20220913-transactions.sql
new file mode 100644
index 0000000000..927e99144b
--- /dev/null
+++ b/migrations/20220913-transactions.sql
@@ -0,0 +1,9 @@
+CREATE TABLE public.transactions (
+ id character varying(36) PRIMARY KEY,
+ created_utc integer NOT NULL,
+ type character varying(12) NOT NULL,
+ amount integer NOT NULL,
+ email character varying(255) NOT NULL
+);
+
+CREATE INDEX transactions_email_idx ON public.transactions USING btree (email);
diff --git a/migrations/20220916-remove-winnings-column.sql b/migrations/20220916-remove-winnings-column.sql
new file mode 100644
index 0000000000..1b9e75110e
--- /dev/null
+++ b/migrations/20220916-remove-winnings-column.sql
@@ -0,0 +1 @@
+alter table users drop column winnings;
diff --git a/migrations/20220920-spider-award.sql b/migrations/20220920-spider-award.sql
new file mode 100644
index 0000000000..b4fd56bbcd
--- /dev/null
+++ b/migrations/20220920-spider-award.sql
@@ -0,0 +1 @@
+alter table users add column spider int;
diff --git a/migrations/20220929-hole-logs.sql b/migrations/20220929-hole-logs.sql
new file mode 100644
index 0000000000..e58762bd00
--- /dev/null
+++ b/migrations/20220929-hole-logs.sql
@@ -0,0 +1,43 @@
+CREATE TABLE public.subactions (
+ id integer PRIMARY KEY,
+ sub character varying(25) NOT NULL,
+ user_id integer,
+ target_user_id integer,
+ target_submission_id integer,
+ target_comment_id integer,
+ created_utc integer NOT NULL,
+ kind character varying(32) DEFAULT NULL::character varying,
+ _note character varying(500) DEFAULT NULL::character varying
+);
+
+CREATE SEQUENCE public.subactions_id_seq
+ AS integer
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE public.subactions_id_seq OWNED BY public.subactions.id;
+
+ALTER TABLE ONLY public.subactions ALTER COLUMN id SET DEFAULT nextval('public.subactions_id_seq'::regclass);
+
+CREATE INDEX fki_subactions_user_fkey ON public.subactions USING btree (target_user_id);
+
+CREATE INDEX modaction_action_idx ON public.subactions USING btree (kind);
+
+CREATE INDEX modaction_pid_idx ON public.subactions USING btree (target_submission_id);
+
+ALTER TABLE ONLY public.subactions
+ ADD CONSTRAINT subactions_submission_fkey FOREIGN KEY (target_submission_id) REFERENCES public.submissions(id);
+
+CREATE INDEX modaction_cid_idx ON public.subactions USING btree (target_comment_id);
+
+ALTER TABLE ONLY public.subactions
+ ADD CONSTRAINT subactions_comment_fkey FOREIGN KEY (target_comment_id) REFERENCES public.comments(id);
+
+ALTER TABLE ONLY public.subactions
+ ADD CONSTRAINT subactions_user_fkey FOREIGN KEY (target_user_id) REFERENCES public.users(id);
+
+ALTER TABLE ONLY public.subactions
+ ADD CONSTRAINT subactions_sub_fkey FOREIGN KEY (sub) REFERENCES public.subs(name);
diff --git a/migrations/20221002-body-tsvector.sql b/migrations/20221002-body-tsvector.sql
new file mode 100644
index 0000000000..1151ef6827
--- /dev/null
+++ b/migrations/20221002-body-tsvector.sql
@@ -0,0 +1,3 @@
+ALTER TABLE public.comments ADD COLUMN body_ts tsvector
+ GENERATED ALWAYS AS (to_tsvector('english', body)) STORED;
+CREATE INDEX comments_body_ts_idx ON public.comments USING GIN (body_ts);
diff --git a/migrations/20221006-media-table.sql b/migrations/20221006-media-table.sql
new file mode 100644
index 0000000000..fa0dc4f4d0
--- /dev/null
+++ b/migrations/20221006-media-table.sql
@@ -0,0 +1,13 @@
+CREATE TABLE public.media (
+ kind character varying(5) NOT NULL,
+ filename character varying(55) NOT NULL,
+ user_id Integer NOT NULL,
+ created_utc integer NOT NULL,
+ size integer NOT NULL
+);
+
+ALTER TABLE ONLY public.media
+ ADD CONSTRAINT media_pkey PRIMARY KEY (kind, filename);
+
+ALTER TABLE ONLY public.media
+ ADD CONSTRAINT media_user_fkey FOREIGN KEY (user_id) REFERENCES public.users(id);
diff --git a/migrations/20221204-new-cc-system.sql b/migrations/20221204-new-cc-system.sql
new file mode 100644
index 0000000000..8956514373
--- /dev/null
+++ b/migrations/20221204-new-cc-system.sql
@@ -0,0 +1,4 @@
+UPDATE submissions SET sub = 'countryclub' WHERE club = true AND sub IS NULL;
+DELETE FROM modactions WHERE kind IN ('club_allow','club_ban','club_post','unclub_post');
+ALTER TABLE submissions DROP COLUMN club;
+ALTER TABLE users DROP COLUMN club_allowed;
diff --git a/schema.sql b/schema.sql
index ee91837d7f..e7ff39b1c5 100644
--- a/schema.sql
+++ b/schema.sql
@@ -107,7 +107,6 @@ CREATE TABLE public.submissions (
is_bot boolean DEFAULT false NOT NULL,
bannedfor character varying(40),
comment_count integer DEFAULT 0 NOT NULL,
- club boolean DEFAULT false NOT NULL,
stickied character varying(40),
title character varying(500) NOT NULL,
url character varying(2083),
@@ -989,7 +988,6 @@ CREATE TABLE public.users (
highlightcomments boolean DEFAULT true NOT NULL,
nitter boolean,
truescore integer DEFAULT 0 NOT NULL,
- club_allowed boolean,
frontsize integer DEFAULT 25 NOT NULL,
coins_spent integer DEFAULT 0 NOT NULL,
marseybux integer DEFAULT 0 NOT NULL,
@@ -2722,4 +2720,3 @@ ALTER TABLE ONLY public.comment_option_votes
--
-- PostgreSQL database dump complete
--
-