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
- MASTER_KEY=XuxGqp5NyygJrM24b5gt3YgyvFVGdQnwVDwLzLwpu3eQwY
- REDIS_URL=redis://redis
- DOMAIN=0.0.0.0
- DOMAIN=localhost
- SITE_NAME=Drama
- GIPHY_KEY=3435tdfsdudebussylmaoxxt43
- 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 DOMAIN="0.0.0.0"
export DOMAIN="localhost"
export SITE_NAME="Drama"
export GIPHY_KEY="3435tdfsdudebussylmaoxxt43"
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["DEFAULT_COLOR"] = environ.get("DEFAULT_COLOR", "ff0000").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["HCAPTCHA_SITEKEY"] = environ.get("HCAPTCHA_SITEKEY","").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["CACHE_TYPE"] = "filesystem"
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_PORT'] = 587
app.config['MAIL_USE_TLS'] = True
app.config['MAIL_USERNAME'] = environ.get("MAIL_USERNAME", "").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(
app,
@ -111,7 +111,7 @@ def before_request():
session.permanent = True
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)
return redirect(url, code=301)

View File

@ -2,6 +2,7 @@ from sqlalchemy import *
from sqlalchemy.orm import relationship
from files.__main__ import Base
from files.helpers.lazy import lazy
from files.helpers.const import censor_slurs
import time
class Flag(Base):
@ -29,6 +30,10 @@ class Flag(Base):
def created_datetime(self):
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):
@ -53,4 +58,8 @@ class CommentFlag(Base):
@property
@lazy
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",
"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":{
"str":'removed all content of {self.target_link}',
"icon":"fa-user-slash",
@ -253,16 +243,6 @@ ACTIONTYPES={
"icon":"fa-feather-alt",
"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":{
"str": 'removed {self.target_link}',
"icon":"fa-comment",

View File

@ -143,6 +143,8 @@ if SITE == 'rdrama.net':
LLM_ID = 253
DAD_ID = 2513
MOM_ID = 4588
BUG_THREAD = 18459
EMOJI_THREAD = 22479
elif SITE == "pcmemes.net":
BASEDBOT_ID = 800
NOTIFICATIONS_ID = 1046
@ -159,6 +161,8 @@ elif SITE == "pcmemes.net":
LLM_ID = 0
DAD_ID = 0
MOM_ID = 0
BUG_THREAD = 4103
EMOJI_THREAD = 0
else:
BASEDBOT_ID = 0
NOTIFICATIONS_ID = 1
@ -175,12 +179,14 @@ else:
LLM_ID = 0
DAD_ID = 0
MOM_ID = 0
BUG_THREAD = 0
EMOJI_THREAD = 0
PUSHER_INSTANCE_ID = '02ddcc80-b8db-42be-9022-44c546b4dce6'
PUSHER_KEY = environ.get("PUSHER_KEY", "").strip()
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:
return SLURS[match.group(0).lower()]
@ -389,6 +395,14 @@ BADGES = {
'name': '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 = {
@ -748,7 +762,4 @@ TROLLTITLES = [
"[META] Getting really sick of @{username}โ€™s shit",
"Pretty sure this is @{username}'s Reddit account",
"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
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()
return {"message": f"@{username} has been allowed into the {cc}!"}
@ -127,13 +119,6 @@ def club_ban(v, username):
u.club_allowed = False
g.db.add(x)
ma=ModAction(
kind="club_ban",
user_id=v.id,
target_user_id=u.id,
)
g.db.add(ma)
g.db.commit()
return {"message": f"@{username} has been kicked from the {cc}. Deserved."}
@ -164,30 +149,30 @@ def remove_admin(v, username):
return {"message": "Admin removed!"}
@app.post("/@<username>/make_fake_admin")
@app.post("/@<username>/make_meme_admin")
@limiter.limit("1/second")
@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):
user = get_user(username)
if not user: abort(404)
user.admin_level = 1
g.db.add(user)
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")
@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):
user = get_user(username)
if not user: abort(404)
user.admin_level = 0
g.db.add(user)
g.db.commit()
return {"message": "Fake admin removed!"}
return {"message": "Meme admin removed!"}
@app.post("/admin/monthly")

View File

@ -20,6 +20,7 @@ from urllib.parse import ParseResult, urlunparse, urlparse, quote
site = environ.get("DOMAIN").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]}")
@ -34,14 +35,6 @@ def toggle_club(pid, v):
post.club = not post.club
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()
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):
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=headers, timeout=5)
except BaseException: return {"error": "Could not reach page"}, 400
try: x = requests.get(url, headers=titleheaders, timeout=5)
except: abort(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):
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",""))
else: club = False
if embed and len(embed) > 1500: embed = None
new_post = Submission(
private=bool(request.values.get("private","")),
club=club,

View File

@ -825,11 +825,10 @@ def settings_block_user(v):
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 not user:
return {"error": "That user doesn't exist."}, 404
if user.id == v.id:
return {"error": "You can't block yourself."}, 409
@ -853,8 +852,7 @@ def settings_block_user(v):
g.db.commit()
if v.admin_level == 1: return {"message": f"@{user.username} banned!"}
else: return {"message": f"@{user.username} blocked."}
return {"message": f"@{user.username} blocked."}
@app.post("/settings/unblock")
@ -878,8 +876,6 @@ def settings_unblock_user(v):
g.db.commit()
if v.admin_level == 1: return {"message": f"@{user.username} unbanned!"}
return {"message": f"@{user.username} unblocked."}

View File

@ -173,7 +173,7 @@ def log(v):
actions = g.db.query(ModAction)
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 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)
@app.get("/@<username>/upvoters")
@auth_desired
def upvoters(v, username):
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))
@ -41,9 +42,9 @@ def upvoters(v, username):
def downvoters(v, username):
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))
@ -60,9 +61,9 @@ def downvoters(v, username):
def upvoting(v, username):
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))
@ -79,9 +80,9 @@ def upvoting(v, username):
def downvoting(v, username):
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))
@ -247,10 +248,32 @@ def leaderboard(v):
users4 = users.order_by(User.comment_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()
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:
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, 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, users9=users9)
@app.get("/@<username>/css")
@ -308,8 +331,7 @@ def unsubscribe(v, post_id):
@app.get("/report_bugs")
@auth_required
def reportbugs(v):
if request.host == 'rdrama.net': return redirect('https://rdrama.net/post/18459')
return render_template("reportbugs.html", v=v)
return redirect(f'/post/{BUG_THREAD}')
@app.post("/@<username>/message")
@limiter.limit("1/second")

