sub -> hole

pull/215/head
Aevann 2023-10-07 20:55:50 +03:00
parent 9be96bf827
commit 62d1940a8f
56 changed files with 739 additions and 720 deletions

View File

@ -4203,7 +4203,7 @@ small, .small {
min-height: 30px;
}
.sub-flair {
.hole-flair {
padding: 3px 5px 2px 5px;
border-radius: 5px;
color: white;
@ -4211,7 +4211,7 @@ small, .small {
margin-right: 3px;
font-weight: bold;
}
.sub-flair:hover {
.hole-flair:hover {
color: var(--white);
text-decoration: none;
}
@ -6919,7 +6919,7 @@ div.markdown {
}
}
.sub-banner-update-section .sub-settings-subsection {
.hole-banner-update-section .hole-settings-subsection {
margin-bottom: 1em;
}
@ -7568,12 +7568,12 @@ p { /* DO NOT REMOVE */
overflow: hidden !important;
}
#sub-name {
#hole-name {
font-size: max(14px, 1.2vw);
}
@media (min-width: 768px) {
#sub-name {
#hole-name {
font-size: 1.5vw;
}
}

View File

@ -1,4 +1,4 @@
const save_value = ['post-title', 'post-text', 'post-url', 'sub']
const save_value = ['post-title', 'post-text', 'post-url', 'hole']
for (const id of save_value) {
const value = localStorage.getItem(id)
if (value)
@ -106,15 +106,15 @@ function autoSuggestTitle() {
function ghost_toggle(t) {
const followers = document.getElementById("post-notify")
const sub = document.getElementById("sub")
const hole = document.getElementById("hole")
if (t.checked == true) {
followers.checked = false;
followers.disabled = true;
sub.value = '';
sub.disabled = true;
hole.value = '';
hole.disabled = true;
} else {
followers.disabled = false;
sub.disabled = false;
hole.disabled = false;
}
}

View File

@ -18,7 +18,7 @@ from .domains import *
from .subscriptions import *
from .mod_logs import *
from .award import *
from .sub_relationship import *
from .hole_relationship import *
from .saves import *
from .views import *
from .notifications import *
@ -28,7 +28,7 @@ from .casino_game import *
from .hats import *
from .emoji import *
from .transactions import *
from .sub_logs import *
from .hole_logs import *
from .media import *
from .push_subscriptions import *
from .group import *

View File

@ -126,13 +126,13 @@ def add_options(self, body, v):
if v:
if kind == 'post':
sub = self.sub
hole = self.hole
elif self.parent_post:
sub = self.post.sub
hole = self.post.hole
else:
sub = None
hole = None
if sub in {'furry','vampire','racist','femboy','edgy'} and not v.house.lower().startswith(sub):
if hole in {'furry','vampire','racist','femboy','edgy'} and not v.house.lower().startswith(hole):
disabled = True
option_body += ' disabled '
@ -407,7 +407,7 @@ class Comment(Base):
body = add_options(self, body, v)
if body:
if not (self.parent_post and self.post.sub == 'chudrama'):
if not (self.parent_post and self.post.hole == 'chudrama'):
body = censor_slurs_profanities(body, v)
body = normalize_urls_runtime(body, v)
@ -423,7 +423,7 @@ class Comment(Base):
if not body: return ""
if not (self.parent_post and self.post.sub == 'chudrama'):
if not (self.parent_post and self.post.hole == 'chudrama'):
body = censor_slurs_profanities(body, v, True)
return body

View File

@ -9,7 +9,7 @@ from files.classes import Base
class Exile(Base):
__tablename__ = "exiles"
user_id = Column(Integer, ForeignKey("users.id"), primary_key=True)
sub = Column(String, ForeignKey("subs.name"), primary_key=True)
hole = Column(String, ForeignKey("holes.name"), primary_key=True)
exiler_id = Column(Integer, ForeignKey("users.id"))
created_utc = Column(Integer)
@ -20,4 +20,4 @@ class Exile(Base):
super().__init__(*args, **kwargs)
def __repr__(self):
return f"<{self.__class__.__name__}(user_id={self.user_id}, sub={self.sub})>"
return f"<{self.__class__.__name__}(user_id={self.user_id}, hole={self.hole})>"

View File

@ -11,23 +11,23 @@ from files.classes import Base
from files.helpers.lazy import lazy
from files.helpers.config.const import *
from .sub_relationship import *
from .hole_relationship import *
class Sub(Base):
__tablename__ = "subs"
name = Column(VARCHAR(SUB_NAME_COLUMN_LENGTH), primary_key=True)
sidebar = Column(VARCHAR(SUB_SIDEBAR_COLUMN_LENGTH))
sidebar_html = Column(VARCHAR(SUB_SIDEBAR_HTML_COLUMN_LENGTH))
sidebarurl = Column(VARCHAR(SUB_SIDEBAR_URL_COLUMN_LENGTH))
bannerurls = Column(MutableList.as_mutable(ARRAY(VARCHAR(SUB_BANNER_URL_COLUMN_LENGTH))), default=MutableList([]), nullable=False)
marseyurl = Column(VARCHAR(SUB_MARSEY_URL_LENGTH))
css = Column(VARCHAR(SUB_CSS_COLUMN_LENGTH))
class Hole(Base):
__tablename__ = "holes"
name = Column(VARCHAR(HOLE_NAME_COLUMN_LENGTH), primary_key=True)
sidebar = Column(VARCHAR(HOLE_SIDEBAR_COLUMN_LENGTH))
sidebar_html = Column(VARCHAR(HOLE_SIDEBAR_HTML_COLUMN_LENGTH))
sidebarurl = Column(VARCHAR(HOLE_SIDEBAR_URL_COLUMN_LENGTH))
bannerurls = Column(MutableList.as_mutable(ARRAY(VARCHAR(HOLE_BANNER_URL_COLUMN_LENGTH))), default=MutableList([]), nullable=False)
marseyurl = Column(VARCHAR(HOLE_MARSEY_URL_LENGTH))
css = Column(VARCHAR(HOLE_CSS_COLUMN_LENGTH))
stealth = Column(Boolean)
created_utc = Column(Integer)
blocks = relationship("SubBlock", primaryjoin="SubBlock.sub==Sub.name")
followers = relationship("SubSubscription", primaryjoin="SubSubscription.sub==Sub.name")
joins = relationship("SubJoin", lazy="dynamic", primaryjoin="SubJoin.sub==Sub.name")
blocks = relationship("HoleBlock", primaryjoin="HoleBlock.hole==Hole.name")
followers = relationship("HoleFollow", primaryjoin="HoleFollow.hole==Hole.name")
joins = relationship("StealthHoleUnblock", lazy="dynamic", primaryjoin="StealthHoleUnblock.hole==Hole.name")
def __init__(self, *args, **kwargs):
if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time())

View File

@ -10,10 +10,10 @@ from files.helpers.lazy import lazy
from files.helpers.slurs_and_profanities import censor_slurs_profanities
from files.helpers.sorting_and_time import make_age_string
class SubAction(Base):
__tablename__ = "subactions"
class HoleAction(Base):
__tablename__ = "hole_actions"
id = Column(Integer, primary_key=True)
sub = Column(String, ForeignKey("subs.name"))
hole = Column(String, ForeignKey("holes.name"))
user_id = Column(Integer, ForeignKey("users.id"))
kind = Column(String)
target_user_id = Column(Integer, ForeignKey("users.id"))
@ -22,8 +22,8 @@ class SubAction(Base):
_note = Column(String)
created_utc = Column(Integer)
user = relationship("User", primaryjoin="User.id==SubAction.user_id")
target_user = relationship("User", primaryjoin="User.id==SubAction.target_user_id")
user = relationship("User", primaryjoin="User.id==HoleAction.user_id")
target_user = relationship("User", primaryjoin="User.id==HoleAction.target_user_id")
target_post = relationship("Post")
target_comment = relationship("Comment")
@ -42,7 +42,7 @@ class SubAction(Base):
@property
@lazy
def string(self):
output = SUBACTION_TYPES[self.kind]["str"].format(self=self)
output = HOLEACTION_TYPES[self.kind]["str"].format(self=self)
if self._note: output += f" <i>({self._note})</i>"
return output
@ -59,16 +59,16 @@ class SubAction(Base):
@property
@lazy
def icon(self):
return SUBACTION_TYPES[self.kind]['icon']
return HOLEACTION_TYPES[self.kind]['icon']
@property
@lazy
def color(self):
return SUBACTION_TYPES[self.kind]['color']
return HOLEACTION_TYPES[self.kind]['color']
@property
@lazy
def permalink(self):
return f"{SITE_FULL}/h/{self.sub}/log/{self.id}"
return f"{SITE_FULL}/h/{self.hole}/log/{self.id}"
from files.helpers.config.subaction_types import SUBACTION_TYPES
from files.helpers.config.holeaction_types import HOLEACTION_TYPES

View File

@ -6,7 +6,7 @@ from sqlalchemy.sql.sqltypes import *
from files.classes import Base
class SubRelationship(Base):
class HoleRelationship(Base):
__tablename__ = NotImplemented
__abstract__ = True
@ -15,8 +15,8 @@ class SubRelationship(Base):
return Column(Integer, ForeignKey("users.id"), primary_key=True)
@declared_attr
def sub(self):
return Column(String(20), ForeignKey("subs.name"), primary_key=True)
def hole(self):
return Column(String(20), ForeignKey("holes.name"), primary_key=True)
@declared_attr
def created_utc(self):
@ -27,13 +27,13 @@ class SubRelationship(Base):
super().__init__(*args, **kwargs)
def __repr__(self):
return f"<{self.__class__.__name__}(user_id={self.user_id}, sub={self.sub})>"
return f"<{self.__class__.__name__}(user_id={self.user_id}, hole={self.hole})>"
class SubJoin(SubRelationship):
__tablename__ = "sub_joins"
class StealthHoleUnblock(HoleRelationship):
__tablename__ = "stealth_hole_unblocks"
class SubBlock(SubRelationship):
__tablename__ = "sub_blocks"
class HoleBlock(HoleRelationship):
__tablename__ = "hole_blocks"
class SubSubscription(SubRelationship):
__tablename__ = "sub_subscriptions"
class HoleFollow(HoleRelationship):
__tablename__ = "hole_follows"

View File

@ -9,7 +9,7 @@ from files.helpers.lazy import *
class Mod(Base):
__tablename__ = "mods"
user_id = Column(Integer, ForeignKey("users.id"), primary_key=True)
sub = Column(String, ForeignKey("subs.name"), primary_key=True)
hole = Column(String, ForeignKey("holes.name"), primary_key=True)
created_utc = Column(Integer)
def __init__(self, *args, **kwargs):
@ -17,4 +17,4 @@ class Mod(Base):
super().__init__(*args, **kwargs)
def __repr__(self):
return f"<{self.__class__.__name__}(user_id={self.user_id}, sub={self.sub})>"
return f"<{self.__class__.__name__}(user_id={self.user_id}, hole={self.hole})>"

View File

@ -17,7 +17,7 @@ from files.helpers.sorting_and_time import make_age_string
from .comment import normalize_urls_runtime, add_options, get_award_classes
from .polls import *
from .sub import *
from .hole import *
from .subscriptions import *
from .saves import SaveRelationship
@ -40,7 +40,7 @@ class Post(Base):
stickied = Column(String)
stickied_utc = Column(Integer)
hole_pinned = Column(String)
sub = Column(String, ForeignKey("subs.name"))
hole = Column(String, ForeignKey("holes.name"))
is_pinned = Column(Boolean, default=False)
private = Column(Boolean, default=False)
comment_count = Column(Integer, default=0)
@ -74,7 +74,7 @@ class Post(Base):
awards = relationship("AwardRelationship", order_by="AwardRelationship.awarded_utc.desc()", back_populates="post")
reports = relationship("Report", order_by="Report.created_utc")
comments = relationship("Comment", primaryjoin="Comment.parent_post==Post.id", back_populates="post")
subr = relationship("Sub", primaryjoin="foreign(Post.sub)==remote(Sub.name)")
hole_obj = relationship("Hole", primaryjoin="foreign(Post.hole)==remote(Hole.name)")
options = relationship("PostOption", order_by="PostOption.id")
def __init__(self, *args, **kwargs):
@ -126,9 +126,9 @@ class Post(Base):
@lazy
def shortlink(self):
link = f"/post/{self.id}"
if self.sub: link = f"/h/{self.sub}{link}"
if self.hole: link = f"/h/{self.hole}{link}"
if self.sub and self.sub in {'chudrama', 'countryclub', 'highrollerclub'}:
if self.hole and self.hole in {'chudrama', 'countryclub', 'highrollerclub'}:
output = '-'
else:
title = self.plaintitle(None).lower()
@ -228,7 +228,7 @@ class Post(Base):
'is_bot': self.is_bot,
'thumb_url': self.thumb_url,
'domain': self.domain,
'sub': self.sub,
'hole': self.hole,
'url': self.realurl(None),
'body': self.body,
'body_html': self.body_html,
@ -307,7 +307,7 @@ class Post(Base):
body = add_options(self, body, v)
if self.sub != 'chudrama':
if self.hole != 'chudrama':
body = censor_slurs_profanities(body, v)
body = normalize_urls_runtime(body, v)
@ -322,7 +322,7 @@ class Post(Base):
body = self.body
if not body: return ""
if self.sub != 'chudrama':
if self.hole != 'chudrama':
body = censor_slurs_profanities(body, v, True)
body = normalize_urls_runtime(body, v)
@ -333,7 +333,7 @@ class Post(Base):
def realtitle(self, v):
title = self.title_html
if self.sub != 'chudrama':
if self.hole != 'chudrama':
title = censor_slurs_profanities(title, v)
return title
@ -342,7 +342,7 @@ class Post(Base):
def plaintitle(self, v):
title = self.title
if self.sub != 'chudrama':
if self.hole != 'chudrama':
title = censor_slurs_profanities(title, v, True)
return title

View File

@ -13,7 +13,7 @@ from flask import g, session, request
from files.classes import Base
from files.classes.casino_game import CasinoGame
from files.classes.group import GroupMembership
from files.classes.sub import Sub
from files.classes.hole import Hole
from files.helpers.config.const import *
from files.helpers.config.modaction_types import *
from files.helpers.config.awards import AWARDS_ENABLED, HOUSE_AWARDS
@ -33,8 +33,8 @@ from .mod import *
from .mod_logs import *
from .notifications import Notification
from .saves import *
from .sub_relationship import *
from .sub_logs import *
from .hole_relationship import *
from .hole_logs import *
from .subscriptions import *
from .userblock import *
from .usermute import *
@ -171,7 +171,7 @@ class User(Base):
designed_hats = relationship("HatDef", primaryjoin="User.id==HatDef.author_id", back_populates="author")
owned_hats = relationship("Hat", back_populates="owners")
hats_equipped = relationship("Hat", lazy="raise", viewonly=True)
sub_mods = relationship("Mod", primaryjoin="User.id == Mod.user_id", lazy="raise")
hole_mods = relationship("Mod", primaryjoin="User.id == Mod.user_id", lazy="raise")
def __init__(self, **kwargs):
@ -414,13 +414,13 @@ class User(Base):
return True
@lazy
def mods(self, sub):
def mods(self, hole):
if self.is_permabanned or self.shadowbanned: return False
if self.admin_level >= PERMS['MODS_EVERY_HOLE']: return True
try:
return any(map(lambda x: x.sub == sub, self.sub_mods))
return any(map(lambda x: x.hole == hole, self.hole_mods))
except:
return bool(g.db.query(Mod.user_id).filter_by(user_id=self.id, sub=sub).one_or_none())
return bool(g.db.query(Mod.user_id).filter_by(user_id=self.id, hole=hole).one_or_none())
@lazy
def mods_group(self, group):
@ -430,8 +430,8 @@ class User(Base):
return bool(g.db.query(GroupMembership.user_id).filter_by(user_id=self.id, group_name=group.name, is_mod=True).one_or_none())
@lazy
def exiler_username(self, sub):
exile = g.db.query(Exile).options(load_only(Exile.exiler_id)).filter_by(user_id=self.id, sub=sub).one_or_none()
def exiler_username(self, hole):
exile = g.db.query(Exile).options(load_only(Exile.exiler_id)).filter_by(user_id=self.id, hole=hole).one_or_none()
if exile:
return exile.exiler.username
else:
@ -439,35 +439,35 @@ class User(Base):
@property
@lazy
def sub_blocks(self):
stealth = set([x[0] for x in g.db.query(Sub.name).filter_by(stealth=True)])
stealth = stealth - set([x[0] for x in g.db.query(SubJoin.sub).filter_by(user_id=self.id)])
def hole_blocks(self):
stealth = set([x[0] for x in g.db.query(Hole.name).filter_by(stealth=True)])
stealth = stealth - set([x[0] for x in g.db.query(StealthHoleUnblock.hole).filter_by(user_id=self.id)])
if self.chud == 1: stealth = stealth - {'chudrama'}
return list(stealth) + [x[0] for x in g.db.query(SubBlock.sub).filter_by(user_id=self.id)]
return list(stealth) + [x[0] for x in g.db.query(HoleBlock.hole).filter_by(user_id=self.id)]
@lazy
def blocks(self, sub):
return g.db.query(SubBlock).filter_by(user_id=self.id, sub=sub).one_or_none()
def blocks(self, hole):
return g.db.query(HoleBlock).filter_by(user_id=self.id, hole=hole).one_or_none()
@lazy
def subscribes(self, sub):
return g.db.query(SubJoin).filter_by(user_id=self.id, sub=sub).one_or_none()
def subscribes(self, hole):
return g.db.query(StealthHoleUnblock).filter_by(user_id=self.id, hole=hole).one_or_none()
@property
@lazy
def all_follows(self):
return [x[0] for x in g.db.query(SubSubscription.sub).filter_by(user_id=self.id)]
return [x[0] for x in g.db.query(HoleFollow.hole).filter_by(user_id=self.id)]
@lazy
def follows(self, sub):
return g.db.query(SubSubscription).filter_by(user_id=self.id, sub=sub).one_or_none()
def follows(self, hole):
return g.db.query(HoleFollow).filter_by(user_id=self.id, hole=hole).one_or_none()
@lazy
def mod_date(self, sub):
def mod_date(self, hole):
if self.admin_level >= PERMS['MODS_EVERY_HOLE']: return 1
mod_ts = g.db.query(Mod.created_utc).filter_by(user_id=self.id, sub=sub).one_or_none()
mod_ts = g.db.query(Mod.created_utc).filter_by(user_id=self.id, hole=hole).one_or_none()
if mod_ts is None:
return None
return mod_ts[0]
@ -737,8 +737,8 @@ class User(Base):
@property
@lazy
def followed_subs(self):
return [x[0] for x in g.db.query(SubSubscription.sub).filter_by(user_id=self.id)]
def followed_holes(self):
return [x[0] for x in g.db.query(HoleFollow.hole).filter_by(user_id=self.id)]
@property
@lazy
@ -796,7 +796,7 @@ class User(Base):
return g.db.query(Post).filter(
Post.created_utc > self.last_viewed_post_notifs,
or_(
Post.sub.in_(self.followed_subs),
Post.hole.in_(self.followed_holes),
and_(
Post.author_id.in_(self.followed_users),
Post.notify == True,
@ -808,7 +808,7 @@ class User(Base):
Post.private == False,
Post.author_id != self.id,
Post.author_id.notin_(self.userblocks),
or_(Post.sub == None, Post.sub.notin_(self.sub_blocks)),
or_(Post.hole == None, Post.hole.notin_(self.hole_blocks)),
).count()
@property
@ -830,11 +830,11 @@ class User(Base):
return q.count()
if self.moderated_subs:
return g.db.query(SubAction).filter(
SubAction.created_utc > self.last_viewed_log_notifs,
SubAction.user_id != self.id,
SubAction.sub.in_(self.moderated_subs),
if self.moderated_holes:
return g.db.query(HoleAction).filter(
HoleAction.created_utc > self.last_viewed_log_notifs,
HoleAction.user_id != self.id,
HoleAction.hole.in_(self.moderated_holes),
).count()
return 0
@ -896,8 +896,8 @@ class User(Base):
@property
@lazy
def moderated_subs(self):
return [x[0] for x in g.db.query(Mod.sub).filter_by(user_id=self.id).order_by(Mod.sub)]
def moderated_holes(self):
return [x[0] for x in g.db.query(Mod.hole).filter_by(user_id=self.id).order_by(Mod.hole)]
@property
@lazy

View File

@ -50,7 +50,7 @@ def snappy_report(post, reason):
send_repeatable_notification(post.author_id, message)
def execute_snappy(post, v):
if post.sub and g.db.query(Exile.user_id).filter_by(user_id=SNAPPY_ID, sub=post.sub).one_or_none():
if post.hole and g.db.query(Exile.user_id).filter_by(user_id=SNAPPY_ID, hole=post.hole).one_or_none():
return
ghost = post.ghost
@ -271,7 +271,7 @@ def execute_zozbot(c, level, post, v):
posting_to_post = isinstance(post, Post)
if posting_to_post and post.sub and g.db.query(Exile.user_id).filter_by(user_id=ZOZBOT_ID, sub=post.sub).one_or_none():
if posting_to_post and post.hole and g.db.query(Exile.user_id).filter_by(user_id=ZOZBOT_ID, hole=post.hole).one_or_none():
return
c2 = Comment(author_id=ZOZBOT_ID,
@ -344,7 +344,7 @@ def execute_longpostbot(c, level, body, body_html, post, v):
posting_to_post = isinstance(post, Post)
if posting_to_post and post.sub and g.db.query(Exile.user_id).filter_by(user_id=LONGPOSTBOT_ID, sub=post.sub).one_or_none():
if posting_to_post and post.hole and g.db.query(Exile.user_id).filter_by(user_id=LONGPOSTBOT_ID, hole=post.hole).one_or_none():
return
body = random.choice(LONGPOSTBOT_REPLIES)

View File

@ -103,7 +103,7 @@ def notif_comment2(p):
if existing: return existing[0], text
else:
if p.sub: text += f" in <a href='/h/{p.sub}'>/h/{p.sub}"
if p.hole: text += f" in <a href='/h/{p.hole}'>/h/{p.hole}"
text_html = sanitize(text, blackjack="notification", post_mention_notif=True)
return create_comment(text_html), text

View File

@ -1,7 +1,7 @@
from .config.const import *
from files.classes.post import Post
from files.classes.comment import Comment
from files.classes.sub import Sub
from files.classes.hole import Hole
from flask import request
def can_see(user, other):
@ -9,7 +9,7 @@ def can_see(user, other):
if not can_see(user, other.author): return False
if user and user.id == other.author_id: return True
if isinstance(other, Post):
if other.sub and not can_see(user, other.subr):
if other.hole and not can_see(user, other.hole_obj):
return False
if request.headers.get("Cf-Ipcountry") == 'NZ':
if 'christchurch' in other.title.lower():
@ -30,7 +30,7 @@ def can_see(user, other):
return user.admin_level >= PERMS['VIEW_MODMAIL']
if other.sentto != user.id:
return user.admin_level >= PERMS['BLACKJACK_NOTIFICATIONS']
elif isinstance(other, Sub):
elif isinstance(other, Hole):
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 == 'highrollerclub': return bool(user) and user.can_see_highrollerclub

View File

@ -292,13 +292,13 @@ POST_SORTS = COMMENT_SORTS | {
### COLUMN INFO
################################################################################
SUB_NAME_COLUMN_LENGTH = 25
SUB_SIDEBAR_COLUMN_LENGTH = 10000
SUB_SIDEBAR_HTML_COLUMN_LENGTH = 20000
SUB_SIDEBAR_URL_COLUMN_LENGTH = 60
SUB_BANNER_URL_COLUMN_LENGTH = 60
SUB_CSS_COLUMN_LENGTH = 6000
SUB_MARSEY_URL_LENGTH = 60
HOLE_NAME_COLUMN_LENGTH = 25
HOLE_SIDEBAR_COLUMN_LENGTH = 10000
HOLE_SIDEBAR_HTML_COLUMN_LENGTH = 20000
HOLE_SIDEBAR_URL_COLUMN_LENGTH = 60
HOLE_BANNER_URL_COLUMN_LENGTH = 60
HOLE_CSS_COLUMN_LENGTH = 6000
HOLE_MARSEY_URL_LENGTH = 60
################################################################################
### SITE SPECIFIC CONSTANTS
@ -487,7 +487,7 @@ COMMENT_MAX_DEPTH = 200
TRANSFER_MESSAGE_LENGTH_LIMIT = 200 # do not make larger than 10000 characters (comment limit) without altering the table
MIN_REPOST_CHECK_URL_LENGTH = 9 # also change the constant in checkRepost() of submit.js
CHAT_LENGTH_LIMIT = 1000
SUB_BANNER_LIMIT = 10
HOLE_BANNER_LIMIT = 10
BIO_FRIENDS_ENEMIES_LENGTH_LIMIT = 5000 # do not make larger than 5000 characters without altering the table
BIO_FRIENDS_ENEMIES_HTML_LENGTH_LIMIT = 20000 # do not make larger than 20000 characters without altering the table
@ -706,7 +706,7 @@ elif SITE == 'watchpeopledie.tv':
PERMS['MODS_EVERY_HOLE'] = 3
PERMS['IS_PERMA_PROGSTACKED'] = 4
SUB_BANNER_LIMIT = 69420
HOLE_BANNER_LIMIT = 69420
ERROR_TITLES.update({
400: "Bad Request",
@ -800,7 +800,7 @@ else: # localhost or testing environment implied
FEATURES['PRONOUNS'] = True
FEATURES['HOUSES'] = True
FEATURES['USERS_PERMANENT_WORD_FILTERS'] = True
SUB_BANNER_LIMIT = 69420
HOLE_BANNER_LIMIT = 69420
HOUSES = ("None","Furry","Femboy","Vampire","Racist","Edgy") if FEATURES['HOUSES'] else ("None")

View File

@ -1,4 +1,4 @@
SUBACTION_TYPES = {
HOLEACTION_TYPES = {
'exile_user': {
"str": 'exiled user {self.target_link}',
"icon": 'fa-user-slash',
@ -116,4 +116,4 @@ SUBACTION_TYPES = {
},
}
SUBACTION_TYPES = dict(sorted(SUBACTION_TYPES.items()))
HOLEACTION_TYPES = dict(sorted(HOLEACTION_TYPES.items()))

View File

@ -1,6 +1,6 @@
from os import path
from files.classes import Emoji, Sub
from files.classes import Emoji, Hole
from files.helpers.config.const import *
SNAPPY_KONGS = []
@ -32,7 +32,7 @@ def const_initialize():
SNAPPY_KONGS = db.query(Emoji.name).filter(Emoji.kind=="Donkey Kong", Emoji.submitter_id==None, Emoji.nsfw == False).all()
SNAPPY_KONGS = [f':#{x[0]}:' for x in SNAPPY_KONGS]
STEALTH_HOLES = [x[0] for x in db.query(Sub.name).filter_by(stealth=True)]
STEALTH_HOLES = [x[0] for x in db.query(Hole.name).filter_by(stealth=True)]
OVER_18_EMOJIS = [x[0] for x in db.query(Emoji.name).filter_by(nsfw=True)]

View File

@ -70,7 +70,7 @@ def cron_fn(every_5m, every_1d, every_fri_12, every_fri_23, every_sat_00, every_
_leaderboard_task()
g.db.commit()
_sub_inactive_purge_task()
_hole_inactive_purge_task()
g.db.commit()
stats.generate_charts_task(SITE)
@ -170,7 +170,7 @@ def _create_post(title, body, pin_hours):
embed=None,
title=title,
title_html=title_html,
sub='countryclub',
hole='countryclub',
ghost=False,
chudded=False,
rainbowed=False,
@ -248,29 +248,29 @@ def _grant_two_year_badges():
from users where created_utc < {two_years_ago} and id not in (select user_id from badges where badge_id=237);""")
g.db.execute(_badge_query)
def _sub_inactive_purge_task():
def _hole_inactive_purge_task():
if not HOLE_INACTIVITY_DELETION:
return False
one_week_ago = time.time() - 604800
active_holes = [x[0] for x in g.db.query(Post.sub).distinct() \
.filter(Post.sub != None, Post.created_utc > one_week_ago,
active_holes = [x[0] for x in g.db.query(Post.hole).distinct() \
.filter(Post.hole != None, Post.created_utc > one_week_ago,
Post.private == False, Post.is_banned == False,
Post.deleted_utc == 0)]
active_holes.extend(['changelog','countryclub','museumofrdrama','highrollerclub']) # holes immune from deletion
dead_holes = g.db.query(Sub).filter(Sub.name.notin_(active_holes)).all()
dead_holes = g.db.query(Hole).filter(Hole.name.notin_(active_holes)).all()
names = [x.name for x in dead_holes]
admins = [x[0] for x in g.db.query(User.id).filter(User.admin_level >= PERMS['NOTIFICATIONS_HOLE_INACTIVITY_DELETION'])]
mods = g.db.query(Mod).filter(Mod.sub.in_(names)).all()
mods = g.db.query(Mod).filter(Mod.hole.in_(names)).all()
for x in mods:
if x.user_id in admins: continue
send_repeatable_notification(x.user_id, f":marseyrave: /h/{x.sub} has been deleted for inactivity after one week without new posts. All posts in it have been moved to the main feed :marseyrave:")
send_repeatable_notification(x.user_id, f":marseyrave: /h/{x.hole} has been deleted for inactivity after one week without new posts. All posts in it have been moved to the main feed :marseyrave:")
for name in names:
first_mod_id = g.db.query(Mod.user_id).filter_by(sub=name).order_by(Mod.created_utc).first()
first_mod_id = g.db.query(Mod.user_id).filter_by(hole=name).order_by(Mod.created_utc).first()
if first_mod_id:
first_mod = get_account(first_mod_id[0])
badge_grant(
@ -282,22 +282,22 @@ def _sub_inactive_purge_task():
for admin in admins:
send_repeatable_notification(admin, f":marseyrave: /h/{name} has been deleted for inactivity after one week without new posts. All posts in it have been moved to the main feed :marseyrave:")
posts = g.db.query(Post).filter(Post.sub.in_(names)).all()
posts = g.db.query(Post).filter(Post.hole.in_(names)).all()
for post in posts:
if post.sub == 'programming':
post.sub = 'slackernews'
if post.hole == 'programming':
post.hole = 'slackernews'
else:
post.sub = None
post.hole = None
post.hole_pinned = None
g.db.add(post)
to_delete = mods \
+ g.db.query(Exile).filter(Exile.sub.in_(names)).all() \
+ g.db.query(SubBlock).filter(SubBlock.sub.in_(names)).all() \
+ g.db.query(SubJoin).filter(SubJoin.sub.in_(names)).all() \
+ g.db.query(SubSubscription).filter(SubSubscription.sub.in_(names)).all() \
+ g.db.query(SubAction).filter(SubAction.sub.in_(names)).all()
+ g.db.query(Exile).filter(Exile.hole.in_(names)).all() \
+ g.db.query(HoleBlock).filter(HoleBlock.hole.in_(names)).all() \
+ g.db.query(StealthHoleUnblock).filter(StealthHoleUnblock.hole.in_(names)).all() \
+ g.db.query(HoleFollow).filter(HoleFollow.hole.in_(names)).all() \
+ g.db.query(HoleAction).filter(HoleAction.hole.in_(names)).all()
for x in to_delete:
g.db.delete(x)

View File

@ -3,7 +3,7 @@ from flask import *
from sqlalchemy import and_, any_, or_
from sqlalchemy.orm import joinedload, Query, load_only
from files.classes import Comment, CommentVote, Hat, Sub, Post, User, UserBlock, Vote
from files.classes import Comment, CommentVote, Hat, Hole, Post, User, UserBlock, Vote
from files.helpers.config.const import *
from files.__main__ import cache
@ -321,16 +321,16 @@ def get_comments_v_properties(v, should_keep_func=None, *criterion):
else: dump.append(comment)
return (comments, output)
def get_sub_by_name(sub, v=None, graceful=False):
if not sub:
def get_hole(hole, v=None, graceful=False):
if not hole:
if graceful: return None
else: abort(404)
sub = sub.replace('/h/', '').replace('h/', '').strip().lower()
if not sub:
hole = hole.replace('/h/', '').replace('h/', '').strip().lower()
if not hole:
if graceful: return None
else: abort(404)
sub = g.db.get(Sub, sub)
if not sub:
hole = g.db.get(Hole, hole)
if not hole:
if graceful: return None
else: abort(404)
return sub

View File

@ -836,10 +836,10 @@ def complies_with_chud(obj):
if isinstance(obj, Post):
if obj.id in ADMIGGER_THREADS: return True
if obj.sub == "chudrama": return True
if obj.hole == "chudrama": return True
elif obj.parent_post:
if obj.parent_post in ADMIGGER_THREADS: return True
if obj.post.sub == "chudrama": return True
if obj.post.hole == "chudrama": return True
#perserve old body_html to be used in checking for chud phrase
old_body_html = obj.body_html

View File

@ -36,7 +36,7 @@ from .feeds import *
if FEATURES['AWARDS']:
from .awards import *
from .giphy import *
from .subs import *
from .holes import *
if FEATURES['GAMBLING']:
from .lottery import *
from .casino import *

View File

@ -1029,7 +1029,7 @@ def ban_user(fullname, v):
except: abort(400)
actual_reason = reason.split(str(post_id))[1].strip()
post = get_post(post_id)
if post.sub != 'chudrama':
if post.hole != 'chudrama':
post.bannedfor = f'{duration} by @{v.username}'
if actual_reason:
post.bannedfor += f' for "{actual_reason}"'
@ -1134,7 +1134,7 @@ def chud(fullname, v):
try: post = int(reason.split("/post/")[1].split(None, 1)[0])
except: abort(400)
post = get_post(post)
if post.sub == 'chudrama':
if post.hole == 'chudrama':
abort(403, "You can't chud people in /h/chudrama")
post.chuddedfor = f'{duration} by @{v.username}'
g.db.add(post)
@ -1142,7 +1142,7 @@ def chud(fullname, v):
try: comment = int(reason.split("/comment/")[1].split(None, 1)[0])
except: abort(400)
comment = get_comment(comment)
if comment.post.sub == 'chudrama':
if comment.post.hole == 'chudrama':
abort(403, "You can't chud people in /h/chudrama")
comment.chuddedfor = f'{duration} by @{v.username}'
g.db.add(comment)

View File

@ -351,8 +351,8 @@ def award_thing(v, thing_type, id):
thing.title_html = filter_emojis_only(thing.title, golden=False, obj=thing, author=author)
elif kind == "chud":
if thing_type == 'post' and thing.sub == 'chudrama' \
or thing_type == 'comment' and thing.post and thing.post.sub == 'chudrama':
if thing_type == 'post' and thing.hole == 'chudrama' \
or thing_type == 'comment' and thing.post and thing.post.hole == 'chudrama':
abort(403, "You can't give the chud award in /h/chudrama")
if author.queen:

View File

@ -38,11 +38,11 @@ def _mark_comment_as_read(cid, vid):
@app.get("/comment/<int:cid>")
@app.get("/post/<int:pid>/<anything>/<int:cid>")
@app.get("/h/<sub>/comment/<int:cid>")
@app.get("/h/<sub>/post/<int:pid>/<anything>/<int:cid>")
@app.get("/h/<hole>/comment/<int:cid>")
@app.get("/h/<hole>/post/<int:pid>/<anything>/<int:cid>")
@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400)
@auth_desired_with_logingate
def post_pid_comment_cid(cid, v, pid=None, anything=None, sub=None):
def post_pid_comment_cid(cid, v, pid=None, anything=None, hole=None):
comment = get_comment(cid, v=v)
@ -95,7 +95,7 @@ def post_pid_comment_cid(cid, v, pid=None, anything=None, sub=None):
else:
if post.is_banned and not (v and (v.admin_level >= PERMS['POST_COMMENT_MODERATION'] or post.author_id == v.id)): template = "post_banned.html"
else: template = "post.html"
return render_template(template, v=v, p=post, sort=sort, comment_info=comment_info, render_replies=True, sub=post.subr)
return render_template(template, v=v, p=post, sort=sort, comment_info=comment_info, render_replies=True, hole=post.hole_obj)
@app.post("/comment")
@limiter.limit('1/second', scope=rpath)
@ -158,10 +158,10 @@ def comment(v):
abort(403, "You can't reply to deleted comments!")
if posting_to_post:
sub = post_target.sub
if sub and v.exiler_username(sub): abort(403, f"You're exiled from /h/{sub}")
if sub in {'furry','vampire','racist','femboy','edgy'} 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}")
hole = post_target.hole
if hole and v.exiler_username(hole): abort(403, f"You're exiled from /h/{hole}")
if hole in {'furry','vampire','racist','femboy','edgy'} and not v.client and not v.house.lower().startswith(hole):
abort(403, f"You need to be a member of House {hole.capitalize()} to comment in /h/{hole}")
if level > COMMENT_MAX_DEPTH: abort(400, f"Max comment level is {COMMENT_MAX_DEPTH}")
@ -255,7 +255,7 @@ def comment(v):
is_bot = v.client is not None and v.id not in BOT_SYMBOL_HIDDEN
chudded = v.chud and not (posting_to_post and post_target.sub == 'chudrama')
chudded = v.chud and not (posting_to_post and post_target.hole == 'chudrama')
c = Comment(author_id=v.id,
parent_post=post_target.id if posting_to_post else None,
@ -610,7 +610,7 @@ def diff_words(answer, guess):
def toggle_comment_nsfw(cid, v):
comment = get_comment(cid)
if comment.author_id != v.id and v.admin_level < PERMS['POST_COMMENT_MODERATION'] and not (comment.post.sub and v.mods(comment.post.sub)):
if comment.author_id != v.id and v.admin_level < PERMS['POST_COMMENT_MODERATION'] and not (comment.post.hole and v.mods(comment.post.hole)):
abort(403)
if comment.nsfw and v.is_permabanned:
@ -628,8 +628,8 @@ def toggle_comment_nsfw(cid, v):
)
g.db.add(ma)
else:
ma = SubAction(
sub = comment.post.sub,
ma = HoleAction(
hole = comment.post.hole,
kind = "set_nsfw_comment" if comment.nsfw else "unset_nsfw_comment",
user_id = v.id,
target_comment_id = comment.id,

View File

@ -13,30 +13,30 @@ from files.routes.wrappers import *
from files.__main__ import app, cache, limiter, redis_instance
@app.get("/")
@app.get("/h/<sub>")
@app.get("/h/<hole>")
@limiter.limit("30/minute;5000/hour;10000/day", deduct_when=lambda response: response.status_code < 400)
@auth_desired_with_logingate
def front_all(v, sub=None):
if sub:
sub = get_sub_by_name(sub, graceful=True)
if sub and not can_see(v, sub):
def front_all(v, hole=None):
if hole:
hole = get_hole(hole, graceful=True)
if hole and not can_see(v, hole):
abort(403)
if request.path.startswith('/h/') and not sub:
if request.path.startswith('/h/') and not hole:
abort(404)
page = get_page()
if v:
defaultsorting = v.defaultsorting
if sub or SITE_NAME != 'rDrama': defaulttime = 'all'
if hole or SITE_NAME != 'rDrama': defaulttime = 'all'
else: defaulttime = v.defaulttime
else:
defaultsorting = "hot"
if sub or SITE_NAME != 'rDrama': defaulttime = 'all'
if hole or SITE_NAME != 'rDrama': defaulttime = 'all'
else: defaulttime = DEFAULT_TIME_FILTER
if sub: defaultsorting = "new"
if hole: defaultsorting = "new"
sort = request.values.get("sort", defaultsorting)
t = request.values.get('t', defaulttime)
@ -53,10 +53,10 @@ def front_all(v, sub=None):
if sort == 'hot': default = True
else: default = False
pins = session.get(f'{sub}_{sort}', default)
pins = session.get(f'{hole}_{sort}', default)
if not v:
result = cache.get(f'frontpage_{sort}_{t}_{page}_{sub}_{pins}')
result = cache.get(f'frontpage_{sort}_{t}_{page}_{hole}_{pins}')
if result:
calc_users()
return result
@ -68,7 +68,7 @@ def front_all(v, sub=None):
filter_words=v.filter_words if v else [],
gt=gt,
lt=lt,
sub=sub,
hole=hole,
pins=pins,
)
@ -79,10 +79,10 @@ def front_all(v, sub=None):
if v and v.client: return {"data": [x.json for x in posts], "total": total}
result = render_template("home.html", v=v, listing=posts, total=total, sort=sort, t=t, page=page, sub=sub, home=True, pins=pins, size=size)
result = render_template("home.html", v=v, listing=posts, total=total, sort=sort, t=t, page=page, hole=hole, home=True, pins=pins, size=size)
if not v:
cache.set(f'frontpage_{sort}_{t}_{page}_{sub}_{pins}', result, timeout=900)
cache.set(f'frontpage_{sort}_{t}_{page}_{hole}_{pins}', result, timeout=900)
return result
@ -92,7 +92,7 @@ LIMITED_WPD_HOLES = ('aftermath', 'fights', 'gore', 'medical', 'request', 'selfh
'countryclub', 'highrollerclub')
@cache.memoize()
def frontlist(v=None, sort="hot", page=1, t="all", ids_only=True, filter_words='', gt=0, lt=0, sub=None, pins=True):
def frontlist(v=None, sort="hot", page=1, t="all", ids_only=True, filter_words='', gt=0, lt=0, hole=None, pins=True):
posts = g.db.query(Post)
if v and v.hidevotedon:
@ -100,13 +100,13 @@ def frontlist(v=None, sort="hot", page=1, t="all", ids_only=True, filter_words='
and_(Vote.post_id == Post.id, Vote.user_id == v.id)
).filter(Vote.post_id == None)
if sub:
posts = posts.filter(Post.sub == sub.name)
if hole:
posts = posts.filter(Post.hole == hole.name)
elif v:
posts = posts.filter(or_(Post.sub == None, Post.sub.notin_(v.sub_blocks)))
posts = posts.filter(or_(Post.hole == None, Post.hole.notin_(v.hole_blocks)))
else:
stealth = [x[0] for x in g.db.query(Sub.name).filter_by(stealth=True)]
posts = posts.filter(or_(Post.sub == None, Post.sub.notin_(stealth)))
stealth = [x[0] for x in g.db.query(Hole.name).filter_by(stealth=True)]
posts = posts.filter(or_(Post.hole == None, Post.hole.notin_(stealth)))
if gt: posts = posts.filter(Post.created_utc > gt)
if lt: posts = posts.filter(Post.created_utc < lt)
@ -121,7 +121,7 @@ def frontlist(v=None, sort="hot", page=1, t="all", ids_only=True, filter_words='
)
if pins and not gt and not lt:
if sub: posts = posts.filter(Post.hole_pinned == None)
if hole: posts = posts.filter(Post.hole_pinned == None)
else: posts = posts.filter(Post.stickied == None)
if v:
@ -141,28 +141,28 @@ def frontlist(v=None, sort="hot", page=1, t="all", ids_only=True, filter_words='
posts = posts.options(load_only(Post.id)).offset(size * (page - 1))
if SITE_NAME == 'WPD' and sort == "hot" and sub == None:
if SITE_NAME == 'WPD' and sort == "hot" and hole == None:
posts = posts.limit(200).all()
to_remove = []
for h in LIMITED_WPD_HOLES:
to_remove += [x.id for x in posts if x.sub == h][1:]
to_remove += [x.id for x in posts if x.hole == h][1:]
posts = [x for x in posts if x.id not in to_remove][:size]
elif SITE_NAME == 'WPD' and not v and sub == None:
elif SITE_NAME == 'WPD' and not v and hole == None:
posts = posts.limit(200).all()
posts = [x for x in posts if x.sub not in {'pets','selfharm'}][:size]
posts = [x for x in posts if x.hole not in {'pets','selfharm'}][:size]
else:
posts = posts.limit(size).all()
if pins and page == 1 and not gt and not lt:
if sub:
pins = g.db.query(Post).options(load_only(Post.id)).filter(Post.sub == sub.name, Post.hole_pinned != None)
if hole:
pins = g.db.query(Post).options(load_only(Post.id)).filter(Post.hole == hole.name, Post.hole_pinned != None)
else:
pins = g.db.query(Post).options(load_only(Post.id)).filter(Post.stickied != None, Post.is_banned == False)
if v:
pins = pins.filter(or_(Post.sub == None, Post.sub.notin_(v.sub_blocks)))
pins = pins.filter(or_(Post.hole == None, Post.hole.notin_(v.hole_blocks)))
if v: pins = pins.filter(Post.author_id.notin_(v.userblocks))
@ -185,7 +185,7 @@ def random_post(v):
Post.deleted_utc == 0,
Post.is_banned == False,
Post.private == False,
or_(Post.sub == None, Post.sub.notin_(v.sub_blocks)),
or_(Post.hole == None, Post.hole.notin_(v.hole_blocks)),
).order_by(func.random()).first()
if p: p = p[0]

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@ from sqlalchemy.sql.expression import not_, and_, or_
from sqlalchemy.orm import load_only
from files.classes.mod_logs import ModAction
from files.classes.sub_logs import SubAction
from files.classes.hole_logs import HoleAction
from files.helpers.config.const import *
from files.helpers.config.modaction_types import *
from files.helpers.get import *
@ -167,7 +167,7 @@ def notifications_posts(v):
listing = g.db.query(Post).filter(
or_(
Post.sub.in_(v.followed_subs),
Post.hole.in_(v.followed_holes),
and_(
Post.author_id.in_(v.followed_users),
Post.notify == True,
@ -179,7 +179,7 @@ def notifications_posts(v):
Post.private == False,
Post.author_id != v.id,
Post.author_id.notin_(v.userblocks),
or_(Post.sub == None, Post.sub.notin_(v.sub_blocks)),
or_(Post.hole == None, Post.hole.notin_(v.hole_blocks)),
).options(load_only(Post.id))
total = listing.count()
@ -217,8 +217,8 @@ def notifications_modactions(v):
if v.admin_level >= PERMS['NOTIFICATIONS_MODERATOR_ACTIONS']:
cls = ModAction
elif v.moderated_subs:
cls = SubAction
elif v.moderated_holes:
cls = HoleAction
else:
abort(403)
@ -230,8 +230,8 @@ def notifications_modactions(v):
if v.admin_level < PERMS['PROGSTACK']:
listing = listing.filter(cls.kind.notin_(MODACTION_PRIVILEGED__TYPES))
if cls == SubAction:
listing = listing.filter(cls.sub.in_(v.moderated_subs))
if cls == HoleAction:
listing = listing.filter(cls.hole.in_(v.moderated_holes))
total = listing.count()
listing = listing.order_by(cls.id.desc())

View File

@ -18,10 +18,10 @@ def vote_option(option_id, v):
abort(404)
option = g.db.get(PostOption, option_id)
if not option: abort(404)
sub = option.parent.sub
hole = option.parent.hole
if sub in {'furry','vampire','racist','femboy','edgy'} and not v.house.lower().startswith(sub):
abort(403, f"You need to be a member of House {sub.capitalize()} to vote on polls in /h/{sub}")
if hole in {'furry','vampire','racist','femboy','edgy'} and not v.house.lower().startswith(hole):
abort(403, f"You need to be a member of House {hole.capitalize()} to vote on polls in /h/{hole}")
if option.exclusive == 2:
if option.parent.total_bet_voted(v):
@ -72,12 +72,12 @@ def vote_option_comment(option_id, v):
if not option: abort(404)
if option.parent.parent_post:
sub = option.parent.post.sub
hole = option.parent.post.hole
else:
sub = None
hole = None
if sub in {'furry','vampire','racist','femboy','edgy'} and not v.house.lower().startswith(sub):
abort(403, f"You need to be a member of House {sub.capitalize()} to vote on polls in /h/{sub}")
if hole in {'furry','vampire','racist','femboy','edgy'} and not v.house.lower().startswith(hole):
abort(403, f"You need to be a member of House {hole.capitalize()} to vote on polls in /h/{hole}")
if option.exclusive == 2:
if option.parent.total_bet_voted(v):

View File

@ -79,25 +79,25 @@ def publish(pid, v):
return {"message": "Post has been published successfully!"}
@app.get("/submit")
@app.get("/h/<sub>/submit")
@app.get("/h/<hole>/submit")
@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400)
@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID)
@auth_required
def submit_get(v, sub=None):
sub = get_sub_by_name(sub, graceful=True)
if request.path.startswith('/h/') and not sub: abort(404)
def submit_get(v, hole=None):
hole = get_hole(hole, graceful=True)
if request.path.startswith('/h/') and not hole: abort(404)
SUBS = [x[0] for x in g.db.query(Sub.name).order_by(Sub.name)]
HOLES = [x[0] for x in g.db.query(Hole.name).order_by(Hole.name)]
return render_template("submit.html", SUBS=SUBS, v=v, sub=sub)
return render_template("submit.html", HOLES=HOLES, v=v, hole=hole)
@app.get("/post/<int:pid>")
@app.get("/post/<int:pid>/<anything>")
@app.get("/h/<sub>/post/<int:pid>")
@app.get("/h/<sub>/post/<int:pid>/<anything>")
@app.get("/h/<hole>/post/<int:pid>")
@app.get("/h/<hole>/post/<int:pid>/<anything>")
@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400)
@auth_desired_with_logingate
def post_id(pid, v, anything=None, sub=None):
def post_id(pid, v, anything=None, hole=None):
p = get_post(pid, v=v)
if not can_see(v, p): abort(403)
@ -192,7 +192,7 @@ def post_id(pid, v, anything=None, sub=None):
template = "post_banned.html"
result = render_template(template, v=v, p=p, ids=list(ids),
sort=sort, render_replies=True, offset=offset, sub=p.subr,
sort=sort, render_replies=True, offset=offset, hole=p.hole_obj,
fart=get_setting('fart_mode'))
if not v:
@ -426,13 +426,13 @@ def is_repost(v):
else: return not_a_repost
@app.post("/submit")
@app.post("/h/<sub>/submit")
@app.post("/h/<hole>/submit")
@limiter.limit('1/second', scope=rpath)
@limiter.limit('1/second', scope=rpath, key_func=get_ID)
@limiter.limit('20/day', deduct_when=lambda response: response.status_code < 400)
@limiter.limit('20/day', deduct_when=lambda response: response.status_code < 400, key_func=get_ID)
@is_not_banned
def submit_post(v, sub=None):
def submit_post(v, hole=None):
url = request.values.get("url", "").strip()
if '\\' in url: abort(400)
@ -446,35 +446,35 @@ def submit_post(v, sub=None):
if not title:
abort(400, "Please enter a better title!")
sub = request.values.get("sub", "").lower().replace('/h/','').strip()
hole = request.values.get("hole", "").lower().replace('/h/','').strip()
if SITE == 'rdrama.net' and (v.chud == 1 or v.id == 253):
sub = 'chudrama'
hole = 'chudrama'
if SITE == 'rdrama.net' and v.id == 10947:
sub = 'mnn'
hole = 'mnn'
if sub == 'changelog':
if hole == 'changelog':
abort(400, "/h/changelog is archived")
if sub in {'furry','vampire','racist','femboy','edgy'} and not v.client and not v.house.lower().startswith(sub):
abort(400, f"You need to be a member of House {sub.capitalize()} to post in /h/{sub}")
if hole in {'furry','vampire','racist','femboy','edgy'} and not v.client and not v.house.lower().startswith(hole):
abort(400, f"You need to be a member of House {hole.capitalize()} to post in /h/{hole}")
if sub and sub != 'none':
sub_name = sub.strip().lower()
sub = g.db.query(Sub).options(load_only(Sub.name)).filter_by(name=sub_name).one_or_none()
if not sub: abort(400, f"/h/{sub_name} not found!")
if hole and hole != 'none':
hole_name = hole.strip().lower()
hole = g.db.query(Hole).options(load_only(Hole.name)).filter_by(name=hole_name).one_or_none()
if not hole: abort(400, f"/h/{hole_name} not found!")
if not can_see(v, sub):
if sub.name == 'highrollerclub':
abort(403, f"Only {patron}s can post in /h/{sub}")
abort(403, f"You're not allowed to post in /h/{sub}")
if not can_see(v, hole):
if hole.name == 'highrollerclub':
abort(403, f"Only {patron}s can post in /h/{hole}")
abort(403, f"You're not allowed to post in /h/{hole}")
sub = sub.name
if v.exiler_username(sub): abort(400, f"You're exiled from /h/{sub}")
else: sub = None
hole = hole.name
if v.exiler_username(hole): abort(400, f"You're exiled from /h/{hole}")
else: hole = None
if not sub and HOLE_REQUIRED:
if not hole and HOLE_REQUIRED:
abort(400, f"You must choose a {HOLE_NAME} for your post!")
if v.longpost and (len(body) < 280 or ' [](' in body or body.startswith('[](')):
@ -536,7 +536,7 @@ def submit_post(v, sub=None):
flag_private = request.values.get("private", False, bool)
flag_ghost = request.values.get("ghost", False, bool) and v.can_post_in_ghost_threads
if flag_ghost: sub = None
if flag_ghost: hole = None
if embed and len(embed) > 1500: embed = None
if embed: embed = embed.strip()
@ -546,7 +546,7 @@ def submit_post(v, sub=None):
if url == '': url = None
flag_chudded = v.chud and sub != 'chudrama'
flag_chudded = v.chud and hole != 'chudrama'
p = Post(
private=flag_private,
@ -560,7 +560,7 @@ def submit_post(v, sub=None):
body=body,
embed=embed,
title=title,
sub=sub,
hole=hole,
ghost=flag_ghost,
chudded=flag_chudded,
rainbowed=bool(v.rainbow),
@ -684,7 +684,7 @@ def submit_post(v, sub=None):
if (SITE == 'rdrama.net'
and v.id in {2008, 3336}
and not (p.sub and p.subr.stealth)) and p.sub != 'slavshit' and not p.ghost:
and not (p.hole and p.hole_obj.stealth)) and p.hole != 'slavshit' and not p.ghost:
p.stickied_utc = int(time.time()) + 28800
p.stickied = "AutoJanny"
@ -766,7 +766,7 @@ def undelete_post_pid(pid, v):
def mark_post_nsfw(pid, v):
p = get_post(pid)
if p.author_id != v.id and v.admin_level < PERMS['POST_COMMENT_MODERATION'] and not (p.sub and v.mods(p.sub)):
if p.author_id != v.id and v.admin_level < PERMS['POST_COMMENT_MODERATION'] and not (p.hole and v.mods(p.hole)):
abort(403)
if p.nsfw and v.is_permabanned:
@ -784,8 +784,8 @@ def mark_post_nsfw(pid, v):
)
g.db.add(ma)
else:
ma = SubAction(
sub = p.sub,
ma = HoleAction(
hole = p.hole,
kind = "set_nsfw",
user_id = v.id,
target_post_id = p.id,
@ -805,7 +805,7 @@ def mark_post_nsfw(pid, v):
def unmark_post_nsfw(pid, v):
p = get_post(pid)
if p.author_id != v.id and v.admin_level < PERMS['POST_COMMENT_MODERATION'] and not (p.sub and v.mods(p.sub)):
if p.author_id != v.id and v.admin_level < PERMS['POST_COMMENT_MODERATION'] and not (p.hole and v.mods(p.hole)):
abort(403)
if p.nsfw and v.is_permabanned:
@ -823,8 +823,8 @@ def unmark_post_nsfw(pid, v):
)
g.db.add(ma)
else:
ma = SubAction(
sub = p.sub,
ma = HoleAction(
hole = p.hole,
kind = "unset_nsfw",
user_id = v.id,
target_post_id = p.id,

View File

@ -2,7 +2,7 @@ from flask import g
from files.classes.reports import Report, CommentReport
from files.classes.mod_logs import ModAction
from files.classes.sub_logs import SubAction
from files.classes.hole_logs import HoleAction
from files.helpers.actions import *
from files.helpers.alerts import *
from files.helpers.get import *
@ -28,7 +28,7 @@ def report_post(pid, v):
if len(reason_html) > 350:
abort(400, "Report reason too long!")
if reason.startswith('!') and (v.admin_level >= PERMS['POST_COMMENT_MODERATION'] or post.sub and v.mods(post.sub)):
if reason.startswith('!') and (v.admin_level >= PERMS['POST_COMMENT_MODERATION'] or post.hole and v.mods(post.hole)):
post.flair = reason_html[1:]
g.db.add(post)
if v.admin_level >= PERMS['POST_COMMENT_MODERATION']:
@ -41,15 +41,15 @@ def report_post(pid, v):
g.db.add(ma)
position = 'a site admin'
else:
ma = SubAction(
sub=post.sub,
ma = HoleAction(
hole=post.hole,
kind="flair_post",
user_id=v.id,
target_post_id=post.id,
_note=f'"{post.flair}"'
)
g.db.add(ma)
position = f'a /h/{post.sub} mod'
position = f'a /h/{post.hole} mod'
if v.id != post.author_id:
message = f'@{v.username} ({position}) has flaired [{post.title}]({post.shortlink}) with the flair: `"{og_flair}"`'
@ -156,75 +156,75 @@ def move_post(post, v, reason):
if not reason.startswith('/h/') and not reason.startswith('h/'):
return False
sub_from = post.sub
sub_to = get_sub_by_name(reason, graceful=True)
sub_to = sub_to.name if sub_to else None
hole_from = post.hole
hole_to = get_hole(reason, graceful=True)
hole_to = hole_to.name if hole_to else None
can_move_post = v.admin_level >= PERMS['POST_COMMENT_MODERATION'] or (post.sub and v.mods(sub_from))
if sub_from != 'chudrama': # posts can only be moved out of /h/chudrama by admins
can_move_post = v.admin_level >= PERMS['POST_COMMENT_MODERATION'] or (post.hole and v.mods(hole_from))
if hole_from != 'chudrama': # posts can only be moved out of /h/chudrama by admins
can_move_post = can_move_post or post.author_id == v.id
if not can_move_post: return False
if sub_to == None:
if hole_to == None:
if HOLE_REQUIRED:
abort(403, "All posts are required to be flaired!")
sub_to_in_notif = 'the main feed'
hole_to_in_notif = 'the main feed'
else:
sub_to_in_notif = f'/h/{sub_to}'
hole_to_in_notif = f'/h/{hole_to}'
if sub_from == sub_to: abort(409, f"Post is already in {sub_to_in_notif}")
if hole_from == hole_to: abort(409, f"Post is already in {hole_to_in_notif}")
if post.author.exiler_username(sub_to):
if post.author.exiler_username(hole_to):
abort(403, f"User is exiled from this {HOLE_NAME}!")
if sub_to == 'changelog':
if hole_to == 'changelog':
abort(403, "/h/changelog is archived!")
if sub_to in {'furry','vampire','racist','femboy','edgy'} and not v.client and not post.author.house.lower().startswith(sub_to):
if hole_to in {'furry','vampire','racist','femboy','edgy'} and not v.client and not post.author.house.lower().startswith(hole_to):
if v.id == post.author_id:
abort(403, f"You need to be a member of House {sub_to.capitalize()} to post in /h/{sub_to}")
abort(403, f"You need to be a member of House {hole_to.capitalize()} to post in /h/{hole_to}")
else:
abort(403, f"@{post.author_name} needs to be a member of House {sub_to.capitalize()} for their post to be moved to /h/{sub_to}")
abort(403, f"@{post.author_name} needs to be a member of House {hole_to.capitalize()} for their post to be moved to /h/{hole_to}")
post.sub = sub_to
post.hole = hole_to
post.hole_pinned = None
g.db.add(post)
if v.id != post.author_id:
sub_from_str = 'main feed' if sub_from is None else \
f'<a href="/h/{sub_from}">/h/{sub_from}</a>'
sub_to_str = 'main feed' if sub_to is None else \
f'<a href="/h/{sub_to}">/h/{sub_to}</a>'
hole_from_str = 'main feed' if hole_from is None else \
f'<a href="/h/{hole_from}">/h/{hole_from}</a>'
hole_to_str = 'main feed' if hole_to is None else \
f'<a href="/h/{hole_to}">/h/{hole_to}</a>'
if v.admin_level >= PERMS['POST_COMMENT_MODERATION']:
ma = ModAction(
kind='move_hole',
user_id=v.id,
target_post_id=post.id,
_note=f'{sub_from_str}{sub_to_str}',
_note=f'{hole_from_str}{hole_to_str}',
)
g.db.add(ma)
else:
ma = SubAction(
sub=sub_from,
ma = HoleAction(
hole=hole_from,
kind='move_hole',
user_id=v.id,
target_post_id=post.id,
_note=f'{sub_from_str}{sub_to_str}',
_note=f'{hole_from_str}{hole_to_str}',
)
g.db.add(ma)
if v.admin_level >= PERMS['POST_COMMENT_MODERATION']: position = 'a site admin'
else: position = f'a /h/{sub_from} mod'
else: position = f'a /h/{hole_from} mod'
if sub_from == None:
sub_from_in_notif = 'the main feed'
if hole_from == None:
hole_from_in_notif = 'the main feed'
else:
sub_from_in_notif = f'/h/{sub_from}'
hole_from_in_notif = f'/h/{hole_from}'
message = f"@{v.username} ({position}) has moved [{post.title}]({post.shortlink}) from {sub_from_in_notif} to {sub_to_in_notif}"
message = f"@{v.username} ({position}) has moved [{post.title}]({post.shortlink}) from {hole_from_in_notif} to {hole_to_in_notif}"
send_repeatable_notification(post.author_id, message)
cache.delete_memoized(frontlist)
return f"Post moved to {sub_to_in_notif} successfully!"
return f"Post moved to {hole_to_in_notif} successfully!"

View File

@ -140,7 +140,7 @@ def searchposts(v):
if search_operator_hole in criteria:
posts = posts.filter(Post.sub == criteria[search_operator_hole])
posts = posts.filter(Post.hole == criteria[search_operator_hole])
if 'after' in criteria:
after = criteria['after']
@ -239,7 +239,7 @@ def searchcomments(v):
if 'nsfw' in criteria: comments = comments.filter(Comment.nsfw == True)
if search_operator_hole in criteria:
comments = comments.filter(Post.sub == criteria[search_operator_hole])
comments = comments.filter(Post.hole == criteria[search_operator_hole])
comments = apply_time_filter(t, comments, Comment)

View File

@ -1300,14 +1300,14 @@ def fp(v, fp):
g.db.add(v)
return '', 204
@app.post("/toggle_pins/<sub>/<sort>")
@app.post("/toggle_pins/<hole>/<sort>")
@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400)
def toggle_pins(sub, sort):
def toggle_pins(hole, sort):
if sort == 'hot': default = True
else: default = False
pins = session.get(f'{sub}_{sort}', default)
session[f'{sub}_{sort}'] = not pins
pins = session.get(f'{hole}_{sort}', default)
session[f'{hole}_{sort}'] = not pins
return {"message": "Pins toggled successfully!"}

View File

@ -153,11 +153,11 @@ def vote_post_comment(target_id, new, v, cls, vote_cls):
or 'forum' in target.domain or 'chan' in target.domain or 'lemmy' in target.domain or 'mastodon' in target.domain
or (target.domain in BOOSTED_SITES and not target.url.startswith('/'))):
mul = 2
elif target.sub in STEALTH_HOLES or target.sub in {'countryclub', 'highrollerclub'}:
elif target.hole in STEALTH_HOLES or target.hole in {'countryclub', 'highrollerclub'}:
mul = 2
elif 6 <= datetime.fromtimestamp(target.created_utc).hour <= 10:
mul = 2
elif target.sub in BOOSTED_HOLES:
elif target.hole in BOOSTED_HOLES:
mul = 1.25
if target.body_html and target.author.id != 8768:

View File

@ -74,8 +74,8 @@
<span class="font-weight-bold"><a {% if v and v.newtab %}data-target="t" target="_blank"{% endif %} href="{{c.post.permalink}}">{{c.post.realtitle(v) | safe}}</a></span>
{% endif %}
{% if c.post.sub %}
<span class="ml-1"> in <a href="/h/{{c.post.sub}}" {% if v and v.newtab %}data-target="t" target="_blank"{% endif %}>/h/{{c.post.sub}}</a></span>
{% if c.post.hole %}
<span class="ml-1"> in <a href="/h/{{c.post.hole}}" {% if v and v.newtab %}data-target="t" target="_blank"{% endif %}>/h/{{c.post.hole}}</a></span>
{% endif %}
{% elif c.author_id==AUTOJANNY_ID %}
<span class="font-weight-bold">Notification</span>
@ -124,17 +124,17 @@
{% endfor %}
{% if c.parent_post %}
{% set sub = c.post.sub %}
{% if sub and c.author.exiler_username(sub) %}
<a><i class="fas fa-campfire text-danger" data-bs-toggle="tooltip" data-bs-placement="bottom" title="User has been exiled from /h/{{sub}} by @{{c.author.exiler_username(sub)}}"></i></a>
{% set hole = c.post.hole %}
{% if hole and c.author.exiler_username(hole) %}
<a><i class="fas fa-campfire text-danger" data-bs-toggle="tooltip" data-bs-placement="bottom" title="User has been exiled from /h/{{hole}} by @{{c.author.exiler_username(hole)}}"></i></a>
{% endif %}
{% endif %}
{% if c.bannedfor and not (c.parent_post and c.post.sub == 'chudrama') %}
{% if c.bannedfor and not (c.parent_post and c.post.hole == 'chudrama') %}
<i class="fas fa-hammer-crash text-danger" data-bs-toggle="tooltip" data-bs-placement="bottom" title="User was banned for this comment {{c.bannedfor}}"></i>
{% endif %}
{% if c.chuddedfor and not (c.parent_post and c.post.sub == 'chudrama') %}
{% if c.chuddedfor and not (c.parent_post and c.post.hole == 'chudrama') %}
<i class="fas fa-face-sleeping text-danger" data-bs-toggle="tooltip" data-bs-placement="bottom" title="User was chudded for this comment {{c.chuddedfor}}"></i>
{% endif %}
@ -436,7 +436,7 @@
{% set url = "sticky_comment" %}
{% elif v.id == c.post.author_id %}
{% set url = "pin_comment" %}
{% elif c.post.sub and v.mods(c.post.sub) %}
{% elif c.post.hole and v.mods(c.post.hole) %}
{% set url = "pin_comment_mod" %}
{% endif %}
@ -466,10 +466,10 @@
{% endif %}
{% if c.parent_post %}
{% set sub = c.post.sub %}
{% if sub and v.mods(sub) and not c.author.mods(sub) %}
<button type="button" id="exile-{{c.id}}" class="d-none {% if not c.author.exiler_username(sub) %}d-md-block{% endif %} dropdown-item list-inline-item text-danger" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/exile/comment/{{c.id}}','exile-{{c.id}}','unexile-{{c.id}}','d-none')"><i class="fas fa-campfire text-danger fa-fw"></i>Exile user</button>
<button type="button" id="unexile-{{c.id}}" class="d-none {% if c.author.exiler_username(sub) %}d-md-block{% endif %} dropdown-item list-inline-item text-success" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/h/{{sub}}/unexile/{{c.author_id}}','exile-{{c.id}}','unexile-{{c.id}}','d-none')"><i class="fas fa-campfire text-success fa-fw"></i>Unexile user</button>
{% set hole = c.post.hole %}
{% if hole and v.mods(hole) and not c.author.mods(hole) %}
<button type="button" id="exile-{{c.id}}" class="d-none {% if not c.author.exiler_username(hole) %}d-md-block{% endif %} dropdown-item list-inline-item text-danger" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/exile/comment/{{c.id}}','exile-{{c.id}}','unexile-{{c.id}}','d-none')"><i class="fas fa-campfire text-danger fa-fw"></i>Exile user</button>
<button type="button" id="unexile-{{c.id}}" class="d-none {% if c.author.exiler_username(hole) %}d-md-block{% endif %} dropdown-item list-inline-item text-success" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/h/{{hole}}/unexile/{{c.author_id}}','exile-{{c.id}}','unexile-{{c.id}}','d-none')"><i class="fas fa-campfire text-success fa-fw"></i>Unexile user</button>
{% endif %}
{% endif %}
@ -478,7 +478,7 @@
<button type="button" id="unprogstack-{{c.id}}" class="dropdown-item list-inline-item d-none {% if c.is_approved == PROGSTACK_ID %}d-md-block{% endif %} text-danger" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/admin/unprogstack/comment/{{c.id}}','progstack-{{c.id}}','unprogstack-{{c.id}}','d-md-block')"><i class="fas fa-bullhorn text-danger fa-fw"></i>Remove Progressive Stack</button>
{% endif %}
{% if FEATURES['NSFW_MARKING'] and (c.parent_post or c.wall_user_id) and (c.author_id==v.id or v.admin_level >= PERMS['POST_COMMENT_MODERATION'] or (c.post.sub and v.mods(c.post.sub))) %}
{% if FEATURES['NSFW_MARKING'] and (c.parent_post or c.wall_user_id) and (c.author_id==v.id or v.admin_level >= PERMS['POST_COMMENT_MODERATION'] or (c.post.hole and v.mods(c.post.hole))) %}
<button type="button" id="mark-{{c.id}}" class="dropdown-item list-inline-item d-none {% if not c.nsfw %}d-md-block{% endif %} text-danger" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/toggle_comment_nsfw/{{c.id}}','mark-{{c.id}}','unmark-{{c.id}}','d-md-block')"><i class="fas fa-eye-evil text-danger fa-fw"></i>Mark NSFW</button>
<button type="button" id="unmark-{{c.id}}" class="dropdown-item list-inline-item d-none {% if c.nsfw %}d-md-block{% endif %} text-success" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/toggle_comment_nsfw/{{c.id}}','mark-{{c.id}}','unmark-{{c.id}}','d-md-block')"><i class="fas fa-eye-evil text-success fa-fw"></i>Unmark NSFW</button>
{% endif %}
@ -636,7 +636,7 @@
{% endif %}
{% endif %}
{% if FEATURES['NSFW_MARKING'] and (c.author_id == v.id or (c.post.sub and v.mods(c.post.sub))) %}
{% if FEATURES['NSFW_MARKING'] and (c.author_id == v.id or (c.post.hole and v.mods(c.post.hole))) %}
<button type="button" id="mark2-{{c.id}}" class="{% if c.nsfw %}d-none{% endif %} list-group-item text-danger" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/toggle_comment_nsfw/{{c.id}}','mark2-{{c.id}}','unmark2-{{c.id}}','d-none')" data-bs-dismiss="modal"><i class="fas fa-eye-evil text-danger mr-2"></i>Mark NSFW</button>
<button type="button" id="unmark2-{{c.id}}" class="{% if not c.nsfw %}d-none{% endif %} list-group-item text-success" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/toggle_comment_nsfw/{{c.id}}','mark2-{{c.id}}','unmark2-{{c.id}}','d-none')" data-bs-dismiss="modal"><i class="fas fa-eye-evil text-success mr-2"></i>Unmark NSFW</button>
@ -646,17 +646,17 @@
{% if c.parent_post and v.id == c.post.author_id %}
<button type="button" id="pin2-{{c.id}}" class="list-group-item {% if c.stickied %}d-none{% endif %} text-info" data-bs-target="#actionsModal-{{c.id}}" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/pin_comment/{{c.id}}','pin2-{{c.id}}','unpin2-{{c.id}}','d-none')" data-bs-dismiss="modal"><i class="fas fa-thumbtack fa-rotate--45 text-info mr-2"></i>Pin</button>
<button type="button" id="unpin2-{{c.id}}" class="list-group-item {% if not c.stickied %}d-none{% endif %} text-info" data-bs-target="#actionsModal-{{c.id}}" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/unpin_comment/{{c.id}}','pin2-{{c.id}}','unpin2-{{c.id}}','d-none')" data-bs-dismiss="modal"><i class="fas fa-thumbtack fa-rotate--45 text-info mr-2"></i>Unpin</button>
{% elif c.post.sub and v.mods(c.post.sub) %}
{% elif c.post.hole and v.mods(c.post.hole) %}
<button type="button" id="pin2-{{c.id}}" class="list-group-item {% if c.stickied %}d-none{% endif %} text-info" data-bs-target="#actionsModal-{{c.id}}" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/pin_comment_mod/{{c.id}}','pin2-{{c.id}}','unpin2-{{c.id}}','d-none')" data-bs-dismiss="modal"><i class="fas fa-thumbtack fa-rotate--45 text-info mr-2"></i>Pin</button>
<button type="button" id="unpin2-{{c.id}}" class="list-group-item {% if not c.stickied %}d-none{% endif %} text-info" data-bs-target="#actionsModal-{{c.id}}" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/unpin_comment_mod/{{c.id}}','pin2-{{c.id}}','unpin2-{{c.id}}','d-none')" data-bs-dismiss="modal"><i class="fas fa-thumbtack fa-rotate--45 text-info mr-2"></i>Unpin</button>
{% endif %}
{% endif %}
{% if c.parent_post %}
{% set sub = c.post.sub %}
{% if sub and v.mods(sub) and not c.author.mods(sub) %}
<button type="button" data-bs-dismiss="modal" id="exile2-{{c.id}}" class="{% if c.author.exiler_username(sub) %}d-none{% endif %} list-group-item text-danger" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/exile/comment/{{c.id}}','exile2-{{c.id}}','unexile2-{{c.id}}','d-none')"><i class="fas fa-campfire text-danger mr-2"></i>Exile user</button>
<button type="button" data-bs-dismiss="modal" id="unexile2-{{c.id}}" class="{% if not c.author.exiler_username(sub) %}d-none{% endif %} list-group-item text-success" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/h/{{sub}}/unexile/{{c.author_id}}','exile2-{{c.id}}','unexile2-{{c.id}}','d-none')"><i class="fas fa-campfire text-success mr-2"></i>Unexile user</button>
{% set hole = c.post.hole %}
{% if hole and v.mods(hole) and not c.author.mods(hole) %}
<button type="button" data-bs-dismiss="modal" id="exile2-{{c.id}}" class="{% if c.author.exiler_username(hole) %}d-none{% endif %} list-group-item text-danger" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/exile/comment/{{c.id}}','exile2-{{c.id}}','unexile2-{{c.id}}','d-none')"><i class="fas fa-campfire text-danger mr-2"></i>Exile user</button>
<button type="button" data-bs-dismiss="modal" id="unexile2-{{c.id}}" class="{% if not c.author.exiler_username(hole) %}d-none{% endif %} list-group-item text-success" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/h/{{hole}}/unexile/{{c.author_id}}','exile2-{{c.id}}','unexile2-{{c.id}}','d-none')"><i class="fas fa-campfire text-success mr-2"></i>Unexile user</button>
{% endif %}
{% endif %}
{% endif %}

View File

@ -9,17 +9,17 @@
{% block banner %}
{% include "modals/expanded_image.html" %}
{% if err or '@' not in request.path %}
{% if IS_FISTMAS() and not sub %}
{% if IS_FISTMAS() and not hole %}
{% include 'events/fistmas/banner.html' %}
{% elif IS_HOMOWEEN() and not sub %}
{% elif IS_HOMOWEEN() and not hole %}
{% include 'events/homoween/banner.html' %}
{% else %}
{% set path = "files/assets/images/" ~ SITE_NAME %}
{% if err and SITE_NAME == 'rDrama' %}
{% set src = "banner_error.webp" | asset_siteimg %}
{% elif sub and sub.has_banners %}
{% set src = sub.random_banner() %}
{% elif hole and hole.has_banners %}
{% set src = hole.random_banner() %}
{% set alt = ['/h/', sub, 'banner']|join %}
{% set class = 'site-banner-hole' %}
{% elif get_orgy(v) and os_path.exists(path ~ "/orgy_banners") %}
@ -34,8 +34,8 @@
{% endif %}
{% if SITE_NAME == "WPD" %}
{% if sub %}
{% set href = "/h/" ~ sub %}
{% if hole %}
{% set href = "/h/" ~ hole %}
{% set expand = false %}
{% else %}
{% set href = "/" %}
@ -62,7 +62,7 @@
<img data-nonce="{{g.nonce}}" data-onclick="{{expand|default('expandImage()')}}" class="{{class|default('site-banner')}}" alt="{{alt|default('site banner')}}" src="{{banner_url}}">
{% endmacro %}
{% if sub and sub.has_banners %}
{% if hole and hole.has_banners %}
{{img_element()}}
{% else %}
<div class="banner-wrapper">

View File

@ -4,7 +4,7 @@
<a href="{{image}}" style="text-decoration:none">
<img class="mb-4" alt="sidebar image" data-nonce="{{g.nonce}}" data-onclick="expandImage()" loading="lazy" src="{{image}}" width="100%">
{% if not sub %}
{% if not hole %}
{% set coordsLookup = ({
"1.webp":({
"left":({

View File

@ -1,4 +1,4 @@
{% if SITE_NAME != 'WPD' and not (v and v.poor) and (not v or v.event_music) and not (sub and sub.name == 'music') and not (IS_HOMOWEEN() and p and p.award_count("haunt", v)) %}
{% if SITE_NAME != 'WPD' and not (v and v.poor) and (not v or v.event_music) and not (hole and hole.name == 'music') and not (IS_HOMOWEEN() and p and p.award_count("haunt", v)) %}
{% set path = "assets/events/" ~ IS_EVENT() ~ "/music" %}
{% set song = SITE_FULL ~ "/" ~ path ~ "/" ~ listdir('files/'~path)|random() ~ '?x=45' %}
<input hidden id="event-song" value="{{song}}">

View File

@ -1,6 +1,6 @@
{%- set search_placeholder = "Search" -%}
{%- if sub -%}
{%- set search_placeholder = "Search (try '" ~ HOLE_NAME ~ ":" ~ sub.name ~ "')" -%}
{%- if hole -%}
{%- set search_placeholder = "Search (try '" ~ HOLE_NAME ~ ":" ~ hole.name ~ "')" -%}
{%- endif -%}
<nav class="shadow-md fixed-top">
@ -84,7 +84,7 @@
<div class="navbar navbar-expand-md navbar-light" id="navbar">
<div class="container-fluid" style="padding:0">
<a href="/" class="navbar-brand mr-auto {% if not has_logo and not sub %}flex-grow-1{% endif %}">
<a href="/" class="navbar-brand mr-auto {% if not has_logo and not hole %}flex-grow-1{% endif %}">
{% if IS_DKD() %}
{% set icon_url = macros.random_image('assets/events/DKD/images/icon') %}
{% elif IS_FISTMAS() %}
@ -112,8 +112,8 @@
{% endif %}
{% endif %}
<img loading="lazy" id="header--icon" alt="header icon"
{%- if sub and sub.marseyurl -%}
src="{{sub.marseyurl}}"
{%- if hole and hole.marseyurl -%}
src="{{hole.marseyurl}}"
{%- else -%}
src="{{icon_url}}"
{%- if width -%}
@ -123,8 +123,8 @@
>
</a>
{% if sub %}
<a id="sub-name" href="/h/{{sub}}" class="font-weight-bold flex-grow-1 ml-2 mt-1" {% if sub.name|length >= 17 %}style="font-size:max(10px,1.2vw)"{% endif %}>{% if not HOLE_STYLE_FLAIR %}/h/{% endif %}{{sub}}</a>
{% if hole %}
<a id="hole-name" href="/h/{{hole}}" class="font-weight-bold flex-grow-1 ml-2 mt-1" {% if hole.name|length >= 17 %}style="font-size:max(10px,1.2vw)"{% endif %}>{% if not HOLE_STYLE_FLAIR %}/h/{% endif %}{{hole}}</a>
{% elif has_logo %}
<div id="logo-container" class="flex-grow-1 logo-container">
<a href="/">

View File

@ -1,7 +1,7 @@
{% extends "default.html" %}
{% block pagetitle %}Users {{verb}} /h/{{sub}}{% endblock %}
{% block pagetitle %}Users {{verb}} /h/{{hole}}{% endblock %}
{% block content %}
<h5 class="mt-3">Users {{verb}} /h/{{sub}}</h5>
<h5 class="mt-3">Users {{verb}} /h/{{hole}}</h5>
<div class="overflow-x-auto mt-1"><table class="table table-striped mb-5">
<thead class="bg-primary text-white">
<tr>

View File

@ -9,7 +9,7 @@
<h3 class=" d-md-none">Create a {{HOLE_NAME}}</h3>
<div class="body">
<input hidden name="formkey" value="{{v|formkey}}">
<label for="title">Sub Name</label>
<label for="title">Hole Name</label>
<input minlength="3" maxlength="25" pattern='[a-zA-Z0-9_\-]*' class="form-control" id="title-register" type="text" name="name" required>
<small class="form-text text-muted">3-25 characters, including letters, numbers, _ , and -</small>
{% if HOLE_INACTIVITY_DELETION %}

View File

@ -1,7 +1,7 @@
{% extends "default.html" %}
{% block pagetitle %}/h/{{sub}} Exiles{% endblock %}
{% block pagetitle %}/h/{{hole}} Exiles{% endblock %}
{% block content %}
<h5 class="my-4 ml-2">Users exiled from /h/{{sub}}</h5>
<h5 class="my-4 ml-2">Users exiled from /h/{{hole}}</h5>
<div class="overflow-x-auto"><table class="table table-striped mb-5">
<thead class="bg-primary text-white">
<tr>
@ -23,8 +23,8 @@
</td>
<td {% if exile.created_utc %}data-time="{{exile.created_utc}}"{% endif %}></td>
<td>
{% if v.mods(sub.name) %}
<form action="/h/{{sub}}/unexile/{{user.id}}" method="post" data-nonce="{{g.nonce}}" data-onsubmit="sendFormXHRReload(this)">
{% if v.mods(hole.name) %}
<form action="/h/{{hole}}/unexile/{{user.id}}" method="post" data-nonce="{{g.nonce}}" data-onsubmit="sendFormXHRReload(this)">
<input hidden name="formkey" value="{{v|formkey}}">
<input autocomplete="off" class="btn btn-primary ml-auto" type="submit" value="Unexile">
</form>

View File

@ -18,15 +18,15 @@
{% for sub, count in subs %}
<tr>
<td>{{loop.index}}</td>
<td><a href="/h/{{sub}}">{{sub}} {% if sub.name in v.sub_blocks %}<span class="text-danger">[blocked, visit it to unblock it]</span>{% endif %}</a></td>
<td><a href="/h/{{sub}}">{{count}}</a></td>
<td><a href="/h/{{sub}}/followers">{{sub.follow_num}}</a></td>
{% if sub.stealth %}
<td>{{total_users - sub.join_num}}</td>
<td><a href="/h/{{hole}}">{{hole}} {% if hole.name in v.hole_blocks %}<span class="text-danger">[blocked, visit it to unblock it]</span>{% endif %}</a></td>
<td><a href="/h/{{hole}}">{{count}}</a></td>
<td><a href="/h/{{hole}}/followers">{{hole.follow_num}}</a></td>
{% if hole.stealth %}
<td>{{total_users - hole.join_num}}</td>
{% else %}
<td><a href="/h/{{sub}}/blockers">{{sub.block_num}}</a></td>
<td><a href="/h/{{hole}}/blockers">{{hole.block_num}}</a></td>
{% endif %}
<td data-time="{{sub.created_utc}}"></td>
<td data-time="{{hole.created_utc}}"></td>
</tr>
{% endfor %}
</table>

View File

@ -1,10 +1,10 @@
{% extends "default.html" %}
{% block pagetitle %}/h/{{sub}} Mods{% endblock %}
{% block pagetitle %}/h/{{hole}} Mods{% endblock %}
{% block content %}
<script defer src="{{'js/remove_mod.js' | asset}}"></script>
<h5 class="mt-2">/h/{{sub}} Mods</h5>
<h5 class="mt-2">/h/{{hole}} Mods</h5>
<div class="overflow-x-auto mt-1"><table class="table table-striped mb-5">
<thead class="bg-primary text-white">
<tr>
@ -20,8 +20,8 @@
<td>{% include "user_in_table.html" %}</td>
<td data-time="{{mod.created_utc}}"></td>
<td>
{% if v.id == user.id or v.mod_date(sub.name) and v.mod_date(sub.name) < mod.created_utc %}
<form action="/h/{{sub}}/remove_mod" method="post" data-nonce="{{g.nonce}}" data-onsubmit="removeMod(this)">
{% if v.id == user.id or v.mod_date(hole.name) and v.mod_date(hole.name) < mod.created_utc %}
<form action="/h/{{hole}}/remove_mod" method="post" data-nonce="{{g.nonce}}" data-onsubmit="removeMod(this)">
<input hidden name="formkey" value="{{v|formkey}}">
<input hidden name="uid" value="{{user.id}}">
<input autocomplete="off" class="btn btn-primary ml-auto" type="submit" value="{% if v.id == user.id %}Resign{% else %}Remove Mod{% endif %}">
@ -33,8 +33,8 @@
</table>
{% if v.mods(sub.name) %}
<form action="/h/{{sub}}/add_mod" method="post" data-nonce="{{g.nonce}}" data-onsubmit="sendFormXHRReload(this)">
{% if v.mods(hole.name) %}
<form action="/h/{{hole}}/add_mod" method="post" data-nonce="{{g.nonce}}" data-onsubmit="sendFormXHRReload(this)">
<input hidden name="formkey" value="{{v|formkey}}">
<input class="form-control" style="display:inline;width:250px" autocomplete="off" type="text" name="user" class="form-control" placeholder="Enter username..">
<input autocomplete="off" class="btn btn-primary ml-auto" type="submit" value="Add Mod" style="margin-bottom: 5px">

View File

@ -1,5 +1,5 @@
{% extends "default.html" %}
{% block pagetitle %}/h/{{sub}} Settings{% endblock %}
{% block pagetitle %}/h/{{hole}} Settings{% endblock %}
{% block content %}
@ -8,7 +8,7 @@
</div>
<div class="d-inline-block w-lg-100 pt-1 pt-lg-3">
<div class="custom-control custom-switch">
<input autocomplete="off" type="checkbox" class="custom-control-input" id="stealth" name="stealth" {% if sub.stealth %}checked{% endif %} data-nonce="{{g.nonce}}" data-onchange="postToastSwitch(this,'/h/{{sub}}/stealth')">
<input autocomplete="off" type="checkbox" class="custom-control-input" id="stealth" name="stealth" {% if hole.stealth %}checked{% endif %} data-nonce="{{g.nonce}}" data-onchange="postToastSwitch(this,'/h/{{hole}}/stealth')">
<label class="custom-control-label" for="stealth"></label>
</div>
<span class="text-small text-muted">
@ -18,8 +18,8 @@
<h5 class="mt-5">Marsey</h5>
<div class="settings-section rounded">
<img loading="lazy" alt="sub marsey picture" src="{{sub.marsey_url}}" style="max-width:100px">
<form class="d-inline-block" action="/h/{{sub}}/marsey_image" method="post" enctype="multipart/form-data">
<img loading="lazy" alt="sub marsey picture" src="{{hole.marsey_url}}" style="max-width:100px">
<form class="d-inline-block" action="/h/{{hole}}/marsey_image" method="post" enctype="multipart/form-data">
<input hidden name="formkey" value="{{v|formkey}}">
<label class="btn btn-secondary text-capitalize mr-2 mb-0">
Upload<input autocomplete="off" type="file" accept="image/*" {% if g.is_tor %}disabled{% endif %} hidden name="marsey" data-nonce="{{g.nonce}}" onchange_submit>
@ -32,8 +32,8 @@
<h5 class=" mt-5">Sidebar Picture</h5>
<div class="settings-section rounded">
<img class="mr-3" loading="lazy" alt="sub sidebar picture" src="{{sub.sidebar_url}}" style="max-width:min(300px,100%)">
<form class="d-inline-block mt-2" action="/h/{{sub}}/sidebar_image" method="post" enctype="multipart/form-data">
<img class="mr-3" loading="lazy" alt="sub sidebar picture" src="{{hole.sidebar_url}}" style="max-width:min(300px,100%)">
<form class="d-inline-block mt-2" action="/h/{{hole}}/sidebar_image" method="post" enctype="multipart/form-data">
<input hidden name="formkey" value="{{v|formkey}}">
<label class="btn btn-secondary text-capitalize mr-2 mb-0">
Upload<input autocomplete="off" type="file" accept="image/*" {% if g.is_tor %}disabled{% endif %} hidden name="sidebar" data-nonce="{{g.nonce}}" onchange_submit>
@ -45,26 +45,26 @@
</div>
<h5 class="mt-5">Banners</h5>
<div class="settings-section rounded sub-banner-update-section">
{% for banner in sub.banner_urls %}
<section id="sub-banner-update-{{loop.index - 1}}" class="mt-5 d-block sub-settings-subsection">
<img class="mr-3" loading="lazy" alt="/h/{{sub.name}} banner" src="{{banner}}" style="max-height:300px;max-width:100%">
<button class="btn btn-danger sub-banner-delete-button mt-2" id="sub-banner-delete-{{loop.index}}" data-nonce="{{g.nonce}}" data-onclick="areyousure(this)" data-areyousure="postToastReload(this, '/h/{{sub.name}}/settings/banners/delete/{{loop.index - 1}}')">Delete</button>
<div class="settings-section rounded hole-banner-update-section">
{% for banner in hole.banner_urls %}
<section id="hole-banner-update-{{loop.index - 1}}" class="mt-5 d-block hole-settings-subsection">
<img class="mr-3" loading="lazy" alt="/h/{{hole.name}} banner" src="{{banner}}" style="max-height:300px;max-width:100%">
<button class="btn btn-danger hole-banner-delete-button mt-2" id="hole-banner-delete-{{loop.index}}" data-nonce="{{g.nonce}}" data-onclick="areyousure(this)" data-areyousure="postToastReload(this, '/h/{{hole.name}}/settings/banners/delete/{{loop.index - 1}}')">Delete</button>
</section>
{% else %}
<section id="sub-banner-no-banners" class="d-block sub-settings-subsection">
<section id="hole-banner-no-banners" class="d-block hole-settings-subsection">
{{macros.ghost_box("No banners uploaded", "", 2, "flex:1")}}
</section>
{% endfor %}
{% if not g.is_tor %}
<section id="sub-banner-upload-new" class="mt-5 sub-settings-subsection">
<form class="d-inline-block" action="/h/{{sub.name}}/settings/banners/" method="post" enctype="multipart/form-data">
<section id="hole-banner-upload-new" class="mt-5 hole-settings-subsection">
<form class="d-inline-block" action="/h/{{hole.name}}/settings/banners/" method="post" enctype="multipart/form-data">
<input hidden name="formkey" value="{{v|formkey}}">
<label class="btn btn-secondary text-capitalize mr-2 mb-0">
Upload New Banner<input autocomplete="off" type="file" accept="image/*" hidden name="banner" data-nonce="{{g.nonce}}" onchange_submit>
</label>
</form>
<button type="button" class="btn btn-danger sub-banner-delete-button" id="sub-banner-delete-all" data-nonce="{{g.nonce}}" data-onclick="areyousure(this)" data-areyousure="postToastReload(this, '/h/{{sub.name}}/settings/banners/delete_all')">Delete All Banners</button>
<button type="button" class="btn btn-danger hole-banner-delete-button" id="hole-banner-delete-all" data-nonce="{{g.nonce}}" data-onclick="areyousure(this)" data-areyousure="postToastReload(this, '/h/{{hole.name}}/settings/banners/delete_all')">Delete All Banners</button>
<div class="text-small text-muted mt-3">
All image files are supported. Max file size is {% if v and v.patron %}16{% else %}8{% endif %} MB.
</div>
@ -80,9 +80,9 @@
</div>
<div class="body d-lg-flex">
<div class="w-lg-100">
<form id="sidebar" action="/h/{{sub}}/sidebar" method="post" data-nonce="{{g.nonce}}" data-onsubmit="sendFormXHR(this)">
<form id="sidebar" action="/h/{{hole}}/sidebar" method="post" data-nonce="{{g.nonce}}" data-onsubmit="sendFormXHR(this)">
<input hidden name="formkey" value="{{v|formkey}}">
<textarea autocomplete="off" maxlength="10000" class="form-control rounded" id="bio-text" placeholder="Enter sidebar here..." rows="10" name="sidebar" form="sidebar">{% if sub.sidebar %}{{sub.sidebar}}{% endif %}</textarea>
<textarea autocomplete="off" maxlength="10000" class="form-control rounded" id="bio-text" placeholder="Enter sidebar here..." rows="10" name="sidebar" form="sidebar">{% if hole.sidebar %}{{hole.sidebar}}{% endif %}</textarea>
<div class="d-flex mt-2">
<input autocomplete="off" class="btn btn-primary ml-auto" type="submit" value="Save">
</div>
@ -101,7 +101,7 @@
</div>
<div class="body d-lg-flex">
<div class="w-lg-100">
<form id="css" action="/h/{{sub}}/css" method="post" data-nonce="{{g.nonce}}" data-onsubmit="sendFormXHR(this)">
<form id="css" action="/h/{{hole}}/css" method="post" data-nonce="{{g.nonce}}" data-onsubmit="sendFormXHR(this)">
<input hidden name="formkey" value="{{v|formkey}}">
<textarea autocomplete="off" maxlength="6000" class="form-control rounded" id="bio-text" placeholder="Enter css here..." rows="10" name="css" form="css">{% if css %}{{css}}{% endif %}</textarea>
<div class="d-flex mt-2">

View File

@ -1,7 +1,7 @@
{% extends "default.html" %}
{% block title %}
{% if sub %}
<title>/h/{{sub.name}}</title>
{% if hole %}
<title>/h/{{hole.name}}</title>
{% elif request.path == '/' %}
{% if IS_DKD() %}
<title>Kongrama</title>
@ -12,13 +12,13 @@
{{super()}}
{% endif %}
{% endblock %}
{% block pagetitle %}{{SITE_NAME if not sub else '/h/' ~ sub.name}}{% endblock %}
{% block pagetitle %}{{SITE_NAME if not hole else '/h/' ~ hole.name}}{% endblock %}
{% block head_final %}
{% set preview = sub.siderbarurl if sub and sub.sidebarurl else sub.bannerurl %}
{% if sub %}
{% set preview = hole.siderbarurl if hole and hole.sidebarurl else hole.bannerurl %}
{% if hole %}
<meta property="og:type" content="article">
<meta property="og:title" content="/h/{{sub}}">
<meta property="og:title" content="/h/{{hole}}">
<meta property="og:site_name" content="{{SITE}}">
<meta property="og:image" content="{{preview}}">
<meta property="og:url" content="{{request.full_path}}">
@ -26,20 +26,20 @@
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="{{SITE_FULL}}">
<meta name="twitter:title" content="/h/{{sub.name}}">
<meta name="twitter:title" content="/h/{{hole.name}}">
<meta name="twitter:creator" content="{{SITE_FULL}}">
<meta name="twitter:image" content="{{preview}}">
<meta name="twitter:url" content="{{request.full_path}}">
{% endif %}
{% if sub.sidebar %}
<meta property="og:description" name="description" content="{{sub.sidebar}}">
<meta name="twitter:description" content="{{sub.sidebar}}">
{% if hole.sidebar %}
<meta property="og:description" name="description" content="{{hole.sidebar}}">
<meta name="twitter:description" content="{{hole.sidebar}}">
{% endif %}
{% endblock %}
{% block desktopBanner %}
{%- set search_placeholder = "Search" -%}
{%- if sub -%}
{%- set search_placeholder = "Search (try '" ~ HOLE_NAME ~ ":" ~ sub.name ~ "')" -%}
{%- if hole -%}
{%- set search_placeholder = "Search (try '" ~ HOLE_NAME ~ ":" ~ hole.name ~ "')" -%}
{%- endif -%}
<div class="row" style="overflow: visible;padding-top:5px">
<div class="col">
@ -52,23 +52,23 @@
</span>
</form>
<a class="btn btn-primary btn-block mt-3" href="{% if sub %}/h/{{sub}}{% endif %}/submit"><i class="fas fa-feather-alt mr-2"></i>Create Post {% if sub %}in /h/{{sub}}{% endif %}</a>
<a class="btn btn-primary btn-block mt-3" href="{% if hole %}/h/{{hole}}{% endif %}/submit"><i class="fas fa-feather-alt mr-2"></i>Create Post {% if hole %}in /h/{{hole}}{% endif %}</a>
{% if sub %}
{% if hole %}
{% if v %}
{% if sub.stealth %}
<button type="button" id="unsubscribe-sub" class="btn btn-primary btn-block {% if not v.subscribes(sub.name) %}d-none{% endif %}" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/h/{{sub.name}}/unsubscribe','subscribe-sub','unsubscribe-sub','d-none')"><i class="fas fa-eye-slash mr-2"></i>Block /h/{{sub.name}}</button>
<button type="button" id="subscribe-sub" class="btn btn-primary btn-block {% if v.subscribes(sub.name) %}d-none{% endif %}" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/h/{{sub.name}}/subscribe','subscribe-sub','unsubscribe-sub','d-none')"><i class="fas fa-eye mr-2"></i>Unblock /h/{{sub.name}}</button>
{% if hole.stealth %}
<button type="button" id="unsubscribe-sub" class="btn btn-primary btn-block {% if not v.subscribes(hole.name) %}d-none{% endif %}" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/h/{{hole.name}}/unsubscribe','subscribe-sub','unsubscribe-sub','d-none')"><i class="fas fa-eye-slash mr-2"></i>Block /h/{{hole.name}}</button>
<button type="button" id="subscribe-sub" class="btn btn-primary btn-block {% if v.subscribes(hole.name) %}d-none{% endif %}" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/h/{{hole.name}}/subscribe','subscribe-sub','unsubscribe-sub','d-none')"><i class="fas fa-eye mr-2"></i>Unblock /h/{{hole.name}}</button>
{% else %}
<button type="button" id="block-sub" class="btn btn-primary btn-block mt-3 {% if v.blocks(sub.name) %}d-none{% endif %}" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/h/{{sub.name}}/block','block-sub','unblock-sub','d-none')"><i class="fas fa-eye-slash mr-2"></i>Block /h/{{sub.name}}</button>
<button type="button" id="unblock-sub" class="btn btn-primary btn-block mt-3 {% if not v.blocks(sub.name) %}d-none{% endif %}" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/h/{{sub.name}}/unblock','block-sub','unblock-sub','d-none')"><i class="fas fa-eye mr-2"></i>Unblock /h/{{sub.name}}</button>
<button type="button" id="block-sub" class="btn btn-primary btn-block mt-3 {% if v.blocks(hole.name) %}d-none{% endif %}" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/h/{{hole.name}}/block','block-sub','unblock-sub','d-none')"><i class="fas fa-eye-slash mr-2"></i>Block /h/{{hole.name}}</button>
<button type="button" id="unblock-sub" class="btn btn-primary btn-block mt-3 {% if not v.blocks(hole.name) %}d-none{% endif %}" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/h/{{hole.name}}/unblock','block-sub','unblock-sub','d-none')"><i class="fas fa-eye mr-2"></i>Unblock /h/{{hole.name}}</button>
{% endif %}
<button type="button" id="follow-sub" class="btn btn-primary btn-follow {% if v.follows(sub.name) %}d-none{% endif %}" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/h/{{sub.name}}/follow','follow-sub','unfollow-sub','d-none')"><i class="fas fa-bell mr-2"></i>Follow /h/{{sub.name}}</button>
<button type="button" id="unfollow-sub" class="btn btn-primary btn-follow {% if not v.follows(sub.name) %}d-none{% endif %}" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/h/{{sub.name}}/unfollow','follow-sub','unfollow-sub','d-none')"><i class="fas fa-bell-slash mr-2"></i>Unfollow /h/{{sub.name}}</button>
<button type="button" id="follow-sub" class="btn btn-primary btn-follow {% if v.follows(hole.name) %}d-none{% endif %}" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/h/{{hole.name}}/follow','follow-sub','unfollow-sub','d-none')"><i class="fas fa-bell mr-2"></i>Follow /h/{{hole.name}}</button>
<button type="button" id="unfollow-sub" class="btn btn-primary btn-follow {% if not v.follows(hole.name) %}d-none{% endif %}" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/h/{{hole.name}}/unfollow','follow-sub','unfollow-sub','d-none')"><i class="fas fa-bell-slash mr-2"></i>Unfollow /h/{{hole.name}}</button>
{% else %}
<a class="btn btn-primary btn-block" href="/login?redirect={{request.full_path | urlencode}}"><i class="fas fa-eye-slash mr-2"></i>Block /h/{{sub.name}}</a>
<a class="btn btn-primary btn-block" href="/login?redirect={{request.full_path | urlencode}}"><i class="fas fa-bell mr-2"></i>Follow /h/{{sub.name}}</a>
<a class="btn btn-primary btn-block" href="/login?redirect={{request.full_path | urlencode}}"><i class="fas fa-eye-slash mr-2"></i>Block /h/{{hole.name}}</a>
<a class="btn btn-primary btn-block" href="/login?redirect={{request.full_path | urlencode}}"><i class="fas fa-bell mr-2"></i>Follow /h/{{hole.name}}</a>
{% endif %}
{% endif %}
@ -77,7 +77,7 @@
{% block navbar %}
<div class="d-flex align-items-center">
{% set pcolor = "primary" if pins else "secondary" %}
<form action="/toggle_pins/{{sub}}/{{sort}}" method="post" data-nonce="{{g.nonce}}" data-onsubmit="sendFormXHRReload(this)">
<form action="/toggle_pins/{{hole}}/{{sort}}" method="post" data-nonce="{{g.nonce}}" data-onsubmit="sendFormXHRReload(this)">
<button type="submit" class="btn btn-{{pcolor}} text-{{pcolor}} mx-2"><i type="submit" class="fas fas fa-thumbtack fa-rotate--45 mr-2"></i>Pins</button>
</form>

View File

@ -5,7 +5,7 @@
<div class="col h-100">
<div class="justify-content-between">
<div>
<h5 class="font-weight-bolder text-center pt-2 pb-3">{% if sub %}<a href="/h/{{sub.name}}">/h/{{sub.name}}</a> {% endif %}<span>Moderation Log</span></h5>
<h5 class="font-weight-bolder text-center pt-2 pb-3">{% if hole %}<a href="/h/{{hole.name}}">/h/{{hole.name}}</a> {% endif %}<span>Moderation Log</span></h5>
</div>
</div>
@ -22,9 +22,9 @@
</button>
<div class="dropdown-menu" x-placement="bottom-start" style="position: absolute; will-change: transform; top: 0px; left: 0px; transform: translate3d(0px, 31px, 0px); max-height: 50vh;
overflow: auto">
<a class="dropdown-item" href="{% if sub %}/h/{{sub}}{% endif %}/log{% if type %}?kind={{type}}{% endif %}"><img loading="lazy" src="{{SITE_FULL_IMAGES}}/e/marseyjanny.webp" alt="avatar" class="profile-pic-20 mr-2">All</a>
<a class="dropdown-item" href="{% if hole %}/h/{{hole}}{% endif %}/log{% if type %}?kind={{type}}{% endif %}"><img loading="lazy" src="{{SITE_FULL_IMAGES}}/e/marseyjanny.webp" alt="avatar" class="profile-pic-20 mr-2">All</a>
{% for a in admins %}
<a class="dropdown-item" href="{% if sub %}/h/{{sub}}{% endif %}/log?{{single_user_url}}={{a}}{% if type %}&kind={{type}}{% endif %}"><img loading="lazy" src="/@{{a}}/pic" alt="avatar" class="profile-pic-20 mr-2">{{a}}</a>
<a class="dropdown-item" href="{% if hole %}/h/{{hole}}{% endif %}/log?{{single_user_url}}={{a}}{% if type %}&kind={{type}}{% endif %}"><img loading="lazy" src="/@{{a}}/pic" alt="avatar" class="profile-pic-20 mr-2">{{a}}</a>
{% endfor %}
</div>
</div>
@ -35,9 +35,9 @@
</button>
<div class="dropdown-menu" x-placement="bottom-start" style="position: absolute; will-change: transform; top: 0px; left: 0px; transform: translate3d(0px, 31px, 0px); max-height: 50vh;
overflow: auto">
<a class="dropdown-item" href="{% if sub %}/h/{{sub}}{% endif %}/log{% if admin %}?{{single_user_url}}={{admin}}{% endif %}"><i class="fas fa-broom mr-2"></i>All</a>
<a class="dropdown-item" href="{% if hole %}/h/{{hole}}{% endif %}/log{% if admin %}?{{single_user_url}}={{admin}}{% endif %}"><i class="fas fa-broom mr-2"></i>All</a>
{% for t, v in types.items() %}
<a class="dropdown-item" href="{% if sub %}/h/{{sub}}{% endif %}/log?{% if admin %}{{single_user_url}}={{admin}}&{% endif %}kind={{t}}"><i class="fas {{v['icon']}} mr-2"></i>{{t}}</a>
<a class="dropdown-item" href="{% if hole %}/h/{{hole}}{% endif %}/log?{% if admin %}{{single_user_url}}={{admin}}&{% endif %}kind={{t}}"><i class="fas {{v['icon']}} mr-2"></i>{{t}}</a>
{% endfor %}
</div>
</div>

View File

@ -25,7 +25,7 @@
Posts {% if v.post_notifications_count %}<span class="font-weight-bold" style="color:#0000ff">({{v.post_notifications_count}})</span>{% endif %}
</a>
</li>
{% if v.admin_level >= PERMS['NOTIFICATIONS_MODERATOR_ACTIONS'] or v.moderated_subs %}
{% if v.admin_level >= PERMS['NOTIFICATIONS_MODERATOR_ACTIONS'] or v.moderated_holes %}
<li class="nav-item">
<a class="nav-link py-3{% if request.path == '/notifications/modactions' %} active{% endif %}" href="/notifications/modactions">
Modactions {% if v.modaction_notifications_count %}<span class="font-weight-bold" style="color:#1ad80d">({{v.modaction_notifications_count}})</span>{% endif %}
@ -83,8 +83,8 @@
</span>
<div class="text-muted pl-3">
<div>
{% if ma.sub %}
<a href="/h/{{ma.sub}}">/h/{{ma.sub}}</a>
{% if ma.hole %}
<a href="/h/{{ma.hole}}">/h/{{ma.hole}}</a>
-
{% endif %}
<a href="{{ma.user.url}}" class="font-weight-bold text-black" target="_self">@{{ma.user.username}}</a>

View File

@ -51,9 +51,9 @@
<button type="button" id="pin-{{p.id}}" class="dropdown-item {% if p.stickied and not p.stickied_utc %}d-none{% endif %} list-inline-item text-info" data-nonce="{{g.nonce}}" data-onclick="pinPost(this, '{{p.id}}')"><i class="fas fa-thumbtack fa-rotate--45"></i>Pin {% if p.stickied_utc %}permanently{% else %}for 1 hour{% endif %}</button>
<button type="button" id="unpin-{{p.id}}" class="dropdown-item {% if not p.stickied %}d-none{% endif %} list-inline-item text-info" data-nonce="{{g.nonce}}" data-onclick="unpinPost(this, '{{p.id}}')"><i class="fas fa-thumbtack fa-rotate--45"></i>Unpin</button>
{% endif %}
{% if p.sub and v.mods(p.sub) %}
<button type="button" id="hole-pin-{{p.id}}" class="dropdown-item {% if p.hole_pinned %}d-none{% endif %} list-inline-item text-info" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/hole_pin/{{p.id}}','hole-pin-{{p.id}}','hole-unpin-{{p.id}}','d-none')"><i class="fas fa-thumbtack fa-rotate--45"></i>Pin to /h/{{p.sub}}</button>
<button type="button" id="hole-unpin-{{p.id}}" class="dropdown-item {% if not p.hole_pinned %}d-none{% endif %} list-inline-item text-info" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/hole_unpin/{{p.id}}','hole-pin-{{p.id}}','hole-unpin-{{p.id}}','d-none')"><i class="fas fa-thumbtack fa-rotate--45"></i>Unpin from /h/{{p.sub}}</button>
{% if p.hole and v.mods(p.hole) %}
<button type="button" id="hole-pin-{{p.id}}" class="dropdown-item {% if p.hole_pinned %}d-none{% endif %} list-inline-item text-info" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/hole_pin/{{p.id}}','hole-pin-{{p.id}}','hole-unpin-{{p.id}}','d-none')"><i class="fas fa-thumbtack fa-rotate--45"></i>Pin to /h/{{p.hole}}</button>
<button type="button" id="hole-unpin-{{p.id}}" class="dropdown-item {% if not p.hole_pinned %}d-none{% endif %} list-inline-item text-info" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/hole_unpin/{{p.id}}','hole-pin-{{p.id}}','hole-unpin-{{p.id}}','d-none')"><i class="fas fa-thumbtack fa-rotate--45"></i>Unpin from /h/{{p.hole}}</button>
{% endif %}
{% if v.admin_level >= PERMS['POST_COMMENT_MODERATION'] %}
<button type="button" id="remove-{{p.id}}" class="dropdown-item {% if p.is_banned %}d-none{% endif %} list-inline-item text-danger" data-nonce="{{g.nonce}}" data-onclick="removePost(this,'{{p.id}}','remove-{{p.id}}','approve-{{p.id}}','d-none')"><i class="fas fa-ban"></i>Remove</button>
@ -63,18 +63,18 @@
<button type="button" id="block-{{p.id}}" class="dropdown-item list-inline-item text-danger {% if p.is_blocking %}d-none{% endif %}" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/block_user?username={{p.author_name}}','block-{{p.id}}','unblock-{{p.id}}','d-none')"><i class="fas fa-eye-slash text-danger"></i>Block user</button>
<button type="button" id="unblock-{{p.id}}" class="dropdown-item text-success list-inline-item {% if not p.is_blocking %}d-none{% endif %}" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/unblock_user?username={{p.author_name}}','block-{{p.id}}','unblock-{{p.id}}','d-none')"><i class="fas fa-eye text-success"></i>Unblock user</button>
{% endif %}
{% if v.id != p.author_id and p.sub %}
<button type="button" id="block-sub-{{p.id}}" class="dropdown-item list-inline-item text-danger {% if v.blocks(p.sub) %}d-none{% endif %}" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/h/{{p.sub}}/block','block-sub-{{p.id}}','unblock-sub-{{p.id}}','d-none')"><i class="fas fa-eye-slash text-danger"></i>Block /h/{{p.sub}}</button>
<button type="button" id="unblock-sub-{{p.id}}" class="dropdown-item text-success list-inline-item {% if not v.blocks(p.sub) %}d-none{% endif %}" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/h/{{p.sub}}/unblock','block-sub-{{p.id}}','unblock-sub-{{p.id}}','d-none')"><i class="fas fa-eye text-success"></i>Unblock /h/{{p.sub}}</button>
{% if v.id != p.author_id and p.hole %}
<button type="button" id="block-hole-{{p.id}}" class="dropdown-item list-inline-item text-danger {% if v.blocks(p.hole) %}d-none{% endif %}" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/h/{{p.hole}}/block','block-hole-{{p.id}}','unblock-hole-{{p.id}}','d-none')"><i class="fas fa-eye-slash text-danger"></i>Block /h/{{p.hole}}</button>
<button type="button" id="unblock-hole-{{p.id}}" class="dropdown-item text-success list-inline-item {% if not v.blocks(p.hole) %}d-none{% endif %}" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/h/{{p.hole}}/unblock','block-hole-{{p.id}}','unblock-hole-{{p.id}}','d-none')"><i class="fas fa-eye text-success"></i>Unblock /h/{{p.hole}}</button>
{% endif %}
{% if p.sub and v.mods(p.sub) %}
{% if p.hole and v.mods(p.hole) %}
<button type="button" class="dropdown-item list-inline-item text-danger" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/kick/{{p.id}}')"><i class="fas fa-sign-out text-danger"></i>Kick</button>
{% if not p.author.mods(p.sub) %}
<button type="button" id="exile-{{p.id}}" class="{% if p.author.exiler_username(p.sub) %}d-none{% endif %} dropdown-item list-inline-item text-danger" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/exile/post/{{p.id}}','exile-{{p.id}}','unexile-{{p.id}}','d-none')"><i class="fas fa-campfire text-danger"></i>Exile user</button>
<button type="button" id="unexile-{{p.id}}" class="{% if not p.author.exiler_username(p.sub) %}d-none{% endif %} dropdown-item list-inline-item text-success" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/h/{{sub}}/unexile/{{p.author_id}}','exile-{{p.id}}','unexile-{{p.id}}','d-none')"><i class="fas fa-campfire text-success"></i>Unexile user</button>
{% if not p.author.mods(p.hole) %}
<button type="button" id="exile-{{p.id}}" class="{% if p.author.exiler_username(p.hole) %}d-none{% endif %} dropdown-item list-inline-item text-danger" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/exile/post/{{p.id}}','exile-{{p.id}}','unexile-{{p.id}}','d-none')"><i class="fas fa-campfire text-danger"></i>Exile user</button>
<button type="button" id="unexile-{{p.id}}" class="{% if not p.author.exiler_username(p.hole) %}d-none{% endif %} dropdown-item list-inline-item text-success" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/h/{{hole}}/unexile/{{p.author_id}}','exile-{{p.id}}','unexile-{{p.id}}','d-none')"><i class="fas fa-campfire text-success"></i>Unexile user</button>
{% endif %}
{% endif %}
{% if FEATURES['NSFW_MARKING'] and (v.id==p.author_id or v.admin_level >= PERMS['POST_COMMENT_MODERATION'] or (p.sub and v.mods(p.sub))) %}
{% if FEATURES['NSFW_MARKING'] and (v.id==p.author_id or v.admin_level >= PERMS['POST_COMMENT_MODERATION'] or (p.hole and v.mods(p.hole))) %}
<button type="button" id="mark-{{p.id}}" class="dropdown-item {% if p.nsfw %}d-none{% endif %} list-inline-item text-danger" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/mark_post_nsfw/{{p.id}}','mark-{{p.id}}','unmark-{{p.id}}','d-none')"><i class="fas fa-eye-evil"></i>Mark NSFW</button>
<button type="button" id="unmark-{{p.id}}" class="dropdown-item {% if not p.nsfw %}d-none{% endif %} list-inline-item text-success" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/unmark_post_nsfw/{{p.id}}','mark-{{p.id}}','unmark-{{p.id}}','d-none')"><i class="fas fa-eye-evil"></i>Unmark NSFW</button>
{% endif %}

View File

@ -31,9 +31,9 @@
<button type="button" id="unpin-profile2-{{p.id}}" class="{% if not p.is_pinned %}d-none{% endif %} nobackground btn btn-link btn-block btn-lg text-muted text-left" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/pin/{{p.id}}','pin-profile2-{{p.id}}','unpin-profile2-{{p.id}}','d-none')" data-bs-dismiss="modal"><i class="fas fa-thumbtack fa-rotate--45 text-center mr-2"></i>Unpin from profile</button>
{% endif %}
{% if p.sub and v.mods(p.sub) %}
<button type="button" id="hole-pin2-{{p.id}}" class="{% if p.hole_pinned %}d-none{% endif %} nobackground btn btn-link btn-block btn-lg text-left text-info" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/hole_pin/{{p.id}}','hole-pin2-{{p.id}}','hole-unpin2-{{p.id}}','d-none')" data-bs-dismiss="modal"><i class="fas fa-thumbtack fa-rotate--45 text-center text-info mr-2"></i>Pin to /h/{{p.sub}}</button>
<button type="button" id="hole-unpin2-{{p.id}}" class="{% if not p.hole_pinned %}d-none{% endif %} nobackground btn btn-link btn-block btn-lg text-left text-info" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/hole_unpin/{{p.id}}','hole-pin2-{{p.id}}','hole-unpin2-{{p.id}}','d-none')" data-bs-dismiss="modal"><i class="fas fa-thumbtack fa-rotate--45 text-center text-info mr-2"></i>Unpin from /h/{{p.sub}}</button>
{% if p.hole and v.mods(p.hole) %}
<button type="button" id="hole-pin2-{{p.id}}" class="{% if p.hole_pinned %}d-none{% endif %} nobackground btn btn-link btn-block btn-lg text-left text-info" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/hole_pin/{{p.id}}','hole-pin2-{{p.id}}','hole-unpin2-{{p.id}}','d-none')" data-bs-dismiss="modal"><i class="fas fa-thumbtack fa-rotate--45 text-center text-info mr-2"></i>Pin to /h/{{p.hole}}</button>
<button type="button" id="hole-unpin2-{{p.id}}" class="{% if not p.hole_pinned %}d-none{% endif %} nobackground btn btn-link btn-block btn-lg text-left text-info" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/hole_unpin/{{p.id}}','hole-pin2-{{p.id}}','hole-unpin2-{{p.id}}','d-none')" data-bs-dismiss="modal"><i class="fas fa-thumbtack fa-rotate--45 text-center text-info mr-2"></i>Unpin from /h/{{p.hole}}</button>
{% endif %}
{% if v.id==p.author_id %}
@ -44,22 +44,22 @@
<button type="button" id="block2-{{p.id}}" class="blockuser nobackground btn btn-link btn-block btn-lg text-danger text-left" data-areyousure="postToastSwitch(this,'/block_user?username={{p.author_name}}','block2-{{p.id}}','unblock2-{{p.id}}','d-none')" data-nonce="{{g.nonce}}" data-onclick="areyousure(this)" data-dismiss="modal"><i class="fas fa-eye-slash mr-2 text-danger"></i>Block user</button>
<button type="button" id="unblock2-{{p.id}}" class="nobackground btn btn-link btn-block btn-lg text-success text-left {% if not p.is_blocking %}d-none{% endif %}" data-bs-dismiss="modal" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/unblock_user?username={{p.author_name}}','block2-{{p.id}}','unblock2-{{p.id}}','d-none')"><i class="fas fa-eye mr-2 text-success"></i>Unblock user</button>
{% endif %}
{% if p.sub %}
<button type="button" id="block-sub2-{{p.id}}" class="nobackground btn btn-link btn-block btn-lg text-danger text-left {% if v.blocks(p.sub) %}d-none{% endif %}" data-bs-dismiss="modal" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/h/{{p.sub}}/block','block-sub2-{{p.id}}','unblock-sub2-{{p.id}}','d-none')"><i class="fas fa-eye mr-2 text-danger"></i>Block /h/{{p.sub}}</button>
<button type="button" id="unblock-sub2-{{p.id}}" class="nobackground btn btn-link btn-block btn-lg text-success text-left {% if not v.blocks(p.sub) %}d-none{% endif %}" data-bs-dismiss="modal" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/h/{{p.sub}}/unblock','block-sub2-{{p.id}}','unblock-sub2-{{p.id}}','d-none')"><i class="fas fa-eye mr-2 text-success"></i>Unblock /h/{{p.sub}}</button>
{% if p.hole %}
<button type="button" id="block-sub2-{{p.id}}" class="nobackground btn btn-link btn-block btn-lg text-danger text-left {% if v.blocks(p.hole) %}d-none{% endif %}" data-bs-dismiss="modal" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/h/{{p.hole}}/block','block-sub2-{{p.id}}','unblock-sub2-{{p.id}}','d-none')"><i class="fas fa-eye mr-2 text-danger"></i>Block /h/{{p.hole}}</button>
<button type="button" id="unblock-sub2-{{p.id}}" class="nobackground btn btn-link btn-block btn-lg text-success text-left {% if not v.blocks(p.hole) %}d-none{% endif %}" data-bs-dismiss="modal" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/h/{{p.hole}}/unblock','block-sub2-{{p.id}}','unblock-sub2-{{p.id}}','d-none')"><i class="fas fa-eye mr-2 text-success"></i>Unblock /h/{{p.hole}}</button>
{% endif %}
{% endif %}
{% if FEATURES['NSFW_MARKING'] and (v.id==p.author_id or (p.sub and v.mods(p.sub))) %}
{% if FEATURES['NSFW_MARKING'] and (v.id==p.author_id or (p.hole and v.mods(p.hole))) %}
<button type="button" id="mark3-{{p.id}}" class="{% if p.nsfw %}d-none{% endif %} nobackground btn btn-link btn-block btn-lg text-left text-danger" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/mark_post_nsfw/{{p.id}}','mark3-{{p.id}}','unmark3-{{p.id}}','d-none')" data-bs-dismiss="modal"><i class="fas fa-eye-evil text-center mr-2"></i>Mark NSFW</button>
<button type="button" id="unmark3-{{p.id}}" class="{% if not p.nsfw %}d-none{% endif %} nobackground btn btn-link btn-block btn-lg text-left text-success" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/unmark_post_nsfw/{{p.id}}','mark3-{{p.id}}','unmark3-{{p.id}}','d-none')" data-bs-dismiss="modal"><i class="fas fa-eye-evil text-center mr-2"></i>Unmark NSFW</button>
{% endif %}
{% if p.sub and v.mods(p.sub) %}
{% if p.hole and v.mods(p.hole) %}
<button type="button" data-bs-dismiss="modal" class="nobackground btn btn-link btn-block btn-lg text-left text-danger" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/kick/{{p.id}}')"><i class="fas fa-sign-out text-danger text-center mr-2"></i>Kick</button>
{% if not p.author.mods(p.sub) %}
<button type="button" data-bs-dismiss="modal" id="exile2" class="{% if p.author.exiler_username(p.sub) %}d-none{% endif %} nobackground btn btn-link btn-block btn-lg text-left text-danger" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/exile/post/{{p.id}}','exile2','unexile2','d-none')"><i class="fas fa-campfire mr-2 text-danger"></i>Exile user</button>
<button type="button" data-bs-dismiss="modal" id="unexile2" class="{% if not p.author.exiler_username(p.sub) %}d-none{% endif %} nobackground btn btn-link btn-block btn-lg text-left text-success" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/h/{{sub}}/unexile/{{p.author_id}}','exile2','unexile2','d-none')"><i class="fas fa-campfire mr-2 text-success"></i>Unexile user</button>
{% if not p.author.mods(p.hole) %}
<button type="button" data-bs-dismiss="modal" id="exile2" class="{% if p.author.exiler_username(p.hole) %}d-none{% endif %} nobackground btn btn-link btn-block btn-lg text-left text-danger" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/exile/post/{{p.id}}','exile2','unexile2','d-none')"><i class="fas fa-campfire mr-2 text-danger"></i>Exile user</button>
<button type="button" data-bs-dismiss="modal" id="unexile2" class="{% if not p.author.exiler_username(p.hole) %}d-none{% endif %} nobackground btn btn-link btn-block btn-lg text-left text-success" data-nonce="{{g.nonce}}" data-onclick="postToastSwitch(this,'/h/{{hole}}/unexile/{{p.author_id}}','exile2','unexile2','d-none')"><i class="fas fa-campfire mr-2 text-success"></i>Unexile user</button>
{% endif %}
{% endif %}

View File

@ -96,7 +96,7 @@
{{macros.post_meta(p)}}
</div>
<h5 class="card-title post-title text-left w-lg-95 pb-0 pb-md-1">
<a id="{{p.id}}-title" {% if v and v.newtab %}data-target="t" target="_blank"{% endif %} href="{{p.permalink}}" class="{% if p.sub %}sub{% endif %} stretched-link {% if p.chudded %}text-uppercase{% endif %}">
<a id="{{p.id}}-title" {% if v and v.newtab %}data-target="t" target="_blank"{% endif %} href="{{p.permalink}}" class="{% if p.hole %}sub{% endif %} stretched-link {% if p.chudded %}text-uppercase{% endif %}">
{% if p.flair %}<span class="patron font-weight-bolder mr-1" style="background-color:var(--primary); font-size:12px; line-height:2">{{p.flair | safe}}</span>{% endif %}
{{p.realtitle(v) | safe}}
</a></h5>

View File

@ -6,8 +6,8 @@
</h5>
</a>
{% if sub %}
{% set image = sub.sidebar_url %}
{% if hole %}
{% set image = hole.sidebar_url %}
{% elif IS_EVENT() %}
{% set image = macros.random_image("assets/events/" ~ IS_EVENT() ~ "/images/sidebar") %}
{% else %}
@ -15,13 +15,13 @@
{% endif %}
{% if request.path != '/sidebar' %}
{% if not sub and (IS_FISTMAS() or IS_HOMOWEEN()) %}
{% if not hole and (IS_FISTMAS() or IS_HOMOWEEN()) %}
{% include "events/shared/eye_tracking.html" %}
{% elif v and (v.is_banned or v.chud) %}
<a href="{{SITE_FULL_IMAGES}}/i/{{SITE_NAME}}/sidebar2.webp">
<img class="mb-4 sidebar-img" alt="sidebar image" data-nonce="{{g.nonce}}" data-onclick="expandImage()" loading="lazy" src="{{SITE_FULL_IMAGES}}/i/{{SITE_NAME}}/sidebar2.webp">
</a>
{% elif not (sub and sub.name == 'chudrama' and v and not v.can_see_chudrama) %}
{% elif not (hole and hole.name == 'chudrama' and v and not v.can_see_chudrama) %}
<a href="{{image}}">
<img class="mb-4 sidebar-img" alt="sidebar image" data-nonce="{{g.nonce}}" data-onclick="expandImage()" loading="lazy" src="{{image}}">
</a>
@ -47,8 +47,8 @@
</div>
{% endif %}
{% if sub and sub.sidebar_html %}
<div class="mb-4">{{sub.sidebar_html|safe}}</div>
{% if hole and hole.sidebar_html %}
<div class="mb-4">{{hole.sidebar_html|safe}}</div>
{% endif %}
<a class="btn btn-primary btn-block mb-3" href="/post/151246/rdrama-featureset">SITE GUIDE</a>
@ -60,17 +60,17 @@
<a class="btn btn-primary btn-block mb-3" href="/holes">BROWSE {{HOLE_NAME|upper}}S</a>
<a class="btn btn-primary btn-block mb-3" href="/create_hole">CREATE {{HOLE_NAME|upper}}</a>
{% if sub %}
{% if hole %}
<br>
{% if v and v.mods(sub.name) %}
<a class="btn btn-primary btn-block mb-3 text-uppercase" style="font-size: 0.87rem" href="/h/{{sub}}/settings">/h/{{sub}} SETTINGS</a>
{% if v and v.mods(hole.name) %}
<a class="btn btn-primary btn-block mb-3 text-uppercase" style="font-size: 0.87rem" href="/h/{{hole}}/settings">/h/{{hole}} SETTINGS</a>
{% endif %}
<a class="btn btn-primary btn-block mb-3 text-uppercase" style="font-size: 0.87rem" href="/h/{{sub}}/log">/h/{{sub}} LOG</a>
<a class="btn btn-primary btn-block mb-3 text-uppercase" style="font-size: 0.87rem" href="/h/{{sub}}/mods">/h/{{sub}} MODS</a>
<a class="btn btn-primary btn-block mb-3 text-uppercase" style="font-size: 0.87rem" href="/h/{{sub}}/exilees">/h/{{sub}} EXILEES</a>
<a class="btn btn-primary btn-block mb-3 text-uppercase" style="font-size: 0.87rem" href="/h/{{sub}}/followers">/h/{{sub}} FOLLOWERS</a>
<a class="btn btn-primary btn-block mb-3 text-uppercase" style="font-size: 0.87rem" href="/h/{{sub}}/blockers">/h/{{sub}} BLOCKERS</a>
<a class="btn btn-primary btn-block mb-3 text-uppercase" style="font-size: 0.87rem" href="/h/{{hole}}/log">/h/{{hole}} LOG</a>
<a class="btn btn-primary btn-block mb-3 text-uppercase" style="font-size: 0.87rem" href="/h/{{hole}}/mods">/h/{{hole}} MODS</a>
<a class="btn btn-primary btn-block mb-3 text-uppercase" style="font-size: 0.87rem" href="/h/{{hole}}/exilees">/h/{{hole}} EXILEES</a>
<a class="btn btn-primary btn-block mb-3 text-uppercase" style="font-size: 0.87rem" href="/h/{{hole}}/followers">/h/{{hole}} FOLLOWERS</a>
<a class="btn btn-primary btn-block mb-3 text-uppercase" style="font-size: 0.87rem" href="/h/{{hole}}/blockers">/h/{{hole}} BLOCKERS</a>
{% else %}
<div class="sidebar--rules sidebar--rules--rdrama pt-2">
{% set rules = "rules_" ~ SITE_NAME ~ ".html" %}

View File

@ -10,7 +10,7 @@
{% block content %}
{% block form %}
<div class="submit-grid-view">
<form id="submitform" action="{% if SITE == 'watchpeopledie.tv' %}https://videos.watchpeopledie.tv{% elif sub %}/h/{{sub}}{% endif %}/submit" method="post" enctype="multipart/form-data" style="grid-column: 2" data-nonce="{{g.nonce}}" data-onsubmit="submit(this)">
<form id="submitform" action="{% if SITE == 'watchpeopledie.tv' %}https://videos.watchpeopledie.tv{% elif hole %}/h/{{hole}}{% endif %}/submit" method="post" enctype="multipart/form-data" style="grid-column: 2" data-nonce="{{g.nonce}}" data-onsubmit="submit(this)">
<div class="container pb-0">
<div class="row justify-content-center">
<div class="col px-3 py-0">
@ -20,9 +20,9 @@
<label class='mt-4' for="title">{{HOLE_NAME|capitalize}}</label>
<div class="input-group">
{%- set hole_placeholder = 'Required' if HOLE_REQUIRED else 'Optional' -%}
<input list="subs" autocomplete="off" id='sub' class="form-control" form="submitform" name="sub" data-nonce="{{g.nonce}}" data-oninput="savetext()" {% if sub %}value="{{sub}}"{% endif %} placeholder="{{hole_placeholder}}" {% if HOLE_REQUIRED %}required{% endif %}>
<datalist id="subs">
{% for s in SUBS %}
<input list="holes" autocomplete="off" id="hole" class="form-control" form="submitform" name="hole" data-nonce="{{g.nonce}}" data-oninput="savetext()" {% if hole %}value="{{hole}}"{% endif %} placeholder="{{hole_placeholder}}" {% if HOLE_REQUIRED %}required{% endif %}>
<datalist id="holes">
{% for s in HOLES %}
<option value="{{s}}"></option>
{% endfor %}
</datalist>

View File

@ -140,10 +140,10 @@
</div>
{% endif %}
{% if u.moderated_subs %}
{% if u.moderated_holes %}
<div class="text-white rounded p-2 mb-3" id="profile--holes" style="background-color: rgba(50, 50, 50, 0.6); width: 30%">
<p class="text-uppercase my-0 pb-1" style="font-weight: bold; font-size: 12px">Moderator of</p>
{% for i in u.moderated_subs %}
{% for i in u.moderated_holes %}
<span class="d-inline-block mx-1">
<a href="/h/{{i}}">/h/{{i}}</a>
</span>
@ -437,10 +437,10 @@
</div>
{% endif %}
{% if u.moderated_subs %}
{% if u.moderated_holes %}
<div class="text-white rounded p-2 mb-3" id="profile-mobile--holes" style="background-color: rgba(50, 50, 50, 0.6)">
<p class="text-uppercase my-0 pb-1" style="font-weight: bold; font-size: 12px">Moderator of</p>
{% for i in u.moderated_subs %}
{% for i in u.moderated_holes %}
<span class="d-inline-block mx-1">
<a href="/h/{{i}}">/h/{{i}}</a>
</span>

View File

@ -57,9 +57,9 @@
- {{u.bio}}
{% endif %}
{% endset %}
{% elif sub %}
{% elif hole %}
{% set title, description =
'/h/'+sub.name, sub.sidebar if sub.sidebar %}
'/h/'+hole.name, hole.sidebar if hole.sidebar %}
{% endif %}
<link rel="icon" type="image/webp" href="/icon.webp?x=6">
@ -135,8 +135,8 @@
<link rel="stylesheet" href="{{'events/homoween/css/main_homoween.css' | asset}}">
{% endif %}
{% if sub and sub.css and not request.path.endswith('settings') and not request.values.get('nocss') %}
<link rel="stylesheet" href="/h/{{sub}}/css">
{% if hole and hole.css and not request.path.endswith('settings') and not request.values.get('nocss') %}
<link rel="stylesheet" href="/h/{{hole}}/css">
{% endif %}
{% if IS_FISTMAS() %}

View File

@ -9,23 +9,23 @@
{%- endmacro -%}
{% macro post_meta(p) %}
{% if p.sub %}
{% if p.hole %}
{% if not HOLE_STYLE_FLAIR -%}
<a class="mr-2 font-weight-bold" href='/h/{{p.sub}}'>/h/{{p.sub}}</a>
<a class="mr-2 font-weight-bold" href='/h/{{p.hole}}'>/h/{{p.hole}}</a>
{%- else -%}
<a href='/h/{{p.sub}}' class="sub-flair font-weight-bold">{{p.sub|capitalize}}</a>
<a href='/h/{{p.hole}}' class="hole-flair font-weight-bold">{{p.hole|capitalize}}</a>
{%- endif %}
{% endif %}
{% if p.sub and p.author.exiler_username(p.sub) %}
<a><i class="fas fa-campfire text-danger" data-bs-toggle="tooltip" data-bs-placement="bottom" title="User has been exiled from /h/{{p.sub}} by @{{p.author.exiler_username(p.sub)}}"></i></a>
{% if p.hole and p.author.exiler_username(p.hole) %}
<a><i class="fas fa-campfire text-danger" data-bs-toggle="tooltip" data-bs-placement="bottom" title="User has been exiled from /h/{{p.hole}} by @{{p.author.exiler_username(p.hole)}}"></i></a>
{% endif %}
{% if p.bannedfor and p.sub != 'chudrama' %}
{% if p.bannedfor and p.hole != 'chudrama' %}
<i class="fas fa-hammer-crash text-danger" data-bs-toggle="tooltip" data-bs-placement="bottom" title="User was banned for this post {{p.bannedfor}}"></i>
{% endif %}
{% if p.chuddedfor and p.sub != 'chudrama' %}
{% if p.chuddedfor and p.hole != 'chudrama' %}
<i class="fas fa-face-sleeping text-danger" data-bs-toggle="tooltip" data-bs-placement="bottom" title="User was chudded for this post {{p.chuddedfor}}"></i>
{% endif %}
@ -46,7 +46,7 @@
{% endif %}
{% if p.hole_pinned %}
<i id='hole-pinned-{{p.id}}' class="fas fa-thumbtack fa-rotate--45 pr-1 ml-1 mt-3 text-blue" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Pinned to /h/{{p.sub}} by @{{p.hole_pinned}}"></i>
<i id='hole-pinned-{{p.id}}' class="fas fa-thumbtack fa-rotate--45 pr-1 ml-1 mt-3 text-blue" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Pinned to /h/{{p.hole}} by @{{p.hole_pinned}}"></i>
{% endif %}
{% if p.distinguish_level %}<i class="fas fa-broom text-admin" data-bs-toggle="tooltip" data-bs-placement="bottom" title="{{SITE_NAME}} Admin, speaking officially"></i>{% endif %}

View File

@ -0,0 +1,19 @@
alter table subs rename to holes;
alter table subactions rename to hole_actions;
alter table hole_actions rename column sub to hole;
alter table sub_joins rename to stealth_hole_unblocks;
alter table stealth_hole_unblocks rename column sub to hole;
alter table sub_blocks rename to hole_blocks;
alter table hole_blocks rename column sub to hole;
alter table sub_subscriptions rename to hole_follows;
alter table hole_follows rename column sub to hole;
alter table mods rename column sub to hole;
alter table posts rename column sub to hole;
alter table exiles rename column sub to hole;