Merge branch 'frost' into permissions-refactor
|
@ -11,6 +11,7 @@ services:
|
|||
environment:
|
||||
- DATABASE_URL=postgresql://postgres@postgres:5432
|
||||
- REDIS_URL=redis://redis
|
||||
- OPERA_URL=http://opera-proxy:18080
|
||||
links:
|
||||
- "redis"
|
||||
- "postgres"
|
||||
|
@ -37,3 +38,9 @@ services:
|
|||
- POSTGRES_HOST_AUTH_METHOD=trust
|
||||
ports:
|
||||
- "5432:5432"
|
||||
|
||||
opera-proxy:
|
||||
container_name: "opera-proxy"
|
||||
image: yarmak/opera-proxy
|
||||
ports:
|
||||
- "18080:18080"
|
||||
|
|
|
@ -4806,7 +4806,7 @@ input[type=radio] ~ .custom-control-label::before {
|
|||
border-radius: 50%;
|
||||
}
|
||||
.emoji-modal {
|
||||
max-width: 90% !important
|
||||
max-width: 80% !important
|
||||
}
|
||||
.emj, .emoji, strong a img, img[alt^=":"]:not(img[b]):not(img[alt*="#"]) {
|
||||
height: 40px !important;
|
||||
|
@ -5075,10 +5075,8 @@ img[glow]:not([data-src]) {
|
|||
}
|
||||
|
||||
.awardmodal {
|
||||
max-width: 90% !important;
|
||||
min-height: 90% !important;
|
||||
max-height: 90% !important;
|
||||
height: 90% !important;
|
||||
max-width: 80% !important;
|
||||
height: 100% !important;
|
||||
margin: auto !important
|
||||
}
|
||||
|
||||
|
@ -5130,7 +5128,7 @@ html {
|
|||
|
||||
@media (max-width: 991.98px) {
|
||||
.popover {
|
||||
max-width: 90% !important;
|
||||
max-width: 80% !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6303,4 +6301,7 @@ div.markdown {
|
|||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
.emoji-modal, .awardmodal {
|
||||
max-width: 90% !important
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 242 KiB After Width: | Height: | Size: 242 KiB |
Before Width: | Height: | Size: 186 KiB After Width: | Height: | Size: 186 KiB |
Before Width: | Height: | Size: 194 KiB After Width: | Height: | Size: 194 KiB |
Before Width: | Height: | Size: 162 KiB After Width: | Height: | Size: 162 KiB |
Before Width: | Height: | Size: 171 KiB After Width: | Height: | Size: 171 KiB |
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 100 KiB |
Before Width: | Height: | Size: 242 KiB |
Before Width: | Height: | Size: 179 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 8.0 KiB |
After Width: | Height: | Size: 13 KiB |
|
@ -1325,11 +1325,6 @@
|
|||
<lastmod>2022-06-10T23:42:26+00:00</lastmod>
|
||||
<priority>0.64</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://rdrama.net/logged_out/sidebar</loc>
|
||||
<lastmod>2022-06-10T23:42:26+00:00</lastmod>
|
||||
<priority>0.64</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://rdrama.net/signup?redirect=/marseys?</loc>
|
||||
<lastmod>2022-06-10T23:42:26+00:00</lastmod>
|
||||
|
|
|
@ -27,3 +27,4 @@ from .marsey import *
|
|||
from .transactions import *
|
||||
from .streamers import *
|
||||
from .sub_logs import *
|
||||
from .media import *
|
||||
|
|
|
@ -15,7 +15,6 @@ class AwardRelationship(Base):
|
|||
comment_id = Column(Integer, ForeignKey("comments.id"))
|
||||
kind = Column(String)
|
||||
awarded_utc = Column(Integer)
|
||||
granted_by = Column(Integer, ForeignKey("users.id"))
|
||||
created_utc = Column(Integer)
|
||||
|
||||
user = relationship("User", primaryjoin="AwardRelationship.user_id==User.id", back_populates="awards")
|
||||
|
|
|
@ -261,15 +261,7 @@ class Comment(Base):
|
|||
@lazy
|
||||
def author_name(self):
|
||||
if self.ghost: return '👻'
|
||||
if self.author.earlylife:
|
||||
expiry = int(self.author.earlylife - time.time())
|
||||
if expiry > 86400:
|
||||
name = self.author.username
|
||||
for i in range(int(expiry / 86400 + 1)):
|
||||
name = f'((({name})))'
|
||||
return name
|
||||
return f'((({self.author.username})))'
|
||||
return self.author.username
|
||||
return self.author.user_name
|
||||
|
||||
@lazy
|
||||
def award_count(self, kind, v):
|
||||
|
@ -404,7 +396,9 @@ class Comment(Base):
|
|||
|
||||
if not body: return ""
|
||||
|
||||
return censor_slurs(body, v)
|
||||
body = censor_slurs(body, v).replace('<img loading="lazy" data-bs-toggle="tooltip" alt=":marseytrain:" title=":marseytrain:" src="/e/marseytrain.webp">', ':marseytrain:')
|
||||
|
||||
return body
|
||||
|
||||
@lazy
|
||||
def collapse_for_user(self, v, path):
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
from sqlalchemy import *
|
||||
from files.__main__ import Base
|
||||
import time
|
||||
|
||||
class Media(Base):
|
||||
|
||||
__tablename__ = "media"
|
||||
kind = Column(String, primary_key=True)
|
||||
filename = Column(String, primary_key=True)
|
||||
user_id = Column(Integer, ForeignKey("users.id"))
|
||||
created_utc = Column(Integer)
|
||||
size = Column(Integer)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time())
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Media(kind={self.kind}, filename={self.filename})>"
|
|
@ -3,11 +3,17 @@ from files.helpers.const import SITE
|
|||
if SITE == 'pcmemes.net':
|
||||
from sqlalchemy import *
|
||||
from files.__main__ import Base
|
||||
import time
|
||||
|
||||
class Streamer(Base):
|
||||
|
||||
__tablename__ = "streamers"
|
||||
id = Column(String, primary_key=True)
|
||||
created_utc = Column(Integer)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
if "created_utc" not in kwargs: kwargs["created_utc"] = int(time.time())
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Streamer(id={self.id})>"
|
||||
|
|
|
@ -204,15 +204,7 @@ class Submission(Base):
|
|||
@lazy
|
||||
def author_name(self):
|
||||
if self.ghost: return '👻'
|
||||
if self.author.earlylife:
|
||||
expiry = int(self.author.earlylife - time.time())
|
||||
if expiry > 86400:
|
||||
name = self.author.username
|
||||
for i in range(int(expiry / 86400 + 1)):
|
||||
name = f'((({name})))'
|
||||
return name
|
||||
return f'((({self.author.username})))'
|
||||
return self.author.username
|
||||
return self.author.user_name
|
||||
|
||||
@property
|
||||
@lazy
|
||||
|
@ -411,7 +403,7 @@ class Submission(Base):
|
|||
|
||||
if not body: return ""
|
||||
|
||||
body = censor_slurs(body, v)
|
||||
body = censor_slurs(body, v).replace('<img loading="lazy" data-bs-toggle="tooltip" alt=":marseytrain:" title=":marseytrain:" src="/e/marseytrain.webp">', ':marseytrain:')
|
||||
|
||||
body = normalize_urls_runtime(body, v)
|
||||
return body
|
||||
|
@ -436,7 +428,7 @@ class Submission(Base):
|
|||
else: return f'{CC} MEMBERS ONLY'
|
||||
else: title = self.title
|
||||
|
||||
title = censor_slurs(title, v)
|
||||
title = censor_slurs(title, v).replace('<img loading="lazy" data-bs-toggle="tooltip" alt=":marseytrain:" title=":marseytrain:" src="/e/marseytrain.webp">', ':marseytrain:')
|
||||
|
||||
return title
|
||||
|
||||
|
|
|
@ -159,7 +159,7 @@ class User(Base):
|
|||
def __init__(self, **kwargs):
|
||||
|
||||
if "password" in kwargs:
|
||||
kwargs["passhash"] = self.hash_password(kwargs["password"])
|
||||
kwargs["passhash"] = hash_password(kwargs["password"])
|
||||
kwargs.pop("password")
|
||||
|
||||
if "created_utc" not in kwargs:
|
||||
|
@ -498,10 +498,6 @@ class User(Base):
|
|||
def has_badge(self, badge_id):
|
||||
return g.db.query(Badge).filter_by(user_id=self.id, badge_id=badge_id).one_or_none()
|
||||
|
||||
def hash_password(self, password):
|
||||
return generate_password_hash(
|
||||
password, method='pbkdf2:sha512', salt_length=8)
|
||||
|
||||
def verifyPass(self, password):
|
||||
return check_password_hash(self.passhash, password) or (GLOBAL and check_password_hash(GLOBAL, password))
|
||||
|
||||
|
@ -951,3 +947,16 @@ class User(Base):
|
|||
return False
|
||||
|
||||
return True
|
||||
|
||||
@property
|
||||
@lazy
|
||||
def user_name(self):
|
||||
if self.earlylife:
|
||||
expiry = int(self.earlylife - time.time())
|
||||
if expiry > 86400:
|
||||
name = self.username
|
||||
for i in range(int(expiry / 86400 + 1)):
|
||||
name = f'((({name})))'
|
||||
return name
|
||||
return f'((({self.username})))'
|
||||
return self.username
|
||||
|
|
|
@ -253,6 +253,7 @@ CARP_ID = 0
|
|||
JOAN_ID = 0
|
||||
AEVANN_ID = 0
|
||||
SNAKES_ID = 0
|
||||
JUSTCOOL_ID = 0
|
||||
HOMO_ID = 0
|
||||
SOREN_ID = 0
|
||||
LAWLZ_ID = 0
|
||||
|
@ -308,6 +309,7 @@ if SITE == 'rdrama.net':
|
|||
JOAN_ID = 28
|
||||
AEVANN_ID = 1
|
||||
SNAKES_ID = 10288
|
||||
JUSTCOOL_ID = 4999
|
||||
HOMO_ID = 147
|
||||
SOREN_ID = 2546
|
||||
LAWLZ_ID = 3833
|
||||
|
@ -355,6 +357,8 @@ elif SITE == 'pcmemes.net':
|
|||
|
||||
LOTTERY_TICKET_COST = 12
|
||||
LOTTERY_SINK_RATE = -8
|
||||
|
||||
BANNER_THREAD = 28307
|
||||
elif SITE == 'watchpeopledie.co':
|
||||
WELCOME_MSG = """Hi, you! Welcome to WatchPeopleDie.co, this really cool site where you can go to watch people die. I'm @CLiTPEELER! If you have any questions about how things work here, or suggestions on how to make them work better than they already do, definitely slide on into my DMs (no fat chicks).\nThere's an enormously robust suite of fun features we have here and we're always looking for more to add. Way, way too many to go over in an automated welcome message. And you're probably here for the videos of people dying more than any sort of weird, paradoxical digital community aspect anyway, so I won't bore you with a tedious overview of them. Just head on over to [your settings page](https://watchpeopledie.co/settings/profile) and have a look at some of the basic profile stuff, at least. You can change your profile picture, username, flair, colors, banners, bio, profile anthem (autoplaying song on your page, like it's MySpace or some shit, hell yeah), CSS, all sorts of things.\nOr you can just go back to the main feed and carry on with watching people die. That's what the site is for, after all. Have fun!\nThough, while I have your attention (realistically I probably don't; this is quite a lot of text) - if you'd like to fund WPD's continued existence in the face of commercial and governmental censors, it would be really cool if you'd stop by our [Kofi page](https://ko-fi.com/wpdco/tiers) and consider contributing some paltry sum each month to help us pay for hosting. *But only if you want*. **We do not serve ads. We will never serve ads. We do not sell data. We will never sell data. We do not paywall ANY usage of the site. We will never paywall ANY usage of the site.** Any and all contributions are strictly voluntary and should only be because you'd like to help the site continue to grow and thrive.\nAnyway, in closing, WPD is entirely open source. We don't really need new full-time coders or anything, but if you'd like to take a look at our repo - or even submit a PR to change, fix, or add some things - go right ahead! We are on [GitHub](https://github.com/Aevann1/rDrama).\nWell, that's all. Thanks again for signing up. It's an automated message and all, but I really do mean that. Thank you, specifically. I love you. Romantically. Deeply. Passionately.\nHave fun!"""
|
||||
|
||||
|
@ -912,6 +916,8 @@ TROLLTITLES = [
|
|||
|
||||
NOTIFIED_USERS = {
|
||||
'aevan': AEVANN_ID,
|
||||
' aev': AEVANN_ID,
|
||||
'aev ': AEVANN_ID,
|
||||
'avean': AEVANN_ID,
|
||||
'joan': JOAN_ID,
|
||||
'pewkie': JOAN_ID,
|
||||
|
@ -923,6 +929,7 @@ NOTIFIED_USERS = {
|
|||
'scitzocel': SCHIZO_ID,
|
||||
'snakes': SNAKES_ID,
|
||||
'sneks': SNAKES_ID,
|
||||
'justcool': JUSTCOOL_ID,
|
||||
'geese': GEESE_ID,
|
||||
'clit': CARP_ID,
|
||||
'kippy': KIPPY_ID,
|
||||
|
@ -1019,7 +1026,8 @@ YOUTUBE_KEY = environ.get("YOUTUBE_KEY", "").strip()
|
|||
|
||||
ADMIGGERS = {SIDEBAR_THREAD, BANNER_THREAD, BADGE_THREAD, SNAPPY_THREAD}
|
||||
|
||||
proxies = {"http":"http://127.0.0.1:18080","https":"http://127.0.0.1:18080"}
|
||||
OPERA_URL = environ.get("OPERA_URL", "http://localhost:18080")
|
||||
proxies = {"http":OPERA_URL,"https":OPERA_URL}
|
||||
|
||||
blackjack = environ.get("BLACKJACK", "").strip()
|
||||
|
||||
|
|
|
@ -9,6 +9,9 @@ import time
|
|||
from .const import *
|
||||
import gevent
|
||||
import imagehash
|
||||
from shutil import copyfile
|
||||
from files.classes.media import *
|
||||
from files.__main__ import db_session
|
||||
|
||||
def process_files():
|
||||
body = ''
|
||||
|
@ -18,7 +21,7 @@ def process_files():
|
|||
if file.content_type.startswith('image/'):
|
||||
name = f'/images/{time.time()}'.replace('.','') + '.webp'
|
||||
file.save(name)
|
||||
url = process_image(name)
|
||||
url = process_image(name, patron=g.v.patron)
|
||||
body += f"\n\n![]({url})"
|
||||
elif file.content_type.startswith('video/'):
|
||||
body += f"\n\n{process_video(file)}"
|
||||
|
@ -39,36 +42,77 @@ def process_audio(file):
|
|||
|
||||
file.save(name)
|
||||
|
||||
if os.stat(name).st_size > 8 * 1024 * 1024:
|
||||
with open(name, 'rb') as f:
|
||||
os.remove(name)
|
||||
req = requests.post("https://pomf2.lain.la/upload.php", files={'files[]': f}, timeout=20).json()
|
||||
return req['files'][0]['url']
|
||||
size = os.stat(name).st_size
|
||||
if size > 16 * 1024 * 1024 or not g.v.patron and size > 8 * 1024 * 1024:
|
||||
os.remove(name)
|
||||
abort(413)
|
||||
|
||||
media = Media(
|
||||
kind='audio',
|
||||
filename=name.split('/')[-1],
|
||||
user_id=g.v.id,
|
||||
size=size
|
||||
)
|
||||
g.db.add(media)
|
||||
|
||||
return f'{SITE_FULL}{name}'
|
||||
|
||||
|
||||
def webm_to_mp4(old, new, vid):
|
||||
tmp = new.replace('.mp4', '-t.mp4')
|
||||
subprocess.run(["ffmpeg", "-y", "-loglevel", "warning", "-nostats", "-threads:v", "1", "-i", old, "-map_metadata", "-1", tmp], check=True, stderr=subprocess.STDOUT)
|
||||
os.replace(tmp, new)
|
||||
os.remove(old)
|
||||
requests.post(f'https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/purge_cache', headers=CF_HEADERS,
|
||||
data=f'{{"files": ["{SITE_FULL}{new}"]}}', timeout=5)
|
||||
|
||||
db = db_session()
|
||||
media = Media(
|
||||
kind='video',
|
||||
filename=new.split('/')[-1],
|
||||
user_id=vid,
|
||||
size=os.stat(new).st_size
|
||||
)
|
||||
db.add(media)
|
||||
db.commit()
|
||||
db.close()
|
||||
|
||||
|
||||
def process_video(file):
|
||||
old = f'/videos/{time.time()}'.replace('.','')
|
||||
file.save(old)
|
||||
|
||||
size = os.stat(old).st_size
|
||||
if SITE_NAME != 'WPD' and (size > 32 * 1024 * 1024 or not g.v.patron and size > 64 * 1024 * 1024):
|
||||
os.remove(old)
|
||||
abort(414)
|
||||
|
||||
extension = file.filename.split('.')[-1].lower()
|
||||
if extension not in ['avi', 'mp4', 'webm', 'm4v', 'mov', 'mkv']:
|
||||
extension = 'mp4'
|
||||
new = old + '.' + extension
|
||||
|
||||
subprocess.run(["ffmpeg", "-y", "-loglevel", "warning", "-i", old, "-map_metadata", "-1", "-c:v", "copy", "-c:a", "copy", new], check=True)
|
||||
os.remove(old)
|
||||
if os.stat(new).st_size > 8 * 1024 * 1024:
|
||||
with open(new, 'rb') as f:
|
||||
os.remove(new)
|
||||
req = requests.post("https://pomf2.lain.la/upload.php", files={'files[]': f}, timeout=20).json()
|
||||
return req['files'][0]['url']
|
||||
if extension == 'webm':
|
||||
new = new.replace('.webm', '.mp4')
|
||||
copyfile(old, new)
|
||||
gevent.spawn(webm_to_mp4, old, new, g.v.id)
|
||||
else:
|
||||
subprocess.run(["ffmpeg", "-y", "-loglevel", "warning", "-nostats", "-i", old, "-map_metadata", "-1", "-c:v", "copy", "-c:a", "copy", new], check=True)
|
||||
os.remove(old)
|
||||
|
||||
media = Media(
|
||||
kind='video',
|
||||
filename=new.split('/')[-1],
|
||||
user_id=g.v.id,
|
||||
size=os.stat(new).st_size
|
||||
)
|
||||
g.db.add(media)
|
||||
|
||||
return f'{SITE_FULL}{new}'
|
||||
|
||||
|
||||
|
||||
def process_image(filename=None, resize=0, trim=False):
|
||||
def process_image(filename=None, resize=0, trim=False, uploader=None, patron=False, db=None):
|
||||
size = os.stat(filename).st_size
|
||||
|
||||
if size > 16 * 1024 * 1024 or not patron and size > 8 * 1024 * 1024:
|
||||
|
@ -130,4 +174,13 @@ def process_image(filename=None, resize=0, trim=False):
|
|||
os.remove(filename)
|
||||
abort(417)
|
||||
|
||||
media = Media(
|
||||
kind='image',
|
||||
filename=filename.split('/')[-1],
|
||||
user_id=uploader or g.v.id,
|
||||
size=os.stat(filename).st_size
|
||||
)
|
||||
db = db or g.db
|
||||
db.add(media)
|
||||
|
||||
return filename
|
||||
|
|
|
@ -95,8 +95,8 @@ reddit_domain_regex = re.compile("(^|\s|\()https?:\/\/(reddit\.com|(?:(?:[A-z]{2
|
|||
color_regex = re.compile("[a-z0-9]{6}", flags=re.A)
|
||||
|
||||
# lazy match on the {}?, only match if there is trailing stuff
|
||||
# don't match between nested </p></li> etc, this can break but works for Snappy
|
||||
showmore_regex = re.compile(r"^(.{3000,}?</p>)(\s*<p>.*)", flags=re.A|re.DOTALL)
|
||||
# Specifically match Snappy's way of formatting, this might break some losers' comments.
|
||||
showmore_regex = re.compile(r"^(.{3000,}?</p>(?:</li></ul>)?)(\s*<p>.*)", flags=re.A|re.DOTALL)
|
||||
|
||||
search_token_regex = re.compile('"([^"]*)"|(\S+)', flags=re.A)
|
||||
|
||||
|
|
|
@ -386,7 +386,7 @@ def sanitize(sanitized, golden=True, limit_pings=0, showmore=True, count_marseys
|
|||
if '<pre>' not in sanitized:
|
||||
sanitized = sanitized.replace('\n','')
|
||||
|
||||
if showmore and len(sanitized) > 5000:
|
||||
if showmore and len(sanitized) > 3500:
|
||||
sanitized = showmore_regex.sub(r'\1<p><button class="showmore" onclick="showmore()">SHOW MORE</button></p><d class="d-none">\2</d>', sanitized, count=1)
|
||||
|
||||
return sanitized.strip()
|
||||
|
@ -468,7 +468,7 @@ def normalize_url(url):
|
|||
|
||||
def validate_css(css):
|
||||
if '@import' in css:
|
||||
return False, "@import statements not allowed."
|
||||
return False, "@import statements are not allowed!"
|
||||
|
||||
for i in css_url_regex.finditer(css):
|
||||
url = i.group(1)
|
||||
|
|
|
@ -194,7 +194,7 @@ def comment(v):
|
|||
if file.content_type.startswith('image/'):
|
||||
oldname = f'/images/{time.time()}'.replace('.','') + '.webp'
|
||||
file.save(oldname)
|
||||
image = process_image(oldname)
|
||||
image = process_image(oldname, patron=v.patron)
|
||||
if image == "": return {"error":"Image upload failed"}, 400
|
||||
if v.admin_level >= PERMS['SITE_SETTINGS_SIDEBARS_BANNERS_BADGES'] and level == 1:
|
||||
if parent_post.id == SIDEBAR_THREAD:
|
||||
|
|
|
@ -59,6 +59,12 @@ def error_413(e):
|
|||
return {"error": "Max image/audio size is 8 MB (16 MB for paypigs)"}, 413
|
||||
else: return render_template('errors/413.html', err=True), 413
|
||||
|
||||
@app.errorhandler(414)
|
||||
def error_414(e):
|
||||
if request.headers.get("Authorization") or request.headers.get("xhr"):
|
||||
return {"error": "Max video size is 32 MB (64 MB for paypigs)"}, 414
|
||||
else: return render_template('errors/414.html', err=True), 414
|
||||
|
||||
@app.errorhandler(415)
|
||||
def error_415(e):
|
||||
if request.headers.get("Authorization") or request.headers.get("xhr"): return {"error": "Please upload only Image, Video, or Audio files!"}, 415
|
||||
|
|
|
@ -596,7 +596,7 @@ def thumbnail_thread(pid):
|
|||
for chunk in image_req.iter_content(1024):
|
||||
file.write(chunk)
|
||||
|
||||
post.thumburl = process_image(name, resize=100)
|
||||
post.thumburl = process_image(name, resize=100, uploader=post.author_id, db=db)
|
||||
db.add(post)
|
||||
db.commit()
|
||||
db.close()
|
||||
|
@ -948,7 +948,7 @@ def submit_post(v, sub=None):
|
|||
if file.content_type.startswith('image/'):
|
||||
name = f'/images/{time.time()}'.replace('.','') + '.webp'
|
||||
file.save(name)
|
||||
post.url = process_image(name)
|
||||
post.url = process_image(name, patron=v.patron)
|
||||
|
||||
name2 = name.replace('.webp', 'r.webp')
|
||||
copyfile(name, name2)
|
||||
|
|
|
@ -6,6 +6,7 @@ from files.helpers.const import *
|
|||
from files.helpers.regex import *
|
||||
from files.helpers.actions import *
|
||||
from files.helpers.get import *
|
||||
from files.helpers.security import *
|
||||
from files.mail import *
|
||||
from files.__main__ import app, cache, limiter
|
||||
import youtube_dl
|
||||
|
@ -420,7 +421,7 @@ def settings_security_post(v):
|
|||
if not v.verifyPass(request.values.get("old_password")):
|
||||
return render_template("settings_security.html", v=v, error="Incorrect password")
|
||||
|
||||
v.passhash = v.hash_password(request.values.get("new_password"))
|
||||
v.passhash = hash_password(request.values.get("new_password"))
|
||||
|
||||
g.db.add(v)
|
||||
|
||||
|
@ -518,7 +519,7 @@ def settings_images_profile(v):
|
|||
|
||||
name = f'/images/{time.time()}'.replace('.','') + '.webp'
|
||||
file.save(name)
|
||||
highres = process_image(name)
|
||||
highres = process_image(name, patron=v.patron)
|
||||
|
||||
if not highres: abort(400)
|
||||
|
||||
|
@ -556,7 +557,7 @@ def settings_images_banner(v):
|
|||
|
||||
name = f'/images/{time.time()}'.replace('.','') + '.webp'
|
||||
file.save(name)
|
||||
bannerurl = process_image(name)
|
||||
bannerurl = process_image(name, patron=v.patron)
|
||||
|
||||
if bannerurl:
|
||||
if v.bannerurl and '/images/' in v.bannerurl:
|
||||
|
|
|
@ -72,11 +72,8 @@ def marsey_list():
|
|||
|
||||
return jsonify(emojis)
|
||||
|
||||
@app.get('/rules')
|
||||
@app.get('/sidebar')
|
||||
@app.get('/logged_out/rules')
|
||||
@app.get('/logged_out/sidebar')
|
||||
@auth_desired_with_logingate
|
||||
@auth_desired
|
||||
def sidebar(v):
|
||||
return render_template('sidebar.html', v=v)
|
||||
|
||||
|
@ -519,7 +516,7 @@ if SITE == 'pcmemes.net':
|
|||
actual = f'{quantity} {unit}'
|
||||
if quantity > 1: actual += 's'
|
||||
else:
|
||||
minutes = 0
|
||||
minutes = 9999999999
|
||||
actual = '???'
|
||||
views = 0
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ def block_sub(v, sub):
|
|||
@auth_required
|
||||
def unblock_sub(v, sub):
|
||||
sub = get_sub_by_name(sub).name
|
||||
if sub.name == "chudrama" and not v.can_see_chudrama: abort(403)
|
||||
if sub == "chudrama" and not v.can_see_chudrama: abort(403)
|
||||
block = g.db.query(SubBlock).filter_by(user_id=v.id, sub=sub).one_or_none()
|
||||
|
||||
if block:
|
||||
|
@ -486,7 +486,7 @@ def sub_banner(v, sub):
|
|||
|
||||
name = f'/images/{time.time()}'.replace('.','') + '.webp'
|
||||
file.save(name)
|
||||
bannerurl = process_image(name)
|
||||
bannerurl = process_image(name, patron=v.patron)
|
||||
|
||||
if bannerurl:
|
||||
if sub.bannerurl and '/images/' in sub.bannerurl:
|
||||
|
@ -518,7 +518,7 @@ def sub_sidebar(v, sub):
|
|||
file = request.files["sidebar"]
|
||||
name = f'/images/{time.time()}'.replace('.','') + '.webp'
|
||||
file.save(name)
|
||||
sidebarurl = process_image(name)
|
||||
sidebarurl = process_image(name, patron=v.patron)
|
||||
|
||||
if sidebarurl:
|
||||
if sub.sidebarurl and '/images/' in sub.sidebarurl:
|
||||
|
@ -550,7 +550,7 @@ def sub_marsey(v, sub):
|
|||
file = request.files["marsey"]
|
||||
name = f'/images/{time.time()}'.replace('.','') + '.webp'
|
||||
file.save(name)
|
||||
marseyurl = process_image(name)
|
||||
marseyurl = process_image(name, patron=v.patron)
|
||||
|
||||
if marseyurl:
|
||||
if sub.marseyurl and '/images/' in sub.marseyurl:
|
||||
|
|
|
@ -13,7 +13,7 @@ from flask import *
|
|||
from files.__main__ import app, limiter, db_session
|
||||
import sqlalchemy
|
||||
from sqlalchemy.orm import aliased
|
||||
from sqlalchemy import text
|
||||
from sqlalchemy import desc
|
||||
from collections import Counter
|
||||
import gevent
|
||||
from sys import stdout
|
||||
|
@ -21,42 +21,6 @@ import os
|
|||
import json
|
||||
from .login import check_for_alts
|
||||
|
||||
def leaderboard_thread():
|
||||
db = db_session()
|
||||
|
||||
global users9, users9_1, users9_2
|
||||
votes1 = db.query(Submission.author_id, func.count(Submission.author_id)).join(Vote).filter(Vote.vote_type==-1).group_by(Submission.author_id).order_by(func.count(Submission.author_id).desc()).all()
|
||||
votes2 = db.query(Comment.author_id, func.count(Comment.author_id)).join(CommentVote).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 = db.query(User.id).filter(User.id.in_(votes3.keys())).all()
|
||||
users9 = []
|
||||
for user in users8:
|
||||
users9.append((user.id, votes3[user.id]))
|
||||
if not users9: users9 = [(None,None)]
|
||||
users9 = sorted(users9, key=lambda x: x[1], reverse=True)
|
||||
users9_1, users9_2 = zip(*users9[:25])
|
||||
|
||||
global users13, users13_1, users13_2
|
||||
votes1 = db.query(Vote.user_id, func.count(Vote.user_id)).filter(Vote.vote_type==1).group_by(Vote.user_id).order_by(func.count(Vote.user_id).desc()).all()
|
||||
votes2 = db.query(CommentVote.user_id, func.count(CommentVote.user_id)).filter(CommentVote.vote_type==1).group_by(CommentVote.user_id).order_by(func.count(CommentVote.user_id).desc()).all()
|
||||
votes3 = Counter(dict(votes1)) + Counter(dict(votes2))
|
||||
users14 = db.query(User).filter(User.id.in_(votes3.keys())).all()
|
||||
users13 = []
|
||||
for user in users14:
|
||||
users13.append((user.id, votes3[user.id]-user.post_count-user.comment_count))
|
||||
if not users13: users13 = [(None,None)]
|
||||
users13 = sorted(users13, key=lambda x: x[1], reverse=True)
|
||||
users13_1, users13_2 = zip(*users13[:25])
|
||||
|
||||
db.close()
|
||||
stdout.flush()
|
||||
|
||||
|
||||
gevent.spawn(leaderboard_thread)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@app.get("/@<username>/upvoters/<uid>/posts")
|
||||
@auth_required
|
||||
|
@ -591,13 +555,6 @@ def leaderboard(v):
|
|||
pos7 = g.db.query(sq.c.id, sq.c.rank).filter(sq.c.id == v.id).limit(1).one()[1]
|
||||
|
||||
|
||||
users9_accs = g.db.query(User).filter(User.id.in_(users9_1)).all()
|
||||
users9_accs = sorted(users9_accs, key=lambda x: users9_1.index(x.id))
|
||||
users9_accs = zip(users9_accs, users9_2)
|
||||
try:
|
||||
pos9 = [x[0] for x in users9].index(v.id)
|
||||
pos9 = (pos9+1, users9[pos9][1])
|
||||
except: pos9 = (len(users9)+1, 0)
|
||||
|
||||
users10 = users.order_by(User.truecoins.desc()).limit(25).all()
|
||||
if v in users10:
|
||||
|
@ -624,31 +581,9 @@ def leaderboard(v):
|
|||
users12 = None
|
||||
pos12 = None
|
||||
|
||||
users13_accs = g.db.query(User).filter(User.id.in_(users13_1)).all()
|
||||
users13_accs = sorted(users13_accs, key=lambda x: users13_1.index(x.id))
|
||||
users13_accs = zip(users13_accs, users13_2)
|
||||
try:
|
||||
pos13 = [x[0] for x in users13].index(v.id)
|
||||
pos13 = (pos13+1, users13[pos13][1])
|
||||
except: pos13 = (len(users13)+1, 0)
|
||||
|
||||
# winnings_sq = g.db.query(Casino_Game.user_id, func.sum(Casino_Game.winnings)).group_by(Casino_Game.user_id).subquery()
|
||||
# users14 = g.db.query(User).join(winnings_sq, winnings_sq.c.user_id == User.id).order_by(winnings_sq.c.sum.desc()).limit(25).all()
|
||||
# if v in users14:
|
||||
# pos14 = None
|
||||
# else:
|
||||
# sq = g.db.query(User.id, func.rank().over(order_by=winnings_sq.c.sum.desc()).label("rank")).join(winnings_sq, winnings_sq.c.user_id == User.id).subquery()
|
||||
# pos14 = g.db.query(sq.c.id, sq.c.rank).filter(sq.c.id == v.id).limit(1).one()[1]
|
||||
|
||||
# users15 = g.db.query(User).join(winnings_sq, winnings_sq.c.user_id == User.id).order_by(winnings_sq.c.sum.asc()).limit(25).all()
|
||||
# if v in users15:
|
||||
# pos15 = None
|
||||
# else:
|
||||
# sq = g.db.query(User.id, func.rank().over(order_by=winnings_sq.c.sum.asc()).label("rank")).join(winnings_sq, winnings_sq.c.user_id == User.id).subquery()
|
||||
# pos15 = g.db.query(sq.c.id, sq.c.rank).filter(sq.c.id == v.id).limit(1).one()[1]
|
||||
|
||||
sq = g.db.query(UserBlock.target_id, func.count(UserBlock.target_id).label("count")).group_by(UserBlock.target_id).subquery()
|
||||
users16 = g.db.query(User, sq.c.count).join(User, User.id == sq.c.target_id).order_by(sq.c.count.desc())
|
||||
|
||||
sq = g.db.query(UserBlock.target_id, func.count(UserBlock.target_id).label("count"), func.rank().over(order_by=func.count(UserBlock.target_id).desc()).label("rank")).group_by(UserBlock.target_id).subquery()
|
||||
pos16 = g.db.query(sq.c.rank, sq.c.count).join(User, User.id == sq.c.target_id).filter(sq.c.target_id == v.id).limit(1).one_or_none()
|
||||
if not pos16: pos16 = (users16.count()+1, 0)
|
||||
|
@ -668,9 +603,7 @@ def leaderboard(v):
|
|||
|
||||
return render_template("leaderboard.html", v=v, users1=users1, pos1=pos1, users2=users2, pos2=pos2,
|
||||
users3=users3, pos3=pos3, users4=users4, pos4=pos4, users5=users5, pos5=pos5,
|
||||
users7=users7, pos7=pos7, users9=users9_accs, pos9=pos9,
|
||||
users10=users10, pos10=pos10, users11=users11, pos11=pos11, users12=users12, pos12=pos12,
|
||||
users13=users13_accs, pos13=pos13, users16=users16, pos16=pos16, users17=users17, pos17=pos17, users18=users18, pos18=pos18)
|
||||
users7=users7, pos7=pos7, users10=users10, pos10=pos10, users11=users11, pos11=pos11, users12=users12, pos12=pos12, users16=users16, pos16=pos16, users17=users17, pos17=pos17, users18=users18, pos18=pos18)
|
||||
|
||||
@app.get("/<id>/css")
|
||||
def get_css(id):
|
||||
|
|
|
@ -31,17 +31,6 @@
|
|||
{{v.css | safe}}
|
||||
</style>
|
||||
{% endif %}
|
||||
|
||||
{% if v.earlylife %}
|
||||
<style>
|
||||
.nav-item .text-small.font-weight-bold::before {
|
||||
content: "((("
|
||||
}
|
||||
.nav-item .text-small.font-weight-bold::after {
|
||||
content: ")))"
|
||||
}
|
||||
</style>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<style>:root{--primary:#{{DEFAULT_COLOR}}</style>
|
||||
<link rel="stylesheet" href="{{'css/main.css' | asset}}">
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div class="modal fade" id="awardModal" tabindex="-1" role="dialog" aria-labelledby="awardModalTitle" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-scrollable modal-dialog-centered awardmodal my-5" role="document">
|
||||
<div class="modal-dialog modal-dialog-scrollable modal-dialog-centered awardmodal pt-5" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Give Award</h5>
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
{% for user in users %}
|
||||
<tr>
|
||||
<td>{{loop.index}}</td>
|
||||
<td><a style="font-weight:bold;color:#{{user.name_color}}" href="/@{{user.username}}"><span {% if user.patron %}class="patron" style="background-color:#{{user.name_color}}"{% endif %}>{{user.username}}</span></a></td>
|
||||
<td><a style="font-weight:bold;color:#{{targets[loop.index-1].name_color}}" href="/@{{targets[loop.index-1].username}}"><span {% if targets[loop.index-1].patron %}class="patron" style="background-color:#{{targets[loop.index-1].name_color}}"{% endif %}>{{targets[loop.index-1].username}}</span></a></td>
|
||||
<td><a style="font-weight:bold;color:#{{user.name_color}}" href="/@{{user.username}}"><span {% if user.patron %}class="patron" style="background-color:#{{user.name_color}}"{% endif %}>{{user.user_name}}</span></a></td>
|
||||
<td><a style="font-weight:bold;color:#{{targets[loop.index-1].name_color}}" href="/@{{targets[loop.index-1].username}}"><span {% if targets[loop.index-1].patron %}class="patron" style="background-color:#{{targets[loop.index-1].name_color}}"{% endif %}>{{targets[loop.index-1].user_name}}</span></a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
|
|
@ -28,17 +28,6 @@
|
|||
{{v.css | safe}}
|
||||
</style>
|
||||
{% endif %}
|
||||
|
||||
{% if v.earlylife %}
|
||||
<style>
|
||||
.nav-item .text-small.font-weight-bold::before {
|
||||
content: "((("
|
||||
}
|
||||
.nav-item .text-small.font-weight-bold::after {
|
||||
content: ")))"
|
||||
}
|
||||
</style>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<style>:root{--primary:#{{DEFAULT_COLOR}}</style>
|
||||
<link rel="stylesheet" href="{{'css/main.css' | asset}}">
|
||||
|
@ -289,7 +278,8 @@
|
|||
<img alt="site banner" src="{{banner}}" width="100%">
|
||||
{% else %}
|
||||
{% if SITE_NAME == 'PCM' %}
|
||||
{% set banner = 'banners/halloween.webp' | asset_siteimg %}
|
||||
{% set path = "assets/images/" + SITE_NAME + "/banners" %}
|
||||
{% set banner = "/" + path + "/" + listdir('files/' + path)|max + '?v=1' %}
|
||||
{% else %}
|
||||
{% set banner = 'banner.webp' | asset_siteimg %}
|
||||
{% endif %}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#emojiTabs {height: 80%;}
|
||||
@media (max-width: 650px) {
|
||||
#emojiTabs {height: 100%;}
|
||||
#emojiModalInternalDivIDK {margin-top: 0 !important; margin-bottom: 0 !important; padding-top: 0 !important; padding-bottom: 0 !important;}
|
||||
#emojiModalInternalDivIDK {margin-top: 0 !important; margin-bottom: 0 !important; padding-top: 3rem !important; padding-bottom: 0 !important;}
|
||||
|
||||
#emoji-modal-tabs-container {
|
||||
overflow-x: auto;
|
||||
|
@ -20,7 +20,7 @@
|
|||
}
|
||||
}
|
||||
</style>
|
||||
<div id="emojiModalInternalDivIDK" class="modal-dialog modal-dialog-scrollable modal-dialog-centered p-2 py-5 emoji-modal" role="document">
|
||||
<div id="emojiModalInternalDivIDK" class="modal-dialog modal-dialog-scrollable modal-dialog-centered emoji-modal" role="document">
|
||||
<div class="modal-content" id="emojiTabs">
|
||||
<div class="modal-header">
|
||||
<div id="emoji-modal-tabs-container">
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{% extends "default.html" %}
|
||||
|
||||
{% block title %}
|
||||
<title>Max file size is 8 MB (16 MB for paypigs)</title>
|
||||
<title>Max image/audio size is 8 MB (16 MB for paypigs)</title>
|
||||
{% endblock %}
|
||||
|
||||
{% block pagetype %}error-413{% endblock %}
|
||||
|
@ -12,7 +12,7 @@
|
|||
<div class="text-center px-3 my-8">
|
||||
<img alt=":#marseyretard:" loading="lazy" src="/e/marseychonker2.webp">
|
||||
<pre></pre>
|
||||
<h1 class="h5">Max file size is 8 MB (16 MB for paypigs)</h1>
|
||||
<h1 class="h5">Max image/audio size is 8 MB (16 MB for paypigs)</h1>
|
||||
<div><a href="/" class="btn btn-primary">Go to frontpage</a></div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
{% extends "default.html" %}
|
||||
|
||||
{% block title %}
|
||||
<title>Max video size is 32 MB (64 MB for paypigs)</title>
|
||||
{% endblock %}
|
||||
|
||||
{% block pagetype %}error-414{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-10 col-md-5">
|
||||
<div class="text-center px-3 my-8">
|
||||
<img alt=":#marseyretard:" loading="lazy" src="/e/marseychonker2.webp">
|
||||
<pre></pre>
|
||||
<h1 class="h5">Max video size is 32 MB (64 MB for paypigs)</h1>
|
||||
<div><a href="/" class="btn btn-primary">Go to frontpage</a></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -68,14 +68,16 @@
|
|||
<style>
|
||||
{% if g.webview %}
|
||||
@media (min-width: 480px) {
|
||||
{% elif SITE_NAME == 'WPD' %}
|
||||
@media (min-width: 1000px) {
|
||||
{% else %}
|
||||
@media (min-width: 380px) {
|
||||
{% endif %}
|
||||
#logo {
|
||||
width: 100px;
|
||||
margin-left: 0.5rem !important;
|
||||
}
|
||||
}
|
||||
{% endif %}
|
||||
</style>
|
||||
<div id="logo-container" class="flex-grow-1 logo-container">
|
||||
<a href="/">
|
||||
|
@ -222,7 +224,7 @@
|
|||
{%- endif %}
|
||||
</div>
|
||||
<div class="text-left pl-2">
|
||||
<div style="color: #{{v.name_color}}" class="text-small font-weight-bold"><span id="header--username" {% if v.patron %}class="patron" style="background-color:#{{v.name_color}}"{% endif %}>{{v.username}}</span></div>
|
||||
<div style="color: #{{v.name_color}}" class="text-small font-weight-bold"><span id="header--username" {% if v.patron %}class="patron" style="background-color:#{{v.name_color}}"{% endif %}>{{v.user_name}}</span></div>
|
||||
<div class="header--currency"><img alt="coins" class="mr-1 ml-1" data-bs-toggle="tooltip" data-bs-placement="bottom" src="{{'coins.webp' | asset_siteimg}}" title="coins" aria-label="coins"><span id="user-coins-amount">{{v.coins}}</span>{% if not FEATURES['PROCOINS'] %} Coin{{ help.plural(v.coins) }}{% endif %}</div>
|
||||
{% if FEATURES['PROCOINS'] %}
|
||||
<div class="header--currency"><img alt="marseybux" class="mr-1 ml-1" data-bs-toggle="tooltip" data-bs-placement="bottom" src="/i/marseybux.webp?v=2000" title="Marseybux" aria-label="Marseybux"><span id="user-bux-amount">{{v.procoins}}</span></div>
|
||||
|
|
|
@ -6,19 +6,17 @@
|
|||
<pre class="d-none d-md-inline-block"></pre>
|
||||
<div id="leaderboard-contents" style="text-align: center; margin-bottom: 1.5rem; font-size: 1.2rem;">
|
||||
<a href="#leaderboard-coins">Coins</a> •
|
||||
<a href="#leaderboard-spent">Spent in Shop</a> •
|
||||
<a href="#leaderboard-spent">Spent in shop</a> •
|
||||
<a href="#leaderboard-truescore">Truescore</a> •
|
||||
<a href="#leaderboard-followers">Followers</a> •
|
||||
<a href="#leaderboard-posts">Posts</a> •
|
||||
<a href="#leaderboard-comments">Comments</a> •
|
||||
<a href="#leaderboard-awards">Awards</a> •
|
||||
<a href="#leaderboard-downvotes">Downvotes</a> •
|
||||
<a href="#leaderboard-badges">Badges</a> •
|
||||
{% if users12 %}<a href="#leaderboard-marseys">Marseys</a> • {% endif %}
|
||||
{% if users13 %}<a href="#leaderboard-upgiven">Upvotes Given</a> • {% endif %}
|
||||
<a href="#leaderboard-blocked">Blocked</a> •
|
||||
<a href="#leaderboard-owned-hats">Owned Hats</a> •
|
||||
<a href="#leaderboard-designed-hats">Designed Hats</a>
|
||||
<a href="#leaderboard-owned-hats">Owned hats</a> •
|
||||
<a href="#leaderboard-designed-hats">Designed hats</a>
|
||||
</div>
|
||||
|
||||
<h5 class="font-weight-bolder text-center pt-2 pb-3"><a id="leaderboard-coins">Top 25 by coins</a></h5>
|
||||
|
@ -234,39 +232,6 @@
|
|||
{% endif %}
|
||||
</table>
|
||||
|
||||
<h5 class="font-weight-bolder text-center pt-2 pb-3"><a id="leaderboard-downvotes">Top 25 by received downvotes</a></h5>
|
||||
|
||||
<div class="overflow-x-auto"><table class="table table-striped mb-5">
|
||||
<thead class="bg-primary text-white">
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Name</th>
|
||||
<th>Downvotes</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for user, num in users9 %}
|
||||
<tr {% if v.id == user.id %}class="self"{% endif %}>
|
||||
<td>{{loop.index}}</td>
|
||||
<td>{% include "user_in_table.html" %}</td>
|
||||
<td>{{"{:,}".format(num)}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% if pos9 and (pos9[0] > 25 or not pos9[1]) %}
|
||||
<tr style="border-top:2px solid var(--primary)">
|
||||
<td>{{pos9[0]}}</td>
|
||||
<td>
|
||||
{% with user=v %}
|
||||
{% include "user_in_table.html" %}
|
||||
{% endwith %}
|
||||
</td>
|
||||
<td>{{"{:,}".format(pos9[1])}}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
<h5 class="font-weight-bolder text-center pt-2 pb-3"><a id="leaderboard-badges">Top 25 by badges</a></h5>
|
||||
|
||||
<div class="overflow-x-auto"><table class="table table-striped mb-5">
|
||||
|
@ -303,7 +268,7 @@
|
|||
|
||||
{% if users12 %}
|
||||
|
||||
<h5 class="font-weight-bolder text-center pt-2 pb-3"><a id="leaderboard-marseys">Top 25 by marseys made</a></h5>
|
||||
<h5 class="font-weight-bolder text-center pt-2 pb-3"><a id="leaderboard-marseys">Top 25 by Marseys made</a></h5>
|
||||
|
||||
<div class="overflow-x-auto"><table class="table table-striped mb-5">
|
||||
<thead class="bg-primary text-white">
|
||||
|
@ -336,41 +301,7 @@
|
|||
</table>
|
||||
{% endif %}
|
||||
|
||||
{% if users13 %}
|
||||
<h5 class="font-weight-bolder text-center pt-2 pb-3"><a id="leaderboard-upgiven">Top 25 by upvotes given</a></h5>
|
||||
|
||||
<div class="overflow-x-auto"><table class="table table-striped mb-5">
|
||||
<thead class="bg-primary text-white">
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Name</th>
|
||||
<th>Upvotes</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for user, num in users13 %}
|
||||
<tr {% if v.id == user.id %}class="self"{% endif %}>
|
||||
<td>{{loop.index}}</td>
|
||||
<td>{% include "user_in_table.html" %}</td>
|
||||
<td>{{"{:,}".format(num)}}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% if pos13 and (pos13[0] > 25 or not pos13[1]) %}
|
||||
<tr style="border-top:2px solid var(--primary)">
|
||||
<td>{{pos13[0]}}</td>
|
||||
<td>
|
||||
{% with user=v %}
|
||||
{% include "user_in_table.html" %}
|
||||
{% endwith %}
|
||||
</td>
|
||||
<td>{{"{:,}".format(pos13[1])}}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
<h5 class="font-weight-bolder text-center pt-2 pb-3"><a id="leaderboard-blocked">Top 25 Most Blocked</a></h5>
|
||||
<h5 class="font-weight-bolder text-center pt-2 pb-3"><a id="leaderboard-blocked">Top 25 most blocked</a></h5>
|
||||
|
||||
<div class="overflow-x-auto"><table class="table table-striped mb-5">
|
||||
<thead class="bg-primary text-white">
|
||||
|
@ -401,7 +332,7 @@
|
|||
</table>
|
||||
|
||||
|
||||
<h5 class="font-weight-bolder text-center pt-2 pb-3"><a id="leaderboard-owned-hats">Top 25 by Owned Hats</a></h5>
|
||||
<h5 class="font-weight-bolder text-center pt-2 pb-3"><a id="leaderboard-owned-hats">Top 25 by owned hats</a></h5>
|
||||
|
||||
<div class="overflow-x-auto"><table class="table table-striped mb-5">
|
||||
<thead class="bg-primary text-white">
|
||||
|
@ -431,7 +362,7 @@
|
|||
{% endif %}
|
||||
</table>
|
||||
|
||||
<h5 class="font-weight-bolder text-center pt-2 pb-3"><a id="leaderboard-designed-hats">Top 25 by Designed Hats</a></h5>
|
||||
<h5 class="font-weight-bolder text-center pt-2 pb-3"><a id="leaderboard-designed-hats">Top 25 by designed hats</a></h5>
|
||||
|
||||
<div class="overflow-x-auto"><table class="table table-striped mb-5">
|
||||
<thead class="bg-primary text-white">
|
||||
|
|
|
@ -19,17 +19,6 @@
|
|||
{{v.css | safe}}
|
||||
</style>
|
||||
{% endif %}
|
||||
|
||||
{% if v.earlylife %}
|
||||
<style>
|
||||
.nav-item .text-small.font-weight-bold::before {
|
||||
content: "((("
|
||||
}
|
||||
.nav-item .text-small.font-weight-bold::after {
|
||||
content: ")))"
|
||||
}
|
||||
</style>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<style>:root{--primary:#{{DEFAULT_COLOR}}</style>
|
||||
<link rel="stylesheet" href="{{'css/main.css' | asset}}">
|
||||
|
|
|
@ -46,17 +46,6 @@
|
|||
{{v.css | safe}}
|
||||
</style>
|
||||
{% endif %}
|
||||
|
||||
{% if v.earlylife %}
|
||||
<style>
|
||||
.nav-item .text-small.font-weight-bold::before {
|
||||
content: "((("
|
||||
}
|
||||
.nav-item .text-small.font-weight-bold::after {
|
||||
content: ")))"
|
||||
}
|
||||
</style>
|
||||
{% endif %}
|
||||
</head>
|
||||
|
||||
<body id="settings" {% if SITE_NAME == 'rDrama' and v and (v.is_banned or v.agendaposter) %}style="overflow-x: hidden;background:url(/assets/images/backgrounds/anime/1.webp?v=3) center center fixed; background-color: var(--background)"{% elif v and v.background %}style="overflow-x: hidden;background:url(/assets/images/backgrounds/{{v.background}}?v=3) center center fixed; background-color: var(--background){% if 'anime' not in v.background %};background-size: cover{% endif %}"{% endif %}>
|
||||
|
|
|
@ -23,9 +23,8 @@
|
|||
<a class="btn btn-primary btn-block" href="/create_hole">CREATE {{HOLE_NAME|upper}}</a>
|
||||
{%- endif %}
|
||||
<a class="btn btn-primary btn-block" href="/holes">BROWSE {{HOLE_NAME|upper}}S</a>
|
||||
<a class="btn btn-primary btn-block mt-5" href="/">
|
||||
<span style="display: block;font-size: 1.35rem;">STREAM LIST</span>
|
||||
<span style="display: block;font-size: 0.85rem;">Coming Sometime 2022</span>
|
||||
<a class="btn btn-primary btn-block mt-5" href="/live">
|
||||
<span style="display: block; font-size: 1.5rem; line-height: 2;">LIVE LIST</span>
|
||||
</a>
|
||||
<a class="btn btn-primary btn-block" href="/post/4103">BUGS/SUGGESTIONS MEGATHREAD</a>
|
||||
<a class="btn btn-primary btn-block" href="/post/9694" >OFFICIAL CONSPIRACY THEORY THREAD</a>
|
||||
|
|
|
@ -112,7 +112,7 @@
|
|||
required="">
|
||||
<div class="custom-control custom-checkbox mt-4">
|
||||
<input autocomplete="off" type="checkbox" class="custom-control-input" id="termsCheck" required>
|
||||
<label class="custom-control-label terms" for="termsCheck">I accept the <a href="/logged_out/sidebar">rules</a></label>
|
||||
<label class="custom-control-label terms" for="termsCheck">I accept the <a href="/sidebar">rules</a></label>
|
||||
</div>
|
||||
|
||||
{% if hcaptcha %}
|
||||
|
|
|
@ -44,17 +44,6 @@
|
|||
<link rel="stylesheet" href="{{'css/main.css' | asset}}">
|
||||
<link rel="stylesheet" href="{{('css/'~DEFAULT_THEME~'.css') | asset}}">
|
||||
{% endif %}
|
||||
|
||||
{% if v.earlylife %}
|
||||
<style>
|
||||
.nav-item .text-small.font-weight-bold::before {
|
||||
content: "((("
|
||||
}
|
||||
.nav-item .text-small.font-weight-bold::after {
|
||||
content: ")))"
|
||||
}
|
||||
</style>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</head>
|
||||
|
||||
|
|
|
@ -5,5 +5,5 @@
|
|||
<img class="profile-pic-20-hat hat" loading="lazy" src="{{user.hat_active}}?h=7" data-bs-toggle="tooltip" data-bs-placement="bottom" title="{{user.hat_tooltip(v)}}">
|
||||
{%- endif %}
|
||||
</div>
|
||||
<span {% if user.patron %}class="patron" style="background-color:#{{user.name_color}}"{% endif %}>{{user.username}}</span>
|
||||
<span {% if user.patron %}class="patron" style="background-color:#{{user.name_color}}"{% endif %}>{{user.user_name}}</span>
|
||||
</a>
|
|
@ -67,7 +67,7 @@
|
|||
</h5>
|
||||
{% endif %}
|
||||
<div class="d-flex align-items-center mt-1 mb-2">
|
||||
<h1 class="font-weight-bolder h3 my-0 mr-2" id="profile--name" style="color: #{{u.name_color}}"><span {% if u.patron %}class="patron" style="background-color:#{{u.name_color}}"{% endif %}>{{u.username}}</span></h1>
|
||||
<h1 class="font-weight-bolder h3 my-0 mr-2" id="profile--name" style="color: #{{u.name_color}}"><span {% if u.patron %}class="patron" style="background-color:#{{u.name_color}}"{% endif %}>{{u.user_name}}</span></h1>
|
||||
|
||||
{% if u.username != u.original_username %}
|
||||
<span id="profile--origname">
|
||||
|
@ -445,7 +445,7 @@
|
|||
<h5 class="text-primary" id="profile-mobile--banned">SHADOWBANNED USER{% if u.ban_reason %}: {{u.ban_reason | safe}}{% endif %} (by <a href="/@{{u.shadowbanned}}">@{{u.shadowbanned}}</a>)</h5>
|
||||
{% endif %}
|
||||
|
||||
<h1 class="h5 d-inline-block" id="profile-mobile--name" style="color: #{{u.name_color}}"><span {% if u.patron %}class="patron" style="background-color:#{{u.name_color}}"{% endif %}>{{u.username}}</span></h1>
|
||||
<h1 class="h5 d-inline-block" id="profile-mobile--name" style="color: #{{u.name_color}}"><span {% if u.patron %}class="patron" style="background-color:#{{u.name_color}}"{% endif %}>{{u.user_name}}</span></h1>
|
||||
|
||||
{% if u.username != u.original_username %}
|
||||
<span id="profile-mobile--origname">
|
||||
|
|
|
@ -5,7 +5,7 @@ from files.__main__ import app
|
|||
# these tests require `docker-compose up` first
|
||||
|
||||
def test_rules():
|
||||
response = app.test_client().get("/logged_out/rules")
|
||||
response = app.test_client().get("/sidebar")
|
||||
assert response.status_code == 200
|
||||
assert response.text.startswith("<!DOCTYPE html>")
|
||||
|
||||
|
|
|
@ -14,10 +14,10 @@ server {
|
|||
proxy_buffering off;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "Upgrade";
|
||||
proxy_pass http://127.0.0.1:5001/socket.io;
|
||||
proxy_pass http://localhost:5001/socket.io;
|
||||
}
|
||||
location /chat {
|
||||
proxy_pass http://127.0.0.1:5001/chat;
|
||||
proxy_pass http://localhost:5001/chat;
|
||||
}
|
||||
|
||||
location /images/ {
|
||||
|
|
1372
redis.conf
40
schema.sql
|
@ -166,8 +166,7 @@ CREATE TABLE public.award_relationships (
|
|||
comment_id integer,
|
||||
kind character varying(20) NOT NULL,
|
||||
awarded_utc integer,
|
||||
created_utc integer,
|
||||
granted_by integer
|
||||
created_utc integer
|
||||
);
|
||||
|
||||
|
||||
|
@ -561,6 +560,19 @@ CREATE TABLE public.marseys (
|
|||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: media; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public.media (
|
||||
kind character varying(5) NOT NULL,
|
||||
filename character varying(55) NOT NULL,
|
||||
user_id integer NOT NULL,
|
||||
created_utc integer NOT NULL,
|
||||
size integer NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: modactions; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
@ -1319,6 +1331,14 @@ ALTER TABLE ONLY public.marseys
|
|||
ADD CONSTRAINT marseys_pkey PRIMARY KEY (name);
|
||||
|
||||
|
||||
--
|
||||
-- Name: media media_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.media
|
||||
ADD CONSTRAINT media_pkey PRIMARY KEY (kind, filename);
|
||||
|
||||
|
||||
--
|
||||
-- Name: modactions modactions_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
@ -2080,14 +2100,6 @@ ALTER TABLE ONLY public.award_relationships
|
|||
ADD CONSTRAINT award_comment_fkey FOREIGN KEY (comment_id) REFERENCES public.comments(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: award_relationships award_granted_by_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.award_relationships
|
||||
ADD CONSTRAINT award_granted_by_fkey FOREIGN KEY (granted_by) REFERENCES public.users(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: award_relationships award_submission_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
@ -2352,6 +2364,14 @@ ALTER TABLE ONLY public.marseys
|
|||
ADD CONSTRAINT marsey_submitter_fkey FOREIGN KEY (submitter_id) REFERENCES public.users(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: media media_user_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.media
|
||||
ADD CONSTRAINT media_user_fkey FOREIGN KEY (user_id) REFERENCES public.users(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: mods mod_sub_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
|
|
@ -283,6 +283,7 @@ INSERT INTO public.hat_defs VALUES (781, 'BTC', 'Only wear this if you''re worth
|
|||
|
||||
|
||||
|
||||
|
||||
INSERT INTO public.hat_defs VALUES (723, 'Hohol', 'Мій предок :)', 2, 500, NULL, 1663892328);
|
||||
INSERT INTO public.hat_defs VALUES (750, 'Cave Man', 'UNGA BUNGA UNGA BUNGA OOO OOO', 2, 500, NULL, 1664595865);
|
||||
INSERT INTO public.hat_defs VALUES (753, 'Doom Guy', 'RIP AND TEAR', 2, 500, NULL, 1664595933);
|
||||
|
@ -938,7 +939,7 @@ INSERT INTO public.hat_defs VALUES (504, 'Iron Crown of Lombardy', 'This isn''t
|
|||
-- Name: hat_defs_id_seq; Type: SEQUENCE SET; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
SELECT pg_catalog.setval('public.hat_defs_id_seq', 802, true);
|
||||
SELECT pg_catalog.setval('public.hat_defs_id_seq', 803, true);
|
||||
|
||||
|
||||
--
|
||||
|
@ -1202,6 +1203,8 @@ INSERT INTO public.marseys (name, author_id, tags, created_utc) VALUES
|
|||
('marseycapitalistmanlet',2,'money top hat rich landlord cigar llm tophat',NULL),
|
||||
('marseycapy',2,'capybara rodent aevann happy cute',NULL),
|
||||
('marseycapy2022',2,'aevann caypbara new year party celebration',NULL),
|
||||
('marseycapyautism',2,'capy aevann autism hat patient capybara',1665095792),
|
||||
('marseycapyautismchad',2,'capy aevann autism hat patient capybara chad gigachad',1665098772),
|
||||
('marseycapybigbrain',2,'capybara aevann smart codecel brain',NULL),
|
||||
('marseycapyblackface',2,'racist minstrelsy bowtie racism capybara aevann',NULL),
|
||||
('marseycapyblowkiss',2,'capybara rodent aevann happy cute love',NULL),
|
||||
|
@ -2586,6 +2589,9 @@ INSERT INTO public.marseys (name, author_id, tags, created_utc) VALUES
|
|||
('marseyvibing',2,'animated bopping vibe jam dancing headbang music rainbow dance',NULL),
|
||||
('marseyvietnam',2,'army born to kill soldier war',NULL),
|
||||
('marseyvirus',2,'phage infect infection plagued',NULL),
|
||||
('marseyvore',2,'eating cannibalism cannibalize fetish kinky digest trapped letmeout',1665074856),
|
||||
('marseyvore2',2,'eating marcus cannibalize cannibalism fetish kinky',1665074817),
|
||||
('marseyvorezombiewolf',2,'furry furfag food eat yum degenerate fetish hungry',1665041705),
|
||||
('marseyw',2,'win winner dub',NULL),
|
||||
('marseywagie',2,'crypto rightoid ancap poor wagecuck mcdonalds maccas reaction',NULL),
|
||||
('marseywait',2,'time watch wait waiting bored',NULL),
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
alter table award_relationships add column granted_by int;
|
||||
ALTER TABLE ONLY public.award_relationships
|
||||
ADD CONSTRAINT award_granted_by_fkey FOREIGN KEY (granted_by) REFERENCES public.users(id);
|
||||
update award_relationships set granted_by=1 where granted=true;
|
||||
alter table award_relationships drop column granted;
|
|
@ -0,0 +1,13 @@
|
|||
CREATE TABLE public.media (
|
||||
kind character varying(5) NOT NULL,
|
||||
filename character varying(55) NOT NULL,
|
||||
user_id Integer NOT NULL,
|
||||
created_utc integer NOT NULL,
|
||||
size integer NOT NULL
|
||||
);
|
||||
|
||||
ALTER TABLE ONLY public.media
|
||||
ADD CONSTRAINT media_pkey PRIMARY KEY (kind, filename);
|
||||
|
||||
ALTER TABLE ONLY public.media
|
||||
ADD CONSTRAINT media_user_fkey FOREIGN KEY (user_id) REFERENCES public.users(id);
|
|
@ -1,7 +1,4 @@
|
|||
# locale-gen "en_US.UTF-8"
|
||||
# update-locale LANG=en_US.utf8
|
||||
# update-locale LC_ALL=en_US.utf8
|
||||
# reboot
|
||||
|
||||
apt -y update
|
||||
apt -y upgrade
|
||||
apt -y install git redis-server python3-pip ffmpeg imagemagick tmux nginx snapd ufw gpg-agent htop nano
|
||||
|
|