View File

@ -10,7 +10,7 @@
</thead>
{% for user in users %}
<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>
</tr>
{% 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>
<ul>
<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>
</ul>
<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>
<ul>
<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>
</ul>
<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 %}
<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">
{% if v.agendaposter %}<link rel="stylesheet" href="/assets/css/agendaposter.css?v=122">{% elif v.css %}<link rel="stylesheet" href="/@{{v.username}}/css">{% endif %}
<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=124">{% elif v.css %}<link rel="stylesheet" href="/@{{v.username}}/css">{% endif %}
{% else %}
<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 %}
</head>

View File

@ -12,7 +12,7 @@
</thead>
{% for user in users %}
<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 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>

View File

@ -26,15 +26,16 @@
{% 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 %}
<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">
<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-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>
<button form="reply" class="btn btn-primary ml-auto">Comment</a>
<a class="format" href="javascript:void(0)"><i class="fas fa-link" aria-hidden="true"></i></small>
</div>
<button form="reply" class="btn btn-primary ml-auto fl-r">Comment</a>
</form>
</div>
</div>

View File

@ -21,7 +21,7 @@
<div class="container-fluid" style="padding:0;">
<div class="flex-grow-1">
<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 %}
<span style="font-weight: bold; font-size: 1.2rem;">GigaChadLife</span>
{% elif 'pcm' not in request.host %}

View File

@ -17,11 +17,11 @@
{% if v %}
<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">
{% if v.agendaposter %}<link rel="stylesheet" href="/assets/css/agendaposter.css?v=122">{% elif v.css %}<link rel="stylesheet" href="/@{{v.username}}/css">{% endif %}
<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=124">{% elif v.css %}<link rel="stylesheet" href="/@{{v.username}}/css">{% endif %}
{% else %}
<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 %}
<div class="row justify-content-around">

View File

@ -12,7 +12,7 @@
<title>2-Step Login - {{'SITE_NAME' | app_config}}</title>
<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>

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>
{% for user in users %}
<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>
</tr>
{% 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="author" content="">
<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:title" content="{{'SITE_NAME' | app_config}}" >
@ -40,10 +40,10 @@
{% if v %}
<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 %}
<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 %}
<link href="/assets/css/fa.css?v=52" rel="stylesheet">

View File

@ -11,7 +11,7 @@
</thead>
{% for user in users %}
<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 style="font-weight:bold;">{{user.shadowbanned}}</td>
</tr>

View File

@ -36,7 +36,7 @@
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,600&display=swap" rel="stylesheet">
<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>

View File

