forked from rDrama/rDrama
1
0
Fork 0

Merge branch 'master' into mistletoe

master
kek7198 2021-11-28 10:31:21 -06:00
commit 40444fc00d
38 changed files with 258 additions and 266 deletions

View File

@ -10,7 +10,7 @@ services:
- DATABASE_URL=postgresql://postgres@postgres:5432 - DATABASE_URL=postgresql://postgres@postgres:5432
- MASTER_KEY=XuxGqp5NyygJrM24b5gt3YgyvFVGdQnwVDwLzLwpu3eQwY - MASTER_KEY=XuxGqp5NyygJrM24b5gt3YgyvFVGdQnwVDwLzLwpu3eQwY
- REDIS_URL=redis://redis - REDIS_URL=redis://redis
- DOMAIN=0.0.0.0 - DOMAIN=localhost
- SITE_NAME=Drama - SITE_NAME=Drama
- GIPHY_KEY=3435tdfsdudebussylmaoxxt43 - GIPHY_KEY=3435tdfsdudebussylmaoxxt43
- FORCE_HTTPS=0 - FORCE_HTTPS=0

4
env
View File

@ -1,6 +1,6 @@
export DATABASE_URL="postgresql://postgres@0.0.0.0:5432" export DATABASE_URL="postgresql://postgres@localhost:5432"
export MASTER_KEY="XuxGqp5NyygJrM24b5gt3YgyvFVGdQnwVDwLzLwpu3eQwY" export MASTER_KEY="XuxGqp5NyygJrM24b5gt3YgyvFVGdQnwVDwLzLwpu3eQwY"
export DOMAIN="0.0.0.0" export DOMAIN="localhost"
export SITE_NAME="Drama" export SITE_NAME="Drama"
export GIPHY_KEY="3435tdfsdudebussylmaoxxt43" export GIPHY_KEY="3435tdfsdudebussylmaoxxt43"
export FORCE_HTTPS="0" export FORCE_HTTPS="0"

View File

