[DO NOT MERGE] multiple sub banners (#59)

allows multiple sub banners

Snakes note: By request of Carp, especially for WPD.

Co-authored-by: justcool393 <justcool393@gmail.com>
Co-authored-by: Snakes <duolsm@outlook.com>
Reviewed-on: #59
Co-authored-by: justcool393 <justcool393@noreply.fsdfsd.net>
Co-committed-by: justcool393 <justcool393@noreply.fsdfsd.net>
pull/64/head
justcool393 2022-12-11 23:44:34 +00:00 committed by Snakes
parent 7778e6078d
commit ab41db22b7
91 changed files with 1573 additions and 1747 deletions

View File

@ -14,7 +14,7 @@ from flask_limiter import Limiter
from sqlalchemy import * from sqlalchemy import *
from sqlalchemy.orm import scoped_session, sessionmaker from sqlalchemy.orm import scoped_session, sessionmaker
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.const_stateful import const_initialize from files.helpers.const_stateful import const_initialize
from files.helpers.settings import reload_settings, start_watching_settings from files.helpers.settings import reload_settings, start_watching_settings

View File

@ -6458,6 +6458,10 @@ div.markdown {
} }
} }
.sub-banner-update-section .sub-settings-subsection {
margin-bottom: 1em;
}
.resizable { .resizable {
resize:both; resize:both;
display:inline-block; display:inline-block;

View File

@ -3,7 +3,7 @@ from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base() Base = declarative_base()
# then load our required constants... # then load our required constants...
from files.helpers.const import FEATURES, KOFI_TOKEN from files.helpers.config.const import FEATURES, KOFI_TOKEN
# then load all of our classes :) # then load all of our classes :)
from .alts import * from .alts import *

View File

@ -5,7 +5,7 @@ from sqlalchemy.orm import relationship
from sqlalchemy.sql.sqltypes import * from sqlalchemy.sql.sqltypes import *
from files.classes import Base from files.classes import Base
from files.helpers.const import AWARDS, HOUSE_AWARDS from files.helpers.config.awards import AWARDS, HOUSE_AWARDS
from files.helpers.lazy import lazy from files.helpers.lazy import lazy

View File

@ -5,7 +5,7 @@ from sqlalchemy.orm import relationship
from sqlalchemy.sql.sqltypes import * from sqlalchemy.sql.sqltypes import *
from files.classes import Base from files.classes import Base
from files.helpers.const import SITE_NAME from files.helpers.config.const import SITE_NAME
from files.helpers.lazy import lazy from files.helpers.lazy import lazy
class BadgeDef(Base): class BadgeDef(Base):

View File

@ -5,7 +5,7 @@ from sqlalchemy.orm import relationship, scoped_session
from sqlalchemy.sql.sqltypes import * from sqlalchemy.sql.sqltypes import *
from files.classes import Base from files.classes import Base
from files.helpers.const import SITE_FULL from files.helpers.config.const import SITE_FULL
from files.helpers.lazy import lazy from files.helpers.lazy import lazy
from .comment import Comment from .comment import Comment

View File

@ -10,7 +10,7 @@ from sqlalchemy.schema import FetchedValue
from sqlalchemy.sql.sqltypes import * from sqlalchemy.sql.sqltypes import *
from files.classes import Base from files.classes import Base
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.lazy import lazy from files.helpers.lazy import lazy
from files.helpers.regex import * from files.helpers.regex import *
from files.helpers.sorting_and_time import * from files.helpers.sorting_and_time import *

View File

@ -3,7 +3,7 @@ from typing import Any, Callable, Optional, Tuple, Union
from sqlalchemy import Column, func from sqlalchemy import Column, func
from sqlalchemy.orm import scoped_session from sqlalchemy.orm import scoped_session
from files.helpers.const import LEADERBOARD_LIMIT from files.helpers.config.const import LEADERBOARD_LIMIT
from .badges import Badge from .badges import Badge
from .marsey import Marsey from .marsey import Marsey

View File

@ -4,7 +4,7 @@ from sqlalchemy import Column, ForeignKey
from sqlalchemy.sql.sqltypes import * from sqlalchemy.sql.sqltypes import *
from files.classes import Base from files.classes import Base
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.lazy import lazy from files.helpers.lazy import lazy
class Lottery(Base): class Lottery(Base):

View File

@ -1,12 +1,11 @@
import time import time
from copy import deepcopy
from sqlalchemy import Column, ForeignKey from sqlalchemy import Column, ForeignKey
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from sqlalchemy.sql.sqltypes import * from sqlalchemy.sql.sqltypes import *
from files.classes import Base from files.classes import Base
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.lazy import lazy from files.helpers.lazy import lazy
from files.helpers.regex import censor_slurs from files.helpers.regex import censor_slurs
from files.helpers.sorting_and_time import make_age_string from files.helpers.sorting_and_time import make_age_string
@ -50,7 +49,7 @@ class ModAction(Base):
@property @property
@lazy @lazy
def string(self): def string(self):
output = ACTIONTYPES[self.kind]["str"].format(self=self) output = MODACTION_TYPES[self.kind]["str"].format(self=self)
if self.note: output += f" <i>({self.note})</i>" if self.note: output += f" <i>({self.note})</i>"
return output return output
@ -65,356 +64,16 @@ class ModAction(Base):
@property @property
@lazy @lazy
def icon(self): def icon(self):
return ACTIONTYPES[self.kind]['icon'] return MODACTION_TYPES[self.kind]['icon']
@property @property
@lazy @lazy
def color(self): def color(self):
return ACTIONTYPES[self.kind]['color'] return MODACTION_TYPES[self.kind]['color']
@property @property
@lazy @lazy
def permalink(self): def permalink(self):
return f"{SITE_FULL}/log/{self.id}" return f"{SITE_FULL}/log/{self.id}"
ACTIONTYPES = { from files.helpers.config.modaction_types import MODACTION_TYPES, MODACTION_TYPES_FILTERED
'chud': {
"str": 'chudded {self.target_link}',
"icon": 'fa-snooze',
"color": 'bg-danger'
},
'approve_app': {
"str": 'approved an application by {self.target_link}',
"icon": 'fa-robot',
"color": 'bg-success'
},
'badge_grant': {
"str": 'granted badge to {self.target_link}',
"icon": 'fa-badge',
"color": 'bg-success'
},
'badge_remove': {
"str": 'removed badge from {self.target_link}',
"icon": 'fa-badge',
"color": 'bg-danger'
},
'ban_comment': {
"str": 'removed {self.target_link}',
"icon": 'fa-comment',
"color": 'bg-danger'
},
'ban_domain': {
"str": 'banned a domain',
"icon": 'fa-globe',
"color": 'bg-danger'
},
'ban_post': {
"str": 'removed post {self.target_link}',
"icon": 'fa-feather-alt',
"color": 'bg-danger'
},
'ban_user': {
"str": 'banned user {self.target_link}',
"icon": 'fa-user-slash',
"color": 'bg-danger'
},
'delete_report': {
"str": 'deleted report on {self.target_link}',
"icon": 'fa-flag',
"color": 'bg-danger'
},
'disable_bots': {
"str": 'disabled bots',
"icon": 'fa-robot',
"color": 'bg-danger'
},
'disable_fart_mode': {
"str": 'disabled fart mode',
"icon": 'fa-gas-pump-slash',
"color": 'bg-danger'
},
'disable_read_only_mode': {
"str": 'disabled read only mode',
"icon": 'fa-book',
"color": 'bg-danger'
},
'disable_signups': {
"str": 'disabled signups',
"icon": 'fa-users',
"color": 'bg-danger'
},
'disable_login_required': {
"str": 'disabled login required',
"icon": 'fa-users',
"color": 'bg-danger'
},
'disable_under_attack': {
"str": 'disabled under attack mode',
"icon": 'fa-shield',
"color": 'bg-muted'
},
'disable_under_siege': {
"str": 'disabled under siege mode',
"icon": 'fa-shield',
"color": 'bg-muted'
},
'distinguish_comment': {
"str": 'distinguished {self.target_link}',
"icon": 'fa-crown',
"color": 'bg-success'
},
'distinguish_post': {
"str": 'distinguished {self.target_link}',
"icon": 'fa-crown',
"color": 'bg-success'
},
'distribute': {
"str": 'distributed bet winnings to voters on {self.target_link}',
"icon": 'fa-dollar-sign',
"color": 'bg-success'
},
'clear_internal_cache': {
"str": 'cleared internal cache',
"icon": 'fa-trash-alt',
"color": 'bg-muted'
},
'edit_post': {
"str": 'edited {self.target_link}',
"icon": 'fa-edit',
"color": 'bg-primary'
},
'edit_rules': {
"str": 'edited the rules',
"icon": 'fa-columns',
"color": 'bg-primary'
},
'enable_bots': {
"str": 'enabled bots',
"icon": 'fa-robot',
"color": 'bg-success'
},
'enable_fart_mode': {
"str": 'enabled fart mode',
"icon": 'fa-gas-pump',
"color": 'bg-success'
},
'enable_read_only_mode': {
"str": 'enabled read only mode',
"icon": 'fa-book',
"color": 'bg-success'
},
'enable_signups': {
"str": 'enabled signups',
"icon": 'fa-users',
"color": 'bg-success'
},
'enable_login_required': {
"str": 'enabled login required',
"icon": 'fa-users',
"color": 'bg-success'
},
'enable_under_attack': {
"str": 'enabled under attack mode',
"icon": 'fa-shield',
"color": 'bg-success'
},
'enable_under_siege': {
"str": 'enabled under siege mode',
"icon": 'fa-shield',
"color": 'bg-success',
},
'flair_post': {
"str": 'set a flair on {self.target_link}',
"icon": 'fa-tag',
"color": 'bg-primary'
},
'link_accounts': {
"str": 'linked {self.target_link}',
"icon": 'fa-link',
"color": 'bg-success'
},
'delink_accounts': {
"str": 'delinked {self.target_link}',
"icon": 'fa-link-slash',
"color": 'bg-danger'
},
'make_admin': {
"str": 'made {self.target_link} an admin',
"icon": 'fa-user-crown',
"color": 'bg-success'
},
'mod_mute_user': {
"str": 'muted reports from user {self.target_link}',
"icon": 'fa-file-signature',
"color": 'bg-danger'
},
'mod_unmute_user': {
"str": 'unmuted reports from user {self.target_link}',
"icon": 'fa-file-signature',
"color": 'bg-success'
},
'monthly': {
"str": 'distributed monthly marseybux',
"icon": 'fa-sack-dollar',
"color": 'bg-success'
},
'move_hole': {
"str": 'changed hole of {self.target_link}',
"icon": 'fa-manhole',
"color": 'bg-primary'
},
'nuke_user': {
"str": 'removed all content of {self.target_link}',
"icon": 'fa-radiation-alt',
"color": 'bg-danger'
},
'pin_comment': {
"str": 'pinned {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"color": 'bg-success'
},
'pin_post': {
"str": 'pinned post {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"color": 'bg-success'
},
'clear_cloudflare_cache': {
"str": 'cleared cloudflare cache',
"icon": 'fab fa-cloudflare',
"color": 'bg-muted'
},
'reject_app': {
"str": 'rejected an application request by {self.target_link}',
"icon": 'fa-robot',
"color": 'bg-muted'
},
'remove_admin': {
"str": 'removed {self.target_link} as admin',
"icon": 'fa-user-crown',
"color": 'bg-danger'
},
'revert': {
"str": 'reverted {self.target_link} mod actions',
"icon": 'fa-history',
"color": 'bg-danger'
},
'revoke_app': {
"str": 'revoked an application by {self.target_link}',
"icon": 'fa-robot',
"color": 'bg-muted'
},
'set_flair_locked': {
"str": "set {self.target_link}'s flair (locked)",
"icon": 'fa-award',
"color": 'bg-primary'
},
'set_flair_notlocked': {
"str": "set {self.target_link}'s flair (not locked)",
"icon": 'fa-award',
"color": 'bg-primary'
},
'set_new': {
"str": 'changed the default sorting of comments on {self.target_link} to `new`',
"icon": 'fa-sparkles',
"color": 'bg-primary'
},
'set_hot': {
"str": 'changed the default sorting of comments on {self.target_link} to `hot`',
"icon": 'fa-fire',
"color": 'bg-primary'
},
'set_nsfw': {
"str": 'set {self.target_link} as +18',
"icon": 'fa-eye-evil',
"color": 'bg-danger'
},
'set_nsfw_comment': {
"str": 'set {self.target_link} as +18',
"icon": 'fa-eye-evil',
"color": 'bg-danger'
},
'shadowban': {
"str": 'shadowbanned {self.target_link}',
"icon": 'fa-eye-slash',
"color": 'bg-danger'
},
'unchud': {
"str": 'unchudded {self.target_link}',
"icon": 'fa-snooze',
"color": 'bg-success'
},
'unban_comment': {
"str": 'reinstated {self.target_link}',
"icon": 'fa-comment',
"color": 'bg-success'
},
'unban_domain': {
"str": 'unbanned a domain',
"icon": 'fa-globe',
"color": 'bg-success'
},
'unban_post': {
"str": 'reinstated post {self.target_link}',
"icon": 'fa-feather-alt',
"color": 'bg-success'
},
'unban_user': {
"str": 'unbanned user {self.target_link}',
"icon": 'fa-user',
"color": 'bg-success'
},
'undistinguish_comment': {
"str": 'un-distinguished {self.target_link}',
"icon": 'fa-crown',
"color": 'bg-muted'
},
'undistinguish_post': {
"str": 'un-distinguished {self.target_link}',
"icon": 'fa-crown',
"color": 'bg-muted'
},
'unnuke_user': {
"str": 'approved all content of {self.target_link}',
"icon": 'fa-radiation-alt',
"color": 'bg-success'
},
'unpin_comment': {
"str": 'unpinned {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"color": 'bg-muted'
},
'unpin_post': {
"str": 'unpinned post {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"color": 'bg-muted'
},
'unset_nsfw': {
"str": 'unset {self.target_link} as +18',
"icon": 'fa-eye-evil',
"color": 'bg-success'
},
'unset_nsfw_comment': {
"str": 'unset {self.target_link} as +18',
"icon": 'fa-eye-evil',
"color": 'bg-success'
},
'unshadowban': {
"str": 'unshadowbanned {self.target_link}',
"icon": 'fa-eye',
"color": 'bg-success'
},
'update_hat': {
"str": 'updated hat image',
"icon": 'fa-hat-cowboy',
"color": 'bg-success'
},
'update_marsey': {
"str": 'updated marsey',
"icon": 'fa-cat',
"color": 'bg-success'
},
}
ACTIONTYPES2 = deepcopy(ACTIONTYPES)
ACTIONTYPES2.pop("shadowban")
ACTIONTYPES2.pop("unshadowban")

View File

@ -1,25 +1,28 @@
from random import Random
import time import time
from os import environ from typing import Optional
from sqlalchemy import Column from sqlalchemy import Column
from sqlalchemy.ext.mutable import MutableList
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from sqlalchemy.sql.sqltypes import * from sqlalchemy.types import VARCHAR, Boolean, Integer
from sqlalchemy.dialects.postgresql import ARRAY
from files.classes import Base from files.classes import Base
from files.helpers.lazy import lazy from files.helpers.lazy import lazy
from files.helpers.const import * from files.helpers.config.const import *
from .sub_relationship import * from .sub_relationship import *
class Sub(Base): class Sub(Base):
__tablename__ = "subs" __tablename__ = "subs"
name = Column(String, primary_key=True) name = Column(VARCHAR(SUB_NAME_COLUMN_LENGTH), primary_key=True)
sidebar = Column(String) sidebar = Column(VARCHAR(SUB_SIDEBAR_COLUMN_LENGTH))
sidebar_html = Column(String) sidebar_html = Column(VARCHAR(SUB_SIDEBAR_HTML_COLUMN_LENGTH))
sidebarurl = Column(String) sidebarurl = Column(VARCHAR(SUB_SIDEBAR_URL_COLUMN_LENGTH))
bannerurl = Column(String) bannerurls = Column(MutableList.as_mutable(ARRAY(VARCHAR(SUB_BANNER_URL_COLUMN_LENGTH))), default=MutableList([]), nullable=False)
marseyurl = Column(String) marseyurl = Column(VARCHAR(SUB_MARSEY_URL_LENGTH))
css = Column(String) css = Column(VARCHAR(SUB_CSS_COLUMN_LENGTH))
stealth = Column(Boolean) stealth = Column(Boolean)
created_utc = Column(Integer) created_utc = Column(Integer)
@ -42,9 +45,20 @@ class Sub(Base):
@property @property
@lazy @lazy
def banner_url(self): def banner_urls(self):
if self.bannerurl: return SITE_FULL + self.bannerurl if self.bannerurls: return [f"{SITE_FULL}{banner}" for banner in self.bannerurls]
return f'/i/{SITE_NAME}/banner.webp?v=3009' return []
@lazy
def random_banner(self, random:Optional[Random]=None):
if not self.banner_urls: return None
if not random: random = Random()
return random.choice(self.banner_urls)
@property
@lazy
def has_banners(self) -> bool:
return bool(self.bannerurls)
@property @property
@lazy @lazy

View File

@ -5,7 +5,7 @@ from sqlalchemy.orm import relationship
from sqlalchemy.sql.sqltypes import * from sqlalchemy.sql.sqltypes import *
from files.classes import Base from files.classes import Base
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.lazy import lazy from files.helpers.lazy import lazy
from files.helpers.regex import censor_slurs from files.helpers.regex import censor_slurs
from files.helpers.sorting_and_time import make_age_string from files.helpers.sorting_and_time import make_age_string
@ -41,7 +41,7 @@ class SubAction(Base):
@property @property
@lazy @lazy
def string(self): def string(self):
output = ACTIONTYPES[self.kind]["str"].format(self=self) output = SUBACTION_TYPES[self.kind]["str"].format(self=self)
if self._note: output += f" <i>({self._note})</i>" if self._note: output += f" <i>({self._note})</i>"
return output return output
@ -56,127 +56,16 @@ class SubAction(Base):
@property @property
@lazy @lazy
def icon(self): def icon(self):
return ACTIONTYPES[self.kind]['icon'] return SUBACTION_TYPES[self.kind]['icon']
@property @property
@lazy @lazy
def color(self): def color(self):
return ACTIONTYPES[self.kind]['color'] return SUBACTION_TYPES[self.kind]['color']
@property @property
@lazy @lazy
def permalink(self): def permalink(self):
return f"{SITE_FULL}/h/{self.sub}/log/{self.id}" return f"{SITE_FULL}/h/{self.sub}/log/{self.id}"
ACTIONTYPES = { from files.helpers.config.subaction_types import SUBACTION_TYPES
'exile_user': {
"str": 'exiled user {self.target_link}',
"icon": 'fa-user-slash',
"color": 'bg-danger'
},
'unexile_user': {
"str": 'unexiled user {self.target_link}',
"icon": 'fa-user',
"color": 'bg-success'
},
'make_mod': {
"str": 'made {self.target_link} a mod',
"icon": 'fa-user-crown',
"color": 'bg-success'
},
'remove_mod': {
"str": 'removed {self.target_link} as mod',
"icon": 'fa-user-crown',
"color": 'bg-danger'
},
'kick_post': {
"str": 'kicked post {self.target_link}',
"icon": 'fa-feather-alt',
"color": 'bg-danger'
},
'move_chudrama': {
"str": 'moved post {self.target_link} to <a href="/h/chudrama">/h/chudrama</a>',
"icon": 'fa-feather-alt',
"color": 'bg-danger'
},
'flair_post': {
"str": 'set a flair on {self.target_link}',
"icon": 'fa-tag',
"color": 'bg-primary'
},
'edit_sidebar': {
"str": 'edited the sidebar',
"icon": 'fa-columns',
"color": 'bg-primary'
},
'edit_css': {
"str": 'edited the css',
"icon": 'fa-css3-alt',
"color": 'bg-primary'
},
'change_banner': {
"str": 'changed the banner',
"icon": 'fa-landscape',
"color": 'bg-primary'
},
'change_sidebar_image': {
"str": 'changed the sidebar image',
"icon": 'fa-image',
"color": 'bg-primary'
},
'change_marsey': {
"str": 'changed the hole marsey',
"icon": 'fa-cat',
"color": 'bg-primary'
},
'pin_post': {
"str": 'pinned post {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"color": 'bg-success'
},
'unpin_post': {
"str": 'unpinned post {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"color": 'bg-muted'
},
'pin_comment': {
"str": 'pinned {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"color": 'bg-success'
},
'unpin_comment': {
"str": 'unpinned {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"color": 'bg-muted'
},
'enable_stealth': {
"str": 'enabled stealth mode',
"icon": 'fa-user-ninja',
"color": 'bg-primary'
},
'disable_stealth': {
"str": 'disabled stealth mode',
"icon": 'fa-user-ninja',
"color": 'bg-muted'
},
'set_nsfw': {
"str": 'set nsfw on post {self.target_link}',
"icon": 'fa-eye-evil',
"color": 'bg-danger'
},
'unset_nsfw': {
"str": 'un-set nsfw on post {self.target_link}',
"icon": 'fa-eye-evil',
"color": 'bg-success'
},
'set_nsfw_comment': {
"str": 'set nsfw on a {self.target_link}',
"icon": 'fa-eye-evil',
"color": 'bg-danger'
},
'unset_nsfw_comment': {
"str": 'un-set nsfw on a {self.target_link}',
"icon": 'fa-eye-evil',
"color": 'bg-success'
},
}

View File

@ -7,7 +7,7 @@ from sqlalchemy.orm import deferred, relationship, scoped_session
from sqlalchemy.sql.sqltypes import * from sqlalchemy.sql.sqltypes import *
from files.classes import Base from files.classes import Base
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.lazy import lazy from files.helpers.lazy import lazy
from files.helpers.regex import * from files.helpers.regex import *
from files.helpers.sorting_and_time import make_age_string from files.helpers.sorting_and_time import make_age_string

View File

@ -6,13 +6,14 @@ import pyotp
from sqlalchemy import Column, ForeignKey from sqlalchemy import Column, ForeignKey
from sqlalchemy.orm import aliased, deferred from sqlalchemy.orm import aliased, deferred
from sqlalchemy.sql import func from sqlalchemy.sql import func
from sqlalchemy.sql.expression import not_, and_, or_, ColumnOperators from sqlalchemy.sql.expression import not_, and_, or_
from sqlalchemy.sql.sqltypes import * from sqlalchemy.sql.sqltypes import *
from files.classes import Base from files.classes import Base
from files.classes.casino_game import Casino_Game from files.classes.casino_game import Casino_Game
from files.classes.sub import Sub from files.classes.sub import Sub
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.config.awards import AWARDS_ENABLED, HOUSE_AWARDS
from files.helpers.media import * from files.helpers.media import *
from files.helpers.security import * from files.helpers.security import *
from files.helpers.sorting_and_time import * from files.helpers.sorting_and_time import *
@ -421,7 +422,7 @@ class User(Base):
@property @property
@lazy @lazy
def user_awards(self): def user_awards(self):
return_value = list(AWARDS2.values()) return_value = list(AWARDS_ENABLED.values())
if self.house: if self.house:
return_value.append(HOUSE_AWARDS[self.house]) return_value.append(HOUSE_AWARDS[self.house])

View File

@ -1,6 +1,6 @@
from sqlalchemy import inspect from sqlalchemy import inspect
from files.helpers.const import AWARDS2, AWARDS_DISABLED from files.helpers.config.awards import AWARDS_ENABLED, AWARDS_DISABLED
from files.__main__ import engine from files.__main__ import engine
from files.events.classes import * from files.events.classes import *
@ -13,10 +13,10 @@ def _build_table():
EventUser.__table__.create(bind=engine, checkfirst=True) EventUser.__table__.create(bind=engine, checkfirst=True)
def _populate_awards(): def _populate_awards():
temp = {x: AWARDS2[x] for x in AWARDS2 if x not in EVENT_AWARDS} temp = {x: AWARDS_ENABLED[x] for x in AWARDS_ENABLED if x not in EVENT_AWARDS}
AWARDS2.clear() AWARDS_ENABLED.clear()
AWARDS2.update(EVENT_AWARDS) AWARDS_ENABLED.update(EVENT_AWARDS)
AWARDS2.update(temp) AWARDS_ENABLED.update(temp)
for award in EVENT_AWARDS: for award in EVENT_AWARDS:
if award in AWARDS_DISABLED: if award in AWARDS_DISABLED:

View File

@ -1,2 +1,2 @@
from .const import * from .config.const import *
from .jinja import * from .jinja import *

View File

@ -12,7 +12,7 @@ from files.classes.notifications import Notification
from files.classes.polls import CommentOption, SubmissionOption from files.classes.polls import CommentOption, SubmissionOption
from files.helpers.alerts import send_repeatable_notification from files.helpers.alerts import send_repeatable_notification
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.const_stateful import * from files.helpers.const_stateful import *
from files.helpers.discord import discord_message_send from files.helpers.discord import discord_message_send
from files.helpers.get import * from files.helpers.get import *

View File

@ -7,7 +7,7 @@ from pywebpush import webpush
from files.classes import Comment, Notification, PushSubscription from files.classes import Comment, Notification, PushSubscription
from .const import * from .config.const import *
from .regex import * from .regex import *
from .sanitize import * from .sanitize import *

View File

@ -5,7 +5,7 @@ from collections import defaultdict
import gevent import gevent
import gevent_inotifyx as inotify import gevent_inotifyx as inotify
from files.helpers.const import HOLIDAY_EVENT from files.helpers.config.const import HOLIDAY_EVENT
ASSET_DIR = 'files/assets' ASSET_DIR = 'files/assets'
ASSET_SUBDIRS = ['/css', '/js', '/js/vendor'] ASSET_SUBDIRS = ['/css', '/js', '/js/vendor']

View File

@ -4,7 +4,7 @@ from flask import g
from files.classes.user import User from files.classes.user import User
from files.helpers.alerts import send_repeatable_notification from files.helpers.alerts import send_repeatable_notification
from files.helpers.const import bots, patron, SITE_NAME from files.helpers.config.const import bots, patron, SITE_NAME
def award_timers(v, bot=False): def award_timers(v, bot=False):
now = time.time() now = time.time()

View File

@ -1,7 +1,7 @@
import time import time
from files.classes.casino_game import Casino_Game from files.classes.casino_game import Casino_Game
from files.helpers.alerts import * from files.helpers.alerts import *
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.useractions import badge_grant from files.helpers.useractions import badge_grant
def get_game_feed(game, db): def get_game_feed(game, db):

View File

@ -3,7 +3,7 @@ from typing import List, Optional, Union
import requests import requests
from files.helpers.const import CF_HEADERS, CF_ZONE, DEFAULT_CONFIG_VALUE from files.helpers.config.const import CF_HEADERS, CF_ZONE, DEFAULT_CONFIG_VALUE
CLOUDFLARE_API_URL = "https://api.cloudflare.com/client/v4" CLOUDFLARE_API_URL = "https://api.cloudflare.com/client/v4"
CLOUDFLARE_REQUEST_TIMEOUT_SECS = 5 CLOUDFLARE_REQUEST_TIMEOUT_SECS = 5

View File

@ -0,0 +1,745 @@
from copy import deepcopy
from files.helpers.config.const import FEATURES, SITE_NAME, patron
AWARDS = {
"fallback": {
"kind": "fallback",
"title": "Unknown",
"description": "",
"icon": "fas fa-block-question",
"color": "text-white",
"price": 0,
"deflectable": False,
"cosmetic": False
},
### Deprecated
"ghost": {
"kind": "ghost",
"title": "Ghost",
"description": "",
"icon": "fas fa-ghost",
"color": "text-white",
"price": 3000,
"deflectable": False,
"cosmetic": False
},
"nword": {
"kind": "nword",
"title": "Nword Pass",
"description": "",
"icon": "fas fa-edit",
"color": "text-success",
"price": 10000,
"deflectable": True,
"cosmetic": False
},
### Fistmas 2021
"snow": {
"kind": "snow",
"title": "Snow",
"description": "",
"icon": "fas fa-snowflake",
"color": "text-blue-200",
"price": 300,
"deflectable": False,
"cosmetic": True
},
"gingerbread": {
"kind": "gingerbread",
"title": "Gingerbread",
"description": "",
"icon": "fas fa-gingerbread-man",
"color": "",
"price": 300,
"deflectable": False,
"cosmetic": True
},
"lights": {
"kind": "lights",
"title": "Lights",
"description": "",
"icon": "fas fa-lights-holiday",
"color": "",
"price": 300,
"deflectable": False,
"cosmetic": True
},
"candycane": {
"kind": "candycane",
"title": "Candy Cane",
"description": "",
"icon": "fas fa-candy-cane",
"color": "",
"price": 400,
"deflectable": False,
"cosmetic": True
},
"fireplace": {
"kind": "fireplace",
"title": "Fireplace",
"description": "",
"icon": "fas fa-fireplace",
"color": "",
"price": 600,
"deflectable": False,
"cosmetic": True
},
"grinch": {
"kind": "grinch",
"title": "Grinch",
"description": "",
"icon": "fas fa-angry",
"color": "text-green-500",
"price": 1000,
"deflectable": True,
"cosmetic": False
},
### Homoween 2021 & 2022
"haunt": {
"kind": "haunt",
"title": "Haunt",
"description": "",
"icon": "fas fa-book-dead",
"color": "text-warning",
"price": 500,
"deflectable": False,
"cosmetic": True
},
"upsidedown": {
"kind": "upsidedown",
"title": "The Upside Down",
"description": "",
"icon": "fas fa-lights-holiday",
"color": "",
"price": 400,
"deflectable": False,
"cosmetic": True
},
"stab": {
"kind": "stab",
"title": "Stab",
"description": "",
"icon": "fas fa-knife-kitchen",
"color": "text-danger",
"price": 300,
"deflectable": False,
"cosmetic": True
},
"spiders": {
"kind": "spiders",
"title": "Spiders",
"description": "",
"icon": "fas fa-spider",
"color": "text-black",
"price": 200,
"deflectable": False,
"cosmetic": True
},
"fog": {
"kind": "fog",
"title": "Fog",
"description": "",
"icon": "fas fa-smoke",
"color": "text-gray",
"price": 200,
"deflectable": False,
"cosmetic": True
},
### Homoween 2022
"jumpscare": {
"kind": "jumpscare",
"title": "Jumpscare",
"description": "",
"icon": "fas fa-coffin-cross",
"color": "text-purple",
"price": 600,
"deflectable": True,
"cosmetic": False
},
"hw-bite": {
"kind": "hw-bite",
"title": "Zombie Bite",
"description": "",
"icon": "fas fa-biohazard",
"color": "text-danger",
"price": 500,
"deflectable": True,
"cosmetic": False
},
"hw-vax": {
"kind": "hw-vax",
"title": "Vaxxmaxx",
"description": "",
"icon": "fas fa-syringe",
"color": "text-blue",
"price": 500,
"deflectable": True,
"cosmetic": False
},
"hw-grinch": {
"kind": "hw-grinch",
"title": "Hallowgrinch",
"description": "",
"icon": "fas fa-angry",
"color": "text-orange",
"price": 1000,
"deflectable": True,
"cosmetic": False
},
"flashlight": {
"kind": "flashlight",
"title": "Flashlight",
"description": "",
"icon": "fas fa-flashlight",
"color": "text-black",
"price": 400,
"deflectable": False,
"cosmetic": True
},
"candy-corn": {
"kind": "candy-corn",
"title": "Candy Corn",
"description": "",
"icon": "fas fa-candy-corn",
"color": "text-orange",
"price": 400,
"deflectable": False,
"cosmetic": True
},
"ectoplasm": {
"kind": "ectoplasm",
"title": "Ectoplasm",
"description": "",
"icon": "fas fa-ghost",
"color": "text-success",
"price": 400,
"deflectable": False,
"cosmetic": True
},
"bones": {
"kind": "bones",
"title": "Bones",
"description": "",
"icon": "fas fa-bone",
"color": "text-white",
"price": 200,
"deflectable": False,
"cosmetic": True
},
"pumpkin": {
"kind": "pumpkin",
"title": "Pumpkin",
"description": "",
"icon": "fas fa-jack-o-lantern",
"color": "text-orange",
"price": 200,
"deflectable": False,
"cosmetic": True
},
### Standard
"marsify": {
"kind": "marsify",
"title": "Marsify",
"description": "Marsifies the recipient's comments for 24 hours.",
"icon": "fas fa-cat",
"color": "text-white",
"price": 150,
"deflectable": True,
"cosmetic": False
},
"shit": {
"kind": "shit",
"title": "Shit",
"description": "Makes flies swarm the post.",
"icon": "fas fa-poop",
"color": "text-black-50",
"price": 150,
"deflectable": False,
"cosmetic": True
},
"fireflies": {
"kind": "fireflies",
"title": "Fireflies",
"description": "Makes fireflies swarm the post.",
"icon": "fas fa-sparkles",
"color": "text-warning",
"price": 150,
"deflectable": False,
"cosmetic": True
},
"train": {
"kind": "train",
"title": "Train",
"description": "Summons a train on the post.",
"icon": "fas fa-train",
"color": "text-pink",
"price": 150,
"deflectable": False,
"cosmetic": True
},
"scooter": {
"kind": "scooter",
"title": "Scooter",
"description": "Summons a scooter on the post.",
"icon": "fas fa-flag-usa",
"color": "text-muted",
"price": 150,
"deflectable": False,
"cosmetic": True
},
"wholesome": {
"kind": "wholesome",
"title": "Wholesome",
"description": "Summons a wholesome marsey on the post.",
"icon": "fas fa-smile-beam",
"color": "text-yellow",
"price": 150,
"deflectable": False,
"cosmetic": True
},
"firework": {
"kind": "firework",
"title": "Fireworks",
"description": "Summons fireworks on the post.",
"icon": "fas fa-bahai",
"color": "text-danger",
"price": 150,
"deflectable": False,
"cosmetic": True
},
"confetti": {
"kind": "confetti",
"title": "Confetti",
"description": "Summons confetti to fall on the post.",
"icon": "fas fa-party-horn",
"color": "text-yellow",
"price": 150,
"deflectable": False,
"cosmetic": True
},
"ricardo": {
"kind": "ricardo",
"title": "Stripper Cake",
"description": "Summons Ricardo to dance on the post.",
"icon": "fas fa-pinata",
"color": "text-pink",
"price": 150,
"deflectable": False,
"cosmetic": True
},
"tilt": {
"kind": "tilt",
"title": "Tilt",
"description": "Tilts the post or comment",
"icon": "fas fa-car-tilt",
"color": "text-blue",
"price": 150,
"deflectable": False,
"cosmetic": True
},
"glowie": {
"kind": "glowie",
"title": "Glowie",
"description": "Indicates that the recipient can be seen when driving. Just run them over.",
"icon": "fas fa-user-secret",
"color": "text-green",
"price": 150,
"deflectable": False,
"cosmetic": True
},
"rehab": {
"kind": "rehab",
"title": "Rehab",
"description": "Prevents the user from gambling for 24 hours in a last ditch effort to save them from themself.",
"icon": "fas fa-dice-six",
"color": "text-black",
"price": 777,
"deflectable": True,
"cosmetic": False
},
"agendaposter": {
"kind": "agendaposter",
"title": "Chud",
"description": "Chuds the recipient for 24 hours.",
"icon": "fas fa-snooze",
"color": "text-purple",
"price": 1000,
"deflectable": True,
"cosmetic": False
},
"offsitementions": {
"kind": "offsitementions",
"title": "Y'all Seein' Eye",
"description": "Gives the recipient access to notifications when people off-site talk about us.",
"icon": "fas fa-eyes",
"color": "text-orange",
"price": 1000,
"deflectable": True,
"cosmetic": False
},
"lootbox": {
"kind": "lootbox",
"title": "Lootbox",
"description": "",
"icon": "fas fa-box-open",
"color": "text-blue",
"price": 1000,
"deflectable": True,
"cosmetic": False
},
"beano": {
"kind": "beano",
"title": "Beano",
"description": "Stops you from embarrassing yourself with your flatulence",
"icon": "fas fa-gas-pump-slash",
"color": "text-green",
"price": 1000,
"deflectable": True,
"cosmetic": False
},
"unpin": {
"kind": "unpin",
"title": "Unpin",
"description": "Removes 1 hour from the pin duration of a post or 6 hours from the pin duration of a comment.",
"icon": "fas fa-thumbtack fa-rotate--45",
"color": "text-black",
"price": 1000,
"deflectable": False,
"cosmetic": False
},
"flairlock": {
"kind": "flairlock",
"title": "1-Day Flairlock",
"description": "Sets a flair for the recipient and locks it for 24 hours.",
"icon": "fas fa-lock",
"color": "text-black",
"price": 1250,
"deflectable": True,
"cosmetic": False
},
"pin": {
"kind": "pin",
"title": "Pin",
"description": "Pins a post for 1 hour or a comment for 6 hours.",
"icon": "fas fa-thumbtack fa-rotate--45",
"color": "text-warning",
"price": 1500,
"deflectable": False,
"cosmetic": False
},
"progressivestack": {
"kind": "progressivestack",
"title": "Progressive Stack",
"description": "Makes votes on the recipient's posts and comments weigh double in the ranking algorithm for 6 hours.",
"icon": "fas fa-bullhorn",
"color": "text-danger",
"price": 1500,
"deflectable": True,
"cosmetic": False
},
"pizzashill": {
"kind": "pizzashill",
"title": "Pizzashill",
"description": "Forces the recipient to make all posts/comments > 280 characters for 24 hours.",
"icon": "fas fa-pizza-slice",
"color": "text-orange",
"price": 1500,
"deflectable": True,
"cosmetic": False
},
"bird": {
"kind": "bird",
"title": "Bird Site",
"description": "Forces the recipient to make all posts/comments < 140 characters for 24 hours.",
"icon": "fab fa-twitter",
"color": "text-blue",
"price": 1500,
"deflectable": True,
"cosmetic": False
},
"spider": {
"kind": "spider",
"title": "Spider!",
"description": f"Summons a spider to terrorize the recipient for 24 hours.",
"icon": "fas fa-spider",
"color": "text-brown",
"price": 2000,
"deflectable": True,
"cosmetic": False
},
"deflector": {
"kind": "deflector",
"title": "Deflector",
"description": "Causes most awards received for the next 10 hours to be deflected back at their giver.",
"icon": "fas fa-shield",
"color": "text-pink",
"price": 2750,
"deflectable": True,
"cosmetic": False
},
"marsey": {
"kind": "marsey",
"title": "Marsey",
"description": "Makes the recipient unable to post/comment anything but marsey emojis for 24 hours.",
"icon": "fas fa-cat",
"color": "text-orange",
"price": 3000,
"deflectable": True,
"cosmetic": False
},
"ban": {
"kind": "ban",
"title": "1-Day Ban",
"description": "Bans the recipient for a day.",
"icon": "fas fa-gavel",
"color": "text-danger",
"price": 3000,
"deflectable": True,
"cosmetic": False
},
"unban": {
"kind": "unban",
"title": "1-Day Unban",
"description": "Removes 1 day from the ban duration of the recipient.",
"icon": "fas fa-gavel",
"color": "text-success",
"price": 3500,
"deflectable": True,
"cosmetic": False
},
"benefactor": {
"kind": "benefactor",
"title": "Benefactor",
"description": f"Grants one month of {patron} status and 2500 marseybux to the recipient. Cannot be used on yourself.",
"icon": "fas fa-gift",
"color": "text-blue",
"price": 4000,
"deflectable": False,
"cosmetic": False
},
"grass": {
"kind": "grass",
"title": "Grass",
"description": "Ban the recipient for 30 days (if they provide a timestamped picture of them touching grass/snow/sand/ass to the admins, they will get unbanned immediately)",
"icon": "fas fa-seedling",
"color": "text-success",
"price": 10000,
"deflectable": True,
"cosmetic": False
},
"eye": {
"kind": "eye",
"title": "All-Seeing Eye",
"description": "Gives the recipient the ability to view private profiles.",
"icon": "fas fa-eye",
"color": "text-silver",
"price": 10000,
"deflectable": True,
"cosmetic": False
},
"unblockable": {
"kind": "unblockable",
"title": "Unblockable",
"description": "Makes the recipient unblockable and removes all blocks on them.",
"icon": "fas fa-laugh-squint",
"color": "text-lightgreen",
"price": 20000,
"deflectable": True,
"cosmetic": False
},
"fish": {
"kind": "fish",
"title": "Fish",
"description": "This user cannot be unfollowed",
"icon": "fas fa-fish",
"color": "text-lightblue",
"price": 20000,
"deflectable": True,
"cosmetic": False
},
"pause": {
"kind": "pause",
"title": "Pause",
"description": "Gives the recipient the ability to pause profile anthems.",
"icon": "fas fa-volume-mute",
"color": "text-danger",
"price": 20000,
"deflectable": True,
"cosmetic": False
},
"unpausable": {
"kind": "unpausable",
"title": "Unpausable",
"description": "Makes the profile anthem of the recipient unpausable.",
"icon": "fas fa-volume",
"color": "text-success",
"price": 40000,
"deflectable": True,
"cosmetic": False
},
"alt": {
"kind": "alt",
"title": "Alt-Seeing Eye",
"description": "Gives the recipient the ability to view alts.",
"icon": "fas fa-eye",
"color": "text-gold",
"price": 50000,
"deflectable": True,
"cosmetic": False
},
"checkmark": {
"kind": "checkmark",
"title": "Checkmark",
"description": "Gives the recipient a checkmark.",
"icon": "fas fa-badge-check",
"color": "checkmark",
"price": 50000,
"deflectable": True,
"cosmetic": False
},
}
if SITE_NAME != 'rDrama':
EXTRA_AWARDS = {
"owoify": {
"kind": "owoify",
"title": "OwOify",
"description": "OwOifies the recipient's comments for 6 hours.",
"icon": "fas fa-paw-simple",
"color": "text-purple",
"price": 400,
"deflectable": True,
"cosmetic": False
},
"rainbow": {
"kind": "rainbow",
"title": "Rainbow",
"description": "Makes the recipient's comments and posts in rainbow text for 24 hours.",
"icon": "fas fa-cloud-rainbow",
"color": "text-pink",
"price": 400,
"deflectable": True,
"cosmetic": False
},
}
AWARDS.update(EXTRA_AWARDS)
if SITE_NAME == 'PCM':
PCM_AWARDS = {
"croag": {
"kind": "croag",
"title": "Croag",
"description": "Summons Croag on the post.",
"icon": "fas fa-head-side",
"color": "text-gold",
"price": 150,
"deflectable": False,
"cosmetic": True
},
"toe": {
"kind": "toe",
"title": "Toe Hype",
"description": "Summons Blade's toe on the post.",
"icon": "fas fa-socks",
"color": "text-blue",
"price": 150,
"deflectable": False,
"cosmetic": True
},
"crab": {
"kind": "crab",
"title": "Crab",
"description": "Rave time!",
"icon": "fas fa-crab",
"color": "text-danger",
"price": 4000,
"deflectable": False,
"cosmetic": True
}
}
AWARDS.update(PCM_AWARDS)
# Permit only cosmetics and pin/unpin on ghosted things.
for award in AWARDS:
AWARDS[award]['ghost'] = AWARDS[award]['cosmetic']
AWARDS['pin']['ghost'] = True
AWARDS['unpin']['ghost'] = True
# Disable unused awards, and site-specific award inclusion/exclusion.
AWARDS_DISABLED = [
'fallback', 'ghost', 'nword', 'lootbox', # Generic
'snow', 'gingerbread', 'lights', 'candycane', 'fireplace', 'grinch', # Fistmas
'haunt', 'upsidedown', 'stab', 'spiders', 'fog', # Homoween '21
'jumpscare', 'hw-bite', 'hw-vax', 'hw-grinch', 'flashlight', # Homoween '22
'candy-corn', 'ectoplasm', 'bones', 'pumpkin', # Homoween '22 (cont'd)
]
HOUSE_AWARDS = {
"Furry": {
"kind": "Furry",
"title": "OwOify",
"description": "OwOifies the recipient's comments for 6 hours.",
"icon": "fas fa-paw-simple",
"color": "text-purple",
"price": 400,
"deflectable": True,
"cosmetic": False,
"ghost": False,
},
"Femboy": {
"kind": "Femboy",
"title": "Rainbow",
"description": "Makes the recipient's comments and posts in rainbow text for 24 hours.",
"icon": "fas fa-cloud-rainbow",
"color": "text-pink",
"price": 400,
"deflectable": True,
"cosmetic": False,
"ghost": False,
},
"Vampire": {
"kind": "Vampire",
"title": "Bite",
"description": "Turns the recipient into a vampire for 2 days.",
"icon": "fas fa-bat",
"color": "text-gray",
"price": 400,
"deflectable": True,
"cosmetic": False,
"ghost": False,
},
"Racist": {
"kind": "Racist",
"title": "Early Life",
"description": "Checks the recipient's Early Life section on Wikipedia. Notices.",
"icon": "fas fa-star-of-david",
"color": "text-yellow",
"price": 400,
"deflectable": True,
"cosmetic": False,
"ghost": False,
},
}
temp = deepcopy(HOUSE_AWARDS).items()
for k, val in temp:
HOUSE_AWARDS[f'{k} Founder'] = val
HOUSE_AWARDS[f'{k} Founder']['kind'] += ' Founder'
HOUSE_AWARDS[f'{k} Founder']['price'] = int(HOUSE_AWARDS[f'{k} Founder']['price'] * 0.75)
if SITE_NAME != 'rDrama':
AWARDS_DISABLED.append('progressivestack')
if SITE_NAME == 'PCM':
# Previous set of disabled, changed temporarily by request 2022-10-17
#AWARDS_DISABLED.extend(['ban','pizzashill','marsey','bird','grass','chud','unblockable'])
AWARDS_DISABLED.extend(['unblockable'])
AWARDS_DISABLED.remove('ghost')
elif SITE_NAME == 'WPD':
AWARDS_DISABLED.remove('lootbox')
if not FEATURES['MARSEYBUX']:
AWARDS_DISABLED.append('benefactor')
AWARDS_ENABLED = {x: AWARDS[x] for x in AWARDS if x not in AWARDS_DISABLED}

View File

@ -1,4 +1,3 @@
from copy import deepcopy
from enum import Enum, auto from enum import Enum, auto
from os import environ, path from os import environ, path
@ -72,9 +71,6 @@ SESSION_LIFETIME = 60 * 60 * 24 * 365
CASINO_RELEASE_DAY = 1662825600 CASINO_RELEASE_DAY = 1662825600
if SITE_NAME == 'rDrama': patron = 'Paypig'
else: patron = 'Patron'
AJ_REPLACEMENTS = { AJ_REPLACEMENTS = {
' your ': " you're ", ' your ': " you're ",
' to ': " too ", ' to ': " too ",
@ -184,11 +180,12 @@ profanity_single_words = "|".join([profanity.lower() for profanity in PROFANITIE
LONGPOST_REPLIES = ('Wow, you must be a JP fan.', 'This is one of the worst posts I have EVER seen. Delete it.', "No, don't reply like this, please do another wall of unhinged rant please.", '<h1>😴😴😴</h1>', "Ma'am we've been over this before. You need to stop.", "I've known more coherent downies.", "Your pulitzer's in the mail", "That's great and all, but I asked for my burger without cheese.", 'That degree finally paying off', "That's nice sweaty. Why don't you have a seat in the time out corner with Pizzashill until you calm down, then you can have your Capri Sun.", "All them words won't bring your pa back.", "You had a chance to not be completely worthless, but it looks like you threw it away. At least you're consistent.", 'Some people are able to display their intelligence by going on at length on a subject and never actually saying anything. This ability is most common in trades such as politics, public relations, and law. You have impressed me by being able to best them all, while still coming off as an absolute idiot.', "You can type 10,000 characters and you decided that these were the one's that you wanted.", 'Have you owned the libs yet?', "I don't know what you said, because I've seen another human naked.", 'Impressive. Normally people with such severe developmental disabilities struggle to write much more than a sentence or two. He really has exceded our expectations for the writing portion. Sadly the coherency of his writing, along with his abilities in the social skills and reading portions, are far behind his peers with similar disabilities.', "This is a really long way of saying you don't fuck.", "Sorry ma'am, looks like his delusions have gotten worse. We'll have to admit him.", 'If only you could put that energy into your relationships', 'Posts like this is why I do Heroine.', 'still unemployed then?', 'K', 'look im gunna have 2 ask u 2 keep ur giant dumps in the toilet not in my replys 😷😷😷', "Mommy is soooo proud of you, sweaty. Let's put this sperg out up on the fridge with all your other failures.", "Good job bobby, here's a star", "That was a mistake. You're about to find out the hard way why.", f'You sat down and wrote all this shit. You could have done so many other things with your life. What happened to your life that made you decide writing novels of bullshit here was the best option?', "I don't have enough spoons to read this shit", "All those words won't bring daddy back.", 'OUT!', "Damn, you're really mad over this, but thanks for the effort you put into typing that all out! Sadly I won't read it all.", "Jesse what the fuck are you talking about??", "▼you're fucking bananas if you think I'm reading all that, take my downvote and shut up idiot", "Are you feeling okay bud?", '<img loading="lazy" data-bs-toggle="tooltip" alt=":#marseywoah:" src="/e/marseywoah.webp" b title=":#marseywoah:">', 'At no point in your rambling, incoherent post were you even close to anything that could be considered a rational thought. Everyone on this site is now dumber for having read it. May God have mercy on your soul.') LONGPOST_REPLIES = ('Wow, you must be a JP fan.', 'This is one of the worst posts I have EVER seen. Delete it.', "No, don't reply like this, please do another wall of unhinged rant please.", '<h1>😴😴😴</h1>', "Ma'am we've been over this before. You need to stop.", "I've known more coherent downies.", "Your pulitzer's in the mail", "That's great and all, but I asked for my burger without cheese.", 'That degree finally paying off', "That's nice sweaty. Why don't you have a seat in the time out corner with Pizzashill until you calm down, then you can have your Capri Sun.", "All them words won't bring your pa back.", "You had a chance to not be completely worthless, but it looks like you threw it away. At least you're consistent.", 'Some people are able to display their intelligence by going on at length on a subject and never actually saying anything. This ability is most common in trades such as politics, public relations, and law. You have impressed me by being able to best them all, while still coming off as an absolute idiot.', "You can type 10,000 characters and you decided that these were the one's that you wanted.", 'Have you owned the libs yet?', "I don't know what you said, because I've seen another human naked.", 'Impressive. Normally people with such severe developmental disabilities struggle to write much more than a sentence or two. He really has exceded our expectations for the writing portion. Sadly the coherency of his writing, along with his abilities in the social skills and reading portions, are far behind his peers with similar disabilities.', "This is a really long way of saying you don't fuck.", "Sorry ma'am, looks like his delusions have gotten worse. We'll have to admit him.", 'If only you could put that energy into your relationships', 'Posts like this is why I do Heroine.', 'still unemployed then?', 'K', 'look im gunna have 2 ask u 2 keep ur giant dumps in the toilet not in my replys 😷😷😷', "Mommy is soooo proud of you, sweaty. Let's put this sperg out up on the fridge with all your other failures.", "Good job bobby, here's a star", "That was a mistake. You're about to find out the hard way why.", f'You sat down and wrote all this shit. You could have done so many other things with your life. What happened to your life that made you decide writing novels of bullshit here was the best option?', "I don't have enough spoons to read this shit", "All those words won't bring daddy back.", 'OUT!', "Damn, you're really mad over this, but thanks for the effort you put into typing that all out! Sadly I won't read it all.", "Jesse what the fuck are you talking about??", "▼you're fucking bananas if you think I'm reading all that, take my downvote and shut up idiot", "Are you feeling okay bud?", '<img loading="lazy" data-bs-toggle="tooltip" alt=":#marseywoah:" src="/e/marseywoah.webp" b title=":#marseywoah:">', 'At no point in your rambling, incoherent post were you even close to anything that could be considered a rational thought. Everyone on this site is now dumber for having read it. May God have mercy on your soul.')
AGENDAPOSTER_PHRASE = 'trans lives matter' AGENDAPOSTER_PHRASE = 'trans lives matter'
AGENDAPOSTER_MSG = """Hi @{username},\n
AGENDAPOSTER_MSG = """Hi @{username},\nYour {type} has been automatically removed because you forgot to include `{AGENDAPOSTER_PHRASE}`.\nDon't worry, we're here to help! We won't let you post or comment anything that doesn't express your love and acceptance towards the trans community. Feel free to resubmit your {type} with `{AGENDAPOSTER_PHRASE}` included. \n*This is an automated message; if you need help, you can message us [here](/contact).*""" Your {type} has been automatically removed because you forgot to include `{AGENDAPOSTER_PHRASE}`.\n
Don't worry, we're here to help! We won't let you post or comment anything that doesn't express your love and acceptance towards the trans community. Feel free to resubmit your {type} with `{AGENDAPOSTER_PHRASE}` included. \n
*This is an automated message; if you need help, you can message us [here](/contact).*"""
AGENDAPOSTER_MSG_HTML = """<p>Hi <a href="/id/{id}"><img loading="lazy" src="/pp/{id}">@{username}</a>,</p> AGENDAPOSTER_MSG_HTML = """<p>Hi <a href="/id/{id}"><img loading="lazy" src="/pp/{id}">@{username}</a>,</p>
<p>Your {type} has been automatically removed because you forgot to include <code>{AGENDAPOSTER_PHRASE}</code>.</p> <p>Your {type} has been automatically removed because you forgot to include <code>{AGENDAPOSTER_PHRASE}</code>.</p>
@ -207,6 +204,18 @@ SORTS = COMMENT_SORTS + ["bump", "comments"]
TIME_FILTERS = ["hour", "day", "week", "month", "year", "all"] TIME_FILTERS = ["hour", "day", "week", "month", "year", "all"]
PAGE_SIZES = (10, 25, 50, 100) PAGE_SIZES = (10, 25, 50, 100)
################################################################################
### 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
################################################################################ ################################################################################
### SITE SPECIFIC CONSTANTS ### SITE SPECIFIC CONSTANTS
################################################################################ ################################################################################
@ -395,7 +404,10 @@ COMMENT_MAX_DEPTH = 200
TRANSFER_MESSAGE_LENGTH_LIMIT = 200 # do not make larger than 10000 characters (comment limit) without altering the table 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 MIN_REPOST_CHECK_URL_LENGTH = 9 # also change the constant in checkRepost() of submit.js
CHAT_LENGTH_LIMIT = 1000 CHAT_LENGTH_LIMIT = 1000
SUB_BANNER_LIMIT = 10
COSMETIC_AWARD_COIN_AWARD_PCT = 0.10 COSMETIC_AWARD_COIN_AWARD_PCT = 0.10
TRUESCORE_CHAT_MINIMUM = 0 TRUESCORE_CHAT_MINIMUM = 0
TRUESCORE_DONATE_MINIMUM = 100 TRUESCORE_DONATE_MINIMUM = 100
TRUESCORE_GHOST_MINIMUM = 0 TRUESCORE_GHOST_MINIMUM = 0
@ -468,7 +480,7 @@ LEADERBOARD_LIMIT = PAGE_SIZE
HOUSE_JOIN_COST = 500 HOUSE_JOIN_COST = 500
HOUSE_SWITCH_COST = 2000 HOUSE_SWITCH_COST = 2000
DONATE_SERVICE = "Gumroad" if not KOFI_TOKEN or KOFI_TOKEN == DEFAULT_CONFIG_VALUE else "KoFi" DONATE_SERVICE = "Gumroad" if not KOFI_TOKEN or KOFI_TOKEN == DEFAULT_CONFIG_VALUE else "KoFi"
DONATE_LINK = GUMROAD_LINK if not KOFI_TOKEN or KOFI_TOKEN == DEFAULT_CONFIG_VALUE else KOFI_LINK DONATE_LINK = GUMROAD_LINK if not KOFI_TOKEN or KOFI_TOKEN == DEFAULT_CONFIG_VALUE else KOFI_LINK
TIERS_ID_TO_NAME = { TIERS_ID_TO_NAME = {
1: "Paypig", 1: "Paypig",
@ -633,7 +645,8 @@ elif SITE == 'watchpeopledie.tv':
PERMS['POST_EDITING'] = 2 PERMS['POST_EDITING'] = 2
PERMS['ADMIN_ADD'] = 4 PERMS['ADMIN_ADD'] = 4
POLL_MAX_OPTIONS = 30 SUB_BANNER_LIMIT = 69420
POLL_MAX_OPTIONS = 50
ERROR_TITLES.update({ ERROR_TITLES.update({
400: "Bad Request", 400: "Bad Request",
@ -700,6 +713,11 @@ else: # localhost or testing environment implied
FEATURES['HOUSES'] = True FEATURES['HOUSES'] = True
FEATURES['USERS_PERMANENT_WORD_FILTERS'] = True FEATURES['USERS_PERMANENT_WORD_FILTERS'] = True
FEATURES['STREAMERS'] = True FEATURES['STREAMERS'] = True
SUB_BANNER_LIMIT = 69420
patron = "Patron"
if SITE_NAME == 'rDrama':
patron = "Paypig"
HOUSES = ("None","Furry","Femboy","Vampire","Racist") if FEATURES['HOUSES'] else ("None") HOUSES = ("None","Furry","Femboy","Vampire","Racist") if FEATURES['HOUSES'] else ("None")
@ -710,757 +728,9 @@ COLORS = {'ff66ac','805ad5','62ca56','38a169','80ffff','2a96f3','eb4963','ff0000
BAN_EVASION_DOMAIN = 'stupidpol.site' BAN_EVASION_DOMAIN = 'stupidpol.site'
BAN_EVASION_FULL = f'https://{BAN_EVASION_DOMAIN}' BAN_EVASION_FULL = f'https://{BAN_EVASION_DOMAIN}'
AWARDS = {
"fallback": {
"kind": "fallback",
"title": "Unknown",
"description": "",
"icon": "fas fa-block-question",
"color": "text-white",
"price": 0,
"deflectable": False,
"cosmetic": False
},
### Deprecated
"ghost": {
"kind": "ghost",
"title": "Ghost",
"description": "",
"icon": "fas fa-ghost",
"color": "text-white",
"price": 3000,
"deflectable": False,
"cosmetic": False
},
"nword": {
"kind": "nword",
"title": "Nword Pass",
"description": "",
"icon": "fas fa-edit",
"color": "text-success",
"price": 10000,
"deflectable": True,
"cosmetic": False
},
### Fistmas 2021
"snow": {
"kind": "snow",
"title": "Snow",
"description": "",
"icon": "fas fa-snowflake",
"color": "text-blue-200",
"price": 300,
"deflectable": False,
"cosmetic": True
},
"gingerbread": {
"kind": "gingerbread",
"title": "Gingerbread",
"description": "",
"icon": "fas fa-gingerbread-man",
"color": "",
"price": 300,
"deflectable": False,
"cosmetic": True
},
"lights": {
"kind": "lights",
"title": "Lights",
"description": "",
"icon": "fas fa-lights-holiday",
"color": "",
"price": 300,
"deflectable": False,
"cosmetic": True
},
"candycane": {
"kind": "candycane",
"title": "Candy Cane",
"description": "",
"icon": "fas fa-candy-cane",
"color": "",
"price": 400,
"deflectable": False,
"cosmetic": True
},
"fireplace": {
"kind": "fireplace",
"title": "Fireplace",
"description": "",
"icon": "fas fa-fireplace",
"color": "",
"price": 600,
"deflectable": False,
"cosmetic": True
},
"grinch": {
"kind": "grinch",
"title": "Grinch",
"description": "",
"icon": "fas fa-angry",
"color": "text-green-500",
"price": 1000,
"deflectable": True,
"cosmetic": False
},
### Homoween 2021 & 2022
"haunt": {
"kind": "haunt",
"title": "Haunt",
"description": "",
"icon": "fas fa-book-dead",
"color": "text-warning",
"price": 500,
"deflectable": False,
"cosmetic": True
},
"upsidedown": {
"kind": "upsidedown",
"title": "The Upside Down",
"description": "",
"icon": "fas fa-lights-holiday",
"color": "",
"price": 400,
"deflectable": False,
"cosmetic": True
},
"stab": {
"kind": "stab",
"title": "Stab",
"description": "",
"icon": "fas fa-knife-kitchen",
"color": "text-danger",
"price": 300,
"deflectable": False,
"cosmetic": True
},
"spiders": {
"kind": "spiders",
"title": "Spiders",
"description": "",
"icon": "fas fa-spider",
"color": "text-black",
"price": 200,
"deflectable": False,
"cosmetic": True
},
"fog": {
"kind": "fog",
"title": "Fog",
"description": "",
"icon": "fas fa-smoke",
"color": "text-gray",
"price": 200,
"deflectable": False,
"cosmetic": True
},
### Homoween 2022
"jumpscare": {
"kind": "jumpscare",
"title": "Jumpscare",
"description": "",
"icon": "fas fa-coffin-cross",
"color": "text-purple",
"price": 600,
"deflectable": True,
"cosmetic": False
},
"hw-bite": {
"kind": "hw-bite",
"title": "Zombie Bite",
"description": "",
"icon": "fas fa-biohazard",
"color": "text-danger",
"price": 500,
"deflectable": True,
"cosmetic": False
},
"hw-vax": {
"kind": "hw-vax",
"title": "Vaxxmaxx",
"description": "",
"icon": "fas fa-syringe",
"color": "text-blue",
"price": 500,
"deflectable": True,
"cosmetic": False
},
"hw-grinch": {
"kind": "hw-grinch",
"title": "Hallowgrinch",
"description": "",
"icon": "fas fa-angry",
"color": "text-orange",
"price": 1000,
"deflectable": True,
"cosmetic": False
},
"flashlight": {
"kind": "flashlight",
"title": "Flashlight",
"description": "",
"icon": "fas fa-flashlight",
"color": "text-black",
"price": 400,
"deflectable": False,
"cosmetic": True
},
"candy-corn": {
"kind": "candy-corn",
"title": "Candy Corn",
"description": "",
"icon": "fas fa-candy-corn",
"color": "text-orange",
"price": 400,
"deflectable": False,
"cosmetic": True
},
"ectoplasm": {
"kind": "ectoplasm",
"title": "Ectoplasm",
"description": "",
"icon": "fas fa-ghost",
"color": "text-success",
"price": 400,
"deflectable": False,
"cosmetic": True
},
"bones": {
"kind": "bones",
"title": "Bones",
"description": "",
"icon": "fas fa-bone",
"color": "text-white",
"price": 200,
"deflectable": False,
"cosmetic": True
},
"pumpkin": {
"kind": "pumpkin",
"title": "Pumpkin",
"description": "",
"icon": "fas fa-jack-o-lantern",
"color": "text-orange",
"price": 200,
"deflectable": False,
"cosmetic": True
},
### Standard
"marsify": {
"kind": "marsify",
"title": "Marsify",
"description": "Marsifies the recipient's comments for 24 hours.",
"icon": "fas fa-cat",
"color": "text-white",
"price": 150,
"deflectable": True,
"cosmetic": False
},
"shit": {
"kind": "shit",
"title": "Shit",
"description": "Makes flies swarm the post.",
"icon": "fas fa-poop",
"color": "text-black-50",
"price": 150,
"deflectable": False,
"cosmetic": True
},
"fireflies": {
"kind": "fireflies",
"title": "Fireflies",
"description": "Makes fireflies swarm the post.",
"icon": "fas fa-sparkles",
"color": "text-warning",
"price": 150,
"deflectable": False,
"cosmetic": True
},
"train": {
"kind": "train",
"title": "Train",
"description": "Summons a train on the post.",
"icon": "fas fa-train",
"color": "text-pink",
"price": 150,
"deflectable": False,
"cosmetic": True
},
"scooter": {
"kind": "scooter",
"title": "Scooter",
"description": "Summons a scooter on the post.",
"icon": "fas fa-flag-usa",
"color": "text-muted",
"price": 150,
"deflectable": False,
"cosmetic": True
},
"wholesome": {
"kind": "wholesome",
"title": "Wholesome",
"description": "Summons a wholesome marsey on the post.",
"icon": "fas fa-smile-beam",
"color": "text-yellow",
"price": 150,
"deflectable": False,
"cosmetic": True
},
"firework": {
"kind": "firework",
"title": "Fireworks",
"description": "Summons fireworks on the post.",
"icon": "fas fa-bahai",
"color": "text-danger",
"price": 150,
"deflectable": False,
"cosmetic": True
},
"confetti": {
"kind": "confetti",
"title": "Confetti",
"description": "Summons confetti to fall on the post.",
"icon": "fas fa-party-horn",
"color": "text-yellow",
"price": 150,
"deflectable": False,
"cosmetic": True
},
"ricardo": {
"kind": "ricardo",
"title": "Stripper Cake",
"description": "Summons Ricardo to dance on the post.",
"icon": "fas fa-pinata",
"color": "text-pink",
"price": 150,
"deflectable": False,
"cosmetic": True
},
"tilt": {
"kind": "tilt",
"title": "Tilt",
"description": "Tilts the post or comment",
"icon": "fas fa-car-tilt",
"color": "text-blue",
"price": 150,
"deflectable": False,
"cosmetic": True
},
"glowie": {
"kind": "glowie",
"title": "Glowie",
"description": "Indicates that the recipient can be seen when driving. Just run them over.",
"icon": "fas fa-user-secret",
"color": "text-green",
"price": 150,
"deflectable": False,
"cosmetic": True
},
"rehab": {
"kind": "rehab",
"title": "Rehab",
"description": "Prevents the user from gambling for 24 hours in a last ditch effort to save them from themself.",
"icon": "fas fa-dice-six",
"color": "text-black",
"price": 777,
"deflectable": True,
"cosmetic": False
},
"agendaposter": {
"kind": "agendaposter",
"title": "Chud",
"description": "Chuds the recipient for 24 hours.",
"icon": "fas fa-snooze",
"color": "text-purple",
"price": 1000,
"deflectable": True,
"cosmetic": False
},
"offsitementions": {
"kind": "offsitementions",
"title": "Y'all Seein' Eye",
"description": "Gives the recipient access to notifications when people off-site talk about us.",
"icon": "fas fa-eyes",
"color": "text-orange",
"price": 1000,
"deflectable": True,
"cosmetic": False
},
"lootbox": {
"kind": "lootbox",
"title": "Lootbox",
"description": "",
"icon": "fas fa-box-open",
"color": "text-blue",
"price": 1000,
"deflectable": True,
"cosmetic": False
},
"beano": {
"kind": "beano",
"title": "Beano",
"description": "Stops you from embarrassing yourself with your flatulence",
"icon": "fas fa-gas-pump-slash",
"color": "text-green",
"price": 1000,
"deflectable": True,
"cosmetic": False
},
"unpin": {
"kind": "unpin",
"title": "Unpin",
"description": "Removes 1 hour from the pin duration of a post or 6 hours from the pin duration of a comment.",
"icon": "fas fa-thumbtack fa-rotate--45",
"color": "text-black",
"price": 1000,
"deflectable": False,
"cosmetic": False
},
"flairlock": {
"kind": "flairlock",
"title": "1-Day Flairlock",
"description": "Sets a flair for the recipient and locks it for 24 hours.",
"icon": "fas fa-lock",
"color": "text-black",
"price": 1250,
"deflectable": True,
"cosmetic": False
},
"pin": {
"kind": "pin",
"title": "Pin",
"description": "Pins a post for 1 hour or a comment for 6 hours.",
"icon": "fas fa-thumbtack fa-rotate--45",
"color": "text-warning",
"price": 1500,
"deflectable": False,
"cosmetic": False
},
"progressivestack": {
"kind": "progressivestack",
"title": "Progressive Stack",
"description": "Makes votes on the recipient's posts and comments weigh double in the ranking algorithm for 6 hours.",
"icon": "fas fa-bullhorn",
"color": "text-danger",
"price": 1500,
"deflectable": True,
"cosmetic": False
},
"pizzashill": {
"kind": "pizzashill",
"title": "Pizzashill",
"description": "Forces the recipient to make all posts/comments > 280 characters for 24 hours.",
"icon": "fas fa-pizza-slice",
"color": "text-orange",
"price": 1500,
"deflectable": True,
"cosmetic": False
},
"bird": {
"kind": "bird",
"title": "Bird Site",
"description": "Forces the recipient to make all posts/comments < 140 characters for 24 hours.",
"icon": "fab fa-twitter",
"color": "text-blue",
"price": 1500,
"deflectable": True,
"cosmetic": False
},
"spider": {
"kind": "spider",
"title": "Spider!",
"description": f"Summons a spider to terrorize the recipient for 24 hours.",
"icon": "fas fa-spider",
"color": "text-brown",
"price": 2000,
"deflectable": True,
"cosmetic": False
},
"deflector": {
"kind": "deflector",
"title": "Deflector",
"description": "Causes most awards received for the next 10 hours to be deflected back at their giver.",
"icon": "fas fa-shield",
"color": "text-pink",
"price": 2750,
"deflectable": True,
"cosmetic": False
},
"marsey": {
"kind": "marsey",
"title": "Marsey",
"description": "Makes the recipient unable to post/comment anything but marsey emojis for 24 hours.",
"icon": "fas fa-cat",
"color": "text-orange",
"price": 3000,
"deflectable": True,
"cosmetic": False
},
"ban": {
"kind": "ban",
"title": "1-Day Ban",
"description": "Bans the recipient for a day.",
"icon": "fas fa-gavel",
"color": "text-danger",
"price": 3000,
"deflectable": True,
"cosmetic": False
},
"unban": {
"kind": "unban",
"title": "1-Day Unban",
"description": "Removes 1 day from the ban duration of the recipient.",
"icon": "fas fa-gavel",
"color": "text-success",
"price": 3500,
"deflectable": True,
"cosmetic": False
},
"benefactor": {
"kind": "benefactor",
"title": "Benefactor",
"description": f"Grants one month of {patron} status and 2500 marseybux to the recipient. Cannot be used on yourself.",
"icon": "fas fa-gift",
"color": "text-blue",
"price": 4000,
"deflectable": False,
"cosmetic": False
},
"grass": {
"kind": "grass",
"title": "Grass",
"description": "Ban the recipient for 30 days (if they provide a timestamped picture of them touching grass/snow/sand/ass to the admins, they will get unbanned immediately)",
"icon": "fas fa-seedling",
"color": "text-success",
"price": 10000,
"deflectable": True,
"cosmetic": False
},
"eye": {
"kind": "eye",
"title": "All-Seeing Eye",
"description": "Gives the recipient the ability to view private profiles.",
"icon": "fas fa-eye",
"color": "text-silver",
"price": 10000,
"deflectable": True,
"cosmetic": False
},
"unblockable": {
"kind": "unblockable",
"title": "Unblockable",
"description": "Makes the recipient unblockable and removes all blocks on them.",
"icon": "fas fa-laugh-squint",
"color": "text-lightgreen",
"price": 20000,
"deflectable": True,
"cosmetic": False
},
"fish": {
"kind": "fish",
"title": "Fish",
"description": "This user cannot be unfollowed",
"icon": "fas fa-fish",
"color": "text-lightblue",
"price": 20000,
"deflectable": True,
"cosmetic": False
},
"pause": {
"kind": "pause",
"title": "Pause",
"description": "Gives the recipient the ability to pause profile anthems.",
"icon": "fas fa-volume-mute",
"color": "text-danger",
"price": 20000,
"deflectable": True,
"cosmetic": False
},
"unpausable": {
"kind": "unpausable",
"title": "Unpausable",
"description": "Makes the profile anthem of the recipient unpausable.",
"icon": "fas fa-volume",
"color": "text-success",
"price": 40000,
"deflectable": True,
"cosmetic": False
},
"alt": {
"kind": "alt",
"title": "Alt-Seeing Eye",
"description": "Gives the recipient the ability to view alts.",
"icon": "fas fa-eye",
"color": "text-gold",
"price": 50000,
"deflectable": True,
"cosmetic": False
},
"checkmark": {
"kind": "checkmark",
"title": "Checkmark",
"description": "Gives the recipient a checkmark.",
"icon": "fas fa-badge-check",
"color": "checkmark",
"price": 50000,
"deflectable": True,
"cosmetic": False
},
}
if SITE_NAME != 'rDrama':
EXTRA_AWARDS = {
"owoify": {
"kind": "owoify",
"title": "OwOify",
"description": "OwOifies the recipient's comments for 6 hours.",
"icon": "fas fa-paw-simple",
"color": "text-purple",
"price": 400,
"deflectable": True,
"cosmetic": False
},
"rainbow": {
"kind": "rainbow",
"title": "Rainbow",
"description": "Makes the recipient's comments and posts in rainbow text for 24 hours.",
"icon": "fas fa-cloud-rainbow",
"color": "text-pink",
"price": 400,
"deflectable": True,
"cosmetic": False
},
}
AWARDS.update(EXTRA_AWARDS)
if SITE_NAME == 'PCM':
PCM_AWARDS = {
"croag": {
"kind": "croag",
"title": "Croag",
"description": "Summons Croag on the post.",
"icon": "fas fa-head-side",
"color": "text-gold",
"price": 150,
"deflectable": False,
"cosmetic": True
},
"toe": {
"kind": "toe",
"title": "Toe Hype",
"description": "Summons Blade's toe on the post.",
"icon": "fas fa-socks",
"color": "text-blue",
"price": 150,
"deflectable": False,
"cosmetic": True
},
"crab": {
"kind": "crab",
"title": "Crab",
"description": "Rave time!",
"icon": "fas fa-crab",
"color": "text-danger",
"price": 4000,
"deflectable": False,
"cosmetic": True
}
}
AWARDS.update(PCM_AWARDS)
# Permit only cosmetics and pin/unpin on ghosted things.
for award in AWARDS:
AWARDS[award]['ghost'] = AWARDS[award]['cosmetic']
AWARDS['pin']['ghost'] = True
AWARDS['unpin']['ghost'] = True
# Disable unused awards, and site-specific award inclusion/exclusion.
AWARDS_DISABLED = [
'fallback', 'ghost', 'nword', 'lootbox', # Generic
'snow', 'gingerbread', 'lights', 'candycane', 'fireplace', 'grinch', # Fistmas
'haunt', 'upsidedown', 'stab', 'spiders', 'fog', # Homoween '21
'jumpscare', 'hw-bite', 'hw-vax', 'hw-grinch', 'flashlight', # Homoween '22
'candy-corn', 'ectoplasm', 'bones', 'pumpkin', # Homoween '22 (cont'd)
]
HOUSE_AWARDS = {
"Furry": {
"kind": "Furry",
"title": "OwOify",
"description": "OwOifies the recipient's comments for 6 hours.",
"icon": "fas fa-paw-simple",
"color": "text-purple",
"price": 400,
"deflectable": True,
"cosmetic": False,
"ghost": False,
},
"Femboy": {
"kind": "Femboy",
"title": "Rainbow",
"description": "Makes the recipient's comments and posts in rainbow text for 24 hours.",
"icon": "fas fa-cloud-rainbow",
"color": "text-pink",
"price": 400,
"deflectable": True,
"cosmetic": False,
"ghost": False,
},
"Vampire": {
"kind": "Vampire",
"title": "Bite",
"description": "Turns the recipient into a vampire for 2 days.",
"icon": "fas fa-bat",
"color": "text-gray",
"price": 400,
"deflectable": True,
"cosmetic": False,
"ghost": False,
},
"Racist": {
"kind": "Racist",
"title": "Early Life",
"description": "Checks the recipient's Early Life section on Wikipedia. Notices.",
"icon": "fas fa-star-of-david",
"color": "text-yellow",
"price": 400,
"deflectable": True,
"cosmetic": False,
"ghost": False,
},
}
temp = deepcopy(HOUSE_AWARDS).items()
for k, val in temp:
HOUSE_AWARDS[f'{k} Founder'] = val
HOUSE_AWARDS[f'{k} Founder']['kind'] += ' Founder'
HOUSE_AWARDS[f'{k} Founder']['price'] = int(HOUSE_AWARDS[f'{k} Founder']['price'] * 0.75)
if SITE_NAME != 'rDrama':
AWARDS_DISABLED.append('progressivestack')
if SITE_NAME == 'PCM':
# Previous set of disabled, changed temporarily by request 2022-10-17
#AWARDS_DISABLED.extend(['ban','pizzashill','marsey','bird','grass','chud','unblockable'])
AWARDS_DISABLED.extend(['unblockable'])
AWARDS_DISABLED.remove('ghost')
elif SITE_NAME == 'WPD':
AWARDS_DISABLED.remove('lootbox')
if not FEATURES['MARSEYBUX']:
AWARDS_DISABLED.append('benefactor')
AWARDS2 = {x: AWARDS[x] for x in AWARDS if x not in AWARDS_DISABLED}
DOUBLE_XP_ENABLED = -1 # set to unixtime for when DXP begins, -1 to disable DOUBLE_XP_ENABLED = -1 # set to unixtime for when DXP begins, -1 to disable
TROLLTITLES = [ ### COMMENT NOTIFICATIONS ###
"how will @{username} ever recover?",
"@{username} BTFO",
"[META] Getting really sick of @{username}'s shit",
"Pretty sure this is @{username}'s Reddit account",
"Hey jannies can you please ban @{username}",
]
FORTUNE_REPLIES = ('<b style="color:#6023f8">Your fortune: Allah Wills It</b>','<b style="color:#d302a7">Your fortune: Inshallah, Only Good Things Shall Come To Pass</b>','<b style="color:#e7890c">Your fortune: Allah Smiles At You This Day</b>','<b style="color:#7fec11">Your fortune: Your Bussy Is In For A Blasting</b>','<b style="color:#43fd3b">Your fortune: You Will Be Propositioned By A High-Tier Twink</b>','<b style="color:#9d05da">Your fortune: Repent, You Have Displeased Allah And His Vengeance Is Nigh</b>','<b style="color:#f51c6a">Your fortune: Reply Hazy, Try Again</b>','<b style="color:#00cbb0">Your fortune: lmao you just lost 100 coins</b>','<b style="color:#2a56fb">Your fortune: Yikes 😬</b>','<b style="color:#0893e1">Your fortune: You Will Be Blessed With Many Black Bulls</b>','<b style="color:#16f174">Your fortune: NEETmax, The Day Is Lost If You Venture Outside</b>','<b style="color:#fd4d32">Your fortune: A Taste Of Jannah Awaits You Today</b>','<b style="color:#bac200">Your fortune: Watch Your Back</b>','<b style="color:#6023f8">Your fortune: Outlook good</b>','<b style="color:#d302a7">Your fortune: Godly Luck</b>','<b style="color:#e7890c">Your fortune: Good Luck</b>','<b style="color:#7fec11">Your fortune: Bad Luck</b>','<b style="color:#43fd3b">Your fortune: Good news will come to you by mail</b>','<b style="color:#9d05da">Your fortune: Very Bad Luck</b>','<b style="color:#00cbb0">Your fortune: キタ━━━━━━(゚∀゚)━━━━━━ !!!!</b>','<b style="color:#2a56fb">Your fortune: Better not tell you now</b>','<b style="color:#0893e1">Your fortune: You will meet a dark handsome stranger</b>','<b style="color:#16f174">Your fortune:  ´_ゝ`)フーン</b>','<b style="color:#fd4d32">Your fortune: Excellent Luck</b>','<b style="color:#bac200">Your fortune: Average Luck</b>') FORTUNE_REPLIES = ('<b style="color:#6023f8">Your fortune: Allah Wills It</b>','<b style="color:#d302a7">Your fortune: Inshallah, Only Good Things Shall Come To Pass</b>','<b style="color:#e7890c">Your fortune: Allah Smiles At You This Day</b>','<b style="color:#7fec11">Your fortune: Your Bussy Is In For A Blasting</b>','<b style="color:#43fd3b">Your fortune: You Will Be Propositioned By A High-Tier Twink</b>','<b style="color:#9d05da">Your fortune: Repent, You Have Displeased Allah And His Vengeance Is Nigh</b>','<b style="color:#f51c6a">Your fortune: Reply Hazy, Try Again</b>','<b style="color:#00cbb0">Your fortune: lmao you just lost 100 coins</b>','<b style="color:#2a56fb">Your fortune: Yikes 😬</b>','<b style="color:#0893e1">Your fortune: You Will Be Blessed With Many Black Bulls</b>','<b style="color:#16f174">Your fortune: NEETmax, The Day Is Lost If You Venture Outside</b>','<b style="color:#fd4d32">Your fortune: A Taste Of Jannah Awaits You Today</b>','<b style="color:#bac200">Your fortune: Watch Your Back</b>','<b style="color:#6023f8">Your fortune: Outlook good</b>','<b style="color:#d302a7">Your fortune: Godly Luck</b>','<b style="color:#e7890c">Your fortune: Good Luck</b>','<b style="color:#7fec11">Your fortune: Bad Luck</b>','<b style="color:#43fd3b">Your fortune: Good news will come to you by mail</b>','<b style="color:#9d05da">Your fortune: Very Bad Luck</b>','<b style="color:#00cbb0">Your fortune: キタ━━━━━━(゚∀゚)━━━━━━ !!!!</b>','<b style="color:#2a56fb">Your fortune: Better not tell you now</b>','<b style="color:#0893e1">Your fortune: You will meet a dark handsome stranger</b>','<b style="color:#16f174">Your fortune:  ´_ゝ`)フーン</b>','<b style="color:#fd4d32">Your fortune: Excellent Luck</b>','<b style="color:#bac200">Your fortune: Average Luck</b>')
FACTCHECK_REPLIES = ('<b style="color:#6023f8">Factcheck: This claim has been confirmed as correct by experts. </b>','<b style="color:#d302a7">Factcheck: This claim has been classified as misogynistic.</b>','<b style="color:#e7890c">Factcheck: This claim is currently being debunked.</b>','<b style="color:#7fec11">Factcheck: This claim is 100% true.</b>','<b style="color:#9d05da">Factcheck: This claim hurts trans lives.</b>','<b style="color:#f51c6a">Factcheck: [REDACTED].</b>','<b style="color:#00cbb0">Factcheck: This claim is both true and false.</b>','<b style="color:#2a56fb">Factcheck: You really believe that shit? Lmao dumbass nigga 🤣</b>','<b style="color:#0893e1">Factcheck: None of this is real.</b>','<b style="color:#16f174">Factcheck: Yes.</b>','<b style="color:#fd4d32">Factcheck: This claim has not been approved by experts.</b>','<b style="color:#bac200">Factcheck: This claim is a gross exageration of reality.</b>','<b style="color:#ff2200">Factcheck: WARNING! THIS CLAIM HAS BEEN CLASSIFIED AS DANGEROUS. PLEASE REMAIN STILL, AN AGENT WILL COME TO MEET YOU SHORTLY.</b>') FACTCHECK_REPLIES = ('<b style="color:#6023f8">Factcheck: This claim has been confirmed as correct by experts. </b>','<b style="color:#d302a7">Factcheck: This claim has been classified as misogynistic.</b>','<b style="color:#e7890c">Factcheck: This claim is currently being debunked.</b>','<b style="color:#7fec11">Factcheck: This claim is 100% true.</b>','<b style="color:#9d05da">Factcheck: This claim hurts trans lives.</b>','<b style="color:#f51c6a">Factcheck: [REDACTED].</b>','<b style="color:#00cbb0">Factcheck: This claim is both true and false.</b>','<b style="color:#2a56fb">Factcheck: You really believe that shit? Lmao dumbass nigga 🤣</b>','<b style="color:#0893e1">Factcheck: None of this is real.</b>','<b style="color:#16f174">Factcheck: Yes.</b>','<b style="color:#fd4d32">Factcheck: This claim has not been approved by experts.</b>','<b style="color:#bac200">Factcheck: This claim is a gross exageration of reality.</b>','<b style="color:#ff2200">Factcheck: WARNING! THIS CLAIM HAS BEEN CLASSIFIED AS DANGEROUS. PLEASE REMAIN STILL, AN AGENT WILL COME TO MEET YOU SHORTLY.</b>')
@ -1492,6 +762,8 @@ if SITE == 'rdrama.net':
elif SITE_NAME == 'WPD': elif SITE_NAME == 'WPD':
REDDIT_NOTIFS_SITE.update({'watchpeopledie', 'makemycoffin'}) REDDIT_NOTIFS_SITE.update({'watchpeopledie', 'makemycoffin'})
### END COMMENT NOTIFICATIONS ###
discounts = { discounts = {
# Big Spender badges, 2pp additive discount each # Big Spender badges, 2pp additive discount each
69: 0.02, 69: 0.02,

View File

@ -0,0 +1,345 @@
from copy import deepcopy
MODACTION_TYPES = {
'chud': {
"str": 'chudded {self.target_link}',
"icon": 'fa-snooze',
"color": 'bg-danger'
},
'approve_app': {
"str": 'approved an application by {self.target_link}',
"icon": 'fa-robot',
"color": 'bg-success'
},
'badge_grant': {
"str": 'granted badge to {self.target_link}',
"icon": 'fa-badge',
"color": 'bg-success'
},
'badge_remove': {
"str": 'removed badge from {self.target_link}',
"icon": 'fa-badge',
"color": 'bg-danger'
},
'ban_comment': {
"str": 'removed {self.target_link}',
"icon": 'fa-comment',
"color": 'bg-danger'
},
'ban_domain': {
"str": 'banned a domain',
"icon": 'fa-globe',
"color": 'bg-danger'
},
'ban_post': {
"str": 'removed post {self.target_link}',
"icon": 'fa-feather-alt',
"color": 'bg-danger'
},
'ban_user': {
"str": 'banned user {self.target_link}',
"icon": 'fa-user-slash',
"color": 'bg-danger'
},
'delete_report': {
"str": 'deleted report on {self.target_link}',
"icon": 'fa-flag',
"color": 'bg-danger'
},
'disable_bots': {
"str": 'disabled bots',
"icon": 'fa-robot',
"color": 'bg-danger'
},
'disable_fart_mode': {
"str": 'disabled fart mode',
"icon": 'fa-gas-pump-slash',
"color": 'bg-danger'
},
'disable_read_only_mode': {
"str": 'disabled read only mode',
"icon": 'fa-book',
"color": 'bg-danger'
},
'disable_signups': {
"str": 'disabled signups',
"icon": 'fa-users',
"color": 'bg-danger'
},
'disable_login_required': {
"str": 'disabled login required',
"icon": 'fa-users',
"color": 'bg-danger'
},
'disable_under_attack': {
"str": 'disabled under attack mode',
"icon": 'fa-shield',
"color": 'bg-muted'
},
'disable_under_siege': {
"str": 'disabled under siege mode',
"icon": 'fa-shield',
"color": 'bg-muted'
},
'distinguish_comment': {
"str": 'distinguished {self.target_link}',
"icon": 'fa-crown',
"color": 'bg-success'
},
'distinguish_post': {
"str": 'distinguished {self.target_link}',
"icon": 'fa-crown',
"color": 'bg-success'
},
'distribute': {
"str": 'distributed bet winnings to voters on {self.target_link}',
"icon": 'fa-dollar-sign',
"color": 'bg-success'
},
'clear_internal_cache': {
"str": 'cleared internal cache',
"icon": 'fa-trash-alt',
"color": 'bg-muted'
},
'edit_post': {
"str": 'edited {self.target_link}',
"icon": 'fa-edit',
"color": 'bg-primary'
},
'edit_rules': {
"str": 'edited the rules',
"icon": 'fa-columns',
"color": 'bg-primary'
},
'enable_bots': {
"str": 'enabled bots',
"icon": 'fa-robot',
"color": 'bg-success'
},
'enable_fart_mode': {
"str": 'enabled fart mode',
"icon": 'fa-gas-pump',
"color": 'bg-success'
},
'enable_read_only_mode': {
"str": 'enabled read only mode',
"icon": 'fa-book',
"color": 'bg-success'
},
'enable_signups': {
"str": 'enabled signups',
"icon": 'fa-users',
"color": 'bg-success'
},
'enable_login_required': {
"str": 'enabled login required',
"icon": 'fa-users',
"color": 'bg-success'
},
'enable_under_attack': {
"str": 'enabled under attack mode',
"icon": 'fa-shield',
"color": 'bg-success'
},
'enable_under_siege': {
"str": 'enabled under siege mode',
"icon": 'fa-shield',
"color": 'bg-success',
},
'flair_post': {
"str": 'set a flair on {self.target_link}',
"icon": 'fa-tag',
"color": 'bg-primary'
},
'link_accounts': {
"str": 'linked {self.target_link}',
"icon": 'fa-link',
"color": 'bg-success'
},
'delink_accounts': {
"str": 'delinked {self.target_link}',
"icon": 'fa-link-slash',
"color": 'bg-danger'
},
'make_admin': {
"str": 'made {self.target_link} an admin',
"icon": 'fa-user-crown',
"color": 'bg-success'
},
'mod_mute_user': {
"str": 'muted reports from user {self.target_link}',
"icon": 'fa-file-signature',
"color": 'bg-danger'
},
'mod_unmute_user': {
"str": 'unmuted reports from user {self.target_link}',
"icon": 'fa-file-signature',
"color": 'bg-success'
},
'monthly': {
"str": 'distributed monthly marseybux',
"icon": 'fa-sack-dollar',
"color": 'bg-success'
},
'move_hole': {
"str": 'changed hole of {self.target_link}',
"icon": 'fa-manhole',
"color": 'bg-primary'
},
'nuke_user': {
"str": 'removed all content of {self.target_link}',
"icon": 'fa-radiation-alt',
"color": 'bg-danger'
},
'pin_comment': {
"str": 'pinned {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"color": 'bg-success'
},
'pin_post': {
"str": 'pinned post {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"color": 'bg-success'
},
'clear_cloudflare_cache': {
"str": 'cleared cloudflare cache',
"icon": 'fab fa-cloudflare',
"color": 'bg-muted'
},
'reject_app': {
"str": 'rejected an application request by {self.target_link}',
"icon": 'fa-robot',
"color": 'bg-muted'
},
'remove_admin': {
"str": 'removed {self.target_link} as admin',
"icon": 'fa-user-crown',
"color": 'bg-danger'
},
'revert': {
"str": 'reverted {self.target_link} mod actions',
"icon": 'fa-history',
"color": 'bg-danger'
},
'revoke_app': {
"str": 'revoked an application by {self.target_link}',
"icon": 'fa-robot',
"color": 'bg-muted'
},
'set_flair_locked': {
"str": "set {self.target_link}'s flair (locked)",
"icon": 'fa-award',
"color": 'bg-primary'
},
'set_flair_notlocked': {
"str": "set {self.target_link}'s flair (not locked)",
"icon": 'fa-award',
"color": 'bg-primary'
},
'set_new': {
"str": 'changed the default sorting of comments on {self.target_link} to `new`',
"icon": 'fa-sparkles',
"color": 'bg-primary'
},
'set_hot': {
"str": 'changed the default sorting of comments on {self.target_link} to `hot`',
"icon": 'fa-fire',
"color": 'bg-primary'
},
'set_nsfw': {
"str": 'set {self.target_link} as +18',
"icon": 'fa-eye-evil',
"color": 'bg-danger'
},
'set_nsfw_comment': {
"str": 'set {self.target_link} as +18',
"icon": 'fa-eye-evil',
"color": 'bg-danger'
},
'shadowban': {
"str": 'shadowbanned {self.target_link}',
"icon": 'fa-eye-slash',
"color": 'bg-danger'
},
'unchud': {
"str": 'unchudded {self.target_link}',
"icon": 'fa-snooze',
"color": 'bg-success'
},
'unban_comment': {
"str": 'reinstated {self.target_link}',
"icon": 'fa-comment',
"color": 'bg-success'
},
'unban_domain': {
"str": 'unbanned a domain',
"icon": 'fa-globe',
"color": 'bg-success'
},
'unban_post': {
"str": 'reinstated post {self.target_link}',
"icon": 'fa-feather-alt',
"color": 'bg-success'
},
'unban_user': {
"str": 'unbanned user {self.target_link}',
"icon": 'fa-user',
"color": 'bg-success'
},
'undistinguish_comment': {
"str": 'un-distinguished {self.target_link}',
"icon": 'fa-crown',
"color": 'bg-muted'
},
'undistinguish_post': {
"str": 'un-distinguished {self.target_link}',
"icon": 'fa-crown',
"color": 'bg-muted'
},
'unnuke_user': {
"str": 'approved all content of {self.target_link}',
"icon": 'fa-radiation-alt',
"color": 'bg-success'
},
'unpin_comment': {
"str": 'unpinned {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"color": 'bg-muted'
},
'unpin_post': {
"str": 'unpinned post {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"color": 'bg-muted'
},
'unset_nsfw': {
"str": 'unset {self.target_link} as +18',
"icon": 'fa-eye-evil',
"color": 'bg-success'
},
'unset_nsfw_comment': {
"str": 'unset {self.target_link} as +18',
"icon": 'fa-eye-evil',
"color": 'bg-success'
},
'unshadowban': {
"str": 'unshadowbanned {self.target_link}',
"icon": 'fa-eye',
"color": 'bg-success'
},
'update_hat': {
"str": 'updated hat image',
"icon": 'fa-hat-cowboy',
"color": 'bg-success'
},
'update_marsey': {
"str": 'updated marsey',
"icon": 'fa-cat',
"color": 'bg-success'
},
}
MODACTION_PRIVILEGED_TYPES = {'shadowban', 'unshadowban',
'mod_mute_user', 'mod_unmute_user',
'link_accounts', 'delink_accounts'}
MODACTION_TYPES_FILTERED = deepcopy({t:v for t,v in MODACTION_TYPES.items()
if not t in MODACTION_PRIVILEGED_TYPES})

View File

@ -0,0 +1,117 @@
SUBACTION_TYPES = {
'exile_user': {
"str": 'exiled user {self.target_link}',
"icon": 'fa-user-slash',
"color": 'bg-danger'
},
'unexile_user': {
"str": 'unexiled user {self.target_link}',
"icon": 'fa-user',
"color": 'bg-success'
},
'make_mod': {
"str": 'made {self.target_link} a mod',
"icon": 'fa-user-crown',
"color": 'bg-success'
},
'remove_mod': {
"str": 'removed {self.target_link} as mod',
"icon": 'fa-user-crown',
"color": 'bg-danger'
},
'kick_post': {
"str": 'kicked post {self.target_link}',
"icon": 'fa-feather-alt',
"color": 'bg-danger'
},
'move_chudrama': {
"str": 'moved post {self.target_link} to <a href="/h/chudrama">/h/chudrama</a>',
"icon": 'fa-feather-alt',
"color": 'bg-danger'
},
'flair_post': {
"str": 'set a flair on {self.target_link}',
"icon": 'fa-tag',
"color": 'bg-primary'
},
'edit_sidebar': {
"str": 'edited the sidebar',
"icon": 'fa-columns',
"color": 'bg-primary'
},
'edit_css': {
"str": 'edited the css',
"icon": 'fa-css3-alt',
"color": 'bg-primary'
},
'upload_banner': {
"str": 'uploaded a banner',
"icon": 'fa-landscape',
"color": 'bg-primary'
},
'delete_banner': {
"str": 'deleted banner',
"icon": 'fa-image-slash',
"color": 'bg-danger',
},
'change_sidebar_image': {
"str": 'changed the sidebar image',
"icon": 'fa-image',
"color": 'bg-primary'
},
'change_marsey': {
"str": 'changed the hole marsey',
"icon": 'fa-cat',
"color": 'bg-primary'
},
'pin_post': {
"str": 'pinned post {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"color": 'bg-success'
},
'unpin_post': {
"str": 'unpinned post {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"color": 'bg-muted'
},
'pin_comment': {
"str": 'pinned {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"color": 'bg-success'
},
'unpin_comment': {
"str": 'unpinned {self.target_link}',
"icon": 'fa-thumbtack fa-rotate--45',
"color": 'bg-muted'
},
'enable_stealth': {
"str": 'enabled stealth mode',
"icon": 'fa-user-ninja',
"color": 'bg-primary'
},
'disable_stealth': {
"str": 'disabled stealth mode',
"icon": 'fa-user-ninja',
"color": 'bg-muted'
},
'set_nsfw': {
"str": 'set nsfw on post {self.target_link}',
"icon": 'fa-eye-evil',
"color": 'bg-danger'
},
'unset_nsfw': {
"str": 'un-set nsfw on post {self.target_link}',
"icon": 'fa-eye-evil',
"color": 'bg-success'
},
'set_nsfw_comment': {
"str": 'set nsfw on a {self.target_link}',
"icon": 'fa-eye-evil',
"color": 'bg-danger'
},
'unset_nsfw_comment': {
"str": 'un-set nsfw on a {self.target_link}',
"icon": 'fa-eye-evil',
"color": 'bg-success'
},
}

View File

@ -3,7 +3,7 @@ from os import path
from sqlalchemy.orm import scoped_session from sqlalchemy.orm import scoped_session
from files.classes import Marsey from files.classes import Marsey
from files.helpers.const import SITE_NAME from files.helpers.config.const import SITE_NAME
marseys_const = [] marseys_const = []
marseys_const2 = [] marseys_const2 = []

View File

@ -13,7 +13,7 @@ import files.routes.streamers as route_streamers
from files.__main__ import cache from files.__main__ import cache
from files.classes import * from files.classes import *
from files.helpers.alerts import send_repeatable_notification from files.helpers.alerts import send_repeatable_notification
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.get import * from files.helpers.get import *
from files.helpers.lottery import check_if_end_lottery_task from files.helpers.lottery import check_if_end_lottery_task
from files.helpers.roulette import spin_roulette_wheel from files.helpers.roulette import spin_roulette_wheel

View File

@ -1,6 +1,6 @@
import requests import requests
from .const import * from .config.const import *
def discord_message_send(channel_id, message): def discord_message_send(channel_id, message):
requests.post( requests.post(

View File

@ -5,7 +5,7 @@ from sqlalchemy import and_, any_, or_
from sqlalchemy.orm import joinedload, selectinload, Query from sqlalchemy.orm import joinedload, selectinload, Query
from files.classes import Comment, CommentVote, Hat, Sub, Submission, User, UserBlock, Vote from files.classes import Comment, CommentVote, Hat, Sub, Submission, User, UserBlock, Vote
from files.helpers.const import AUTOJANNY_ID from files.helpers.config.const import AUTOJANNY_ID
def sanitize_username(username:str) -> str: def sanitize_username(username:str) -> str:
if not username: return username if not username: return username

View File

@ -1,4 +1,4 @@
from files.helpers.const import LOG_DIRECTORY from files.helpers.config.const import LOG_DIRECTORY
def log_file(log_str:str, log_filename="rdrama.log"): def log_file(log_str:str, log_filename="rdrama.log"):
''' '''

View File

@ -8,7 +8,7 @@ from files.classes.lottery import Lottery
from files.helpers.alerts import * from files.helpers.alerts import *
from files.helpers.useractions import * from files.helpers.useractions import *
from .const import * from .config.const import *
LOTTERY_WINNER_BADGE_ID = 137 LOTTERY_WINNER_BADGE_ID = 137

View File

@ -2,7 +2,7 @@ import requests
import time import time
from files.helpers.security import * from files.helpers.security import *
from files.helpers.const import EMAIL, MAILGUN_KEY from files.helpers.config.const import EMAIL, MAILGUN_KEY
from urllib.parse import quote from urllib.parse import quote

View File

@ -16,7 +16,7 @@ from sqlalchemy.orm.session import Session
from files.classes.media import * from files.classes.media import *
from files.helpers.cloudflare import purge_files_in_cache from files.helpers.cloudflare import purge_files_in_cache
from .const import * from .config.const import *
def process_files(files, v): def process_files(files, v):
body = '' body = ''
@ -124,8 +124,6 @@ def process_video(file, v):
return new return new
def process_image(filename:str, v, resize=0, trim=False, uploader_id:Optional[int]=None, db=None): def process_image(filename:str, v, resize=0, trim=False, uploader_id:Optional[int]=None, db=None):
# thumbnails are processed in a thread and not in the request context # thumbnails are processed in a thread and not in the request context
# if an image is too large or webp conversion fails, it'll crash # if an image is too large or webp conversion fails, it'll crash

View File

@ -7,7 +7,7 @@ from flask_caching import Cache
from flask import g from flask import g
from sqlalchemy import or_ from sqlalchemy import or_
import files.helpers.const as const import files.helpers.config.const as const
from files.classes.badges import Badge from files.classes.badges import Badge
from files.classes.comment import Comment from files.classes.comment import Comment
from files.classes.user import User from files.classes.user import User

View File

@ -3,7 +3,7 @@ import re
from random import choice, choices from random import choice, choices
from typing import List, Optional, Union from typing import List, Optional, Union
from .const import * from .config.const import *
valid_username_chars = 'a-zA-Z0-9_\-' valid_username_chars = 'a-zA-Z0-9_\-'
valid_username_regex = re.compile("^[a-zA-Z0-9_\-]{3,25}$", flags=re.A) valid_username_regex = re.compile("^[a-zA-Z0-9_\-]{3,25}$", flags=re.A)

View File

@ -14,7 +14,7 @@ from bs4 import BeautifulSoup
from mistletoe import markdown from mistletoe import markdown
from files.classes.domains import BannedDomain from files.classes.domains import BannedDomain
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.const_stateful import * from files.helpers.const_stateful import *
from files.helpers.regex import * from files.helpers.regex import *
from .get import * from .get import *

View File

@ -1,6 +1,6 @@
from werkzeug.security import * from werkzeug.security import *
from .const import * from .config.const import *
def generate_hash(string): def generate_hash(string):
msg = bytes(string, "utf-16") msg = bytes(string, "utf-16")

View File

@ -4,7 +4,7 @@ import os
import gevent import gevent
import gevent_inotifyx as inotify import gevent_inotifyx as inotify
from files.helpers.const import SETTINGS_FILENAME from files.helpers.config.const import SETTINGS_FILENAME
_SETTINGS = { _SETTINGS = {
"bots": True, "bots": True,

View File

@ -9,7 +9,7 @@ from files.classes.comment import Comment
from files.classes.user import User from files.classes.user import User
from files.helpers.casino import distribute_wager_badges from files.helpers.casino import distribute_wager_badges
from .const import * from .config.const import *
minimum_bet = 5 minimum_bet = 5
maximum_bet = INFINITY maximum_bet = INFINITY

View File

@ -3,7 +3,7 @@ from typing import Optional
from sqlalchemy.sql import func from sqlalchemy.sql import func
from files.helpers.const import * from files.helpers.config.const import *
def apply_time_filter(t, objects, cls): def apply_time_filter(t, objects, cls):
now = int(time.time()) now = int(time.time())

View File

@ -10,7 +10,7 @@ from files.classes.comment import Comment
from files.classes.votes import Vote, CommentVote from files.classes.votes import Vote, CommentVote
from files.classes.marsey import Marsey from files.classes.marsey import Marsey
from files.classes.award import AwardRelationship from files.classes.award import AwardRelationship
from files.helpers.const import * from files.helpers.config.const import *
def generate_charts_task(site): def generate_charts_task(site):
chart(kind='daily', site=site) chart(kind='daily', site=site)

View File

@ -1,7 +1,7 @@
from math import floor from math import floor
from random import randint from random import randint
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.lottery import * from files.helpers.lottery import *
special_min = 100 special_min = 100

View File

@ -1,5 +1,5 @@
# import constants then... # import constants then...
from files.helpers.const import FEATURES from files.helpers.config.const import FEATURES
# import flask then... # import flask then...
from flask import g, request, render_template, make_response, redirect, jsonify, send_file from flask import g, request, render_template, make_response, redirect, jsonify, send_file

View File

@ -8,7 +8,7 @@ from files.classes import *
from files.helpers.actions import * from files.helpers.actions import *
from files.helpers.alerts import * from files.helpers.alerts import *
from files.helpers.cloudflare import * from files.helpers.cloudflare import *
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.get import * from files.helpers.get import *
from files.helpers.media import * from files.helpers.media import *
from files.helpers.sanitize import * from files.helpers.sanitize import *
@ -45,7 +45,7 @@ def loggedout_list(v):
@app.get('/admin/merge/<id1>/<id2>') @app.get('/admin/merge/<id1>/<id2>')
@admin_level_required(PERMS['USER_MERGE']) @admin_level_required(PERMS['USER_MERGE'])
def merge(v, id1, id2): def merge(v:User, id1, id2):
if v.id != AEVANN_ID: abort(403) if v.id != AEVANN_ID: abort(403)
if time.time() - session.get('verified', 0) > 3: if time.time() - session.get('verified', 0) > 3:
@ -107,7 +107,7 @@ def merge(v, id1, id2):
@app.get('/admin/merge_all/<id>') @app.get('/admin/merge_all/<id>')
@admin_level_required(PERMS['USER_MERGE']) @admin_level_required(PERMS['USER_MERGE'])
def merge_all(v, id): def merge_all(v:User, id):
if v.id != AEVANN_ID: abort(403) if v.id != AEVANN_ID: abort(403)
if time.time() - session.get('verified', 0) > 3: if time.time() - session.get('verified', 0) > 3:
@ -191,7 +191,7 @@ def edit_rules_post(v):
@app.post("/@<username>/make_admin") @app.post("/@<username>/make_admin")
@admin_level_required(PERMS['ADMIN_ADD']) @admin_level_required(PERMS['ADMIN_ADD'])
def make_admin(v, username): def make_admin(v:User, username):
if SITE == 'rdrama.net': abort(403) if SITE == 'rdrama.net': abort(403)
user = get_user(username) user = get_user(username)
@ -211,7 +211,7 @@ def make_admin(v, username):
@app.post("/@<username>/remove_admin") @app.post("/@<username>/remove_admin")
@admin_level_required(PERMS['ADMIN_REMOVE']) @admin_level_required(PERMS['ADMIN_REMOVE'])
def remove_admin(v, username): def remove_admin(v:User, username):
user = get_user(username) user = get_user(username)
if user.id == v.id: if user.id == v.id:
abort(403, "You can't remove yourself JC") abort(403, "You can't remove yourself JC")
@ -231,7 +231,7 @@ def remove_admin(v, username):
@app.post("/distribute/<option_id>") @app.post("/distribute/<option_id>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit(DEFAULT_RATELIMIT_SLOWER)
@admin_level_required(PERMS['POST_BETS_DISTRIBUTE']) @admin_level_required(PERMS['POST_BETS_DISTRIBUTE'])
def distribute(v, option_id): def distribute(v:User, option_id):
autojanny = get_account(AUTOJANNY_ID) autojanny = get_account(AUTOJANNY_ID)
if autojanny.coins == 0: abort(400, "@AutoJanny has 0 coins") if autojanny.coins == 0: abort(400, "@AutoJanny has 0 coins")
@ -287,7 +287,7 @@ def distribute(v, option_id):
@app.post("/@<username>/revert_actions") @app.post("/@<username>/revert_actions")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit(DEFAULT_RATELIMIT_SLOWER)
@admin_level_required(PERMS['ADMIN_ACTIONS_REVERT']) @admin_level_required(PERMS['ADMIN_ACTIONS_REVERT'])
def revert_actions(v, username): def revert_actions(v:User, username):
user = get_user(username) user = get_user(username)
ma = ModAction( ma = ModAction(
@ -453,7 +453,7 @@ def admin_git_head():
@app.post("/admin/site_settings/<setting>") @app.post("/admin/site_settings/<setting>")
@admin_level_required(PERMS['SITE_SETTINGS']) @admin_level_required(PERMS['SITE_SETTINGS'])
def change_settings(v, setting): def change_settings(v:User, setting):
if setting not in get_settings().keys(): if setting not in get_settings().keys():
abort(404, f"Setting '{setting}' not found") abort(404, f"Setting '{setting}' not found")
val = toggle_setting(setting) val = toggle_setting(setting)
@ -745,14 +745,14 @@ def alt_votes_get(v):
@app.get("/@<username>/alts/") @app.get("/@<username>/alts/")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit(DEFAULT_RATELIMIT_SLOWER)
@admin_level_required(PERMS['USER_LINK']) @admin_level_required(PERMS['USER_LINK'])
def admin_view_alts(v, username=None): def admin_view_alts(v:User, username=None):
u = get_user(username or request.values.get('username'), graceful=True) u = get_user(username or request.values.get('username'), graceful=True)
return render_template('admin/alts.html', v=v, u=u, alts=u.alts_unique if u else None) return render_template('admin/alts.html', v=v, u=u, alts=u.alts_unique if u else None)
@app.post('/@<username>/alts/') @app.post('/@<username>/alts/')
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit(DEFAULT_RATELIMIT_SLOWER)
@admin_level_required(PERMS['USER_LINK']) @admin_level_required(PERMS['USER_LINK'])
def admin_add_alt(v, username): def admin_add_alt(v:User, username):
user1 = get_user(username) user1 = get_user(username)
user2 = get_user(request.values.get('other_username')) user2 = get_user(request.values.get('other_username'))
if user1.id == user2.id: abort(400, "Can't add the same account as alts of each other") if user1.id == user2.id: abort(400, "Can't add the same account as alts of each other")
@ -788,7 +788,7 @@ def admin_add_alt(v, username):
@app.route('/@<username>/alts/<int:other>/deleted', methods=["PUT", "DELETE"]) @app.route('/@<username>/alts/<int:other>/deleted', methods=["PUT", "DELETE"])
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit(DEFAULT_RATELIMIT_SLOWER)
@admin_level_required(PERMS['USER_LINK']) @admin_level_required(PERMS['USER_LINK'])
def admin_delink_relink_alt(v, username, other): def admin_delink_relink_alt(v:User, username, other):
is_delinking = request.method == 'PUT' # we're adding the 'deleted' state if a PUT request is_delinking = request.method == 'PUT' # we're adding the 'deleted' state if a PUT request
user1 = get_user(username) user1 = get_user(username)
user2 = get_account(other) user2 = get_account(other)
@ -1143,7 +1143,7 @@ def unban_user(user_id, v):
@app.post("/mute_user/<int:user_id>") @app.post("/mute_user/<int:user_id>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit(DEFAULT_RATELIMIT_SLOWER)
@admin_level_required(PERMS['USER_BAN']) @admin_level_required(PERMS['USER_BAN'])
def mute_user(v, user_id): def mute_user(v:User, user_id):
user = get_account(user_id) user = get_account(user_id)
if not user.is_muted: if not user.is_muted:
@ -1162,7 +1162,7 @@ def mute_user(v, user_id):
@app.post("/unmute_user/<int:user_id>") @app.post("/unmute_user/<int:user_id>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit(DEFAULT_RATELIMIT_SLOWER)
@admin_level_required(PERMS['USER_BAN']) @admin_level_required(PERMS['USER_BAN'])
def unmute_user(v, user_id): def unmute_user(v:User, user_id):
user = get_account(user_id) user = get_account(user_id)
if user.is_muted: if user.is_muted:
@ -1495,7 +1495,7 @@ def ban_domain(v):
@app.post("/admin/unban_domain/<domain>") @app.post("/admin/unban_domain/<domain>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit(DEFAULT_RATELIMIT_SLOWER)
@admin_level_required(PERMS['DOMAINS_BAN']) @admin_level_required(PERMS['DOMAINS_BAN'])
def unban_domain(v, domain): def unban_domain(v:User, domain):
existing = g.db.get(BannedDomain, domain) existing = g.db.get(BannedDomain, domain)
if not existing: abort(400, 'Domain is not banned!') if not existing: abort(400, 'Domain is not banned!')

View File

@ -1,6 +1,6 @@
import secrets import secrets
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.settings import get_setting from files.helpers.settings import get_setting
from files.helpers.cloudflare import CLOUDFLARE_AVAILABLE from files.helpers.cloudflare import CLOUDFLARE_AVAILABLE
from files.routes.wrappers import * from files.routes.wrappers import *

View File

@ -5,7 +5,7 @@ from files.classes.marsey import Marsey
from files.classes.hats import Hat, HatDef from files.classes.hats import Hat, HatDef
from files.classes.mod_logs import ModAction from files.classes.mod_logs import ModAction
from files.helpers.cloudflare import purge_files_in_cache from files.helpers.cloudflare import purge_files_in_cache
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.get import * from files.helpers.get import *
from files.helpers.media import * from files.helpers.media import *
from files.helpers.useractions import * from files.helpers.useractions import *

View File

@ -7,7 +7,8 @@ from files.classes.award import AwardRelationship
from files.classes.userblock import UserBlock from files.classes.userblock import UserBlock
from files.helpers.actions import * from files.helpers.actions import *
from files.helpers.alerts import * from files.helpers.alerts import *
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.config.awards import AWARDS_ENABLED, HOUSE_AWARDS
from files.helpers.get import * from files.helpers.get import *
from files.helpers.marsify import marsify from files.helpers.marsify import marsify
from files.helpers.owoify import owoify from files.helpers.owoify import owoify
@ -23,7 +24,7 @@ from .front import frontlist
@app.get("/settings/shop") @app.get("/settings/shop")
@auth_required @auth_required
def shop(v:User): def shop(v:User):
AWARDS = deepcopy(AWARDS2) AWARDS = deepcopy(AWARDS_ENABLED)
if v.house: if v.house:
AWARDS[v.house] = deepcopy(HOUSE_AWARDS[v.house]) AWARDS[v.house] = deepcopy(HOUSE_AWARDS[v.house])
@ -53,7 +54,7 @@ def buy(v:User, award):
if award == 'ghost' and v.admin_level < PERMS['BUY_GHOST_AWARD']: if award == 'ghost' and v.admin_level < PERMS['BUY_GHOST_AWARD']:
abort(403, "Only admins can buy this award") abort(403, "Only admins can buy this award")
AWARDS = deepcopy(AWARDS2) AWARDS = deepcopy(AWARDS_ENABLED)
if v.house: if v.house:
AWARDS[v.house] = HOUSE_AWARDS[v.house] AWARDS[v.house] = HOUSE_AWARDS[v.house]
@ -139,7 +140,7 @@ def award_thing(v, thing_type, id):
kind = request.values.get("kind", "").strip() kind = request.values.get("kind", "").strip()
AWARDS = deepcopy(AWARDS2) AWARDS = deepcopy(AWARDS_ENABLED)
if v.house: if v.house:
AWARDS[v.house] = HOUSE_AWARDS[v.house] AWARDS[v.house] = HOUSE_AWARDS[v.house]

View File

@ -1,7 +1,7 @@
from files.classes.casino_game import CASINO_GAME_KINDS from files.classes.casino_game import CASINO_GAME_KINDS
from files.helpers.alerts import * from files.helpers.alerts import *
from files.helpers.casino import * from files.helpers.casino import *
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.get import * from files.helpers.get import *
from files.helpers.lottery import * from files.helpers.lottery import *
from files.helpers.roulette import * from files.helpers.roulette import *

View File

@ -6,7 +6,7 @@ from flask_socketio import SocketIO, emit
from files.helpers.actions import * from files.helpers.actions import *
from files.helpers.alerts import * from files.helpers.alerts import *
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.regex import * from files.helpers.regex import *
from files.helpers.sanitize import sanitize from files.helpers.sanitize import sanitize
from files.routes.wrappers import * from files.routes.wrappers import *

View File

@ -9,7 +9,7 @@ from files.classes import *
from files.helpers.actions import * from files.helpers.actions import *
from files.helpers.alerts import * from files.helpers.alerts import *
from files.helpers.cloudflare import purge_files_in_cache from files.helpers.cloudflare import purge_files_in_cache
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.get import * from files.helpers.get import *
from files.helpers.marsify import marsify from files.helpers.marsify import marsify
from files.helpers.media import * from files.helpers.media import *

View File

@ -3,7 +3,7 @@ from urllib.parse import quote, urlencode
from flask import redirect, render_template, request, session, g from flask import redirect, render_template, request, session, g
from files.helpers.const import ERROR_MARSEYS, ERROR_MSGS, ERROR_TITLES, WERKZEUG_ERROR_DESCRIPTIONS, is_site_url from files.helpers.config.const import ERROR_MARSEYS, ERROR_MSGS, ERROR_TITLES, WERKZEUG_ERROR_DESCRIPTIONS, is_site_url
from files.helpers.settings import get_setting from files.helpers.settings import get_setting
from files.__main__ import app from files.__main__ import app

View File

@ -4,7 +4,7 @@ from sqlalchemy import or_, not_
from files.classes.submission import Submission from files.classes.submission import Submission
from files.classes.votes import Vote from files.classes.votes import Vote
from files.helpers.awards import award_timers from files.helpers.awards import award_timers
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.get import * from files.helpers.get import *
from files.helpers.sorting_and_time import * from files.helpers.sorting_and_time import *
from files.routes.wrappers import * from files.routes.wrappers import *

View File

@ -1,6 +1,6 @@
import requests import requests
from files.helpers.const import * from files.helpers.config.const import *
from files.routes.wrappers import * from files.routes.wrappers import *
from files.__main__ import app from files.__main__ import app

View File

@ -2,7 +2,7 @@ from sqlalchemy import func
from files.classes.hats import * from files.classes.hats import *
from files.helpers.alerts import * from files.helpers.alerts import *
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.useractions import * from files.helpers.useractions import *
from files.routes.wrappers import * from files.routes.wrappers import *
from files.__main__ import app, limiter from files.__main__ import app, limiter

View File

@ -9,7 +9,7 @@ from jinja2 import pass_context
from files.classes.user import User from files.classes.user import User
from files.helpers.assetcache import assetcache_path from files.helpers.assetcache import assetcache_path
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.settings import get_settings from files.helpers.settings import get_settings
from files.helpers.sorting_and_time import make_age_string from files.helpers.sorting_and_time import make_age_string
from files.routes.routehelpers import get_formkey from files.routes.routehelpers import get_formkey

View File

@ -6,7 +6,7 @@ import requests
from files.__main__ import app, cache, get_CF, limiter from files.__main__ import app, cache, get_CF, limiter
from files.classes.follows import Follow from files.classes.follows import Follow
from files.helpers.actions import * from files.helpers.actions import *
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.settings import get_setting from files.helpers.settings import get_setting
from files.helpers.get import * from files.helpers.get import *
from files.helpers.mail import send_mail, send_verification_email from files.helpers.mail import send_mail, send_verification_email

View File

@ -1,5 +1,5 @@
from files.helpers.alerts import * from files.helpers.alerts import *
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.get import * from files.helpers.get import *
from files.helpers.lottery import * from files.helpers.lottery import *
from files.routes.wrappers import * from files.routes.wrappers import *

View File

@ -1,7 +1,7 @@
import time import time
from files.classes import * from files.classes import *
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.get import * from files.helpers.get import *
from files.helpers.mail import * from files.helpers.mail import *
from files.helpers.useractions import * from files.helpers.useractions import *

View File

@ -4,7 +4,7 @@ from sqlalchemy.sql.expression import not_, and_, or_
from files.classes.mod_logs import ModAction from files.classes.mod_logs import ModAction
from files.classes.sub_logs import SubAction from files.classes.sub_logs import SubAction
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.get import * from files.helpers.get import *
from files.routes.wrappers import * from files.routes.wrappers import *
from files.__main__ import app from files.__main__ import app

View File

@ -2,7 +2,7 @@ import sqlalchemy.exc
from files.classes import * from files.classes import *
from files.helpers.alerts import * from files.helpers.alerts import *
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.get import * from files.helpers.get import *
from files.routes.wrappers import * from files.routes.wrappers import *
from files.__main__ import app, limiter from files.__main__ import app, limiter

View File

@ -1,5 +1,5 @@
from files.classes import * from files.classes import *
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.get import * from files.helpers.get import *
from files.routes.wrappers import * from files.routes.wrappers import *
from files.__main__ import app from files.__main__ import app

View File

@ -15,7 +15,7 @@ from files.__main__ import app, cache, limiter
from files.classes import * from files.classes import *
from files.helpers.actions import * from files.helpers.actions import *
from files.helpers.alerts import * from files.helpers.alerts import *
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.discord import * from files.helpers.discord import *
from files.helpers.get import * from files.helpers.get import *
from files.helpers.regex import * from files.helpers.regex import *

View File

@ -7,7 +7,7 @@ from typing import Optional, Union
from flask import g, session from flask import g, session
from files.classes import Alt, Comment, User, Submission from files.classes import Alt, Comment, User, Submission
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.security import generate_hash, validate_hash from files.helpers.security import generate_hash, validate_hash
def get_raw_formkey(u:User): def get_raw_formkey(u:User):

View File

@ -9,7 +9,7 @@ import youtube_dl
from files.helpers.actions import * from files.helpers.actions import *
from files.helpers.alerts import * from files.helpers.alerts import *
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.get import * from files.helpers.get import *
from files.helpers.mail import * from files.helpers.mail import *
from files.helpers.media import process_files, process_image from files.helpers.media import process_files, process_image

View File

@ -7,11 +7,12 @@ from files.helpers.media import process_files
import files.helpers.stats as statshelper import files.helpers.stats as statshelper
from files.classes.award import AWARDS from files.classes.award import AWARDS
from files.classes.badges import Badge, BadgeDef from files.classes.badges import Badge, BadgeDef
from files.classes.mod_logs import ModAction, ACTIONTYPES, ACTIONTYPES2 from files.classes.mod_logs import ModAction
from files.classes.userblock import UserBlock from files.classes.userblock import UserBlock
from files.helpers.actions import * from files.helpers.actions import *
from files.helpers.alerts import * from files.helpers.alerts import *
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.config.modaction_types import MODACTION_TYPES, MODACTION_TYPES_FILTERED, MODACTION_PRIVILEGED_TYPES
from files.routes.wrappers import * from files.routes.wrappers import *
from files.__main__ import app, cache, limiter from files.__main__ import app, cache, limiter
@ -135,8 +136,8 @@ def log(v:User):
kind = request.values.get("kind") kind = request.values.get("kind")
if v and v.admin_level >= PERMS['USER_SHADOWBAN']: types = ACTIONTYPES if v and v.admin_level >= PERMS['USER_SHADOWBAN']: types = MODACTION_TYPES
else: types = ACTIONTYPES2 else: types = MODACTION_TYPES_FILTERED
if kind and kind not in types: if kind and kind not in types:
kind = None kind = None
@ -144,11 +145,7 @@ def log(v:User):
else: else:
actions = g.db.query(ModAction) actions = g.db.query(ModAction)
if not (v and v.admin_level >= PERMS['USER_SHADOWBAN']): if not (v and v.admin_level >= PERMS['USER_SHADOWBAN']):
actions = actions.filter(ModAction.kind.notin_([ actions = actions.filter(ModAction.kind.notin_(MODACTION_PRIVILEGED_TYPES))
"shadowban","unshadowban",
"mod_mute_user","mod_unmute_user",
"link_accounts","delink_accounts",
]))
if admin_id: if admin_id:
actions = actions.filter_by(user_id=admin_id) actions = actions.filter_by(user_id=admin_id)
@ -180,8 +177,8 @@ def log_item(id, v):
admins = [x[0] for x in g.db.query(User.username).filter(User.admin_level >= PERMS['ADMIN_MOP_VISIBLE']).all()] admins = [x[0] for x in g.db.query(User.username).filter(User.admin_level >= PERMS['ADMIN_MOP_VISIBLE']).all()]
if v and v.admin_level >= PERMS['USER_SHADOWBAN']: types = ACTIONTYPES if v and v.admin_level >= PERMS['USER_SHADOWBAN']: types = MODACTION_TYPES
else: types = ACTIONTYPES2 else: types = MODACTION_TYPES_FILTERED
return render_template("log.html", v=v, actions=[action], next_exists=False, page=1, action=action, admins=admins, types=types, single_user_url='admin') return render_template("log.html", v=v, actions=[action], next_exists=False, page=1, action=action, admins=admins, types=types, single_user_url='admin')

View File

@ -4,7 +4,7 @@ import requests
from files.classes.streamers import Streamer from files.classes.streamers import Streamer
from files.helpers.alerts import send_repeatable_notification from files.helpers.alerts import send_repeatable_notification
from files.helpers.const import * from files.helpers.config.const import *
from files.routes.wrappers import * from files.routes.wrappers import *
from files.__main__ import app, cache from files.__main__ import app, cache

View File

@ -9,10 +9,9 @@ from files.routes.wrappers import *
from .front import frontlist from .front import frontlist
from files.__main__ import app, cache, limiter from files.__main__ import app, cache, limiter
@app.post("/exile/post/<pid>") @app.post("/exile/post/<pid>")
@is_not_permabanned @is_not_permabanned
def exile_post(v, pid): def exile_post(v:User, pid):
if v.shadowbanned: return {"error": "Internal Server Error"}, 500 if v.shadowbanned: return {"error": "Internal Server Error"}, 500
p = get_post(pid) p = get_post(pid)
sub = p.sub sub = p.sub
@ -41,11 +40,9 @@ def exile_post(v, pid):
return {"message": f"@{u.username} has been exiled from /h/{sub} successfully!"} return {"message": f"@{u.username} has been exiled from /h/{sub} successfully!"}
@app.post("/exile/comment/<cid>") @app.post("/exile/comment/<cid>")
@is_not_permabanned @is_not_permabanned
def exile_comment(v, cid): def exile_comment(v:User, cid):
if v.shadowbanned: return {"error": "Internal Server Error"}, 500 if v.shadowbanned: return {"error": "Internal Server Error"}, 500
c = get_comment(cid) c = get_comment(cid)
sub = c.post.sub sub = c.post.sub
@ -74,10 +71,9 @@ def exile_comment(v, cid):
return {"message": f"@{u.username} has been exiled from /h/{sub} successfully!"} return {"message": f"@{u.username} has been exiled from /h/{sub} successfully!"}
@app.post("/h/<sub>/unexile/<uid>") @app.post("/h/<sub>/unexile/<uid>")
@is_not_permabanned @is_not_permabanned
def unexile(v, sub, uid): def unexile(v:User, sub, uid):
u = get_account(uid) u = get_account(uid)
if not v.mods(sub): abort(403) if not v.mods(sub): abort(403)
@ -103,22 +99,17 @@ def unexile(v, sub, uid):
return redirect(f'/h/{sub}/exilees') return redirect(f'/h/{sub}/exilees')
@app.post("/h/<sub>/block") @app.post("/h/<sub>/block")
@auth_required @auth_required
def block_sub(v:User, sub): def block_sub(v:User, sub):
sub = get_sub_by_name(sub).name sub = get_sub_by_name(sub).name
existing = g.db.query(SubBlock).filter_by(user_id=v.id, sub=sub).one_or_none() existing = g.db.query(SubBlock).filter_by(user_id=v.id, sub=sub).one_or_none()
if not existing: if not existing:
block = SubBlock(user_id=v.id, sub=sub) block = SubBlock(user_id=v.id, sub=sub)
g.db.add(block) g.db.add(block)
cache.delete_memoized(frontlist) cache.delete_memoized(frontlist)
return {"message": f"/h/{sub} blocked successfully!"} return {"message": f"/h/{sub} blocked successfully!"}
@app.post("/h/<sub>/unblock") @app.post("/h/<sub>/unblock")
@auth_required @auth_required
def unblock_sub(v:User, sub): def unblock_sub(v:User, sub):
@ -134,18 +125,15 @@ def unblock_sub(v:User, sub):
return {"message": f"/h/{sub.name} unblocked successfully!"} return {"message": f"/h/{sub.name} unblocked successfully!"}
@app.post("/h/<sub>/subscribe") @app.post("/h/<sub>/subscribe")
@auth_required @auth_required
def subscribe_sub(v:User, sub): def subscribe_sub(v:User, sub):
sub = get_sub_by_name(sub).name sub = get_sub_by_name(sub).name
existing = g.db.query(SubJoin).filter_by(user_id=v.id, sub=sub).one_or_none() existing = g.db.query(SubJoin).filter_by(user_id=v.id, sub=sub).one_or_none()
if not existing: if not existing:
subscribe = SubJoin(user_id=v.id, sub=sub) subscribe = SubJoin(user_id=v.id, sub=sub)
g.db.add(subscribe) g.db.add(subscribe)
cache.delete_memoized(frontlist) cache.delete_memoized(frontlist)
return {"message": f"/h/{sub} unblocked successfully!"} return {"message": f"/h/{sub} unblocked successfully!"}
@app.post("/h/<sub>/unsubscribe") @app.post("/h/<sub>/unsubscribe")
@ -153,11 +141,9 @@ def subscribe_sub(v:User, sub):
def unsubscribe_sub(v:User, sub): def unsubscribe_sub(v:User, sub):
sub = get_sub_by_name(sub).name sub = get_sub_by_name(sub).name
subscribe = g.db.query(SubJoin).filter_by(user_id=v.id, sub=sub).one_or_none() subscribe = g.db.query(SubJoin).filter_by(user_id=v.id, sub=sub).one_or_none()
if subscribe: if subscribe:
g.db.delete(subscribe) g.db.delete(subscribe)
cache.delete_memoized(frontlist) cache.delete_memoized(frontlist)
return {"message": f"/h/{sub} blocked successfully!"} return {"message": f"/h/{sub} blocked successfully!"}
@app.post("/h/<sub>/follow") @app.post("/h/<sub>/follow")
@ -241,7 +227,7 @@ def sub_followers(v:User, sub):
@limiter.limit("1/second;30/day") @limiter.limit("1/second;30/day")
@is_not_permabanned @is_not_permabanned
@ratelimit_user("1/second;30/day") @ratelimit_user("1/second;30/day")
def add_mod(v, sub): def add_mod(v:User, sub):
if SITE_NAME == 'WPD': abort(403) if SITE_NAME == 'WPD': abort(403)
sub = get_sub_by_name(sub).name sub = get_sub_by_name(sub).name
if not v.mods(sub): abort(403) if not v.mods(sub): abort(403)
@ -275,10 +261,9 @@ def add_mod(v, sub):
return redirect(f'/h/{sub}/mods') return redirect(f'/h/{sub}/mods')
@app.post("/h/<sub>/remove_mod") @app.post("/h/<sub>/remove_mod")
@is_not_permabanned @is_not_permabanned
def remove_mod(v, sub): def remove_mod(v:User, sub):
sub = get_sub_by_name(sub).name sub = get_sub_by_name(sub).name
if not v.mods(sub): abort(403) if not v.mods(sub): abort(403)
@ -358,7 +343,7 @@ def create_sub2(v):
@app.post("/kick/<pid>") @app.post("/kick/<pid>")
@is_not_permabanned @is_not_permabanned
def kick(v, pid): def kick(v:User, pid):
post = get_post(pid) post = get_post(pid)
if not post.sub: abort(403) if not post.sub: abort(403)
@ -389,7 +374,7 @@ def kick(v, pid):
@app.get('/h/<sub>/settings') @app.get('/h/<sub>/settings')
@is_not_permabanned @is_not_permabanned
def sub_settings(v, sub): def sub_settings(v:User, sub):
sub = get_sub_by_name(sub) sub = get_sub_by_name(sub)
if not v.mods(sub.name): abort(403) if not v.mods(sub.name): abort(403)
return render_template('sub/settings.html', v=v, sidebar=sub.sidebar, sub=sub) return render_template('sub/settings.html', v=v, sidebar=sub.sidebar, sub=sub)
@ -399,7 +384,7 @@ def sub_settings(v, sub):
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit(DEFAULT_RATELIMIT_SLOWER)
@is_not_permabanned @is_not_permabanned
@ratelimit_user() @ratelimit_user()
def post_sub_sidebar(v, sub): def post_sub_sidebar(v:User, sub):
sub = get_sub_by_name(sub) sub = get_sub_by_name(sub)
if not v.mods(sub.name): abort(403) if not v.mods(sub.name): abort(403)
if v.shadowbanned: return redirect(f'/h/{sub}/settings') if v.shadowbanned: return redirect(f'/h/{sub}/settings')
@ -424,7 +409,7 @@ def post_sub_sidebar(v, sub):
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit(DEFAULT_RATELIMIT_SLOWER)
@is_not_permabanned @is_not_permabanned
@ratelimit_user() @ratelimit_user()
def post_sub_css(v, sub): def post_sub_css(v:User, sub):
sub = get_sub_by_name(sub) sub = get_sub_by_name(sub)
css = request.values.get('css', '').strip() css = request.values.get('css', '').strip()
@ -452,7 +437,6 @@ def post_sub_css(v, sub):
return redirect(f'/h/{sub}/settings') return redirect(f'/h/{sub}/settings')
@app.get("/h/<sub>/css") @app.get("/h/<sub>/css")
def get_sub_css(sub): def get_sub_css(sub):
sub = g.db.query(Sub.css).filter_by(name=sub.strip().lower()).one_or_none() sub = g.db.query(Sub.css).filter_by(name=sub.strip().lower()).one_or_none()
@ -461,13 +445,12 @@ def get_sub_css(sub):
resp.headers.add("Content-Type", "text/css") resp.headers.add("Content-Type", "text/css")
return resp return resp
@app.post("/h/<sub>/settings/banners/")
@app.post("/h/<sub>/banner")
@limiter.limit("1/second;10/day") @limiter.limit("1/second;10/day")
@is_not_permabanned @is_not_permabanned
@ratelimit_user("1/second;10/day") @ratelimit_user("1/second;10/day")
def sub_banner(v, sub): def upload_sub_banner(v:User, sub:str):
if g.is_tor: abort(403, "Image uploads are not allowed through TOR.") if g.is_tor: abort(403, "Image uploads are not allowed through Tor")
sub = get_sub_by_name(sub) sub = get_sub_by_name(sub)
if not v.mods(sub.name): abort(403) if not v.mods(sub.name): abort(403)
@ -479,26 +462,81 @@ def sub_banner(v, sub):
file.save(name) file.save(name)
bannerurl = process_image(name, v, resize=1200) bannerurl = process_image(name, v, resize=1200)
if bannerurl: sub.bannerurls.append(bannerurl)
if sub.bannerurl:
os.remove(sub.bannerurl) g.db.add(sub)
sub.bannerurl = bannerurl
g.db.add(sub)
ma = SubAction( ma = SubAction(
sub=sub.name, sub=sub.name,
kind='change_banner', kind='upload_banner',
user_id=v.id user_id=v.id
) )
g.db.add(ma) g.db.add(ma)
return redirect(f'/h/{sub}/settings') return redirect(f'/h/{sub}/settings')
@app.delete("/h/<sub>/settings/banners/<int:index>")
@limiter.limit("1/2 second;30/day")
@is_not_permabanned
@ratelimit_user("1/2 second;30/day")
def delete_sub_banner(v:User, sub:str, index:int):
sub = get_sub_by_name(sub)
if not v.mods(sub.name): abort(403)
if v.shadowbanned: return redirect(f'/h/{sub}/settings')
if not sub.bannerurls:
abort(404, f"Banner not found (/h/{sub.name} has no banners)")
if index < 0 or index >= len(sub.bannerurls):
abort(404, f'Banner not found (banner index {index} is not between 0 and {len(sub.bannerurls)})')
banner = sub.bannerurls[index]
try:
os.remove(banner)
except FileNotFoundError:
pass
del sub.bannerurls[index]
g.db.add(sub)
ma = SubAction(
sub=sub.name,
kind='delete_banner',
_note=index,
user_id=v.id
)
g.db.add(ma)
return {"message": f"Deleted banner {index} from /h/{sub} successfully"}
@app.delete("/h/<sub>/settings/banners/")
@limiter.limit("1/10 second;30/day")
@is_not_permabanned
@ratelimit_user("1/10 second;30/day")
def delete_all_sub_banners(v:User, sub:str):
sub = get_sub_by_name(sub)
if not v.mods(sub.name): abort(403)
if v.shadowbanned: return redirect(f'/h/{sub}/settings')
for banner in sub.banner_urls:
try:
os.remove(banner)
except FileNotFoundError:
pass
sub.bannerurls = []
g.db.add(sub)
ma = SubAction(
sub=sub.name,
kind='delete_banner',
_note='all',
user_id=v.id
)
g.db.add(ma)
return {"message": f"Deleted all banners from /h/{sub} successfully"}
@app.post("/h/<sub>/sidebar_image") @app.post("/h/<sub>/sidebar_image")
@limiter.limit("1/second;10/day") @limiter.limit("1/second;10/day")
@is_not_permabanned @is_not_permabanned
@ratelimit_user("1/second;10/day") @ratelimit_user("1/second;10/day")
def sub_sidebar(v, sub): def sub_sidebar(v:User, sub):
if g.is_tor: abort(403, "Image uploads are not allowed through TOR.") if g.is_tor: abort(403, "Image uploads are not allowed through TOR.")
sub = get_sub_by_name(sub) sub = get_sub_by_name(sub)
@ -529,7 +567,7 @@ def sub_sidebar(v, sub):
@limiter.limit("1/second;10/day") @limiter.limit("1/second;10/day")
@is_not_permabanned @is_not_permabanned
@ratelimit_user("1/second;10/day") @ratelimit_user("1/second;10/day")
def sub_marsey(v, sub): def sub_marsey(v:User, sub):
if g.is_tor: abort(403, "Image uploads are not allowed through TOR.") if g.is_tor: abort(403, "Image uploads are not allowed through TOR.")
sub = get_sub_by_name(sub) sub = get_sub_by_name(sub)
@ -565,7 +603,7 @@ def subs(v:User):
@app.post("/hole_pin/<pid>") @app.post("/hole_pin/<pid>")
@is_not_permabanned @is_not_permabanned
def hole_pin(v, pid): def hole_pin(v:User, pid):
p = get_post(pid) p = get_post(pid)
if not p.sub: abort(403) if not p.sub: abort(403)
@ -591,7 +629,7 @@ def hole_pin(v, pid):
@app.post("/hole_unpin/<pid>") @app.post("/hole_unpin/<pid>")
@is_not_permabanned @is_not_permabanned
def hole_unpin(v, pid): def hole_unpin(v:User, pid):
p = get_post(pid) p = get_post(pid)
if not p.sub: abort(403) if not p.sub: abort(403)
@ -618,7 +656,7 @@ def hole_unpin(v, pid):
@app.post('/h/<sub>/stealth') @app.post('/h/<sub>/stealth')
@is_not_permabanned @is_not_permabanned
def sub_stealth(v, sub): def sub_stealth(v:User, sub):
sub = get_sub_by_name(sub) sub = get_sub_by_name(sub)
if sub.name == 'braincels': abort(403) if sub.name == 'braincels': abort(403)
if not v.mods(sub.name): abort(403) if not v.mods(sub.name): abort(403)
@ -716,7 +754,7 @@ def hole_log(v:User, sub):
kind = request.values.get("kind") kind = request.values.get("kind")
types = ACTIONTYPES types = SUBACTION_TYPES
if kind and kind not in types: if kind and kind not in types:
kind = None kind = None
@ -758,6 +796,6 @@ def hole_log_item(id, v, sub):
mods = [x[0] for x in g.db.query(Mod.user_id).filter_by(sub=sub.name).all()] mods = [x[0] for x in g.db.query(Mod.user_id).filter_by(sub=sub.name).all()]
mods = [x[0] for x in g.db.query(User.username).filter(User.id.in_(mods)).order_by(User.username).all()] mods = [x[0] for x in g.db.query(User.username).filter(User.id.in_(mods)).order_by(User.username).all()]
types = ACTIONTYPES types = SUBACTION_TYPES
return render_template("log.html", v=v, actions=[action], next_exists=False, page=1, action=action, admins=mods, types=types, sub=sub, single_user_url='mod') return render_template("log.html", v=v, actions=[action], next_exists=False, page=1, action=action, admins=mods, types=types, sub=sub, single_user_url='mod')

View File

@ -16,7 +16,7 @@ from files.classes.transactions import *
from files.classes.views import * from files.classes.views import *
from files.helpers.actions import execute_blackjack, execute_under_siege from files.helpers.actions import execute_blackjack, execute_under_siege
from files.helpers.alerts import * from files.helpers.alerts import *
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.mail import * from files.helpers.mail import *
from files.helpers.sanitize import * from files.helpers.sanitize import *
from files.helpers.sorting_and_time import * from files.helpers.sorting_and_time import *

View File

@ -1,5 +1,5 @@
from files.classes import * from files.classes import *
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.get import * from files.helpers.get import *
from files.routes.wrappers import * from files.routes.wrappers import *
from files.__main__ import app, limiter from files.__main__ import app, limiter

View File

@ -3,7 +3,7 @@ from flask import g, request, session
from files.classes.clients import ClientAuth from files.classes.clients import ClientAuth
from files.helpers.alerts import * from files.helpers.alerts import *
from files.helpers.const import * from files.helpers.config.const import *
from files.helpers.get import get_account from files.helpers.get import get_account
from files.helpers.logging import log_file from files.helpers.logging import log_file
from files.helpers.settings import get_setting from files.helpers.settings import get_setting

View File

@ -2,28 +2,9 @@
{% block pagetitle %}{{"Badge Grant" if grant else "Badge Remove"}}{% endblock %} {% block pagetitle %}{{"Badge Grant" if grant else "Badge Remove"}}{% endblock %}
{% block pagetype %}message{% endblock %} {% block pagetype %}message{% endblock %}
{% block content %} {% block content %}
{% if error %}
<div class="alert alert-danger alert-dismissible fade show my-3" role="alert"> {% if error %}{{macros.alert(error, true)}}{% endif %}
<i class="fas fa-exclamation-circle my-auto"></i> {% if msg %}{{macros.alert(msg, false)}}{% endif %}
<span>
{{error}}
</span>
<button type="button" class="close" data-bs-dismiss="alert" aria-label="Close">
<span aria-hidden="true"><i class="far fa-times"></i></span>
</button>
</div>
{% endif %}
{% if msg %}
<div class="alert alert-success alert-dismissible fade show my-3" role="alert">
<i class="fas fa-check-circle my-auto" aria-hidden="true"></i>
<span>
{{msg}}
</span>
<button type="button" class="close" data-bs-dismiss="alert" aria-label="Close">
<span aria-hidden="true"><i class="far fa-times"></i></span>
</button>
</div>
{% endif %}
<h5 class="mt-2">{{title}}</h5> <h5 class="mt-2">{{title}}</h5>
{% set form_action = "/admin/badge_grant" if grant else "/admin/badge_remove" %} {% set form_action = "/admin/badge_grant" if grant else "/admin/badge_remove" %}

View File

@ -3,19 +3,7 @@
{% block pagetitle %}Edit {{SITE_NAME}}'s rules{% endblock %} {% block pagetitle %}Edit {{SITE_NAME}}'s rules{% endblock %}
{% block content %} {% block content %}
{% if msg %}{{macros.alert(msg, false)}}{% endif %}
{% if msg %}
<div class="alert alert-success alert-dismissible fade show my-3" role="alert">
<i class="fas fa-check-circle my-auto" aria-hidden="true"></i>
<span>
{{msg}}
</span>
<button class="close" data-bs-dismiss="alert" aria-label="Close">
<span aria-hidden="true"><i class="far fa-times"></i></span>
</button>
</div>
{% endif %}
<div class="row my-5"> <div class="row my-5">
<div class="col"> <div class="col">
<div class="settings mx-3"> <div class="settings mx-3">
@ -38,5 +26,4 @@
</div> </div>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -362,7 +362,7 @@
<div class="col">{% block screen %} {% endblock %}</div> <div class="col">{% block screen %} {% endblock %}</div>
<div class="col"> <div class="col">
<div id="casinoGameResult" class="alert" role="alert"> <div id="casinoGameResult" class="alert" role="alert">
{% block result %} {% endblock %} {% block result %}{% endblock %}
</div> </div>
</div> </div>
<div class="col"> <div class="col">

View File

@ -1,20 +1,8 @@
{% extends "default.html" %} {% extends "default.html" %}
{% block pagetitle %}Contact{% endblock %} {% block pagetitle %}Contact{% endblock %}
{% block content %} {% block content %}
{% if msg %} {% if msg %}{{macros.alert(msg, false)}}{% endif %}
<div class="alert alert-success alert-dismissible fade show my-3" role="alert">
<i class="fas fa-check-circle my-auto" aria-hidden="true"></i>
<span>
{{msg}}
</span>
<button type="button" class="close" data-bs-dismiss="alert" aria-label="Close">
<span aria-hidden="true"><i class="far fa-times"></i></span>
</button>
</div>
{% endif %}
<h1 class="article-title">Contact {{SITE_NAME}} Admins</h1> <h1 class="article-title">Contact {{SITE_NAME}} Admins</h1>
{% if v %} {% if v %}
<p>Use this form to contact {{SITE_NAME}} Admins.</p> <p>Use this form to contact {{SITE_NAME}} Admins.</p>

View File

@ -9,8 +9,8 @@
{% else %} {% else %}
{% if err and SITE_NAME == 'rDrama' %} {% if err and SITE_NAME == 'rDrama' %}
{% set src = "banner_error.webp" | asset_siteimg %} {% set src = "banner_error.webp" | asset_siteimg %}
{% elif sub %} {% elif sub and sub.has_banners %}
{% set src = sub.banner_url %} {% set src = sub.random_banner() %}
{% set alt = ['/h/', sub, 'banner']|join %} {% set alt = ['/h/', sub, 'banner']|join %}
{% set class = 'site-banner-hole' %} {% set class = 'site-banner-hole' %}
{% elif SITE_NAME == "rDrama" %} {% elif SITE_NAME == "rDrama" %}

View File

@ -19,28 +19,8 @@
} }
</script> </script>
{% if error %} {% if error %}{{macros.alert(error, true)}}{% endif %}
<div class="alert alert-danger alert-dismissible fade show my-3" role="alert"> {% if msg %}{{macros.alert(msg, false)}}{% endif %}
<i class="fas fa-exclamation-circle my-auto"></i>
<span>
{{error}}
</span>
<button type="button" class="close" data-bs-dismiss="alert" aria-label="Close">
<span aria-hidden="true"><i class="far fa-times"></i></span>
</button>
</div>
{% endif %}
{% if msg %}
<div class="alert alert-success alert-dismissible fade show my-3" role="alert">
<i class="fas fa-check-circle my-auto" aria-hidden="true"></i>
<span>
{{msg}}
</span>
<button type="button" class="close" data-bs-dismiss="alert" aria-label="Close">
<span aria-hidden="true"><i class="far fa-times"></i></span>
</button>
</div>
{% endif %}
<div class="px-2 mb-4"> <div class="px-2 mb-4">
<h1 class="py-3"><i class="fas fa-circle mr-3" style="color:red"></i>Live</h1> <h1 class="py-3"><i class="fas fa-circle mr-3" style="color:red"></i>Live</h1>

View File

@ -15,26 +15,9 @@
<div class="col-10 col-md-7"> <div class="col-10 col-md-7">
<h2>{% block authtitle %}{% endblock %}</h2> <h2>{% block authtitle %}{% endblock %}</h2>
<p class="text-muted mb-md-5">{% block authtext %}{% endblock %}</p> <p class="text-muted mb-md-5">{% block authtext %}{% endblock %}</p>
{% if error %} {% if error %}{{macros.alert(error, true)}}{% endif %}
<div class="alert alert-danger fade show d-flex my-3" role="alert"> {% if msg %}{{macros.alert(msg, false)}}{% endif %}
<i class="fas fa-exclamation-circle my-auto"></i> {% block content %}{% endblock %}
<span>
{{error}}
</span>
</div>
{% endif %}
{% if msg %}
<div class="alert alert-success alert-dismissible fade show d-flex my-3" role="alert">
<i class="fas fa-info-circle my-auto" aria-hidden="true"></i>
<span>
{{msg}}
</span>
<button type="button" class="close" data-bs-dismiss="alert" aria-label="Close">
<span aria-hidden="true"><i class="far fa-times"></i></span>
</button>
</div>
{% endif %}
{% block content %}{% endblock %}
</div> </div>
</div> </div>
</div> </div>

View File

@ -11,19 +11,11 @@
{% block authtext %}Glad to have you back!{% endblock %} {% block authtext %}Glad to have you back!{% endblock %}
{% block content %} {% block content %}
<div id="login-form"> <div id="login-form">
{% if failed %} {%- set error_text -%}
<div class="alert alert-danger alert-dismissible fade show d-flex my-3" role="alert"> Incorrect username, email address, or password.<br>
<i class="fas fa-exclamation-circle my-auto"></i> <a href="/forgot" class="alert-link">Forgot password?</a>
<div> {%- endset -%}
Incorrect username, email address, or password. {% if failed %}{{macros.alert(error_text, true)}}{% endif %}
<br>
<a href="/forgot" class="alert-link">Forgot password?</a>
</div>
<button type="button" class="close" data-bs-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endif %}
<form action="/login" method="post" class="mt-md-3" id="login"> <form action="/login" method="post" class="mt-md-3" id="login">
<label for="username" class="mt-3">Username or Email Address</label> <label for="username" class="mt-3">Username or Email Address</label>
<input autocomplete="off" class="form-control" id="username" aria-describedby="usernameHelp" <input autocomplete="off" class="form-control" id="username" aria-describedby="usernameHelp"

View File

@ -11,13 +11,7 @@
<div id="login-form"> <div id="login-form">
<h2>Two-step login</h2> <h2>Two-step login</h2>
<p class="text-muted mb-md-5">To login, please enter the 6-digit verification code generated in your authenticator app.</p> <p class="text-muted mb-md-5">To login, please enter the 6-digit verification code generated in your authenticator app.</p>
{% if failed %} {% if failed %}{{macros.alert('Invalid verification code. Please try again.', true)}}{% endif %}
<div class="alert alert-danger alert-dismissible fade show d-flex my-3" role="alert">
<i class="fas fa-exclamation-circle my-auto"></i>
<div>Invalid verification code. Please try again.</div>
<button type="button" class="close" data-bs-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div> </div>
{% endif %} {% endif %}
<form action="/login" method="post" class="mt-md-3" id="login"> <form action="/login" method="post" class="mt-md-3" id="login">

View File

@ -7,14 +7,8 @@
{% if error %} {% if error %}
<div class="row no-gutters"> <div class="row no-gutters">
<div class="col"> <div class="col">
<div class="text-center px-3 my-3"> {{macros.ghost_box(error, '', 1)}}
<span class="fa-stack fa-2x text-muted mb-4">
<i class="fas fa-square text-gray-500 opacity-25 fa-stack-2x"></i>
<i class="fas text-gray-500 fa-ghost fa-stack-1x text-lg"></i>
</span>
<h5>{{error}}</h5>
</div>
</div> </div>
</div> </div>
{% endif %} {% endif %}

View File

@ -7,30 +7,8 @@
<div class="container"> <div class="container">
<div class="row justify-content-around"> <div class="row justify-content-around">
<div class="col h-100"> <div class="col h-100">
{% if error %}{{macros.alert(error, true)}}{% endif %}
{% if error %} {% if msg %}{{macros.alert(msg, false)}}{% endif %}
<div class="alert alert-danger alert-dismissible fade show my-3" role="alert">
<i class="fas fa-exclamation-circle my-auto"></i>
<span>
{{error}}
</span>
<button type="button" class="close" data-bs-dismiss="alert" aria-label="Close">
<span aria-hidden="true"><i class="far fa-times"></i></span>
</button>
</div>
{% endif %}
{% if msg %}
<div class="alert alert-success alert-dismissible fade show my-3" role="alert">
<i class="fas fa-check-circle my-auto" aria-hidden="true"></i>
<span>
{{msg}}
</span>
<button type="button" class="close" data-bs-dismiss="alert" aria-label="Close">
<span aria-hidden="true"><i class="far fa-times"></i></span>
</button>
</div>
{% endif %}
<div class="mt-3"> <div class="mt-3">
<h1 class="d-mob-none">Settings</h1> <h1 class="d-mob-none">Settings</h1>
<h3 class="mt-5 d-md-none">Settings</h3> <h3 class="mt-5 d-md-none">Settings</h3>

View File

@ -136,17 +136,7 @@
<section id="site-settings-blocks-section" class="settings-section-section"> <section id="site-settings-blocks-section" class="settings-section-section">
<div class="row"> <div class="row">
<div class="col"> <div class="col">
{% if error %} {% if error %}{{macros.alert(error, true)}}{% endif %}
<div class="alert alert-danger alert-dismissible fade show my-3" role="alert">
<i class="fas fa-exclamation-circle my-auto"></i>
<span>
{{error}}
</span>
<button type="button" class="close" data-bs-dismiss="alert" aria-label="Close">
<span aria-hidden="true"><i class="far fa-times"></i></span>
</button>
</div>
{% endif %}
</div> </div>
</div> </div>
<div class="row"> <div class="row">
@ -187,10 +177,7 @@
</table> </table>
</div> </div>
{% else %} {% else %}
<div class="text-center border-md rounded py-7"> {{macros.ghost_box('No blocked users', '', 2)}}
<i class="fas fa-ghost text-gray-500 mb-3" style="font-size: 3.5rem;"></i>
<p class="font-weight-bold text-gray-500 mb-0">No blocked users</p>
</div>
{% endif %} {% endif %}
</div> </div>
</div> </div>

View File

@ -1,30 +1,9 @@
{% extends "default.html" %} {% extends "default.html" %}
{% block pagetitle %}/h/{{sub}} Settings{% endblock %} {% block pagetitle %}/h/{{sub}} Settings{% endblock %}
{% block content %} {% block content %}
{% if error %} {% if error %}{{macros.alert(error, true)}}{% endif %}
<div class="alert alert-danger alert-dismissible fade show mb-3 mt-4" role="alert"> {% if msg %}{{macros.alert(msg, false)}}{% endif %}
<i class="fas fa-exclamation-circle my-auto"></i>
<span>
{{error}}
</span>
<button type="button" class="close" data-bs-dismiss="alert" aria-label="Close">
<span aria-hidden="true"><i class="far fa-times"></i></span>
</button>
</div>
{% endif %}
{% if msg %}
<div class="alert alert-success alert-dismissible fade show my-3" role="alert">
<i class="fas fa-check-circle my-auto" aria-hidden="true"></i>
<span>
{{msg}}
</span>
<button type="button" class="close" data-bs-dismiss="alert" aria-label="Close">
<span aria-hidden="true"><i class="far fa-times"></i></span>
</button>
</div>
{% endif %}
<div class="title w-lg-25 mt-5"> <div class="title w-lg-25 mt-5">
<label class="text-lg" for="stealth">Stealth Mode</label> <label class="text-lg" for="stealth">Stealth Mode</label>
@ -37,21 +16,14 @@
<span class="text-small text-muted">Make this hole blocked by default (users can visit it to unblock it).</span> <span class="text-small text-muted">Make this hole blocked by default (users can visit it to unblock it).</span>
</div> </div>
<h5 class="mt-5">Marsey</h5>
<h5 class=" mt-5">Marsey</h5>
<div class="settings-section rounded"> <div class="settings-section rounded">
<div class="d-flex"> <div class="d-flex">
<div class="title w-lg-25 text-md-center"> <div class="title w-lg-25 text-md-center">
<img loading="lazy" alt="sub marsey picture" src="{{sub.marsey_url}}" class="profile-pic-75"> <img loading="lazy" alt="sub marsey picture" src="{{sub.marsey_url}}" class="profile-pic-75">
</div> </div>
<div class="body w-lg-100 my-auto"> <div class="body w-lg-100 my-auto">
<div class="d-flex"> <div class="d-flex">
<div> <div>
<form action="/h/{{sub}}/marsey_image" method="post" enctype="multipart/form-data"> <form action="/h/{{sub}}/marsey_image" method="post" enctype="multipart/form-data">
<input type="hidden" name="formkey" value="{{v|formkey}}"> <input type="hidden" name="formkey" value="{{v|formkey}}">
@ -59,34 +31,21 @@
Update<input autocomplete="off" type="file" accept="image/*" {% if g.is_tor %}disabled{% endif %} hidden name="marsey" onchange="form.submit()"> Update<input autocomplete="off" type="file" accept="image/*" {% if g.is_tor %}disabled{% endif %} hidden name="marsey" onchange="form.submit()">
</label> </label>
</form> </form>
</div> </div>
</div> </div>
<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> <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>
</div> </div>
</div> </div>
</div> </div>
<h5 class=" mt-5">Sidebar Picture</h5> <h5 class=" mt-5">Sidebar Picture</h5>
<div class="settings-section rounded"> <div class="settings-section rounded">
<div class="d-flex"> <div class="d-flex">
<div class="title w-lg-25 text-md-center"> <div class="title w-lg-25 text-md-center">
<img loading="lazy" alt="sub sidebar picture" src="{{sub.sidebar_url}}" class="profile-pic-75"> <img loading="lazy" alt="sub sidebar picture" src="{{sub.sidebar_url}}" class="profile-pic-75">
</div> </div>
<div class="body w-lg-100 my-auto"> <div class="body w-lg-100 my-auto">
<div class="d-flex"> <div class="d-flex">
<div> <div>
<form action="/h/{{sub}}/sidebar_image" method="post" enctype="multipart/form-data"> <form action="/h/{{sub}}/sidebar_image" method="post" enctype="multipart/form-data">
<input type="hidden" name="formkey" value="{{v|formkey}}"> <input type="hidden" name="formkey" value="{{v|formkey}}">
@ -94,70 +53,62 @@
Update<input autocomplete="off" type="file" accept="image/*" {% if g.is_tor %}disabled{% endif %} hidden name="sidebar" onchange="form.submit()"> Update<input autocomplete="off" type="file" accept="image/*" {% if g.is_tor %}disabled{% endif %} hidden name="sidebar" onchange="form.submit()">
</label> </label>
</form> </form>
</div> </div>
</div> </div>
<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> <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>
</div> </div>
</div> </div>
</div> </div>
<h5 class="mt-5">Banners</h5>
<div class="settings-section rounded sub-banner-update-section">
<h5 class=" mt-5">Banner</h5> {% for banner in sub.banner_urls %}
<section id="sub-banner-update-{{loop.index - 1}}" class="d-flex sub-settings-subsection">
<div class="settings-section rounded">
<div class="d-flex">
<div class="title w-lg-75 text-md-center"> <div class="title w-lg-75 text-md-center">
<img loading="lazy" alt="/h/{[sub.name]} banner" src="{{sub.banner_url}}" class="banner-pic-135"> <img loading="lazy" alt="/h/{{sub.name}} banner" src="{{banner}}" class="banner-pic-135 sub-banner-preview sub-banner-{{sub.name}}">
</div> </div>
<div class="body w-lg-100 my-auto"> <div class="body w-lg-100 my-auto">
<div class="d-flex"> <div class="d-flex">
<button class="btn btn-danger sub-banner-delete-button" id="sub-banner-delete-{{loop.index}}" onclick="areyousure(this)" data-click2="postToastReload(this, '/h/{{sub.name}}/settings/banners/{{loop.index - 1}}', 'DELETE');">Delete</button>
</div>
</div>
</section>
{% else %}
<section id="sub-banner-no-banners" class="d-flex sub-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="d-flex sub-settings-subsection">
<div class="body w-lg-100 my-auto">
<div class="d-flex">
<div> <div>
<form action="/h/{{sub}}/banner" method="post" enctype="multipart/form-data"> <form action="/h/{{sub.name}}/settings/banners/" method="post" enctype="multipart/form-data">
<input type="hidden" name="formkey" value="{{v|formkey}}"> <input type="hidden" name="formkey" value="{{v|formkey}}">
<label class="btn btn-secondary text-capitalize mr-2 mb-0"> <label class="btn btn-secondary text-capitalize mr-2 mb-0">
Update<input autocomplete="off" type="file" {% if g.is_tor %}disabled{% endif %} accept="image/*" hidden name="banner" onchange="form.submit()"> Upload New Banner<input autocomplete="off" type="file" accept="image/*" hidden name="banner" onchange="form.submit()">
</label> </label>
<button type="button" class="btn btn-danger sub-banner-delete-button" id="sub-banner-delete-all" onclick="areyousure(this)" data-click2="postToastReload(this, '/h/{{sub.name}}/settings/banners/', 'DELETE');">Delete All Banners</button>
</form> </form>
</div> </div>
</div> </div>
<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> <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>
</div> </div>
</section>
</div> {% endif %}
</div> </div>
<div class="row my-5 pt-5"> <div class="row my-5 pt-5">
<div class="col col-md-8"> <div class="col col-md-8">
<div class="settings"> <div class="settings">
<div id="description"> <div id="description">
<h2>Edit Sidebar</h2> <h2>Edit Sidebar</h2><br>
<br>
</div> </div>
<div class="body d-lg-flex"> <div class="body d-lg-flex">
<div class="w-lg-100"> <div class="w-lg-100">
<form id="sidebar" action="/h/{{sub}}/sidebar" method="post"> <form id="sidebar" action="/h/{{sub}}/sidebar" method="post">
<input type="hidden" name="formkey" value="{{v|formkey}}"> <input type="hidden" name="formkey" value="{{v|formkey}}">
<textarea autocomplete="off" maxlength="10000" class="form-control rounded" id="bio-text" aria-label="With textarea" 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" aria-label="With textarea" placeholder="Enter sidebar here..." rows="10" name="sidebar" form="sidebar">{% if sub.sidebar %}{{sub.sidebar}}{% endif %}</textarea>
<div class="d-flex mt-2"> <div class="d-flex mt-2">
<input autocomplete="off" class="btn btn-primary ml-auto" type="submit" onclick="disable(this)" value="Save"> <input autocomplete="off" class="btn btn-primary ml-auto" type="submit" onclick="disable(this)" value="Save">
</div> </div>
@ -172,15 +123,13 @@
<div class="col col-md-8"> <div class="col col-md-8">
<div class="settings"> <div class="settings">
<div id="description"> <div id="description">
<h2>Edit CSS</h2> <h2>Edit CSS</h2><br>
<br>
</div> </div>
<div class="body d-lg-flex"> <div class="body d-lg-flex">
<div class="w-lg-100"> <div class="w-lg-100">
<form id="css" action="/h/{{sub}}/css" method="post"> <form id="css" action="/h/{{sub}}/css" method="post">
<input type="hidden" name="formkey" value="{{v|formkey}}"> <input type="hidden" name="formkey" value="{{v|formkey}}">
<textarea autocomplete="off" maxlength="6000" class="form-control rounded" id="bio-text" aria-label="With textarea" placeholder="Enter css here..." rows="10" name="css" form="css">{% if sub.css %}{{sub.css}}{% endif %}</textarea> <textarea autocomplete="off" maxlength="6000" class="form-control rounded" id="bio-text" aria-label="With textarea" placeholder="Enter css here..." rows="10" name="css" form="css">{% if sub.css %}{{sub.css}}{% endif %}</textarea>
<div class="d-flex mt-2"> <div class="d-flex mt-2">
<input autocomplete="off" class="btn btn-primary ml-auto" type="submit" onclick="disable(this)" value="Save"> <input autocomplete="off" class="btn btn-primary ml-auto" type="submit" onclick="disable(this)" value="Save">
</div> </div>
@ -190,5 +139,4 @@
</div> </div>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -378,54 +378,39 @@
</script> </script>
{% endif %} {% endif %}
{% elif not p.replies and p.deleted_utc == 0 %} {% elif not p.replies and p.deleted_utc == 0 %}
<div class="comment-section" id="replies-of-{{p.fullname}}"> <div class="comment-section no-replies" id="replies-of-{{p.fullname}}">
<div class="text-center py-7"> {% if v %}
<span class="fa-stack fa-2x text-muted mb-4"> {% set ghost_town = 'This comment section is a ghost town...' %}
<i class="fas fa-square text-gray-500 opacity-25 fa-stack-2x"></i> {% else %}
<i class="fas text-gray-500 fa-ghost fa-stack-1x text-lg"></i> {% set ghost_town = 'This comment section is a ghost town... <a href="/login?redirect={{request.full_path | urlencode}}">Sign in</a></p> '%}
</span> {% endif %}
<h5>Be the first to comment!</h5> {{macros.ghost_box('Be the first to comment!', ghost_town, 1)}}
{% if v %}
<p class="text-muted">This comment section is a ghost town...</p>
{% else %}
<p class="text-muted">This comment section is a ghost town. <a href="/login?redirect={{request.full_path | urlencode}}">Sign in</a></p>
{% endif %}
</div>
</div> </div>
{% endif %} {% endif %}
</div> </div>
</div> </div>
{% if v and v.id==p.author_id %}
{% include "modals/delete_post.html" %}
{% endif %}
{% if v %} {% if v %}
{% if v.id == p.author_id %}{% include "modals/delete_post.html" %}{% endif %}
{% include "modals/report_post.html" %} {% include "modals/report_post.html" %}
{% endif %} {% if v.can_edit(p) %}
<script defer src="{{'js/togglePostEdit.js' | asset}}"></script>
{% if v and v.can_edit(p) %} {% endif %}
<script defer src="{{'js/togglePostEdit.js' | asset}}"></script> {% if v.admin_level >= PERMS['POST_COMMENT_MODERATION'] %}
<script defer src="{{'js/pinpost.js' | asset}}"></script>
{% endif %}
{% endif %} {% endif %}
{% if not v or v.highlightcomments %} {% if not v or v.highlightcomments %}
<script defer src="{{'js/highlightcomments.js' | asset}}"></script> <script defer src="{{'js/highlightcomments.js' | asset}}"></script>
{% endif %} {% endif %}
{% if v and v.admin_level >= PERMS['POST_COMMENT_MODERATION'] %}
<script defer src="{{'js/pinpost.js' | asset}}"></script>
{% endif %}
<script defer src="{{'js/vendor/clipboard.js' | asset}}"></script> <script defer src="{{'js/vendor/clipboard.js' | asset}}"></script>
{% if not p.replies %} {% if not p.replies %}{% include "comments.html" %}{% endif %}
{% include "comments.html" %}
{% endif %}
{% if not v or v.highlightcomments %}
<script> <script>
{% if not v or v.highlightcomments %}
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
showNewCommentCounts('{{p.id}}', {{p.comment_count}}) showNewCommentCounts('{{p.id}}', {{p.comment_count}})
{% if "?context" not in request.full_path %} {% if "?context" not in request.full_path %}
@ -437,9 +422,8 @@
localStorage.setItem("comment-counts", JSON.stringify(comments)) localStorage.setItem("comment-counts", JSON.stringify(comments))
{% endif %} {% endif %}
}) })
{% endif %}
</script> </script>
{% endif %}
{% if success %} {% if success %}
<script> <script>
history.pushState(null, null, '{{p.permalink}}'); history.pushState(null, null, '{{p.permalink}}');

View File

@ -101,11 +101,7 @@
{% endif %} {% endif %}
</div> </div>
{% endif %} {% endif %}
</div> </div>
<div class="card-block text-left x-scroll-parent w-100"> <div class="card-block text-left x-scroll-parent w-100">
<div class="post-meta text-left x-scroll mb-md-2"> <div class="post-meta text-left x-scroll mb-md-2">
<div style="white-space:nowrap;width:0"> <div style="white-space:nowrap;width:0">
@ -261,23 +257,9 @@
</div> </div>
{% endif %} {% endif %}
{% endif %} {% endif %}
</div> </div>
{% else %} {% else %}
{% if u %}
{% if request.path.endswith('/admin/queue') %}
<div class="row no-gutters">
<div class="col">
<div class="text-center py-7">
<h4 class="p-2">This queue is empty. (That's a good thing.)</h4>
</div>
</div>
</div>
{% elif u %}
{% if v and v.id == u.id %} {% if v and v.id == u.id %}
<div class="row no-gutters"> <div class="row no-gutters">
<div class="col"> <div class="col">
@ -292,8 +274,6 @@
</div> </div>
</div> </div>
</div> </div>
{% else %} {% else %}
<div class="row no-gutters"> <div class="row no-gutters">
<div class="col"> <div class="col">
@ -311,22 +291,12 @@
{% elif request.path != '/notifications/posts' %} {% elif request.path != '/notifications/posts' %}
<div class="row no-gutters"> <div class="row no-gutters">
<div class="col"> <div class="col">
<div class="text-center px-3 my-3"> {{macros.ghost_box(error if request.path.startswith('/search') else '', '', 1)}}
<span class="fa-stack fa-2x text-muted mb-4">
<i class="fas fa-square text-gray-500 opacity-25 fa-stack-2x"></i>
<i class="fas text-gray-500 fa-ghost fa-stack-1x text-lg"></i>
</span>
{% if request.path.startswith('/search') and error %}
<h5>{{error}}</h5>
{% endif %}
</div>
</div> </div>
</div> </div>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
{% if v %} {% if v %}

View File

@ -2,28 +2,8 @@
{% block pagetitle %}Submit Hats{% endblock %} {% block pagetitle %}Submit Hats{% endblock %}
{% block pagetype %}message{% endblock %} {% block pagetype %}message{% endblock %}
{% block content %} {% block content %}
{% if error %} {% if error %}{{macros.alert(error, true)}}{% endif %}
<div class="alert alert-danger alert-dismissible fade show mb-3 mt-4" role="alert"> {% if msg %}{{macros.alert(msg, false)}}{% endif %}
<i class="fas fa-exclamation-circle my-auto"></i>
<span>
{{error}}
</span>
<button type="button" class="close" data-bs-dismiss="alert" aria-label="Close">
<span aria-hidden="true"><i class="far fa-times"></i></span>
</button>
</div>
{% endif %}
{% if msg %}
<div class="alert alert-success alert-dismissible fade show my-3" role="alert">
<i class="fas fa-check-circle my-auto" aria-hidden="true"></i>
<span>
{{msg}}
</span>
<button type="button" class="close" data-bs-dismiss="alert" aria-label="Close">
<span aria-hidden="true"><i class="far fa-times"></i></span>
</button>
</div>
{% endif %}
<div class="mx-4"> <div class="mx-4">
<h2 class="mt-5">Submit Hat</h2> <h2 class="mt-5">Submit Hat</h2>

View File

@ -7,30 +7,8 @@
text-transform: lowercase; text-transform: lowercase;
} }
</style> </style>
{% if error %}{{macros.alert(error, true)}}{% endif %}
{% if error %} {% if msg %}{{macros.alert(msg, false)}}{% endif %}
<div class="alert alert-danger alert-dismissible fade show mb-3 mt-4" role="alert">
<i class="fas fa-exclamation-circle my-auto"></i>
<span>
{{error}}
</span>
<button type="button" class="close" data-bs-dismiss="alert" aria-label="Close">
<span aria-hidden="true"><i class="far fa-times"></i></span>
</button>
</div>
{% endif %}
{% if msg %}
<div class="alert alert-success alert-dismissible fade show my-3" role="alert">
<i class="fas fa-check-circle my-auto" aria-hidden="true"></i>
<span>
{{msg}}
</span>
<button type="button" class="close" data-bs-dismiss="alert" aria-label="Close">
<span aria-hidden="true"><i class="far fa-times"></i></span>
</button>
</div>
{% endif %}
<div class="mx-4"> <div class="mx-4">
<h2 class="mt-5">Submit Marsey</h2> <h2 class="mt-5">Submit Marsey</h2>
<div class="settings-section rounded"> <div class="settings-section rounded">

View File

@ -2,28 +2,8 @@
{% block pagetitle %}Update {{type}}{% endblock %} {% block pagetitle %}Update {{type}}{% endblock %}
{% block pagetype %}message{% endblock %} {% block pagetype %}message{% endblock %}
{% block content %} {% block content %}
{% if error %} {% if error %}{{macros.alert(error, true)}}{% endif %}
<div class="alert alert-danger alert-dismissible fade show mb-3 mt-4" role="alert"> {% if msg %}{{macros.alert(msg, false)}}{% endif %}
<i class="fas fa-exclamation-circle my-auto"></i>
<span>
{{error}}
</span>
<button type="button" class="close" data-bs-dismiss="alert" aria-label="Close">
<span aria-hidden="true"><i class="far fa-times"></i></span>
</button>
</div>
{% endif %}
{% if msg %}
<div class="alert alert-success alert-dismissible fade show my-3" role="alert">
<i class="fas fa-check-circle my-auto" aria-hidden="true"></i>
<span>
{{msg}}
</span>
<button type="button" class="close" data-bs-dismiss="alert" aria-label="Close">
<span aria-hidden="true"><i class="far fa-times"></i></span>
</button>
</div>
{% endif %}
<div class="mx-4"> <div class="mx-4">
<h2 class="mt-5">Update {{type}}</h2> <h2 class="mt-5">Update {{type}}</h2>

View File

@ -159,3 +159,37 @@
{% endif %} {% endif %}
</div> </div>
{% endmacro %} {% endmacro %}
{% macro ghost_box(text1, text2, mode, extra_css) %}
{# TODO: use in saved (search for "fa-ghost" in source) #}
{% if mode == 1 %}
<div class="text-center py-7 ghost-town-box ghost-town-box-1"{% if extra_css %} style="{{extra_css}}"{% endif %}>
<span class="fa-stack fa-2x text-muted mb-4">
<i class="fas fa-square text-gray-500 opacity-25 fa-stack-2x"></i>
<i class="fas text-gray-500 fa-ghost fa-stack-1x text-lg"></i>
</span>
{% if text1 %}
<h5>{{text1|safe}}</h5>
<p></p>
{% endif %}
{% if text2 %}
<p class="text-muted">{{text2|safe}}</p>
{% endif %}
</div>
{% elif mode == 2 %}
<div class="text-center border-md rounded py-7 ghost-town-box ghost-town-box-2"{% if extra_css %} style="{{extra_css}}"{% endif %}>
<i class="fas fa-ghost text-gray-500 mb-3" style="font-size: 3.5rem;"></i>
<p class="font-weight-bold text-gray-500 mb-0">{{text1|safe}}</p>
</div>
{% endif %}
{% endmacro %}
{% macro alert(msg, error=false) %}
<div class="alert {% if error %}alert-danger{% else %}alert-success{% endif %} alert-dismissible fade show mb-3 mt-4" role="alert">
<i class="fas {% if error %}fa-exclamation-circle{% else %}fa-check-circle{% endif %} my-auto"></i>
<span>{{msg}}</span>
<button type="button" class="close" data-bs-dismiss="alert" aria-label="Close">
<span aria-hidden="true"><i class="far fa-times"></i></span>
</button>
</div>
{% endmacro %}

View File

@ -0,0 +1,8 @@
UPDATE subactions SET kind = 'upload_banner' WHERE kind = 'change_banner'; -- update mod actions
ALTER TABLE subs RENAME COLUMN bannerurl TO bannerurls;
ALTER TABLE subs ALTER COLUMN bannerurls TYPE VARCHAR(60)[] USING ARRAY[bannerurls];
ALTER TABLE subs ALTER COLUMN bannerurls SET DEFAULT '{}';
ALTER TABLE subs ALTER COLUMN bannerurls SET NOT NULL; -- multiple banners <3
UPDATE subs SET bannerurls = '{}' WHERE bannerurls = '{NULL}'; -- update subs with no banners