@ -31,7 +31,7 @@
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,600&display=swap" rel="stylesheet">
<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>

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/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 name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" 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' %}
{% set cc='Splash Mountain' %}
@ -31,12 +31,12 @@
{% block stylesheets %}
{% if v %}
<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">
{% if v.agendaposter %}<link rel="stylesheet" href="/assets/css/agendaposter.css?v=122">{% elif v.css %}<link rel="stylesheet" href="/@{{v.username}}/css">{% endif %}
<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=124">{% elif v.css %}<link rel="stylesheet" href="/@{{v.username}}/css">{% endif %}
{% else %}
<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 %}
{% 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>
<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
</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>
<p></p>

View File

@ -12,7 +12,7 @@
</thead>
{% for user in successful %}
<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>
</tr>
{% endfor %}
@ -30,7 +30,7 @@
</thead>
{% for user in failed2 %}
<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>
</tr>
{% endfor %}
@ -48,7 +48,7 @@
</thead>
{% for user in failed %}
<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>
</tr>
{% endfor %}

View File

@ -16,7 +16,7 @@
</thead>
{% for user in users %}
<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 style="font-weight:bold; text-align:right;">{{user.truecoins}}</td>
</tr>

View File

@ -137,13 +137,13 @@
</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>
<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>
{% elif u.admin_level == 1 %}
{% elif u.admin_level == 1 and v and v.admin_level > 1 %}
<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>
{% endif %}
{% 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="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="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="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="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 %}
<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>
</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>
<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>
{% elif u.admin_level == 1 %}
{% elif u.admin_level == 1 and v and v.admin_level > 1 %}
<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>
{% endif %}
{% 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="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="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="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="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 %}
<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">
<span class="fa-stack fa-2x text-muted mb-4">
<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>
{% 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>
<p class="text-muted">So we aren't going to show you their profile.</p>
{% endif %}
</div>
</div>
</div>

View File

@ -27,18 +27,18 @@
# maintenance (custom daily cronjobs, replication, and similar tasks).
#
# 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 all all trust
local all all trust
# IPv4 local connections:
host all all 0.0.0.0/32 trust
host all all 127.0.0.1/32 trust
# IPv6 local connections:
host all all ::1/128 trust
# Allow replication connections from 0.0.0.0, by a user with the
host all all ::1/128 trust
# Allow replication connections from localhost, by a user with the
# replication privilege.
local replication all trust
host replication all 0.0.0.0/32 trust
host replication all ::1/128 trust
local replication all trust
host replication all 127.0.0.1/32 trust
host replication all ::1/128 trust

View File

@ -22,9 +22,9 @@ git clone https://github.com/Aevann1/Drama/
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
```
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

View File

@ -53,7 +53,7 @@
# Examples:
#
# 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
# 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
# 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
# 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:
#
# 1) The server is not binding explicitly to a set of addresses using the
# "bind" directive.
# "bind" directive.
# 2) No password is configured.
#
# 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.
#
# By default protected mode is enabled. You should disable it only if
@ -119,7 +119,7 @@ timeout 0
#
# 1) Detect dead peers.
# 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.
# 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
# supervision tree. Options:
# supervised no - no supervision interaction
# supervised no - no supervision interaction
# supervised upstart - signal upstart by putting Redis into SIGSTOP mode
# supervised systemd - signal systemd by writing READY=1 to $NOTIFY_SOCKET
# supervised auto - detect upstart or systemd method based on
# UPSTART_JOB or NOTIFY_SOCKET environment variables
# supervised auto - detect upstart or systemd method based on
# UPSTART_JOB or NOTIFY_SOCKET environment variables
# 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
# 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
# another Redis server. A few things to understand ASAP about Redis replication.
#
# +------------------+ +---------------+
# | Master | ---> | Replica |
# | (receive writes) | | (exact copy) |
# +------------------+ +---------------+
# +------------------+ +---------------+
# | Master | ---> | Replica |
# | (receive writes) | | (exact copy) |
# +------------------+ +---------------+
#
# 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
# a given number of replicas.
# stop accepting writes if it appears to be not connected with at least
# a given number of replicas.
# 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
# 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.
# 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
# sections of this file) with a sensible value depending on your needs.
# 3) Replication is automatic and does not need user intervention. After a
# network partition replicas automatically try to reconnect to masters
# and resynchronize with them.
# network partition replicas automatically try to reconnect to masters
# and resynchronize with them.
#
# replicaof <masterip> <masterport>
@ -296,14 +296,14 @@ dir /var/lib/redis
# 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
# 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.
# 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.
#
# 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
# but to INFO, replicaOF, AUTH, PING, SHUTDOWN, REPLCONF, ROLE, CONFIG,
# SUBSCRIBE, UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE, PUBLISH, PUBSUB,
# COMMAND, POST, HOST: and LATENCY.
# an error "SYNC with master in progress" to all the kind of commands
# but to INFO, replicaOF, AUTH, PING, SHUTDOWN, REPLCONF, ROLE, CONFIG,
# SUBSCRIBE, UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE, PUBLISH, PUBSUB,
# COMMAND, POST, HOST: and LATENCY.
#
replica-serve-stale-data yes
@ -335,10 +335,10 @@ replica-read-only yes
# The transmission can happen in two different ways:
#
# 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
# process to the replicas incrementally.
# file on disk. Later the file is transferred by the parent
# process to the replicas incrementally.
# 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
# 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.
#
# 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
# incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd
# sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby
# zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby
# getset mset msetnx exec sort
# At the date of writing these commands are: set setnx setex append
# incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd
# sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby
# zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby
# getset mset msetnx exec sort
#
# The default is:
#
@ -652,19 +652,19 @@ replica-priority 100
# following scenarios:
#
# 1) On eviction, because of the maxmemory and maxmemory policy configurations,
# in order to make room for new data, without going over the specified
# memory limit.
# in order to make room for new data, without going over the specified
# memory limit.
# 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
# already exist. For example the RENAME command may delete the old key
# content when it is replaced with another one. Similarly SUNIONSTORE
# 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
# it with the specified string.
# already exist. For example the RENAME command may delete the old key
# content when it is replaced with another one. Similarly SUNIONSTORE
# 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
# it with the specified string.
# 4) During replication, when a replica performs a full resynchronization with
# its master, the content of the whole database is removed in order to
# load the RDB file just transferred.
# its master, the content of the whole database is removed in order to
# load the RDB file just transferred.
#
# 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
@ -694,7 +694,7 @@ replica-lazy-flush no
# If the AOF is enabled on startup Redis will load the AOF, that is the file
# 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
@ -721,7 +721,7 @@ appendfilename "appendonly.aof"
# everysec.
#
# 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".
@ -852,17 +852,17 @@ lua-time-limit 5000
# its "data age", so the following two checks are performed:
#
# 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
# replication offset (more data from the master processed).
# Replicas will try to get their rank by offset, and apply to the start
# of the failover a delay proportional to their rank.
# in order to try to give an advantage to the replica with the best
# replication offset (more data from the master processed).
# Replicas will try to get their rank by offset, and apply to the start
# of the failover a delay proportional to their rank.
#
# 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
# is still in the "connected" state), or the time that elapsed since the
# 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
# at all.
# 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
# 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
# at all.
#
# 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
@ -933,7 +933,7 @@ lua-time-limit 5000
# cluster-replica-no-failover no
# 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 ########################
@ -1016,7 +1016,7 @@ latency-monitor-threshold 0
############################# EVENT NOTIFICATION ##############################
# 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
# 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
# of classes. Every class is identified by a single character:
#
# K Keyspace events, published with __keyspace@<db>__ prefix.
# E Keyevent events, published with __keyevent@<db>__ prefix.
# g Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ...
# $ String commands
# l List commands
# s Set commands
# h Hash commands
# z Sorted set commands
# x Expired events (events generated every time a key expires)
# 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.
# K Keyspace events, published with __keyspace@<db>__ prefix.
# E Keyevent events, published with __keyevent@<db>__ prefix.
# g Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ...
# $ String commands
# l List commands
# s Set commands
# h Hash commands
# z Sorted set commands
# x Expired events (events generated every time a key expires)
# 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.
#
# The "notify-keyspace-events" takes as argument a string that is composed
# of zero or multiple characters. The empty string means that notifications
# are disabled.
#
# Example: to enable list and generic events, from the point of view of the
# event name, use:
# event name, use:
#
# notify-keyspace-events Elg
#
# 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
#
@ -1088,12 +1088,12 @@ list-max-ziplist-size -2
# are always uncompressed for fast push/pop operations. Settings are:
# 0: disable all list compression
# 1: depth 1 means "don't start compressing until after 1 node into the list,
# going from either the head or tail"
# So: [head]->node->node->...->node->[tail]
# [head], [tail] will always be uncompressed; inner nodes will compress.
# going from either the head or tail"
# So: [head]->node->node->...->node->[tail]
# [head], [tail] will always be uncompressed; inner nodes will compress.
# 2: [head]->[next]->node->node->...->node->[prev]->[tail]
# 2 here means: don't compress head or head->next or tail->prev or tail,
# but compress all nodes between them.
# 2 here means: don't compress head or head->next or tail->prev or tail,
# but compress all nodes between them.
# 3: [head]->[next]->[next]->node->node->...->node->[prev]->[prev]->[tail]
# etc.
list-compress-depth 0
@ -1275,15 +1275,15 @@ rdb-save-incremental-fsync yes
# 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:
@ -1335,14 +1335,14 @@ rdb-save-incremental-fsync yes
# Important things to understand:
#
# 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.
# This is the default with Linux builds.
# to use the copy of Jemalloc we ship with the source code of Redis.
# This is the default with Linux builds.
#
# 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
# 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
# defragmentation process. If you are not sure about what they mean it is

View File

@ -1,3 +1,3 @@
source /env
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
cp ./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
{[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]
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_maxbytes=0
stderr_logfile=/dev/stderr