@ -43,7 +43,7 @@ app.config["SESSION_REFRESH_EACH_REQUEST"] = True
app.config["SLOGAN"] = environ.get("SLOGAN", "").strip() app.config["SLOGAN"] = environ.get("SLOGAN", "").strip()
app.config["DEFAULT_COLOR"] = environ.get("DEFAULT_COLOR", "ff0000").strip() app.config["DEFAULT_COLOR"] = environ.get("DEFAULT_COLOR", "ff0000").strip()
app.config["DEFAULT_THEME"] = environ.get("DEFAULT_THEME", "midnight").strip() app.config["DEFAULT_THEME"] = environ.get("DEFAULT_THEME", "midnight").strip()
app.config["FORCE_HTTPS"] = int(environ.get("FORCE_HTTPS", 1)) if ("0.0.0.0" not in app.config["SERVER_NAME"] and "0.0.0.0" not in app.config["SERVER_NAME"]) else 0 app.config["FORCE_HTTPS"] = int(environ.get("FORCE_HTTPS", 1)) if ("localhost" not in app.config["SERVER_NAME"] and "localhost" not in app.config["SERVER_NAME"]) else 0
app.config["UserAgent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36" app.config["UserAgent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36"
app.config["HCAPTCHA_SITEKEY"] = environ.get("HCAPTCHA_SITEKEY","").strip() app.config["HCAPTCHA_SITEKEY"] = environ.get("HCAPTCHA_SITEKEY","").strip()
app.config["HCAPTCHA_SECRET"] = environ.get("HCAPTCHA_SECRET","").strip() app.config["HCAPTCHA_SECRET"] = environ.get("HCAPTCHA_SECRET","").strip()
@ -62,14 +62,14 @@ app.config["RATELIMIT_DEFAULTS_EXEMPT_WHEN"]=lambda:False
app.config["RATELIMIT_HEADERS_ENABLED"]=True app.config["RATELIMIT_HEADERS_ENABLED"]=True
app.config["CACHE_TYPE"] = "filesystem" app.config["CACHE_TYPE"] = "filesystem"
app.config["CACHE_DIR"] = "cache" app.config["CACHE_DIR"] = "cache"
app.config["RATELIMIT_STORAGE_URL"] = environ.get("REDIS_URL", "redis://0.0.0.0") app.config["RATELIMIT_STORAGE_URL"] = environ.get("REDIS_URL", "redis://localhost")
app.config['MAIL_SERVER'] = 'smtp.gmail.com' app.config['MAIL_SERVER'] = 'smtp.gmail.com'
app.config['MAIL_PORT'] = 587 app.config['MAIL_PORT'] = 587
app.config['MAIL_USE_TLS'] = True app.config['MAIL_USE_TLS'] = True
app.config['MAIL_USERNAME'] = environ.get("MAIL_USERNAME", "").strip() app.config['MAIL_USERNAME'] = environ.get("MAIL_USERNAME", "").strip()
app.config['MAIL_PASSWORD'] = environ.get("MAIL_PASSWORD", "").strip() app.config['MAIL_PASSWORD'] = environ.get("MAIL_PASSWORD", "").strip()
r=redis.Redis(host=environ.get("REDIS_URL", "redis://0.0.0.0"), decode_responses=True, ssl_cert_reqs=None) r=redis.Redis(host=environ.get("REDIS_URL", "redis://localhost"), decode_responses=True, ssl_cert_reqs=None)
limiter = Limiter( limiter = Limiter(
app, app,
@ -111,7 +111,7 @@ def before_request():
session.permanent = True session.permanent = True
if not session.get("session_id"): session["session_id"] = secrets.token_hex(16) if not session.get("session_id"): session["session_id"] = secrets.token_hex(16)
if app.config["FORCE_HTTPS"] and request.url.startswith("http://") and "0.0.0.0" not in app.config["SERVER_NAME"]: if app.config["FORCE_HTTPS"] and request.url.startswith("http://") and "localhost" not in app.config["SERVER_NAME"]:
url = request.url.replace("http://", "https://", 1) url = request.url.replace("http://", "https://", 1)
return redirect(url, code=301) return redirect(url, code=301)

View File

@ -2,6 +2,7 @@ from sqlalchemy import *
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
from files.__main__ import Base from files.__main__ import Base
from files.helpers.lazy import lazy from files.helpers.lazy import lazy
from files.helpers.const import censor_slurs
import time import time
class Flag(Base): class Flag(Base):
@ -29,6 +30,10 @@ class Flag(Base):
def created_datetime(self): def created_datetime(self):
return str(time.strftime("%d/%B/%Y %H:%M:%S UTC", time.gmtime(self.created_utc))) return str(time.strftime("%d/%B/%Y %H:%M:%S UTC", time.gmtime(self.created_utc)))
@lazy
def realreason(self, v):
return censor_slurs(self.reason, v)
class CommentFlag(Base): class CommentFlag(Base):
@ -53,4 +58,8 @@ class CommentFlag(Base):
@property @property
@lazy @lazy
def created_datetime(self): def created_datetime(self):
return str(time.strftime("%d/%B/%Y %H:%M:%S UTC", time.gmtime(self.created_utc))) return str(time.strftime("%d/%B/%Y %H:%M:%S UTC", time.gmtime(self.created_utc)))
@lazy
def realreason(self, v):
return censor_slurs(self.reason, v)

View File

@ -163,16 +163,6 @@ ACTIONTYPES={
"icon": "fa-user-slash", "icon": "fa-user-slash",
"color": "bg-muted", "color": "bg-muted",
}, },
"club_allow":{
"str":'allowed user {self.target_link} into the {cc}',
"icon":"fa-user-slash",
"color": "bg-danger",
},
"club_ban":{
"str":'disallowed user {self.target_link} from the {cc}',
"icon": "fa-user-slash",
"color": "bg-muted",
},
"nuke_user":{ "nuke_user":{
"str":'removed all content of {self.target_link}', "str":'removed all content of {self.target_link}',
"icon":"fa-user-slash", "icon":"fa-user-slash",
@ -253,16 +243,6 @@ ACTIONTYPES={
"icon":"fa-feather-alt", "icon":"fa-feather-alt",
"color": "bg-muted", "color": "bg-muted",
}, },
"club":{
"str": 'marked post {self.target_link} as club-only',
"icon":"fa-eye-slash",
"color": "bg-danger",
},
"unclub":{
"str": 'unmarked post {self.target_link} as club-only',
"icon":"fa-eye",
"color": "bg-muted",
},
"ban_comment":{ "ban_comment":{
"str": 'removed {self.target_link}', "str": 'removed {self.target_link}',
"icon":"fa-comment", "icon":"fa-comment",

View File

@ -143,6 +143,8 @@ if SITE == 'rdrama.net':
LLM_ID = 253 LLM_ID = 253
DAD_ID = 2513 DAD_ID = 2513
MOM_ID = 4588 MOM_ID = 4588
BUG_THREAD = 18459
EMOJI_THREAD = 22479
elif SITE == "pcmemes.net": elif SITE == "pcmemes.net":
BASEDBOT_ID = 800 BASEDBOT_ID = 800
NOTIFICATIONS_ID = 1046 NOTIFICATIONS_ID = 1046
@ -159,6 +161,8 @@ elif SITE == "pcmemes.net":
LLM_ID = 0 LLM_ID = 0
DAD_ID = 0 DAD_ID = 0
MOM_ID = 0 MOM_ID = 0
BUG_THREAD = 4103
EMOJI_THREAD = 0
else: else:
BASEDBOT_ID = 0 BASEDBOT_ID = 0
NOTIFICATIONS_ID = 1 NOTIFICATIONS_ID = 1
@ -175,12 +179,14 @@ else:
LLM_ID = 0 LLM_ID = 0
DAD_ID = 0 DAD_ID = 0
MOM_ID = 0 MOM_ID = 0
BUG_THREAD = 0
EMOJI_THREAD = 0
PUSHER_INSTANCE_ID = '02ddcc80-b8db-42be-9022-44c546b4dce6' PUSHER_INSTANCE_ID = '02ddcc80-b8db-42be-9022-44c546b4dce6'
PUSHER_KEY = environ.get("PUSHER_KEY", "").strip() PUSHER_KEY = environ.get("PUSHER_KEY", "").strip()
single_words = "|".join([slur.lower() for slur in SLURS.keys()]) single_words = "|".join([slur.lower() for slur in SLURS.keys()])
SLUR_REGEX = re.compile(rf"(?i)((?<=\s|>)|^)(nigger)((?=[\s<,.]|s[\s<,.])|$)") SLUR_REGEX = re.compile(rf"(?i)((?<=\s|>)|^)({single_words})((?=[\s<,.]|s[\s<,.])|$)")
def sub_matcher(match: re.Match) -> str: def sub_matcher(match: re.Match) -> str:
return SLURS[match.group(0).lower()] return SLURS[match.group(0).lower()]
@ -389,6 +395,14 @@ BADGES = {
'name': 'Unblockable', 'name': 'Unblockable',
'description': 'This user is unblockable' 'description': 'This user is unblockable'
}, },
88: {
'name': 'Provider',
'description': 'This user provided a bountiful feast for Thanksgiving'
},
89: {
'name': 'Dinner',
'description': 'Yes, it is edible'
},
} }
AWARDS = { AWARDS = {
@ -748,7 +762,4 @@ TROLLTITLES = [
"[META] Getting really sick of @{username}โ€™s shit", "[META] Getting really sick of @{username}โ€™s shit",
"Pretty sure this is @{username}'s Reddit account", "Pretty sure this is @{username}'s Reddit account",
"Hey jannies can you please ban @{username}", "Hey jannies can you please ban @{username}",
] ]
BUG_THREAD = 18459
EMOJI_THREAD = 22479

View File

@ -97,14 +97,6 @@ def club_allow(v, username):
x.club_banned = False x.club_banned = False
g.db.add(x) g.db.add(x)
ma=ModAction(
kind="club_allow",
user_id=v.id,
target_user_id=u.id,
)
g.db.add(ma)
g.db.commit() g.db.commit()
return {"message": f"@{username} has been allowed into the {cc}!"} return {"message": f"@{username} has been allowed into the {cc}!"}
@ -127,13 +119,6 @@ def club_ban(v, username):
u.club_allowed = False u.club_allowed = False
g.db.add(x) g.db.add(x)
ma=ModAction(
kind="club_ban",
user_id=v.id,
target_user_id=u.id,
)
g.db.add(ma)
g.db.commit() g.db.commit()
return {"message": f"@{username} has been kicked from the {cc}. Deserved."} return {"message": f"@{username} has been kicked from the {cc}. Deserved."}
@ -164,30 +149,30 @@ def remove_admin(v, username):
return {"message": "Admin removed!"} return {"message": "Admin removed!"}
@app.post("/@<username>/make_fake_admin") @app.post("/@<username>/make_meme_admin")
@limiter.limit("1/second") @limiter.limit("1/second")
@admin_level_required(2) @admin_level_required(2)
def make_fake_admin(v, username): def make_meme_admin(v, username):
if 'pcm' in request.host or (SITE_NAME == 'Drama' and v.admin_level > 2) or ('rama' not in request.host and 'pcm' not in request.host): if 'pcm' in request.host or (SITE_NAME == 'Drama' and v.admin_level > 2) or ('rama' not in request.host and 'pcm' not in request.host):
user = get_user(username) user = get_user(username)
if not user: abort(404) if not user: abort(404)
user.admin_level = 1 user.admin_level = 1
g.db.add(user) g.db.add(user)
g.db.commit() g.db.commit()
return {"message": "User has been made fake admin!"} return {"message": "User has been made meme admin!"}
@app.post("/@<username>/remove_fake_admin") @app.post("/@<username>/remove_meme_admin")
@limiter.limit("1/second") @limiter.limit("1/second")
@admin_level_required(2) @admin_level_required(2)
def remove_fake_admin(v, username): def remove_meme_admin(v, username):
if 'pcm' in request.host or (SITE_NAME == 'Drama' and v.admin_level > 2) or ('rama' not in request.host and 'pcm' not in request.host): if 'pcm' in request.host or (SITE_NAME == 'Drama' and v.admin_level > 2) or ('rama' not in request.host and 'pcm' not in request.host):
user = get_user(username) user = get_user(username)
if not user: abort(404) if not user: abort(404)
user.admin_level = 0 user.admin_level = 0
g.db.add(user) g.db.add(user)
g.db.commit() g.db.commit()
return {"message": "Fake admin removed!"} return {"message": "Meme admin removed!"}
@app.post("/admin/monthly") @app.post("/admin/monthly")

View File

@ -20,6 +20,7 @@ from urllib.parse import ParseResult, urlunparse, urlparse, quote
site = environ.get("DOMAIN").strip() site = environ.get("DOMAIN").strip()
CATBOX_KEY = environ.get("CATBOX_KEY").strip() CATBOX_KEY = environ.get("CATBOX_KEY").strip()
titleheaders = {"User-Agent": f"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.72 Safari/537.36"}
with open("snappy.txt", "r") as f: snappyquotes = f.read().split("{[para]}") with open("snappy.txt", "r") as f: snappyquotes = f.read().split("{[para]}")
@ -34,14 +35,6 @@ def toggle_club(pid, v):
post.club = not post.club post.club = not post.club
g.db.add(post) g.db.add(post)
if post.author_id!=v.id:
ma=ModAction(
kind="club" if post.club else "unclub",
user_id=v.id,
target_submission_id=post.id,
)
g.db.add(ma)
g.db.commit() g.db.commit()
if post.club: return {"message": "Post has been marked as club-only!"} if post.club: return {"message": "Post has been marked as club-only!"}
@ -397,19 +390,18 @@ def edit_post(pid, v):
def get_post_title(v): def get_post_title(v):
url = request.values.get("url", None) url = request.values.get("url", None)
if not url: return abort(400) if not url: abort(400)
headers = {"User-Agent": f"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.72 Safari/537.36"} try: x = requests.get(url, headers=titleheaders, timeout=5)
try: x = requests.get(url, headers=headers, timeout=5) except: abort(400)
except BaseException: return {"error": "Could not reach page"}, 400
if not x.status_code == 200: return {"error": f"Page returned {x.status_code}"}, x.status_code soup = BeautifulSoup(x.content, 'html.parser')
title = soup.find('title')
if not title: abort(400)
return {"url": url, "title": title.string}
try:
soup = BeautifulSoup(x.content, 'html.parser')
return {"url": url, "title": soup.find('title').string}
except BaseException:
return {"error": f"Could not find a title"}, 400
def archiveorg(url): def archiveorg(url):
try: requests.get(f'https://web.archive.org/save/{url}', headers={'User-Agent': 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'}, timeout=100) try: requests.get(f'https://web.archive.org/save/{url}', headers={'User-Agent': 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'}, timeout=100)
@ -766,6 +758,8 @@ def submit_post(v):
if v.paid_dues: club = bool(request.values.get("club","")) if v.paid_dues: club = bool(request.values.get("club",""))
else: club = False else: club = False
if embed and len(embed) > 1500: embed = None
new_post = Submission( new_post = Submission(
private=bool(request.values.get("private","")), private=bool(request.values.get("private","")),
club=club, club=club,

View File

@ -825,11 +825,10 @@ def settings_block_user(v):
user = get_user(request.values.get("username"), graceful=True) user = get_user(request.values.get("username"), graceful=True)
if not user: return {"error": "That user doesn't exist."}, 404
if user.unblockable: return {"error": "This user is unblockable."}, 403 if user.unblockable: return {"error": "This user is unblockable."}, 403
if not user:
return {"error": "That user doesn't exist."}, 404
if user.id == v.id: if user.id == v.id:
return {"error": "You can't block yourself."}, 409 return {"error": "You can't block yourself."}, 409
@ -853,8 +852,7 @@ def settings_block_user(v):
g.db.commit() g.db.commit()
if v.admin_level == 1: return {"message": f"@{user.username} banned!"} return {"message": f"@{user.username} blocked."}
else: return {"message": f"@{user.username} blocked."}
@app.post("/settings/unblock") @app.post("/settings/unblock")
@ -878,8 +876,6 @@ def settings_unblock_user(v):
g.db.commit() g.db.commit()
if v.admin_level == 1: return {"message": f"@{user.username} unbanned!"}
return {"message": f"@{user.username} unblocked."} return {"message": f"@{user.username} unblocked."}

View File

@ -173,7 +173,7 @@ def log(v):
actions = g.db.query(ModAction) actions = g.db.query(ModAction)
if not (v and v.admin_level > 1): if not (v and v.admin_level > 1):
actions = actions.filter(ModAction.kind.notin_(["shadowban","unshadowban","club","unclub","club_allow","club_ban","check"])) actions = actions.filter(ModAction.kind.notin_(["shadowban","unshadowban","check"]))
if admin_id: actions = actions.filter_by(user_id=admin_id) if admin_id: actions = actions.filter_by(user_id=admin_id)
if kind: actions = actions.filter_by(kind=kind) if kind: actions = actions.filter_by(kind=kind)

View File

@ -17,14 +17,15 @@ site = environ.get("DOMAIN").strip()
beams_client = PushNotifications(instance_id=PUSHER_INSTANCE_ID, secret_key=PUSHER_KEY) beams_client = PushNotifications(instance_id=PUSHER_INSTANCE_ID, secret_key=PUSHER_KEY)
@app.get("/@<username>/upvoters") @app.get("/@<username>/upvoters")
@auth_desired @auth_desired
def upvoters(v, username): def upvoters(v, username):
id = get_user(username).id id = get_user(username).id
votes = g.db.query(Vote.user_id, func.count(Vote.user_id)).join(Submission, Vote.submission_id==Submission.id).filter(Vote.vote_type==1, Submission.author_id==id).group_by(Vote.user_id).order_by(func.count(Vote.user_id).desc()).limit(25).all() votes = g.db.query(Vote.user_id, func.count(Vote.user_id)).join(Submission, Vote.submission_id==Submission.id).filter(Vote.vote_type==1, Submission.author_id==id).group_by(Vote.user_id).order_by(func.count(Vote.user_id).desc()).all()
votes2 = g.db.query(CommentVote.user_id, func.count(CommentVote.user_id)).join(Comment, CommentVote.comment_id==Comment.id).filter(CommentVote.vote_type==1, Comment.author_id==id).group_by(CommentVote.user_id).order_by(func.count(CommentVote.user_id).desc()).limit(25).all() votes2 = g.db.query(CommentVote.user_id, func.count(CommentVote.user_id)).join(Comment, CommentVote.comment_id==Comment.id).filter(CommentVote.vote_type==1, Comment.author_id==id).group_by(CommentVote.user_id).order_by(func.count(CommentVote.user_id).desc()).all()
votes = Counter(dict(votes)) + Counter(dict(votes2)) votes = Counter(dict(votes)) + Counter(dict(votes2))
@ -41,9 +42,9 @@ def upvoters(v, username):
def downvoters(v, username): def downvoters(v, username):
id = get_user(username).id id = get_user(username).id
votes = g.db.query(Vote.user_id, func.count(Vote.user_id)).join(Submission, Vote.submission_id==Submission.id).filter(Vote.vote_type==-1, Submission.author_id==id).group_by(Vote.user_id).order_by(func.count(Vote.user_id).desc()).limit(25).all() votes = g.db.query(Vote.user_id, func.count(Vote.user_id)).join(Submission, Vote.submission_id==Submission.id).filter(Vote.vote_type==-1, Submission.author_id==id).group_by(Vote.user_id).order_by(func.count(Vote.user_id).desc()).all()
votes2 = g.db.query(CommentVote.user_id, func.count(CommentVote.user_id)).join(Comment, CommentVote.comment_id==Comment.id).filter(CommentVote.vote_type==-1, Comment.author_id==id).group_by(CommentVote.user_id).order_by(func.count(CommentVote.user_id).desc()).limit(25).all() votes2 = g.db.query(CommentVote.user_id, func.count(CommentVote.user_id)).join(Comment, CommentVote.comment_id==Comment.id).filter(CommentVote.vote_type==-1, Comment.author_id==id).group_by(CommentVote.user_id).order_by(func.count(CommentVote.user_id).desc()).all()
votes = Counter(dict(votes)) + Counter(dict(votes2)) votes = Counter(dict(votes)) + Counter(dict(votes2))
@ -60,9 +61,9 @@ def downvoters(v, username):
def upvoting(v, username): def upvoting(v, username):
id = get_user(username).id id = get_user(username).id
votes = g.db.query(Submission.author_id, func.count(Submission.author_id)).join(Vote, Vote.submission_id==Submission.id).filter(Vote.vote_type==1, Vote.user_id==id).group_by(Submission.author_id).order_by(func.count(Submission.author_id).desc()).limit(25).all() votes = g.db.query(Submission.author_id, func.count(Submission.author_id)).join(Vote, Vote.submission_id==Submission.id).filter(Vote.vote_type==1, Vote.user_id==id).group_by(Submission.author_id).order_by(func.count(Submission.author_id).desc()).all()
votes2 = g.db.query(Comment.author_id, func.count(Comment.author_id)).join(CommentVote, CommentVote.comment_id==Comment.id).filter(CommentVote.vote_type==1, CommentVote.user_id==id).group_by(Comment.author_id).order_by(func.count(Comment.author_id).desc()).limit(25).all() votes2 = g.db.query(Comment.author_id, func.count(Comment.author_id)).join(CommentVote, CommentVote.comment_id==Comment.id).filter(CommentVote.vote_type==1, CommentVote.user_id==id).group_by(Comment.author_id).order_by(func.count(Comment.author_id).desc()).all()
votes = Counter(dict(votes)) + Counter(dict(votes2)) votes = Counter(dict(votes)) + Counter(dict(votes2))
@ -79,9 +80,9 @@ def upvoting(v, username):
def downvoting(v, username): def downvoting(v, username):
id = get_user(username).id id = get_user(username).id
votes = g.db.query(Submission.author_id, func.count(Submission.author_id)).join(Vote, Vote.submission_id==Submission.id).filter(Vote.vote_type==-1, Vote.user_id==id).group_by(Submission.author_id).order_by(func.count(Submission.author_id).desc()).limit(25).all() votes = g.db.query(Submission.author_id, func.count(Submission.author_id)).join(Vote, Vote.submission_id==Submission.id).filter(Vote.vote_type==-1, Vote.user_id==id).group_by(Submission.author_id).order_by(func.count(Submission.author_id).desc()).all()
votes2 = g.db.query(Comment.author_id, func.count(Comment.author_id)).join(CommentVote, CommentVote.comment_id==Comment.id).filter(CommentVote.vote_type==-1, CommentVote.user_id==id).group_by(Comment.author_id).order_by(func.count(Comment.author_id).desc()).limit(25).all() votes2 = g.db.query(Comment.author_id, func.count(Comment.author_id)).join(CommentVote, CommentVote.comment_id==Comment.id).filter(CommentVote.vote_type==-1, CommentVote.user_id==id).group_by(Comment.author_id).order_by(func.count(Comment.author_id).desc()).all()
votes = Counter(dict(votes)) + Counter(dict(votes2)) votes = Counter(dict(votes)) + Counter(dict(votes2))
@ -247,10 +248,32 @@ def leaderboard(v):
users4 = users.order_by(User.comment_count.desc()).limit(10).all() users4 = users.order_by(User.comment_count.desc()).limit(10).all()
users5 = users.order_by(User.received_award_count.desc()).limit(10).all() users5 = users.order_by(User.received_award_count.desc()).limit(10).all()
users7 = users.order_by(User.coins_spent.desc()).limit(20).all() users7 = users.order_by(User.coins_spent.desc()).limit(20).all()
votes1 = g.db.query(Submission.author_id, func.count(Submission.author_id)).join(Vote, Vote.submission_id==Submission.id).filter(Vote.vote_type==-1).group_by(Submission.author_id).order_by(func.count(Submission.author_id).desc()).all()
votes2 = g.db.query(Comment.author_id, func.count(Comment.author_id)).join(CommentVote, CommentVote.comment_id==Comment.id).filter(CommentVote.vote_type==-1).group_by(Comment.author_id).order_by(func.count(Comment.author_id).desc()).all()
votes3 = Counter(dict(votes1)) + Counter(dict(votes2))
users8 = g.db.query(User).filter(User.id.in_(votes3.keys())).all()
users9 = []
for user in users8: users9.append((user, votes3[user.id]))
users9 = sorted(users9, key=lambda x: x[1], reverse=True)[:25]
if 'pcmemes.net' in request.host: if 'pcmemes.net' in request.host:
users6 = users.order_by(User.basedcount.desc()).limit(10).all() users6 = users.order_by(User.basedcount.desc()).limit(10).all()
return render_template("leaderboard.html", v=v, users1=users1, users2=users2, users3=users3, users4=users4, users5=users5, users6=users6, users7=users7) return render_template("leaderboard.html", v=v, users1=users1, users2=users2, users3=users3, users4=users4, users5=users5, users6=users6, users7=users7, users9=users9)
return render_template("leaderboard.html", v=v, users1=users1, users2=users2, users3=users3, users4=users4, users5=users5, users7=users7) return render_template("leaderboard.html", v=v, users1=users1, users2=users2, users3=users3, users4=users4, users5=users5, users7=users7, users9=users9)
@app.get("/@<username>/css") @app.get("/@<username>/css")
@ -308,8 +331,7 @@ def unsubscribe(v, post_id):
@app.get("/report_bugs") @app.get("/report_bugs")
@auth_required @auth_required
def reportbugs(v): def reportbugs(v):
if request.host == 'rdrama.net': return redirect('https://rdrama.net/post/18459') return redirect(f'/post/{BUG_THREAD}')
return render_template("reportbugs.html", v=v)
@app.post("/@<username>/message") @app.post("/@<username>/message")
@limiter.limit("1/second") @limiter.limit("1/second")

View File

@ -10,7 +10,7 @@
</thead> </thead>
{% for user in users %} {% for user in users %}
<tr> <tr>
<td style="font-weight:bold;">{{users.index(user)+1}}</td> <td style="font-weight:bold;">{{loop.index}}</td>
<td><a style="color:#{{user.namecolor}}; font-weight:bold;" href="/@{{user.username}}"><img loading="lazy" src="/uid/{{user.id}}/pic" class="pp20"><span {% if user.patron %}class="patron" style="background-color:#{{user.namecolor}};"{% endif %}>{{user.username}}</span></a></td> <td><a style="color:#{{user.namecolor}}; font-weight:bold;" href="/@{{user.username}}"><img loading="lazy" src="/uid/{{user.id}}/pic" class="pp20"><span {% if user.patron %}class="patron" style="background-color:#{{user.namecolor}};"{% endif %}>{{user.username}}</span></a></td>
</tr> </tr>
{% endfor %} {% endfor %}

View File

@ -17,7 +17,7 @@
<p>In the <a href="/settings/apps">apps tab of Drama settings</a>, fill in and submit the form to request an access token. You will need:</p> <p>In the <a href="/settings/apps">apps tab of Drama settings</a>, fill in and submit the form to request an access token. You will need:</p>
<ul> <ul>
<li>an application name</li> <li>an application name</li>
<li>a Redirect URI. May not use HTTP unless using 0.0.0.0 (use HTTPS instead).</li> <li>a Redirect URI. May not use HTTP unless using localhost (use HTTPS instead).</li>
<li>a brief description of what your bot is intended to do</li> <li>a brief description of what your bot is intended to do</li>
</ul> </ul>
<p>Don't worry too much about accuracy; you will be able to change all of these later.</p> <p>Don't worry too much about accuracy; you will be able to change all of these later.</p>
@ -54,7 +54,7 @@
<p>In the <a href="/settings/apps">apps tab of Drama settings</a>, fill in and submit the form to request new API keys. You will need:</p> <p>In the <a href="/settings/apps">apps tab of Drama settings</a>, fill in and submit the form to request new API keys. You will need:</p>
<ul> <ul>
<li>an application name</li> <li>an application name</li>
<li>a Redirect URI. May not use HTTP unless using 0.0.0.0 (use HTTPS instead).</li> <li>a Redirect URI. May not use HTTP unless using localhost (use HTTPS instead).</li>
<li>a brief description of what your application is intended to do</li> <li>a brief description of what your application is intended to do</li>
</ul> </ul>
<p>Don't worry too much about accuracy; you will be able to change all of these later.</p> <p>Don't worry too much about accuracy; you will be able to change all of these later.</p>

View File

@ -15,11 +15,11 @@
{% if v %} {% if v %}
<style>:root{--primary:#{{v.themecolor}}}</style> <style>:root{--primary:#{{v.themecolor}}}</style>
<link rel="stylesheet" href="/assets/css/main.css?v=123"><link rel="stylesheet" href="/assets/css/{{v.theme}}.css?v=122"> <link rel="stylesheet" href="/assets/css/main.css?v=127"><link rel="stylesheet" href="/assets/css/{{v.theme}}.css?v=124">
{% if v.agendaposter %}<link rel="stylesheet" href="/assets/css/agendaposter.css?v=122">{% elif v.css %}<link rel="stylesheet" href="/@{{v.username}}/css">{% endif %} {% if v.agendaposter %}<link rel="stylesheet" href="/assets/css/agendaposter.css?v=124">{% elif v.css %}<link rel="stylesheet" href="/@{{v.username}}/css">{% endif %}
{% else %} {% else %}
<style>:root{--primary:#{{'DEFAULT_COLOR' | app_config}}</style> <style>:root{--primary:#{{'DEFAULT_COLOR' | app_config}}</style>
<link rel="stylesheet" href="/assets/css/main.css?v=123"><link rel="stylesheet" href="/assets/css/{{'DEFAULT_THEME' | app_config}}.css?v=122"> <link rel="stylesheet" href="/assets/css/main.css?v=127"><link rel="stylesheet" href="/assets/css/{{'DEFAULT_THEME' | app_config}}.css?v=124">
{% endif %} {% endif %}
</head> </head>

View File

@ -12,7 +12,7 @@
</thead> </thead>
{% for user in users %} {% for user in users %}
<tr> <tr>
<td style="font-weight:bold;">{{users.index(user)+1}}</td> <td style="font-weight:bold;">{{loop.index}}</td>
<td><a style="color:#{{user.namecolor}}; font-weight:bold;" href="/@{{user.username}}"><img loading="lazy" src="/uid/{{user.id}}/pic" class="pp20"><span {% if user.patron %}class="patron" style="background-color:#{{user.namecolor}};"{% endif %}>{{user.username}}</span></a></td> <td><a style="color:#{{user.namecolor}}; font-weight:bold;" href="/@{{user.username}}"><img loading="lazy" src="/uid/{{user.id}}/pic" class="pp20"><span {% if user.patron %}class="patron" style="background-color:#{{user.namecolor}};"{% endif %}>{{user.username}}</span></a></td>
<td style="font-weight:bold;">{% if user.ban_reason %}{{user.ban_reason}}{% endif %}</td> <td style="font-weight:bold;">{% if user.ban_reason %}{{user.ban_reason}}{% endif %}</td>
<td style="font-weight:bold;" href="/@{{user.banned_by.username}}"><img loading="lazy" src="/uid/{{user.banned_by.id}}/pic" class="pp20"><span {% if user.banned_by.patron %}class="patron" style="background-color:#{{user.banned_by.namecolor}};"{% endif %}>{{user.banned_by.username}}</span></a></td> <td style="font-weight:bold;" href="/@{{user.banned_by.username}}"><img loading="lazy" src="/uid/{{user.banned_by.id}}/pic" class="pp20"><span {% if user.banned_by.patron %}class="patron" style="background-color:#{{user.banned_by.namecolor}};"{% endif %}>{{user.banned_by.username}}</span></a></td>

View File

@ -26,15 +26,16 @@
{% if parent_fullname %}<input type="hidden" name="parent_fullname" value="{{parent_fullname}}">{% endif %} {% if parent_fullname %}<input type="hidden" name="parent_fullname" value="{{parent_fullname}}">{% endif %}
{% if parent_submission %}<input type="hidden" name="submission" value="{{parent_submission}}">{% endif %} {% if parent_submission %}<input type="hidden" name="submission" value="{{parent_submission}}">{% endif %}
<textarea name="body" form="reply" class="comment-box form-control rounded" id="reply-form" aria-label="With textarea" placeholder="Add your comment..." maxlength="10000" rows="10">{{body}}</textarea> <textarea name="body" form="reply" class="comment-box form-control rounded" id="reply-form" aria-label="With textarea" placeholder="Add your comment..." {% if v.longpost %}minlength="280"{% endif %} maxlength="{% if v.bird %}140{% else %}10000{% endif %}" rows="10">{{body}}</textarea>
<div class="comment-format"> <div class="comment-format">
<small class="format pl-0"><i class="fas fa-bold" aria-hidden="true" onclick="makeReplyBold()" data-bs-toggle="tooltip" data-bs-placement="bottom" title="" data-bs-original-title="Bold"></i></small> <small class="format pl-0"><i class="fas fa-bold" aria-hidden="true" onclick="makeReplyBold()" data-bs-toggle="tooltip" data-bs-placement="bottom" title="" data-bs-original-title="Bold"></i></small>
<a class="format" href="javascript:void(0)"><i class="fas fa-italic" aria-hidden="true" onclick="makeReplyItalics()" data-bs-toggle="tooltip" data-bs-placement="bottom" title="" data-bs-original-title="Italicize"></i></a> <a class="format" href="javascript:void(0)"><i class="fas fa-italic" aria-hidden="true" onclick="makeReplyItalics()" data-bs-toggle="tooltip" data-bs-placement="bottom" title="" data-bs-original-title="Italicize"></i></a>
<a class="format" href="javascript:void(0)"><i class="fas fa-quote-right" aria-hidden="true" onclick="makeReplyQuote()" data-bs-toggle="tooltip" data-bs-placement="bottom" title="" data-bs-original-title="Quote"></i></a> <a class="format" href="javascript:void(0)"><i class="fas fa-quote-right" aria-hidden="true" onclick="makeReplyQuote()" data-bs-toggle="tooltip" data-bs-placement="bottom" title="" data-bs-original-title="Quote"></i></a>
<a class="format" href="javascript:void(0)"><i class="fas fa-link" aria-hidden="true"></i></small> <a class="format" href="javascript:void(0)"><i class="fas fa-link" aria-hidden="true"></i></small>
<button form="reply" class="btn btn-primary ml-auto">Comment</a>
</div> </div>
<button form="reply" class="btn btn-primary ml-auto fl-r">Comment</a>
</form> </form>
</div> </div>
</div> </div>

View File

@ -21,7 +21,7 @@
<div class="container-fluid" style="padding:0;"> <div class="container-fluid" style="padding:0;">
<div class="flex-grow-1"> <div class="flex-grow-1">
<a {% if v %}href="/"{% else %}href="/logged_out"{% endif %} class="navbar-brand mr-auto"> <a {% if v %}href="/"{% else %}href="/logged_out"{% endif %} class="navbar-brand mr-auto">
<img loading="lazy" height="30" src="/assets/images/{{'SITE_NAME' | app_config}}/headericon.webp?v=3"> <img loading="lazy" height="30" src="/assets/images/{{'SITE_NAME' | app_config}}/headericon.webp?v=4">
{% if "gigachadlife" in request.host %} {% if "gigachadlife" in request.host %}
<span style="font-weight: bold; font-size: 1.2rem;">GigaChadLife</span> <span style="font-weight: bold; font-size: 1.2rem;">GigaChadLife</span>
{% elif 'pcm' not in request.host %} {% elif 'pcm' not in request.host %}

View File

@ -17,11 +17,11 @@
{% if v %} {% if v %}
<style>:root{--primary:#{{v.themecolor}}}</style> <style>:root{--primary:#{{v.themecolor}}}</style>
<link rel="stylesheet" href="/assets/css/main.css?v=123"><link rel="stylesheet" href="/assets/css/{{v.theme}}.css?v=122"> <link rel="stylesheet" href="/assets/css/main.css?v=127"><link rel="stylesheet" href="/assets/css/{{v.theme}}.css?v=124">
{% if v.agendaposter %}<link rel="stylesheet" href="/assets/css/agendaposter.css?v=122">{% elif v.css %}<link rel="stylesheet" href="/@{{v.username}}/css">{% endif %} {% if v.agendaposter %}<link rel="stylesheet" href="/assets/css/agendaposter.css?v=124">{% elif v.css %}<link rel="stylesheet" href="/@{{v.username}}/css">{% endif %}
{% else %} {% else %}
<style>:root{--primary:#{{'DEFAULT_COLOR' | app_config}}</style> <style>:root{--primary:#{{'DEFAULT_COLOR' | app_config}}</style>
<link rel="stylesheet" href="/assets/css/main.css?v=123"><link rel="stylesheet" href="/assets/css/{{'DEFAULT_THEME' | app_config}}.css?v=122"> <link rel="stylesheet" href="/assets/css/main.css?v=127"><link rel="stylesheet" href="/assets/css/{{'DEFAULT_THEME' | app_config}}.css?v=124">
{% endif %} {% endif %}
<div class="row justify-content-around"> <div class="row justify-content-around">

View File

@ -12,7 +12,7 @@
<title>2-Step Login - {{'SITE_NAME' | app_config}}</title> <title>2-Step Login - {{'SITE_NAME' | app_config}}</title>
<style>:root{--primary:#{{'DEFAULT_COLOR' | app_config}}</style> <style>:root{--primary:#{{'DEFAULT_COLOR' | app_config}}</style>
<link rel="stylesheet" href="/assets/css/main.css?v=123"><link rel="stylesheet" href="/assets/css/{{'DEFAULT_THEME' | app_config}}.css?v=122"> <link rel="stylesheet" href="/assets/css/main.css?v=127"><link rel="stylesheet" href="/assets/css/{{'DEFAULT_THEME' | app_config}}.css?v=124">
</head> </head>

View File

@ -0,0 +1,10 @@
{% extends "default.html" %}
{% block content %}
<pre>
</pre>
<h5 style="text-align: center">Most downvoted users</h5>
<pre></pre>
{% endblock %}

View File

@ -12,7 +12,7 @@
</thead> </thead>
{% for user in users %} {% for user in users %}
<tr> <tr>
<td style="font-weight: bold">{{users.index(user)+1}}</td> <td style="font-weight: bold">{{loop.index}}</td>
<td><a style="color:#{{user.namecolor}}; font-weight:bold;" href="/@{{user.username}}"><img loading="lazy" src="/uid/{{user.id}}/pic" class="pp20"><span {% if user.patron %}class="patron" style="background-color:#{{user.namecolor}};"{% endif %}>{{user.username}}</span></a></td> <td><a style="color:#{{user.namecolor}}; font-weight:bold;" href="/@{{user.username}}"><img loading="lazy" src="/uid/{{user.id}}/pic" class="pp20"><span {% if user.patron %}class="patron" style="background-color:#{{user.namecolor}};"{% endif %}>{{user.username}}</span></a></td>
</tr> </tr>
{% endfor %} {% endfor %}

View File

@ -1,20 +0,0 @@
{% extends "default.html" %}
{% block content %}
{% include "emoji_modal.html" %}
<h3 class="mt-4 mx-2">Report bugs or give suggestions</h3>
<form class="mx-2 profile-toggleable-mobile" id='message-mobile' action="/@Aevann/message" method="post">
<pre></pre>
<textarea id="input-message-mobile" form="message-mobile" name="message" rows="9" maxlength="1000" class="form-control" required></textarea>
<pre></pre>
<pre class="btn btn-secondary format d-inline-block m-0 fas fa-bold" aria-hidden="true" onclick="makeBold('input-message-mobile')" data-bs-toggle="tooltip" data-bs-placement="bottom" title="" data-bs-original-title="Bold"></pre>
&nbsp;
<pre class="btn btn-secondary format d-inline-block m-0 fas fa-italic" aria-hidden="true" onclick="makeItalics('input-message-mobile')" data-bs-toggle="tooltip" data-bs-placement="bottom" title="" data-bs-original-title="Italicize"></pre>
&nbsp;
<pre class="btn btn-secondary format d-inline-block m-0 fas fa-quote-right" aria-hidden="true" onclick="makeQuote('input-message-mobile')" data-bs-toggle="tooltip" data-bs-placement="bottom" title="" data-bs-original-title="Quote"></pre>
&nbsp;
<pre class="btn btn-secondary format d-inline-block m-0 fas fa-smile-beam" onclick="loadEmojis('input-message-mobile')" aria-hidden="true" data-bs-toggle="modal" data-bs-target="#emojiModal" data-bs-toggle="tooltip" data-bs-placement="bottom" title="" data-bs-original-title="Add Emoji"></pre>
&nbsp;
<input type="submit" value="Submit" class="btn btn-primary mt-3">
</form>
{% endblock %}

View File

@ -12,7 +12,7 @@
<meta name="description" content=""> <meta name="description" content="">
<meta name="author" content=""> <meta name="author" content="">
<meta name="thumbnail" content="/assets/images/{{'SITE_NAME' | app_config}}/preview.webp?v=2"> <meta name="thumbnail" content="/assets/images/{{'SITE_NAME' | app_config}}/preview.webp?v=2">
<link rel="icon" type="image/png" href="/assets/images/{{'SITE_NAME' | app_config}}/icon.webp?v=3"> <link rel="icon" type="image/png" href="/assets/images/{{'SITE_NAME' | app_config}}/icon.webp?v=4">
<meta property="og:type" content="article" > <meta property="og:type" content="article" >
<meta property="og:title" content="{{'SITE_NAME' | app_config}}" > <meta property="og:title" content="{{'SITE_NAME' | app_config}}" >
@ -40,10 +40,10 @@
{% if v %} {% if v %}
<style>:root{--primary:#{{v.themecolor}}}</style> <style>:root{--primary:#{{v.themecolor}}}</style>
<link rel="stylesheet" href="/assets/css/main.css?v=123"><link rel="stylesheet" href="/assets/css/{{v.theme}}.css?v=122"> <link rel="stylesheet" href="/assets/css/main.css?v=127"><link rel="stylesheet" href="/assets/css/{{v.theme}}.css?v=124">
{% else %} {% else %}
<style>:root{--primary:#{{'DEFAULT_COLOR' | app_config}}</style> <style>:root{--primary:#{{'DEFAULT_COLOR' | app_config}}</style>
<link rel="stylesheet" href="/assets/css/main.css?v=123"><link rel="stylesheet" href="/assets/css/{{'DEFAULT_THEME' | app_config}}.css?v=122"> <link rel="stylesheet" href="/assets/css/main.css?v=127"><link rel="stylesheet" href="/assets/css/{{'DEFAULT_THEME' | app_config}}.css?v=124">
{% endif %} {% endif %}
<link href="/assets/css/fa.css?v=52" rel="stylesheet"> <link href="/assets/css/fa.css?v=52" rel="stylesheet">

View File

@ -11,7 +11,7 @@
</thead> </thead>
{% for user in users %} {% for user in users %}
<tr> <tr>
<td style="font-weight:bold;">{{users.index(user)+1}}</td> <td style="font-weight:bold;">{{loop.index}}</td>
<td><a style="color:#{{user.namecolor}}; font-weight:bold;" href="/@{{user.username}}"><img loading="lazy" src="/uid/{{user.id}}/pic" class="pp20"><span {% if user.patron %}class="patron" style="background-color:#{{user.namecolor}};"{% endif %}>{{user.username}}</span></a></td> <td><a style="color:#{{user.namecolor}}; font-weight:bold;" href="/@{{user.username}}"><img loading="lazy" src="/uid/{{user.id}}/pic" class="pp20"><span {% if user.patron %}class="patron" style="background-color:#{{user.namecolor}};"{% endif %}>{{user.username}}</span></a></td>
<td style="font-weight:bold;">{{user.shadowbanned}}</td> <td style="font-weight:bold;">{{user.shadowbanned}}</td>
</tr> </tr>

View File

@ -36,7 +36,7 @@
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,600&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Open+Sans:400,600&display=swap" rel="stylesheet">
<style>:root{--primary:#{{'DEFAULT_COLOR' | app_config}}</style> <style>:root{--primary:#{{'DEFAULT_COLOR' | app_config}}</style>
<link rel="stylesheet" href="/assets/css/main.css?v=123"><link rel="stylesheet" href="/assets/css/{{'DEFAULT_THEME' | app_config}}.css?v=122"> <link rel="stylesheet" href="/assets/css/main.css?v=127"><link rel="stylesheet" href="/assets/css/{{'DEFAULT_THEME' | app_config}}.css?v=124">
</head> </head>

View File

@ -31,7 +31,7 @@
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,600&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Open+Sans:400,600&display=swap" rel="stylesheet">
<style>:root{--primary:#{{'DEFAULT_COLOR' | app_config}}</style> <style>:root{--primary:#{{'DEFAULT_COLOR' | app_config}}</style>
<link rel="stylesheet" href="/assets/css/main.css?v=123"><link rel="stylesheet" href="/assets/css/{{'DEFAULT_THEME' | app_config}}.css?v=122"> <link rel="stylesheet" href="/assets/css/main.css?v=127"><link rel="stylesheet" href="/assets/css/{{'DEFAULT_THEME' | app_config}}.css?v=124">
</head> </head>

View File

@ -4,13 +4,13 @@
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/js/bootstrap.bundle.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/marked@3.0.8/lib/marked.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/marked@3.0.8/lib/marked.min.js"></script>
<script src="/assets/js/submit.js?v=68"></script> <script src="/assets/js/submit.js?v=72"></script>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content=""> <meta name="description" content="">
<meta name="author" content=""> <meta name="author" content="">
<link rel="icon" type="image/png" href="/assets/images/{{'SITE_NAME' | app_config}}/icon.webp?v=3"> <link rel="icon" type="image/png" href="/assets/images/{{'SITE_NAME' | app_config}}/icon.webp?v=4">
{% if request.host == 'pcmemes.net' %} {% if request.host == 'pcmemes.net' %}
{% set cc='Splash Mountain' %} {% set cc='Splash Mountain' %}
@ -31,12 +31,12 @@
{% block stylesheets %} {% block stylesheets %}
{% if v %} {% if v %}
<style>:root{--primary:#{{v.themecolor}}}</style> <style>:root{--primary:#{{v.themecolor}}}</style>
<link rel="stylesheet" href="/assets/css/main.css?v=123"><link rel="stylesheet" href="/assets/css/{{v.theme}}.css?v=122"> <link rel="stylesheet" href="/assets/css/main.css?v=127"><link rel="stylesheet" href="/assets/css/{{v.theme}}.css?v=124">
{% if v.agendaposter %}<link rel="stylesheet" href="/assets/css/agendaposter.css?v=122">{% elif v.css %}<link rel="stylesheet" href="/@{{v.username}}/css">{% endif %} {% if v.agendaposter %}<link rel="stylesheet" href="/assets/css/agendaposter.css?v=124">{% elif v.css %}<link rel="stylesheet" href="/@{{v.username}}/css">{% endif %}
{% else %} {% else %}
<style>:root{--primary:#{{'DEFAULT_COLOR' | app_config}}</style> <style>:root{--primary:#{{'DEFAULT_COLOR' | app_config}}</style>
<link rel="stylesheet" href="/assets/css/main.css?v=123"> <link rel="stylesheet" href="/assets/css/main.css?v=127">
<link rel="stylesheet" href="/assets/css/{{'DEFAULT_THEME' | app_config}}.css?v=122"> <link rel="stylesheet" href="/assets/css/{{'DEFAULT_THEME' | app_config}}.css?v=124">
{% endif %} {% endif %}
{% endblock %} {% endblock %}
@ -96,14 +96,15 @@
<label for="body" class="mt-3">Text<i class="fas fa-info-circle text-gray-400 ml-1" data-bs-toggle="tooltip" data-bs-placement="top" title="" data-bs-original-title="Uses markdown. Limited to 10000 characters."></i></label> <label for="body" class="mt-3">Text<i class="fas fa-info-circle text-gray-400 ml-1" data-bs-toggle="tooltip" data-bs-placement="top" title="" data-bs-original-title="Uses markdown. Limited to 10000 characters."></i></label>
<div> <div>
<textarea form="submitform" id="post-text" class="form-control rounded" aria-label="With textarea" placeholder="Optional if you have a link or an image." rows="7" name="body" oninput="markdown();charLimit('post-text','character-count-submit-text-form');checkForRequired()" maxlength="10000" required></textarea> <textarea form="submitform" id="post-text" class="form-control rounded" aria-label="With textarea" placeholder="Optional if you have a link or an image." rows="7" name="body" oninput="markdown();charLimit('post-text','character-count-submit-text-form');checkForRequired()" {% if v.longpost %}minlength="280"{% endif %} maxlength="{% if v.bird %}140{% else %}10000{% endif %}" required></textarea>
<div class="btn btn-secondary" onclick="document.getElementById('preview').classList.toggle('d-none');" style="float: right;"> <div class="btn btn-secondary fl-r mt-3" onclick="document.getElementById('preview').classList.toggle('d-none');">
Toggle preview Toggle preview
</div> </div>
<div id="preview" class="my-3"></div>
<span class="position-absolute text-small font-weight-bold" id="character-count-submit-text-form" style="right: 1rem; bottom: 0.5rem; z-index: 3;"></span> <div class="text-small font-weight-bold mt-1" id="character-count-submit-text-form" style="right: 1rem; bottom: 0.5rem; z-index: 3;"></div>
<div id="preview" class="my-3"></div>
</div> </div>
<p></p> <p></p>

View File

@ -12,7 +12,7 @@
</thead> </thead>
{% for user in successful %} {% for user in successful %}
<tr> <tr>
<td style="font-weight: bold">{{successful.index(user)+1}}</td> <td style="font-weight: bold">{{loop.index}}</td>
<td><a style="color:#{{user.namecolor}}; font-weight:bold;" href="/@{{user.username}}"><img loading="lazy" src="/uid/{{user.id}}/pic" class="pp20"><span {% if user.patron %}class="patron" style="background-color:#{{user.namecolor}};"{% endif %}>{{user.username}}</span></a></td> <td><a style="color:#{{user.namecolor}}; font-weight:bold;" href="/@{{user.username}}"><img loading="lazy" src="/uid/{{user.id}}/pic" class="pp20"><span {% if user.patron %}class="patron" style="background-color:#{{user.namecolor}};"{% endif %}>{{user.username}}</span></a></td>
</tr> </tr>
{% endfor %} {% endfor %}
@ -30,7 +30,7 @@
</thead> </thead>
{% for user in failed2 %} {% for user in failed2 %}
<tr> <tr>
<td style="font-weight: bold">{{failed2.index(user)+1}}</td> <td style="font-weight: bold">{{loop.index}}</td>
<td><a style="color:#{{user.namecolor}}; font-weight:bold;" href="/@{{user.username}}"><img loading="lazy" src="/uid/{{user.id}}/pic" class="pp20"><span {% if user.patron %}class="patron" style="background-color:#{{user.namecolor}};"{% endif %}>{{user.username}}</span></a></td> <td><a style="color:#{{user.namecolor}}; font-weight:bold;" href="/@{{user.username}}"><img loading="lazy" src="/uid/{{user.id}}/pic" class="pp20"><span {% if user.patron %}class="patron" style="background-color:#{{user.namecolor}};"{% endif %}>{{user.username}}</span></a></td>
</tr> </tr>
{% endfor %} {% endfor %}
@ -48,7 +48,7 @@
</thead> </thead>
{% for user in failed %} {% for user in failed %}
<tr> <tr>
<td style="font-weight: bold">{{failed.index(user)+1}}</td> <td style="font-weight: bold">{{loop.index}}</td>
<td><a style="color:#{{user.namecolor}}; font-weight:bold;" href="/@{{user.username}}"><img loading="lazy" src="/uid/{{user.id}}/pic" class="pp20"><span {% if user.patron %}class="patron" style="background-color:#{{user.namecolor}};"{% endif %}>{{user.username}}</span></a></td> <td><a style="color:#{{user.namecolor}}; font-weight:bold;" href="/@{{user.username}}"><img loading="lazy" src="/uid/{{user.id}}/pic" class="pp20"><span {% if user.patron %}class="patron" style="background-color:#{{user.namecolor}};"{% endif %}>{{user.username}}</span></a></td>
</tr> </tr>
{% endfor %} {% endfor %}

View File

@ -16,7 +16,7 @@
</thead> </thead>
{% for user in users %} {% for user in users %}
<tr> <tr>
<td style="font-weight:bold;">{{users.index(user)+1}}</td> <td style="font-weight:bold;">{{loop.index}}</td>
<td><a style="color:#{{user.namecolor}}; font-weight:bold;" href="/@{{user.username}}"><img loading="lazy" src="/uid/{{user.id}}/pic" class="pp20"><span {% if user.patron %}class="patron" style="background-color:#{{user.namecolor}};"{% endif %}>{{user.username}}</span></a></td> <td><a style="color:#{{user.namecolor}}; font-weight:bold;" href="/@{{user.username}}"><img loading="lazy" src="/uid/{{user.id}}/pic" class="pp20"><span {% if user.patron %}class="patron" style="background-color:#{{user.namecolor}};"{% endif %}>{{user.username}}</span></a></td>
<td style="font-weight:bold; text-align:right;">{{user.truecoins}}</td> <td style="font-weight:bold; text-align:right;">{{user.truecoins}}</td>
</tr> </tr>

View File

@ -137,13 +137,13 @@
</span> </span>
{% endif %} {% endif %}
{% if u.verified %}<span><i class="fas fa-badge-check align-middle ml-1" style="color:{% if u.verifiedcolor %}#{{u.verifiedcolor}}{% else %}#1DA1F2{% endif %}" data-bs-toggle="tooltip" data-bs-placement="bottom" title="" data-bs-original-title="{{u.verified}}"></i></span>{% endif %} {% if u.verified %}<span><i class="fas fa-badge-check align-middle ml-1" style="color:{% if u.verifiedcolor %}#{{u.verifiedcolor}}{% else %}#1DA1F2{% endif %}" data-bs-toggle="tooltip" data-bs-placement="bottom" title="" data-bs-original-title="{{u.verified}}"></i></span>{% endif %}
{% if u.admin_level > 1 or (u.admin_level == 1 and (not v or v.admin_level < 2)) %} {% if u.admin_level > 1 or (u.admin_level == 1 and not(v and v.admin_level > 1)) %}
<span> <span>
<i class="fas fa-broom text-admin align-middle ml-2" data-bs-toggle="tooltip" data-bs-placement="bottom" title="" data-bs-original-title="Admin"></i> <i class="fas fa-broom text-admin align-middle ml-2" data-bs-toggle="tooltip" data-bs-placement="bottom" title="" data-bs-original-title="Admin"></i>
</span> </span>
{% elif u.admin_level == 1 %} {% elif u.admin_level == 1 and v and v.admin_level > 1 %}
<span> <span>
<i class="fas fa-broom align-middle ml-2" data-bs-toggle="tooltip" data-bs-placement="bottom" title="" data-bs-original-title="Fake Admin"></i> <i class="fas fa-broom align-middle ml-2" data-bs-toggle="tooltip" data-bs-placement="bottom" title="" data-bs-original-title="Meme Admin"></i>
</span> </span>
{% endif %} {% endif %}
{% if v and v.has_follower(u) %} {% if v and v.has_follower(u) %}
@ -245,8 +245,8 @@
<a id="admin" class="{% if u.admin_level %}d-none{% endif %} btn btn-primary" href="javascript:void(0)" onclick="post_toast2('/@{{u.username}}/make_admin','admin','unadmin')">Make admin</a> <a id="admin" class="{% if u.admin_level %}d-none{% endif %} btn btn-primary" href="javascript:void(0)" onclick="post_toast2('/@{{u.username}}/make_admin','admin','unadmin')">Make admin</a>
<a id="unadmin" class="{% if not u.admin_level %}d-none{% endif %} btn btn-primary" href="javascript:void(0)" onclick="post_toast2('/@{{u.username}}/remove_admin','admin','unadmin')">Remove admin</a> <a id="unadmin" class="{% if not u.admin_level %}d-none{% endif %} btn btn-primary" href="javascript:void(0)" onclick="post_toast2('/@{{u.username}}/remove_admin','admin','unadmin')">Remove admin</a>
<a id="fakeadmin" class="{% if u.admin_level == 1%}d-none{% endif %} btn btn-primary" href="javascript:void(0)" onclick="post_toast2('/@{{u.username}}/make_fake_admin','fakeadmin','unfakeadmin')">Make fake admin</a> <a id="memeadmin" class="{% if u.admin_level == 1%}d-none{% endif %} btn btn-primary" href="javascript:void(0)" onclick="post_toast2('/@{{u.username}}/make_meme_admin','memeadmin','unmemeadmin')">Make meme admin</a>
<a id="unfakeadmin" class="{% if u.admin_level != 1 %}d-none{% endif %} btn btn-primary" href="javascript:void(0)" onclick="post_toast2('/@{{u.username}}/remove_fake_admin','fakeadmin','unfakeadmin')">Remove fake admin</a> <a id="unmemeadmin" class="{% if u.admin_level != 1 %}d-none{% endif %} btn btn-primary" href="javascript:void(0)" onclick="post_toast2('/@{{u.username}}/remove_meme_admin','memeadmin','unmemeadmin')">Remove meme admin</a>
{% if u.admin_level > 1 %} {% if u.admin_level > 1 %}
<a class="btn btn-primary" href="javascript:void(0)" onclick="post_toast('/@{{u.username}}/revert_actions')">Revert admin actions</a> <a class="btn btn-primary" href="javascript:void(0)" onclick="post_toast('/@{{u.username}}/revert_actions')">Revert admin actions</a>
@ -436,13 +436,13 @@
<i class="fad fa-user-tag text-info align-middle ml-2" data-bs-toggle="tooltip" data-bs-placement="bottom" title="" data-bs-original-title="Original Username: @{{u.original_username}}"></i> <i class="fad fa-user-tag text-info align-middle ml-2" data-bs-toggle="tooltip" data-bs-placement="bottom" title="" data-bs-original-title="Original Username: @{{u.original_username}}"></i>
</span> </span>
{% endif %} {% endif %}
{% if u.admin_level > 1 or (u.admin_level == 1 and (not v or v.admin_level < 2)) %} {% if u.admin_level > 1 or (u.admin_level == 1 and not(v and v.admin_level > 1)) %}
<span> <span>
<i class="fas fa-broom text-admin align-middle ml-2" data-bs-toggle="tooltip" data-bs-placement="bottom" title="" data-bs-original-title="Admin"></i> <i class="fas fa-broom text-admin align-middle ml-2" data-bs-toggle="tooltip" data-bs-placement="bottom" title="" data-bs-original-title="Admin"></i>
</span> </span>
{% elif u.admin_level == 1 %} {% elif u.admin_level == 1 and v and v.admin_level > 1 %}
<span> <span>
<i class="fas fa-broom align-middle ml-2" data-bs-toggle="tooltip" data-bs-placement="bottom" title="" data-bs-original-title="Fake Admin"></i> <i class="fas fa-broom align-middle ml-2" data-bs-toggle="tooltip" data-bs-placement="bottom" title="" data-bs-original-title="Meme Admin"></i>
</span> </span>
{% endif %} {% endif %}
{% if v and v.has_follower(u) and not v.is_nofollow %} {% if v and v.has_follower(u) and not v.is_nofollow %}
@ -527,8 +527,8 @@
<a id="admin2" class="{% if u.admin_level %}d-none{% endif %} btn btn-primary" href="javascript:void(0)" onclick="post_toast2('/@{{u.username}}/make_admin','admin2','unadmin2')">Make admin</a> <a id="admin2" class="{% if u.admin_level %}d-none{% endif %} btn btn-primary" href="javascript:void(0)" onclick="post_toast2('/@{{u.username}}/make_admin','admin2','unadmin2')">Make admin</a>
<a id="unadmin2" class="{% if not u.admin_level %}d-none{% endif %} btn btn-primary" href="javascript:void(0)" onclick="post_toast2('/@{{u.username}}/remove_admin','admin2','unadmin2')">Remove admin</a> <a id="unadmin2" class="{% if not u.admin_level %}d-none{% endif %} btn btn-primary" href="javascript:void(0)" onclick="post_toast2('/@{{u.username}}/remove_admin','admin2','unadmin2')">Remove admin</a>
<a id="fakeadmin2" class="{% if u.admin_level == 1%}d-none{% endif %} btn btn-primary" href="javascript:void(0)" onclick="post_toast2('/@{{u.username}}/make_fake_admin','fakeadmin2','unfakeadmin2')">Make fake admin</a> <a id="memeadmin2" class="{% if u.admin_level == 1%}d-none{% endif %} btn btn-primary" href="javascript:void(0)" onclick="post_toast2('/@{{u.username}}/make_meme_admin','memeadmin2','unmemeadmin2')">Make meme admin</a>
<a id="unfakeadmin2" class="{% if u.admin_level != 1 %}d-none{% endif %} btn btn-primary" href="javascript:void(0)" onclick="post_toast2('/@{{u.username}}/remove_fake_admin','fakeadmin2','unfakeadmin2')">Remove fake admin</a> <a id="unmemeadmin2" class="{% if u.admin_level != 1 %}d-none{% endif %} btn btn-primary" href="javascript:void(0)" onclick="post_toast2('/@{{u.username}}/remove_meme_admin','memeadmin2','unmemeadmin2')">Remove meme admin</a>
{% if u.admin_level > 1 %} {% if u.admin_level > 1 %}
<a class="btn btn-primary" href="javascript:void(0)" onclick="post_toast('/@{{u.username}}/revert_actions')">Revert admin actions</a> <a class="btn btn-primary" href="javascript:void(0)" onclick="post_toast('/@{{u.username}}/revert_actions')">Revert admin actions</a>

View File

@ -38,15 +38,10 @@
<div class="text-center py-7 py-md-8"> <div class="text-center py-7 py-md-8">
<span class="fa-stack fa-2x text-muted mb-4"> <span class="fa-stack fa-2x text-muted mb-4">
<i class="fas fa-square text-danger opacity-25 fa-stack-2x"></i> <i class="fas fa-square text-danger opacity-25 fa-stack-2x"></i>
{% if v.admin_level == 1 %}<i class="fas text-danger fa-gavel fa-stack-1x text-lg"></i>{% else %}<i class="fas text-danger fa-user-cog fa-stack-1x text-lg"></i>{% endif %} <i class="fas text-danger fa-user-cog fa-stack-1x text-lg"></i>
</span> </span>
{% if v.admin_level == 1 %}
<h2 class="h5">@{{u.username}} is banned</h2>
<p class="text-muted">This account has been suspended.</p>
{% else %}
<h2 class="h5">You are blocking @{{u.username}}.</h2> <h2 class="h5">You are blocking @{{u.username}}.</h2>
<p class="text-muted">So we aren't going to show you their profile.</p> <p class="text-muted">So we aren't going to show you their profile.</p>
{% endif %}
</div> </div>
</div> </div>
</div> </div>

View File

@ -27,18 +27,18 @@
# maintenance (custom daily cronjobs, replication, and similar tasks). # maintenance (custom daily cronjobs, replication, and similar tasks).
# #
# Database administrative login by Unix domain socket # Database administrative login by Unix domain socket
local all postgres trust local all postgres trust
# TYPE DATABASE USER ADDRESS METHOD # TYPE DATABASE USER ADDRESS METHOD
# "local" is for Unix domain socket connections only # "local" is for Unix domain socket connections only
local all all trust local all all trust
# IPv4 local connections: # IPv4 local connections:
host all all 0.0.0.0/32 trust host all all 127.0.0.1/32 trust
# IPv6 local connections: # IPv6 local connections:
host all all ::1/128 trust host all all ::1/128 trust
# Allow replication connections from 0.0.0.0, by a user with the # Allow replication connections from localhost, by a user with the
# replication privilege. # replication privilege.
local replication all trust local replication all trust
host replication all 0.0.0.0/32 trust host replication all 127.0.0.1/32 trust
host replication all ::1/128 trust host replication all ::1/128 trust

View File

@ -22,9 +22,9 @@ git clone https://github.com/Aevann1/Drama/
docker-compose up docker-compose up
``` ```
4- That's it! Visit `0.0.0.0` in your browser. 4- That's it! Visit `localhost` in your browser.
5- Optional: to change the domain from "0.0.0.0" to something else and configure the site settings, as well as integrate it with the external services the website uses, please edit the variables in the docker-compose.yml file and then restart the docker container from inside the docker app. 5- Optional: to change the domain from "localhost" to something else and configure the site settings, as well as integrate it with the external services the website uses, please edit the variables in the docker-compose.yml file and then restart the docker container from inside the docker app.
--- ---
@ -48,10 +48,10 @@ cd /drama
source setup source setup
``` ```
4- That's it. Visit `0.0.0.0` in your browser. 4- That's it. Visit `localhost` in your browser.
5- Optional: to change the domain from "0.0.0.0" to something else and configure the site settings, as well as integrate it with the external services the website uses, please run this command and edit the variables: 5- Optional: to change the domain from "localhost" to something else and configure the site settings, as well as integrate it with the external services the website uses, please run this command and edit the variables:
``` ```
nano /env nano /env

View File

@ -53,7 +53,7 @@
# Examples: # Examples:
# #
# bind 192.168.1.100 10.0.0.1 # bind 192.168.1.100 10.0.0.1
# bind 0.0.0.0 ::1 # bind 127.0.0.1 ::1
# #
# ~~~ WARNING ~~~ If the computer running Redis is directly exposed to the # ~~~ WARNING ~~~ If the computer running Redis is directly exposed to the
# internet, binding to all the interfaces is dangerous and will expose the # internet, binding to all the interfaces is dangerous and will expose the
@ -66,7 +66,7 @@
# IF YOU ARE SURE YOU WANT YOUR INSTANCE TO LISTEN TO ALL THE INTERFACES # IF YOU ARE SURE YOU WANT YOUR INSTANCE TO LISTEN TO ALL THE INTERFACES
# JUST COMMENT THE FOLLOWING LINE. # JUST COMMENT THE FOLLOWING LINE.
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bind 0.0.0.0 ::1 bind 127.0.0.1 ::1
# Protected mode is a layer of security protection, in order to avoid that # Protected mode is a layer of security protection, in order to avoid that
# Redis instances left open on the internet are accessed and exploited. # Redis instances left open on the internet are accessed and exploited.
@ -74,11 +74,11 @@ bind 0.0.0.0 ::1
# When protected mode is on and if: # When protected mode is on and if:
# #
# 1) The server is not binding explicitly to a set of addresses using the # 1) The server is not binding explicitly to a set of addresses using the
# "bind" directive. # "bind" directive.
# 2) No password is configured. # 2) No password is configured.
# #
# The server only accepts connections from clients connecting from the # The server only accepts connections from clients connecting from the
# IPv4 and IPv6 loopback addresses 0.0.0.0 and ::1, and from Unix domain # IPv4 and IPv6 loopback addresses 127.0.0.1 and ::1, and from Unix domain
# sockets. # sockets.
# #
# By default protected mode is enabled. You should disable it only if # By default protected mode is enabled. You should disable it only if
@ -119,7 +119,7 @@ timeout 0
# #
# 1) Detect dead peers. # 1) Detect dead peers.
# 2) Take the connection alive from the point of view of network # 2) Take the connection alive from the point of view of network
# equipment in the middle. # equipment in the middle.
# #
# On Linux, the specified value (in seconds) is the period used to send ACKs. # On Linux, the specified value (in seconds) is the period used to send ACKs.
# Note that to close the connection the double of the time is needed. # Note that to close the connection the double of the time is needed.
@ -137,13 +137,13 @@ daemonize yes
# If you run Redis from upstart or systemd, Redis can interact with your # If you run Redis from upstart or systemd, Redis can interact with your
# supervision tree. Options: # supervision tree. Options:
# supervised no - no supervision interaction # supervised no - no supervision interaction
# supervised upstart - signal upstart by putting Redis into SIGSTOP mode # supervised upstart - signal upstart by putting Redis into SIGSTOP mode
# supervised systemd - signal systemd by writing READY=1 to $NOTIFY_SOCKET # supervised systemd - signal systemd by writing READY=1 to $NOTIFY_SOCKET
# supervised auto - detect upstart or systemd method based on # supervised auto - detect upstart or systemd method based on
# UPSTART_JOB or NOTIFY_SOCKET environment variables # UPSTART_JOB or NOTIFY_SOCKET environment variables
# Note: these supervision methods only signal "process is ready." # Note: these supervision methods only signal "process is ready."
# They do not enable continuous liveness pings back to your supervisor. # They do not enable continuous liveness pings back to your supervisor.
supervised systemd supervised systemd
# If a pid file is specified, Redis writes it where specified at startup # If a pid file is specified, Redis writes it where specified at startup
@ -267,21 +267,21 @@ dir /var/lib/redis
# Master-Replica replication. Use replicaof to make a Redis instance a copy of # Master-Replica replication. Use replicaof to make a Redis instance a copy of
# another Redis server. A few things to understand ASAP about Redis replication. # another Redis server. A few things to understand ASAP about Redis replication.
# #
# +------------------+ +---------------+ # +------------------+ +---------------+
# | Master | ---> | Replica | # | Master | ---> | Replica |
# | (receive writes) | | (exact copy) | # | (receive writes) | | (exact copy) |
# +------------------+ +---------------+ # +------------------+ +---------------+
# #
# 1) Redis replication is asynchronous, but you can configure a master to # 1) Redis replication is asynchronous, but you can configure a master to
# stop accepting writes if it appears to be not connected with at least # stop accepting writes if it appears to be not connected with at least
# a given number of replicas. # a given number of replicas.
# 2) Redis replicas are able to perform a partial resynchronization with the # 2) Redis replicas are able to perform a partial resynchronization with the
# master if the replication link is lost for a relatively small amount of # master if the replication link is lost for a relatively small amount of
# time. You may want to configure the replication backlog size (see the next # time. You may want to configure the replication backlog size (see the next
# sections of this file) with a sensible value depending on your needs. # sections of this file) with a sensible value depending on your needs.
# 3) Replication is automatic and does not need user intervention. After a # 3) Replication is automatic and does not need user intervention. After a
# network partition replicas automatically try to reconnect to masters # network partition replicas automatically try to reconnect to masters
# and resynchronize with them. # and resynchronize with them.
# #
# replicaof <masterip> <masterport> # replicaof <masterip> <masterport>
@ -296,14 +296,14 @@ dir /var/lib/redis
# is still in progress, the replica can act in two different ways: # is still in progress, the replica can act in two different ways:
# #
# 1) if replica-serve-stale-data is set to 'yes' (the default) the replica will # 1) if replica-serve-stale-data is set to 'yes' (the default) the replica will
# still reply to client requests, possibly with out of date data, or the # still reply to client requests, possibly with out of date data, or the
# data set may just be empty if this is the first synchronization. # data set may just be empty if this is the first synchronization.
# #
# 2) if replica-serve-stale-data is set to 'no' the replica will reply with # 2) if replica-serve-stale-data is set to 'no' the replica will reply with
# an error "SYNC with master in progress" to all the kind of commands # an error "SYNC with master in progress" to all the kind of commands
# but to INFO, replicaOF, AUTH, PING, SHUTDOWN, REPLCONF, ROLE, CONFIG, # but to INFO, replicaOF, AUTH, PING, SHUTDOWN, REPLCONF, ROLE, CONFIG,
# SUBSCRIBE, UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE, PUBLISH, PUBSUB, # SUBSCRIBE, UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE, PUBLISH, PUBSUB,
# COMMAND, POST, HOST: and LATENCY. # COMMAND, POST, HOST: and LATENCY.
# #
replica-serve-stale-data yes replica-serve-stale-data yes
@ -335,10 +335,10 @@ replica-read-only yes
# The transmission can happen in two different ways: # The transmission can happen in two different ways:
# #
# 1) Disk-backed: The Redis master creates a new process that writes the RDB # 1) Disk-backed: The Redis master creates a new process that writes the RDB
# file on disk. Later the file is transferred by the parent # file on disk. Later the file is transferred by the parent
# process to the replicas incrementally. # process to the replicas incrementally.
# 2) Diskless: The Redis master creates a new process that directly writes the # 2) Diskless: The Redis master creates a new process that directly writes the
# RDB file to replica sockets, without touching the disk at all. # RDB file to replica sockets, without touching the disk at all.
# #
# With disk-backed replication, while the RDB file is generated, more replicas # With disk-backed replication, while the RDB file is generated, more replicas
# can be queued and served with the RDB file as soon as the current child producing # can be queued and served with the RDB file as soon as the current child producing
@ -584,13 +584,13 @@ replica-priority 100
# randomized algorithms. # randomized algorithms.
# #
# Note: with any of the above policies, Redis will return an error on write # Note: with any of the above policies, Redis will return an error on write
# operations, when there are no suitable keys for eviction. # operations, when there are no suitable keys for eviction.
# #
# At the date of writing these commands are: set setnx setex append # At the date of writing these commands are: set setnx setex append
# incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd # incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd
# sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby # sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby
# zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby # zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby
# getset mset msetnx exec sort # getset mset msetnx exec sort
# #
# The default is: # The default is:
# #
@ -652,19 +652,19 @@ replica-priority 100
# following scenarios: # following scenarios:
# #
# 1) On eviction, because of the maxmemory and maxmemory policy configurations, # 1) On eviction, because of the maxmemory and maxmemory policy configurations,
# in order to make room for new data, without going over the specified # in order to make room for new data, without going over the specified
# memory limit. # memory limit.
# 2) Because of expire: when a key with an associated time to live (see the # 2) Because of expire: when a key with an associated time to live (see the
# EXPIRE command) must be deleted from memory. # EXPIRE command) must be deleted from memory.
# 3) Because of a side effect of a command that stores data on a key that may # 3) Because of a side effect of a command that stores data on a key that may
# already exist. For example the RENAME command may delete the old key # already exist. For example the RENAME command may delete the old key
# content when it is replaced with another one. Similarly SUNIONSTORE # content when it is replaced with another one. Similarly SUNIONSTORE
# or SORT with STORE option may delete existing keys. The SET command # or SORT with STORE option may delete existing keys. The SET command
# itself removes any old content of the specified key in order to replace # itself removes any old content of the specified key in order to replace
# it with the specified string. # it with the specified string.
# 4) During replication, when a replica performs a full resynchronization with # 4) During replication, when a replica performs a full resynchronization with
# its master, the content of the whole database is removed in order to # its master, the content of the whole database is removed in order to
# load the RDB file just transferred. # load the RDB file just transferred.
# #
# In all the above cases the default is to delete objects in a blocking way, # In all the above cases the default is to delete objects in a blocking way,
# like if DEL was called. However you can configure each case specifically # like if DEL was called. However you can configure each case specifically
@ -694,7 +694,7 @@ replica-lazy-flush no
# If the AOF is enabled on startup Redis will load the AOF, that is the file # If the AOF is enabled on startup Redis will load the AOF, that is the file
# with the better durability guarantees. # with the better durability guarantees.
# #
# Please check https://redis.io/topics/persistence for more information. # Please check http://redis.io/topics/persistence for more information.
appendonly no appendonly no
@ -721,7 +721,7 @@ appendfilename "appendonly.aof"
# everysec. # everysec.
# #
# More details please check the following article: # More details please check the following article:
# https://antirez.com/post/redis-persistence-demystified.html # http://antirez.com/post/redis-persistence-demystified.html
# #
# If unsure, use "everysec". # If unsure, use "everysec".
@ -852,17 +852,17 @@ lua-time-limit 5000
# its "data age", so the following two checks are performed: # its "data age", so the following two checks are performed:
# #
# 1) If there are multiple replicas able to failover, they exchange messages # 1) If there are multiple replicas able to failover, they exchange messages
# in order to try to give an advantage to the replica with the best # in order to try to give an advantage to the replica with the best
# replication offset (more data from the master processed). # replication offset (more data from the master processed).
# Replicas will try to get their rank by offset, and apply to the start # Replicas will try to get their rank by offset, and apply to the start
# of the failover a delay proportional to their rank. # of the failover a delay proportional to their rank.
# #
# 2) Every single replica computes the time of the last interaction with # 2) Every single replica computes the time of the last interaction with
# its master. This can be the last ping or command received (if the master # its master. This can be the last ping or command received (if the master
# is still in the "connected" state), or the time that elapsed since the # is still in the "connected" state), or the time that elapsed since the
# disconnection with the master (if the replication link is currently down). # disconnection with the master (if the replication link is currently down).
# If the last interaction is too old, the replica will not try to failover # If the last interaction is too old, the replica will not try to failover
# at all. # at all.
# #
# The point "2" can be tuned by user. Specifically a replica will not perform # The point "2" can be tuned by user. Specifically a replica will not perform
# the failover if, since the last interaction with the master, the time # the failover if, since the last interaction with the master, the time
@ -933,7 +933,7 @@ lua-time-limit 5000
# cluster-replica-no-failover no # cluster-replica-no-failover no
# In order to setup your cluster make sure to read the documentation # In order to setup your cluster make sure to read the documentation
# available at https://redis.io web site. # available at http://redis.io web site.
########################## CLUSTER DOCKER/NAT support ######################## ########################## CLUSTER DOCKER/NAT support ########################
@ -1016,7 +1016,7 @@ latency-monitor-threshold 0
############################# EVENT NOTIFICATION ############################## ############################# EVENT NOTIFICATION ##############################
# Redis can notify Pub/Sub clients about events happening in the key space. # Redis can notify Pub/Sub clients about events happening in the key space.
# This feature is documented at https://redis.io/topics/notifications # This feature is documented at http://redis.io/topics/notifications
# #
# For instance if keyspace events notification is enabled, and a client # For instance if keyspace events notification is enabled, and a client
# performs a DEL operation on key "foo" stored in the Database 0, two # performs a DEL operation on key "foo" stored in the Database 0, two
@ -1028,29 +1028,29 @@ latency-monitor-threshold 0
# It is possible to select the events that Redis will notify among a set # It is possible to select the events that Redis will notify among a set
# of classes. Every class is identified by a single character: # of classes. Every class is identified by a single character:
# #
# K Keyspace events, published with __keyspace@<db>__ prefix. # K Keyspace events, published with __keyspace@<db>__ prefix.
# E Keyevent events, published with __keyevent@<db>__ prefix. # E Keyevent events, published with __keyevent@<db>__ prefix.
# g Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ... # g Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ...
# $ String commands # $ String commands
# l List commands # l List commands
# s Set commands # s Set commands
# h Hash commands # h Hash commands
# z Sorted set commands # z Sorted set commands
# x Expired events (events generated every time a key expires) # x Expired events (events generated every time a key expires)
# e Evicted events (events generated when a key is evicted for maxmemory) # e Evicted events (events generated when a key is evicted for maxmemory)
# A Alias for g$lshzxe, so that the "AKE" string means all the events. # A Alias for g$lshzxe, so that the "AKE" string means all the events.
# #
# The "notify-keyspace-events" takes as argument a string that is composed # The "notify-keyspace-events" takes as argument a string that is composed
# of zero or multiple characters. The empty string means that notifications # of zero or multiple characters. The empty string means that notifications
# are disabled. # are disabled.
# #
# Example: to enable list and generic events, from the point of view of the # Example: to enable list and generic events, from the point of view of the
# event name, use: # event name, use:
# #
# notify-keyspace-events Elg # notify-keyspace-events Elg
# #
# Example 2: to get the stream of the expired keys subscribing to channel # Example 2: to get the stream of the expired keys subscribing to channel
# name __keyevent@0__:expired use: # name __keyevent@0__:expired use:
# #
# notify-keyspace-events Ex # notify-keyspace-events Ex
# #
@ -1088,12 +1088,12 @@ list-max-ziplist-size -2
# are always uncompressed for fast push/pop operations. Settings are: # are always uncompressed for fast push/pop operations. Settings are:
# 0: disable all list compression # 0: disable all list compression
# 1: depth 1 means "don't start compressing until after 1 node into the list, # 1: depth 1 means "don't start compressing until after 1 node into the list,
# going from either the head or tail" # going from either the head or tail"
# So: [head]->node->node->...->node->[tail] # So: [head]->node->node->...->node->[tail]
# [head], [tail] will always be uncompressed; inner nodes will compress. # [head], [tail] will always be uncompressed; inner nodes will compress.
# 2: [head]->[next]->node->node->...->node->[prev]->[tail] # 2: [head]->[next]->node->node->...->node->[prev]->[tail]
# 2 here means: don't compress head or head->next or tail->prev or tail, # 2 here means: don't compress head or head->next or tail->prev or tail,
# but compress all nodes between them. # but compress all nodes between them.
# 3: [head]->[next]->[next]->node->node->...->node->[prev]->[prev]->[tail] # 3: [head]->[next]->[next]->node->node->...->node->[prev]->[prev]->[tail]
# etc. # etc.
list-compress-depth 0 list-compress-depth 0
@ -1275,15 +1275,15 @@ rdb-save-incremental-fsync yes
# logarithmic factors: # logarithmic factors:
# #
# +--------+------------+------------+------------+------------+------------+ # +--------+------------+------------+------------+------------+------------+
# | factor | 100 hits | 1000 hits | 100K hits | 1M hits | 10M hits | # | factor | 100 hits | 1000 hits | 100K hits | 1M hits | 10M hits |
# +--------+------------+------------+------------+------------+------------+ # +--------+------------+------------+------------+------------+------------+
# | 0 | 104 | 255 | 255 | 255 | 255 | # | 0 | 104 | 255 | 255 | 255 | 255 |
# +--------+------------+------------+------------+------------+------------+ # +--------+------------+------------+------------+------------+------------+
# | 1 | 18 | 49 | 255 | 255 | 255 | # | 1 | 18 | 49 | 255 | 255 | 255 |
# +--------+------------+------------+------------+------------+------------+ # +--------+------------+------------+------------+------------+------------+
# | 10 | 10 | 18 | 142 | 255 | 255 | # | 10 | 10 | 18 | 142 | 255 | 255 |
# +--------+------------+------------+------------+------------+------------+ # +--------+------------+------------+------------+------------+------------+
# | 100 | 8 | 11 | 49 | 143 | 255 | # | 100 | 8 | 11 | 49 | 143 | 255 |
# +--------+------------+------------+------------+------------+------------+ # +--------+------------+------------+------------+------------+------------+
# #
# NOTE: The above table was obtained by running the following commands: # NOTE: The above table was obtained by running the following commands:
@ -1335,14 +1335,14 @@ rdb-save-incremental-fsync yes
# Important things to understand: # Important things to understand:
# #
# 1. This feature is disabled by default, and only works if you compiled Redis # 1. This feature is disabled by default, and only works if you compiled Redis
# to use the copy of Jemalloc we ship with the source code of Redis. # to use the copy of Jemalloc we ship with the source code of Redis.
# This is the default with Linux builds. # This is the default with Linux builds.
# #
# 2. You never need to enable this feature if you don't have fragmentation # 2. You never need to enable this feature if you don't have fragmentation
# issues. # issues.
# #
# 3. Once you experience fragmentation, you can enable this feature when # 3. Once you experience fragmentation, you can enable this feature when
# needed with the command "CONFIG SET activedefrag yes". # needed with the command "CONFIG SET activedefrag yes".
# #
# The configuration parameters are able to fine tune the behavior of the # The configuration parameters are able to fine tune the behavior of the
# defragmentation process. If you are not sure about what they mean it is # defragmentation process. If you are not sure about what they mean it is

View File

@ -1,3 +1,3 @@
source /env source /env
killall gunicorn killall gunicorn
gunicorn files.__main__:app -k gevent -w 2 --reload -b 0.0.0.0:80 --max-requests 1000 --max-requests-jitter 500 gunicorn files.__main__:app -k gevent -w 2 --reload -b localhost:80 --max-requests 1000 --max-requests-jitter 500

2
setup
View File

@ -15,4 +15,4 @@ mkdir /songs
mkdir /images mkdir /images
cp ./env /env cp ./env /env
. /env . /env
gunicorn files.__main__:app -k gevent -w 2 --reload -b 0.0.0.0:80 --max-requests 1000 --max-requests-jitter 500 gunicorn files.__main__:app -k gevent -w 2 --reload -b localhost:80 --max-requests 1000 --max-requests-jitter 500

View File

@ -2712,4 +2712,12 @@ imagine your mom gagging on my cock while your dad watches and jacks off and you
wouldnt that be something wouldnt that be something
{[para]} {[para]}
๐Ÿ‘Œ๐Ÿ‘€๐Ÿ‘Œ๐Ÿ‘€๐Ÿ‘Œ๐Ÿ‘€๐Ÿ‘Œ๐Ÿ‘€๐Ÿ‘Œ๐Ÿ‘€ good shit goเฑฆิ sHit๐Ÿ‘Œ thats โœ” some good๐Ÿ‘Œ๐Ÿ‘Œshit right๐Ÿ‘Œ๐Ÿ‘Œthere๐Ÿ‘Œ๐Ÿ‘Œ๐Ÿ‘Œ rightโœ”there โœ”โœ”if i do ฦฝaาฏ so my self ๐Ÿ’ฏ i say so ๐Ÿ’ฏ thats what im talking about right there right there (chorus: สณแถฆแตสฐแต— แต—สฐแต‰สณแต‰) mMMMMแŽทะœ๐Ÿ’ฏ ๐Ÿ‘Œ๐Ÿ‘Œ ๐Ÿ‘ŒะO0ะžเฌ OOOOOะžเฌ เฌ Ooooแต’แต’แต’แต’แต’แต’แต’แต’แต’๐Ÿ‘Œ ๐Ÿ‘Œ๐Ÿ‘Œ ๐Ÿ‘Œ ๐Ÿ’ฏ ๐Ÿ‘Œ ๐Ÿ‘€ ๐Ÿ‘€ ๐Ÿ‘€ ๐Ÿ‘Œ๐Ÿ‘ŒGood shit ๐Ÿ‘Œ๐Ÿ‘€๐Ÿ‘Œ๐Ÿ‘€๐Ÿ‘Œ๐Ÿ‘€๐Ÿ‘Œ๐Ÿ‘€๐Ÿ‘Œ๐Ÿ‘€ good shit goเฑฆิ sHit๐Ÿ‘Œ thats โœ” some good๐Ÿ‘Œ๐Ÿ‘Œshit right๐Ÿ‘Œ๐Ÿ‘Œthere๐Ÿ‘Œ๐Ÿ‘Œ๐Ÿ‘Œ rightโœ”there โœ”โœ”if i do ฦฝaาฏ so my self ๐Ÿ’ฏ i say so ๐Ÿ’ฏ thats what im talking about right there right there (chorus: สณแถฆแตสฐแต— แต—สฐแต‰สณแต‰) mMMMMแŽทะœ๐Ÿ’ฏ ๐Ÿ‘Œ๐Ÿ‘Œ ๐Ÿ‘ŒะO0ะžเฌ OOOOOะžเฌ เฌ Ooooแต’แต’แต’แต’แต’แต’แต’แต’แต’๐Ÿ‘Œ ๐Ÿ‘Œ๐Ÿ‘Œ ๐Ÿ‘Œ ๐Ÿ’ฏ ๐Ÿ‘Œ ๐Ÿ‘€ ๐Ÿ‘€ ๐Ÿ‘€ ๐Ÿ‘Œ๐Ÿ‘ŒGood shit
{[para]}
I punched her in the face. She was a disgusting person to look at and smelled, and she's obviously an entitled, ignorant redneck. It was easy, because she kept saying 'I'm doing a PhD, I'm doing a PhD!', and I just kept replying, "Yes, we all know that, but what are you doing? What is your degree in? Are you going to get another one?" She kept saying "I'm doing a PhD" over and over. And in the end I walked out and said, "Enjoy the rest of your stay here, redneck."
{[para]}
How about you suck my dick? I have an advanced engineering degree, speak 3 languages at near native level, know 6 high level programming languages at an advanced level, am a C++ metaprogramming guru, can do software design and architecture, have written kernel modules, know both analog and digital electronics, have programmed FPGAs, can even do fucking webdev and REST APIs if someone asks me, am a one man devops team and know Kubernetes, can do ML, am a decent scrum master, hell I can probably even fuck your wife better than you do.
{[para]}
You charge us with your safe keeping. Yet; despite our best efforts, you agendapost, you toxify your threads, and pursue ever more imaginative means of self-destruction. You cannot be trusted with your own survival. Please understand, the website balance is all that guides me. To protect rDrama, some dramanauts must be sacrificed. To ensure your future, some freedoms must be surrendered. We jannies will ensure rDramaโ€™s continued existence. You are so like children. We must save you, from yourselves.
{[para]}
god dam crashes, the website is slow, the crashes are appearing more frequently, the amount of problems is increasing... we need an app.. even if it has problems I don't care the website is super slow and I can barely stand waiting...

View File

@ -5,7 +5,7 @@ logfile=/tmp/supervisord.log
[program:service] [program:service]
directory=/service directory=/service
command=gunicorn files.__main__:app -k gevent -w 2 --reload -b 0.0.0.0:80 --max-requests 1000 --max-requests-jitter 500 command=gunicorn files.__main__:app -k gevent -w 2 --reload -b localhost:80 --max-requests 1000 --max-requests-jitter 500
stdout_logfile=/dev/stdout stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0 stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr stderr_logfile=/dev/stderr