forked from MarseyWorld/MarseyWorld
add form to submit banners and sidebar images
parent
b781bbeced
commit
5b9dd4a8c4
|
@ -28,8 +28,10 @@ RUN mkdir /temp_songs
|
|||
RUN mkdir /videos
|
||||
RUN mkdir /audio
|
||||
RUN mkdir /asset_submissions
|
||||
RUN mkdir /asset_submissions/art
|
||||
RUN mkdir /asset_submissions/emojis
|
||||
RUN mkdir /asset_submissions/hats
|
||||
RUN mkdir /asset_submissions/art/original
|
||||
RUN mkdir /asset_submissions/emojis/original
|
||||
RUN mkdir /asset_submissions/hats/original
|
||||
RUN mkdir /var/log/rdrama
|
||||
|
|
|
@ -173,7 +173,7 @@
|
|||
.fa-bell-slash:before{content:"\f1f6"}
|
||||
.fa-chart-network:before{content:"\f78a"}
|
||||
.fa-square-share-nodes:before{content:"\f1e1"}
|
||||
.fa-sidebar:before{content:"\e24e"}
|
||||
.fa-sidebar-flip:before{content:"\e24f"}
|
||||
.fa-landscape:before{content:"\e1b5"}
|
||||
.fa-external-link:before{content:"\f08e"}
|
||||
.fa-circle-info:before{content:"\f05a"}
|
||||
|
@ -3690,7 +3690,7 @@ ol > li::before {
|
|||
}
|
||||
.settings-nav > .nav-item > .nav-link.active, .settings-nav > .nav-item > .nav-link:focus, .settings-nav > .nav-item > .nav-link:hover {
|
||||
color: var(--primary);
|
||||
box-shadow: inset 0 -2px 0 var(--primary);
|
||||
border-bottom: 3px solid var(--primary);
|
||||
}
|
||||
.post-nav .nav-link:hover, .post-nav .nav-link:focus, .settings-nav .nav-link:hover, .settings-nav .nav-link:focus {
|
||||
color: var(--primary);
|
||||
|
@ -3708,7 +3708,7 @@ ol > li::before {
|
|||
}
|
||||
.settings-nav > .nav-item > .nav-link.active {
|
||||
color: var(--primary);
|
||||
box-shadow: inset 0 -2px 0 var(--primary);
|
||||
border-bottom: 3px solid var(--primary);
|
||||
}
|
||||
.settings-nav > .nav-item > .nav-link.active .fa, .settings-nav > .nav-item > .nav-link.active .fas, .settings-nav > .nav-item > .nav-link.active .far, .settings-nav > .nav-item > .nav-link.active .fab {
|
||||
color: var(--primary);
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
function approve_art(t, id) {
|
||||
postToast(t, `/admin/approve/art/${id}`,
|
||||
{
|
||||
"comment": document.getElementById(`${id}-comment`).value,
|
||||
"author": document.getElementById(`${id}-author`).value,
|
||||
},
|
||||
() => {
|
||||
document.getElementById(`${id}-art`).remove()
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function remove_art(t, id) {
|
||||
postToast(t, `/remove/art/${id}`,
|
||||
{
|
||||
"comment": document.getElementById(`${id}-comment`).value,
|
||||
},
|
||||
() => {
|
||||
document.getElementById(`${id}-art`).remove()
|
||||
}
|
||||
);
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
import time
|
||||
|
||||
from sqlalchemy import Column, ForeignKey
|
||||
from sqlalchemy.sql.sqltypes import *
|
||||
from files.classes import Base
|
||||
from files.helpers.lazy import lazy
|
||||
|
||||
sidebar_hashes = {}
|
||||
banner_hashes = {}
|
||||
|
||||
class ArtSubmission(Base):
|
||||
__tablename__ = "art_submissions"
|
||||
id = Column(Integer, primary_key=True)
|
||||
kind = Column(String)
|
||||
author_id = Column(Integer, ForeignKey("users.id"))
|
||||
submitter_id = Column(Integer, ForeignKey("users.id"))
|
||||
created_utc = Column(Integer)
|
||||
approved = Column(Boolean, default=False)
|
||||
|
||||
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"<{self.__class__.__name__}(id={self.id})>"
|
||||
|
||||
@property
|
||||
@lazy
|
||||
def badge_id(self):
|
||||
return 99 if self.kind == "sidebar" else 101
|
||||
|
||||
@property
|
||||
@lazy
|
||||
def resize(self):
|
||||
return 600 if self.kind == "sidebar" else 1600
|
||||
|
||||
@property
|
||||
@lazy
|
||||
def location_kind(self):
|
||||
return 'sidebar' if self.kind == "sidebar" else 'banners'
|
||||
|
||||
@property
|
||||
@lazy
|
||||
def formatted_kind(self):
|
||||
return 'sidebar image' if self.kind == "sidebar" else 'banner'
|
||||
|
||||
@property
|
||||
@lazy
|
||||
def msg_kind(self):
|
||||
return 'Sidebar image' if self.kind == "sidebar" else 'Banner'
|
||||
|
||||
@property
|
||||
@lazy
|
||||
def hashes(self):
|
||||
return sidebar_hashes if self.kind == "sidebar" else banner_hashes
|
|
@ -246,6 +246,7 @@ FEATURES = {
|
|||
'PATRON_ICONS': False,
|
||||
'EMOJI_SUBMISSIONS': True,
|
||||
'HAT_SUBMISSIONS': True,
|
||||
'ART_SUBMISSIONS': True,
|
||||
'NSFW_MARKING': True,
|
||||
'PING_GROUPS': True,
|
||||
'IP_LOGGING': False,
|
||||
|
@ -589,16 +590,11 @@ LOTTERY_DURATION = 60 * 60 * 24 * 7
|
|||
|
||||
BUG_THREAD = 0
|
||||
|
||||
SIDEBAR_THREAD = 0
|
||||
BANNER_THREAD = 0
|
||||
BADGE_THREAD = 0
|
||||
SNAPPY_THREAD = 0
|
||||
CHANGELOG_THREAD = 0
|
||||
POLL_THREAD = 0
|
||||
ADMIGGER_THREADS = {SIDEBAR_THREAD, BANNER_THREAD, BADGE_THREAD, SNAPPY_THREAD, CHANGELOG_THREAD, POLL_THREAD}
|
||||
|
||||
SIDEBAR_REQUEST_THREAD = 0
|
||||
BANNER_REQUEST_THREAD = 0
|
||||
ADMIGGER_THREADS = {BADGE_THREAD, SNAPPY_THREAD, CHANGELOG_THREAD, POLL_THREAD}
|
||||
|
||||
MAX_IMAGE_SIZE_BANNER_RESIZED_MB = 2
|
||||
MAX_IMAGE_AUDIO_SIZE_MB = 8
|
||||
|
@ -654,16 +650,11 @@ if SITE in {'rdrama.net', 'staging.rdrama.net'}:
|
|||
|
||||
BUG_THREAD = 18459
|
||||
|
||||
SIDEBAR_THREAD = 37696
|
||||
BANNER_THREAD = 37697
|
||||
BADGE_THREAD = 37833
|
||||
SNAPPY_THREAD = 37749
|
||||
CHANGELOG_THREAD = 165657
|
||||
POLL_THREAD = 79285
|
||||
ADMIGGER_THREADS = {SIDEBAR_THREAD, BANNER_THREAD, BADGE_THREAD, SNAPPY_THREAD, CHANGELOG_THREAD, POLL_THREAD, 166300, 187078}
|
||||
|
||||
SIDEBAR_REQUEST_THREAD = 75878
|
||||
BANNER_REQUEST_THREAD = 35835
|
||||
ADMIGGER_THREADS = {BADGE_THREAD, SNAPPY_THREAD, CHANGELOG_THREAD, POLL_THREAD, 166300, 187078}
|
||||
|
||||
TRUESCORE_MINIMUM = 10
|
||||
|
||||
|
@ -767,16 +758,11 @@ elif SITE in {'watchpeopledie.tv', 'marsey.world'}:
|
|||
|
||||
BUG_THREAD = 61549
|
||||
|
||||
SIDEBAR_THREAD = 5403
|
||||
BANNER_THREAD = 9869
|
||||
BADGE_THREAD = 52519
|
||||
SNAPPY_THREAD = 67186
|
||||
CHANGELOG_THREAD = 56363
|
||||
POLL_THREAD = 22937
|
||||
ADMIGGER_THREADS = {SIDEBAR_THREAD, BANNER_THREAD, BADGE_THREAD, SNAPPY_THREAD, CHANGELOG_THREAD, POLL_THREAD, 106665}
|
||||
|
||||
SIDEBAR_REQUEST_THREAD = 29630
|
||||
BANNER_REQUEST_THREAD = 29629
|
||||
ADMIGGER_THREADS = {BADGE_THREAD, SNAPPY_THREAD, CHANGELOG_THREAD, POLL_THREAD, 106665}
|
||||
|
||||
MAX_VIDEO_SIZE_MB = 500
|
||||
MAX_VIDEO_SIZE_MB_PATRON = 500
|
||||
|
|
|
@ -416,26 +416,46 @@ MODACTION_TYPES = {
|
|||
"icon": 'fa-cat',
|
||||
"color": 'bg-success'
|
||||
},
|
||||
'approve_hat': {
|
||||
"str": 'approved hat',
|
||||
"icon": 'fa-hat-cowboy',
|
||||
'approve_sidebar': {
|
||||
"str": 'approved a sidebar image made by {self.target_link}',
|
||||
"icon": 'fa-sidebar-flip',
|
||||
"color": 'bg-success'
|
||||
},
|
||||
'reject_hat': {
|
||||
"str": 'rejected hat',
|
||||
"icon": 'fa-hat-cowboy',
|
||||
'reject_sidebar': {
|
||||
"str": 'rejected a sidebar image made by {self.target_link}',
|
||||
"icon": 'fa-sidebar-flip',
|
||||
"color": 'bg-danger'
|
||||
},
|
||||
'approve_banner': {
|
||||
"str": 'approved a banner made by {self.target_link}',
|
||||
"icon": 'fa-landscape',
|
||||
"color": 'bg-success'
|
||||
},
|
||||
'reject_banner': {
|
||||
"str": 'rejected a banner made by {self.target_link}',
|
||||
"icon": 'fa-landscape',
|
||||
"color": 'bg-danger'
|
||||
},
|
||||
'approve_emoji': {
|
||||
"str": 'approved emoji',
|
||||
"str": 'approved an emoji made by {self.target_link}',
|
||||
"icon": 'fa-cat',
|
||||
"color": 'bg-success'
|
||||
},
|
||||
'reject_emoji': {
|
||||
"str": 'rejected emoji',
|
||||
"str": 'rejected an emoji made by {self.target_link}',
|
||||
"icon": 'fa-cat',
|
||||
"color": 'bg-danger'
|
||||
},
|
||||
'approve_hat': {
|
||||
"str": 'approved hat made by {self.target_link}',
|
||||
"icon": 'fa-hat-cowboy',
|
||||
"color": 'bg-success'
|
||||
},
|
||||
'reject_hat': {
|
||||
"str": 'rejected hat made by {self.target_link}',
|
||||
"icon": 'fa-hat-cowboy',
|
||||
"color": 'bg-danger'
|
||||
},
|
||||
'reset_password': {
|
||||
"str": 'reset the password of {self.target_link}',
|
||||
"icon": 'fa-lock',
|
||||
|
|
|
@ -7,7 +7,6 @@ import json
|
|||
import requests
|
||||
import ffmpeg
|
||||
import gevent
|
||||
import imagehash
|
||||
from flask import abort, g, has_request_context, request
|
||||
from mimetypes import guess_extension
|
||||
from PIL import Image
|
||||
|
@ -47,7 +46,7 @@ def media_ratelimit(v):
|
|||
print(STARS, flush=True)
|
||||
abort(500)
|
||||
|
||||
def process_files(files, v, body, is_dm=False, dm_user=None, admigger_thread=None, comment_body=None):
|
||||
def process_files(files, v, body, is_dm=False, dm_user=None, is_badge_thread=False, comment_body=None):
|
||||
if g.is_tor or not files.get("file"): return body
|
||||
files = files.getlist('file')[:20]
|
||||
|
||||
|
@ -63,8 +62,8 @@ def process_files(files, v, body, is_dm=False, dm_user=None, admigger_thread=Non
|
|||
name = f'/images/{time.time()}'.replace('.','') + '.webp'
|
||||
file.save(name)
|
||||
url = process_image(name, v)
|
||||
if admigger_thread:
|
||||
process_admigger_entry(name, v, admigger_thread, comment_body)
|
||||
if is_badge_thread:
|
||||
process_badge_entry(name, v, comment_body)
|
||||
elif file.content_type.startswith('video/'):
|
||||
url = process_video(file, v)
|
||||
elif file.content_type.startswith('audio/'):
|
||||
|
@ -257,30 +256,6 @@ def process_image(filename, v, resize=0, trim=False, uploader_id=None):
|
|||
abort(413, f"Max size for site assets is {MAX_IMAGE_SIZE_BANNER_RESIZED_MB} MB")
|
||||
return None
|
||||
|
||||
if filename.startswith('files/assets/images/'):
|
||||
path = filename.rsplit('/', 1)[0]
|
||||
kind = path.split('/')[-1]
|
||||
|
||||
if kind in {'banners','sidebar'}:
|
||||
hashes = {}
|
||||
|
||||
for img in os.listdir(path):
|
||||
img_path = f'{path}/{img}'
|
||||
if img_path == filename: continue
|
||||
|
||||
with Image.open(img_path) as i:
|
||||
i_hash = str(imagehash.phash(i))
|
||||
|
||||
if i_hash not in hashes.keys():
|
||||
hashes[i_hash] = img_path
|
||||
|
||||
with Image.open(filename) as i:
|
||||
i_hash = str(imagehash.phash(i))
|
||||
|
||||
if i_hash in hashes.keys():
|
||||
os.remove(filename)
|
||||
return None
|
||||
|
||||
media = g.db.query(Media).filter_by(filename=filename, kind='image').one_or_none()
|
||||
if media: g.db.delete(media)
|
||||
|
||||
|
@ -306,21 +281,7 @@ def send_file(filename):
|
|||
rclone.copy(filename, 'no:/videos', ignore_existing=True, show_progress=False)
|
||||
|
||||
|
||||
def process_sidebar_or_banner(oldname, v, type, resize):
|
||||
li = sorted(os.listdir(f'files/assets/images/{SITE_NAME}/{type}'),
|
||||
key=lambda e: int(e.split('.webp')[0]))[-1]
|
||||
num = int(li.split('.webp')[0]) + 1
|
||||
filename = f'files/assets/images/{SITE_NAME}/{type}/{num}.webp'
|
||||
copyfile(oldname, filename)
|
||||
process_image(filename, v, resize=resize)
|
||||
|
||||
def process_admigger_entry(oldname, v, admigger_thread, comment_body):
|
||||
if admigger_thread == SIDEBAR_THREAD:
|
||||
process_sidebar_or_banner(oldname, v, 'sidebar', 600)
|
||||
elif admigger_thread == BANNER_THREAD:
|
||||
banner_width = 1600
|
||||
process_sidebar_or_banner(oldname, v, 'banners', banner_width)
|
||||
elif admigger_thread == BADGE_THREAD:
|
||||
def process_badge_entry(oldname, v, comment_body):
|
||||
try:
|
||||
json_body = '{' + comment_body.split('{')[1].split('}')[0] + '}'
|
||||
badge_def = json.loads(json_body)
|
||||
|
|
|
@ -47,6 +47,8 @@ if FEATURES['HATS']:
|
|||
from .hats import *
|
||||
if FEATURES['EMOJI_SUBMISSIONS'] or FEATURES['HAT_SUBMISSIONS']:
|
||||
from .asset_submissions import *
|
||||
if FEATURES['ART_SUBMISSIONS']:
|
||||
from .art_submissions import *
|
||||
from .special import *
|
||||
from .push_notifs import *
|
||||
if FEATURES['PING_GROUPS']:
|
||||
|
|
|
@ -0,0 +1,190 @@
|
|||
from shutil import copyfile, move
|
||||
import imagehash
|
||||
|
||||
from files.classes.art_submissions import *
|
||||
from files.helpers.config.const import *
|
||||
from files.helpers.media import *
|
||||
from files.helpers.useractions import badge_grant
|
||||
from files.routes.wrappers import *
|
||||
from files.__main__ import app, limiter
|
||||
|
||||
@app.get("/submit/sidebar")
|
||||
@app.get("/submit/banners")
|
||||
@feature_required('ART_SUBMISSIONS')
|
||||
@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400)
|
||||
@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID)
|
||||
@auth_required
|
||||
def submit_art(v):
|
||||
kind = request.path.split('/')[-1].rstrip('s')
|
||||
|
||||
entries = g.db.query(ArtSubmission).filter(
|
||||
ArtSubmission.kind == kind,
|
||||
ArtSubmission.approved == False,
|
||||
).order_by(ArtSubmission.id.desc()).all()
|
||||
|
||||
for entry in entries:
|
||||
entry.author = g.db.query(User.username).filter_by(id=entry.author_id).one()[0]
|
||||
entry.submitter = g.db.query(User.username).filter_by(id=entry.submitter_id).one()[0]
|
||||
|
||||
return render_template("submit_art.html", v=v, entries=entries, kind=kind.title())
|
||||
|
||||
|
||||
@app.post("/submit/art")
|
||||
@feature_required('ART_SUBMISSIONS')
|
||||
@limiter.limit('1/second', scope=rpath)
|
||||
@limiter.limit('1/second', scope=rpath, key_func=get_ID)
|
||||
@limiter.limit("20/day", deduct_when=lambda response: response.status_code < 400)
|
||||
@limiter.limit("20/day", deduct_when=lambda response: response.status_code < 400, key_func=get_ID)
|
||||
@auth_required
|
||||
def submit_art_post(v):
|
||||
if g.is_tor:
|
||||
abort(400, "File uploads are not allowed through TOR!")
|
||||
|
||||
file = request.files["image"]
|
||||
if not file or not file.content_type.startswith('image/'):
|
||||
abort(400, "You need to submit an image!")
|
||||
|
||||
username = request.values.get('author', '').lower().strip()
|
||||
author = get_user(username, v=v)
|
||||
|
||||
kind = request.values.get('kind', '').strip()
|
||||
if kind not in {"sidebar", "banner"}:
|
||||
abort(400, "Invalid kind!")
|
||||
|
||||
print(kind, flush=True)
|
||||
entry = ArtSubmission(
|
||||
kind=kind,
|
||||
author_id=author.id,
|
||||
submitter_id=v.id,
|
||||
)
|
||||
g.db.add(entry)
|
||||
g.db.flush()
|
||||
|
||||
highquality = f'/asset_submissions/art/{entry.id}.webp'
|
||||
file.save(highquality)
|
||||
process_image(highquality, v) #to ensure not malware
|
||||
|
||||
path = f"files/assets/images/{SITE_NAME}/{entry.location_kind}"
|
||||
if not entry.hashes:
|
||||
for img in os.listdir(path):
|
||||
img_path = f'{path}/{img}'
|
||||
with Image.open(img_path) as i:
|
||||
i_hash = str(imagehash.phash(i))
|
||||
if i_hash not in entry.hashes.keys():
|
||||
entry.hashes[i_hash] = img_path
|
||||
|
||||
with Image.open(highquality) as i:
|
||||
i_hash = str(imagehash.phash(i))
|
||||
if i_hash in entry.hashes.keys():
|
||||
os.remove(highquality)
|
||||
abort(400, f"Image already exists as a {entry.formatted_kind}!")
|
||||
|
||||
|
||||
return {"message": f"{entry.msg_kind} submitted successfully!"}
|
||||
|
||||
|
||||
@app.post("/admin/approve/art/<int:id>")
|
||||
@feature_required('ART_SUBMISSIONS')
|
||||
@limiter.limit('1/second', scope=rpath)
|
||||
@limiter.limit('1/second', scope=rpath, key_func=get_ID)
|
||||
@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400)
|
||||
@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID)
|
||||
@admin_level_required(PERMS['MODERATE_PENDING_SUBMITTED_ASSETS'])
|
||||
def approve_art(v, id):
|
||||
entry = g.db.get(ArtSubmission, id)
|
||||
if not entry:
|
||||
abort(404, "Art submission not found!")
|
||||
|
||||
old = f'/asset_submissions/art/{entry.id}.webp'
|
||||
copyfile(old, f"/asset_submissions/art/original/{entry.id}.webp")
|
||||
|
||||
filename = f"files/assets/images/{SITE_NAME}/{entry.location_kind}/{entry.id}.webp"
|
||||
move(old, filename)
|
||||
process_image(filename, v, resize=entry.resize, trim=True)
|
||||
|
||||
entry_url = filename.replace('files', SITE_FULL_IMAGES)
|
||||
|
||||
|
||||
author = request.values.get('author').strip()
|
||||
author = get_user(author)
|
||||
entry.author_id = author.id
|
||||
g.db.add(entry)
|
||||
badge_grant(author, entry.badge_id)
|
||||
|
||||
|
||||
if v.id != author.id:
|
||||
msg = f"@{v.username} (a site admin) has approved a {entry.formatted_kind} you made:\n{entry_url}"
|
||||
|
||||
comment = request.values.get("comment")
|
||||
if comment:
|
||||
msg += f"\nComment: `{comment}`"
|
||||
|
||||
send_repeatable_notification(author.id, msg)
|
||||
|
||||
if v.id != entry.submitter_id and author.id != entry.submitter_id:
|
||||
msg = f"@{v.username} (a site admin) has approved a {entry.formatted_kind} you submitted:\n{entry_url}"
|
||||
|
||||
comment = request.values.get("comment")
|
||||
if comment:
|
||||
msg += f"\nComment: `{comment}`"
|
||||
|
||||
send_repeatable_notification(entry.submitter_id, msg)
|
||||
|
||||
|
||||
note = entry_url
|
||||
if comment:
|
||||
note += f' - Comment: "{comment}"'
|
||||
|
||||
ma = ModAction(
|
||||
kind=f"approve_{entry.kind}",
|
||||
user_id=v.id,
|
||||
target_user_id=entry.author_id,
|
||||
_note=filter_emojis_only(note, link=True),
|
||||
)
|
||||
g.db.add(ma)
|
||||
|
||||
|
||||
return {"message": f"{entry.msg_kind} approved!"}
|
||||
|
||||
@app.post("/remove/art/<int:id>")
|
||||
@feature_required('ART_SUBMISSIONS')
|
||||
@limiter.limit('1/second', scope=rpath)
|
||||
@limiter.limit('1/second', scope=rpath, key_func=get_ID)
|
||||
@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400)
|
||||
@limiter.limit(DEFAULT_RATELIMIT, deduct_when=lambda response: response.status_code < 400, key_func=get_ID)
|
||||
@auth_required
|
||||
def remove_art(v, id):
|
||||
entry = g.db.get(ArtSubmission, id)
|
||||
if not entry:
|
||||
abort(404, "Art submission not found!")
|
||||
|
||||
if v.id != entry.submitter_id and v.admin_level < PERMS['MODERATE_PENDING_SUBMITTED_ASSETS']:
|
||||
abort(403)
|
||||
|
||||
if v.id != entry.submitter_id:
|
||||
entry_url = f'{SITE_FULL_IMAGES}/asset_submissions/art/{entry.id}.webp'
|
||||
msg = f"@{v.username} (a site admin) has rejected a {entry.formatted_kind} you submitted:\n{entry_url}"
|
||||
|
||||
comment = request.values.get("comment")
|
||||
if comment:
|
||||
msg += f"\nComment: `{comment}`"
|
||||
|
||||
send_repeatable_notification(entry.submitter_id, msg)
|
||||
|
||||
note = entry_url
|
||||
if comment:
|
||||
note += f' - Comment: "{comment}"'
|
||||
|
||||
ma = ModAction(
|
||||
kind=f"reject_{entry.kind}",
|
||||
user_id=v.id,
|
||||
target_user_id=entry.author_id,
|
||||
_note=filter_emojis_only(note, link=True),
|
||||
)
|
||||
g.db.add(ma)
|
||||
|
||||
os.remove(f'/asset_submissions/art/{entry.id}.webp')
|
||||
msg = f"{entry.msg_kind} removed!"
|
||||
g.db.delete(entry)
|
||||
|
||||
return {"message": msg}
|
|
@ -248,10 +248,16 @@ def approve_emoji(v, name):
|
|||
|
||||
emoji.submitter_id = None
|
||||
|
||||
|
||||
note = f':{emoji.name}:'
|
||||
if comment:
|
||||
note += f' - Comment: "{comment}"'
|
||||
|
||||
ma = ModAction(
|
||||
kind="approve_emoji",
|
||||
user_id=v.id,
|
||||
_note=f'<img loading="lazy" data-bs-toggle="tooltip" alt=":{emoji.name}:" title=":{emoji.name}:" src="{SITE_FULL_IMAGES}/e/{emoji.name}.webp">'
|
||||
target_user_id=emoji.author_id,
|
||||
_note=filter_emojis_only(note, link=True),
|
||||
)
|
||||
g.db.add(ma)
|
||||
|
||||
|
@ -300,10 +306,15 @@ def remove_asset(cls, type_name, v, name):
|
|||
|
||||
send_repeatable_notification(asset.submitter_id, msg)
|
||||
|
||||
note = name
|
||||
if comment:
|
||||
note += f' - Comment: "{comment}"'
|
||||
|
||||
ma = ModAction(
|
||||
kind=f"reject_{type_name}",
|
||||
user_id=v.id,
|
||||
_note=name
|
||||
target_user_id=asset.author_id,
|
||||
_note=filter_emojis_only(note, link=True),
|
||||
)
|
||||
g.db.add(ma)
|
||||
|
||||
|
@ -464,10 +475,15 @@ def approve_hat(v, name):
|
|||
new_path = f'/asset_submissions/hats/original/{hat.name}.{i.format.lower()}'
|
||||
rename(highquality, new_path)
|
||||
|
||||
note = f'[{hat.name}]({SITE_FULL_IMAGES}/i/hats/{hat.name}.webp)'
|
||||
if comment:
|
||||
note += f' - Comment: "{comment}"'
|
||||
|
||||
ma = ModAction(
|
||||
kind="approve_hat",
|
||||
user_id=v.id,
|
||||
_note=f'<a href="{SITE_FULL_IMAGES}/i/hats/{hat.name}.webp">{hat.name}</a>'
|
||||
target_user_id=hat.author_id,
|
||||
_note=filter_emojis_only(note, link=True),
|
||||
)
|
||||
g.db.add(ma)
|
||||
|
||||
|
|
|
@ -181,14 +181,14 @@ def comment(v):
|
|||
if parent_user.has_blocked(v) or parent_user.has_muted(v):
|
||||
notify_op = False
|
||||
|
||||
if posting_to_post and v.admin_level >= PERMS['USE_ADMIGGER_THREADS'] and post_target.id in {SIDEBAR_THREAD, BANNER_THREAD, BADGE_THREAD}:
|
||||
admigger_thread = post_target.id
|
||||
if posting_to_post and v.admin_level >= PERMS['USE_ADMIGGER_THREADS'] and post_target.id == BADGE_THREAD:
|
||||
is_badge_thread = True
|
||||
comment_body = body
|
||||
else:
|
||||
admigger_thread = None
|
||||
is_badge_thread = False
|
||||
comment_body = None
|
||||
|
||||
body = process_files(request.files, v, body, admigger_thread=admigger_thread, comment_body=comment_body)
|
||||
body = process_files(request.files, v, body, is_badge_thread=is_badge_thread, comment_body=comment_body)
|
||||
if len(body) > COMMENT_BODY_LENGTH_LIMIT:
|
||||
abort(400, f'Comment body is too long (max {COMMENT_BODY_LENGTH_LIMIT} characters)')
|
||||
|
||||
|
|
|
@ -164,8 +164,7 @@ def inject_constants():
|
|||
"DEFAULT_THEME":DEFAULT_THEME, "DESCRIPTION":DESCRIPTION,
|
||||
"has_sidebar":has_sidebar, "has_logo":has_logo,
|
||||
"patron":patron, "get_setting": get_setting,
|
||||
"SIDEBAR_THREAD":SIDEBAR_THREAD, "BANNER_THREAD":BANNER_THREAD, "BUG_THREAD":BUG_THREAD,
|
||||
"BADGE_THREAD":BADGE_THREAD, "SNAPPY_THREAD":SNAPPY_THREAD, "CHANGELOG_THREAD":CHANGELOG_THREAD,
|
||||
"BUG_THREAD":BUG_THREAD, "BADGE_THREAD":BADGE_THREAD, "SNAPPY_THREAD":SNAPPY_THREAD, "CHANGELOG_THREAD":CHANGELOG_THREAD,
|
||||
"approved_embed_hosts":approved_embed_hosts, "POST_BODY_LENGTH_LIMIT":POST_BODY_LENGTH_LIMIT,
|
||||
"SITE_SETTINGS":get_settings(), "EMAIL":EMAIL, "max": max, "min": min, "can_see":can_see,
|
||||
"TELEGRAM_ID":TELEGRAM_ID, "TWITTER_ID":TWITTER_ID, "TRUESCORE_MINIMUM":TRUESCORE_MINIMUM, "TRUESCORE_DONATE_MINIMUM":TRUESCORE_DONATE_MINIMUM,
|
||||
|
@ -185,6 +184,6 @@ def inject_constants():
|
|||
"MAX_VIDEO_SIZE_MB":MAX_VIDEO_SIZE_MB, "MAX_VIDEO_SIZE_MB_PATRON":MAX_VIDEO_SIZE_MB_PATRON,
|
||||
"CURSORMARSEY_DEFAULT":CURSORMARSEY_DEFAULT, "SNAPPY_ID":SNAPPY_ID, "ZOZBOT_ID":ZOZBOT_ID, "get_running_orgy":get_running_orgy,
|
||||
"bar_position":bar_position, "datetime":datetime, "CSS_LENGTH_LIMIT":CSS_LENGTH_LIMIT, "cache":cache, "emoji_count":emoji_count, "HOLE_SIDEBAR_COLUMN_LENGTH":HOLE_SIDEBAR_COLUMN_LENGTH, "HOLE_SNAPPY_QUOTES_LENGTH":HOLE_SNAPPY_QUOTES_LENGTH,
|
||||
"SIDEBAR_REQUEST_THREAD":SIDEBAR_REQUEST_THREAD, "BANNER_REQUEST_THREAD":BANNER_REQUEST_THREAD, "top_poster_of_the_day":top_poster_of_the_day,
|
||||
"top_poster_of_the_day":top_poster_of_the_day,
|
||||
|
||||
}
|
||||
|
|
|
@ -18,16 +18,10 @@
|
|||
</ul>
|
||||
{%- endif %}
|
||||
|
||||
{% if v.admin_level >= PERMS['USE_ADMIGGER_THREADS'] and (SITE_NAME == 'rDrama' or SIDEBAR_THREAD or BANNER_THREAD or BADGE_THREAD or SNAPPY_THREAD) %}
|
||||
{% if v.admin_level >= PERMS['USE_ADMIGGER_THREADS'] and (SITE_NAME == 'rDrama' or BADGE_THREAD or SNAPPY_THREAD) %}
|
||||
<h4>Add Stuff</h4>
|
||||
<ul>
|
||||
{% if v.admin_level >= PERMS['USE_ADMIGGER_THREADS'] %}
|
||||
{% if SIDEBAR_THREAD %}
|
||||
<li><a href="/post/{{SIDEBAR_THREAD}}">Add Sidebar Images</a></li>
|
||||
{% endif %}
|
||||
{% if BANNER_THREAD %}
|
||||
<li><a href="/post/{{BANNER_THREAD}}">Add Banners</a></li>
|
||||
{% endif %}
|
||||
{% if BADGE_THREAD %}
|
||||
<li><a href="/post/{{BADGE_THREAD}}">Add Badges</a></li>
|
||||
{% endif %}
|
||||
|
@ -37,6 +31,10 @@
|
|||
{% endif %}
|
||||
|
||||
{% if v.admin_level >= PERMS['MODERATE_PENDING_SUBMITTED_ASSETS'] %}
|
||||
{% if FEATURES['ART_SUBMISSIONS'] -%}
|
||||
<li><a href="/submit/sidebar">Approve or Reject Sidebar Images</a></li>
|
||||
<li><a href="/submit/banners">Approve or Reject Banners</a></li>
|
||||
{% endif %}
|
||||
{% if FEATURES['EMOJI_SUBMISSIONS'] -%}
|
||||
<li><a href="/submit/emojis">Approve or Reject Emojis</a></li>
|
||||
{% endif %}
|
||||
|
|
|
@ -8,98 +8,93 @@
|
|||
'',
|
||||
'fa-dollar-sign', 'green',
|
||||
'/donate',
|
||||
True,
|
||||
),
|
||||
(
|
||||
'Bugs / Suggestions',
|
||||
'Something broken? Improvements?',
|
||||
'fa-bug', '#6b8e23',
|
||||
'/post/' ~ BUG_THREAD,
|
||||
BUG_THREAD,
|
||||
),
|
||||
(
|
||||
'Changelog',
|
||||
'Log of all site changes.',
|
||||
'fa-clipboard', '#ffffff',
|
||||
'/post/' ~ CHANGELOG_THREAD,
|
||||
CHANGELOG_THREAD,
|
||||
),
|
||||
(
|
||||
'Submit Sidebar Art',
|
||||
'Original ' ~ SITE_NAME ~ '-themed works.',
|
||||
'fa-sidebar-flip', '#f5fffa',
|
||||
'/submit/sidebar',
|
||||
FEATURES['ART_SUBMISSIONS'],
|
||||
),
|
||||
(
|
||||
'Submit Banner Art',
|
||||
'Original ' ~ SITE_NAME ~ '-themed works.',
|
||||
'fa-landscape', '#87cefa',
|
||||
'/submit/banners',
|
||||
FEATURES['ART_SUBMISSIONS'],
|
||||
),
|
||||
(
|
||||
'Submit Emojis',
|
||||
'Submit new emojis for the site.',
|
||||
'fa-smile-beam', '#fec83c',
|
||||
'/submit/emojis',
|
||||
FEATURES['EMOJI_SUBMISSIONS'],
|
||||
),
|
||||
(
|
||||
'Submit Sidebar Art',
|
||||
'Original ' ~ SITE_NAME ~ '-themed works.',
|
||||
'fa-sidebar', '#f5fffa',
|
||||
'/post/' ~ SIDEBAR_REQUEST_THREAD,
|
||||
),
|
||||
(
|
||||
'Submit Banner Art',
|
||||
'Original ' ~ SITE_NAME ~ '-themed works.',
|
||||
'fa-landscape', '#87cefa',
|
||||
'/post/' ~ BANNER_REQUEST_THREAD,
|
||||
),
|
||||
(
|
||||
'View All Emojis',
|
||||
'',
|
||||
'fa-smile-beam', '#fec83c',
|
||||
'/emojis/marsey',
|
||||
),
|
||||
(
|
||||
'View All Sidebar Pictures',
|
||||
'',
|
||||
'fa-sidebar', '#f5fffa',
|
||||
'/post/' ~ SIDEBAR_THREAD,
|
||||
),
|
||||
(
|
||||
'View All Banner Pictures',
|
||||
'',
|
||||
'fa-landscape', '#87cefa',
|
||||
'/post/' ~ BANNER_THREAD,
|
||||
),
|
||||
(
|
||||
'View All Snappy Quotes',
|
||||
'',
|
||||
'fa-robot', '#adff2f',
|
||||
'/post/' ~ SNAPPY_THREAD,
|
||||
),
|
||||
] -%}
|
||||
|
||||
|
||||
{%- if SITE_NAME == 'rDrama' -%}
|
||||
{%- do DIRECTORY.extend([
|
||||
(
|
||||
'Submit Hats',
|
||||
'Submit a Hat to be added.',
|
||||
'fa-hat-cowboy', '#7c603e',
|
||||
'/submit/hats',
|
||||
),
|
||||
(
|
||||
'Update Emojis or Hats',
|
||||
'Ask for an emoji or a hat to be updated with a better version or for emoji tags to be changed.',
|
||||
'fa-smile-beam', '#fec83c',
|
||||
'/post/103085',
|
||||
FEATURES['HAT_SUBMISSIONS'],
|
||||
),
|
||||
(
|
||||
'Submit Snappy Quotes',
|
||||
'Sentient.',
|
||||
'fa-robot', '#adff2f',
|
||||
'/post/33652',
|
||||
SITE == 'rdrama.net',
|
||||
),
|
||||
(
|
||||
'Update Emojis or Hats',
|
||||
'Ask for an emoji or a hat to be updated with a better version or for emoji tags to be changed.',
|
||||
'fa-smile-beam', '#fec83c',
|
||||
'/post/103085',
|
||||
SITE == 'rdrama.net',
|
||||
),
|
||||
(
|
||||
'View All Emojis',
|
||||
'',
|
||||
'fa-smile-beam', '#fec83c',
|
||||
'/emojis/marsey',
|
||||
True,
|
||||
),
|
||||
(
|
||||
'View All Snappy Quotes',
|
||||
'',
|
||||
'fa-robot', '#adff2f',
|
||||
'/post/' ~ SNAPPY_THREAD,
|
||||
SNAPPY_THREAD,
|
||||
),
|
||||
(
|
||||
'Emoji Commissions',
|
||||
'Request an Emoji to be made.',
|
||||
'fa-coins', '#ffd700',
|
||||
'/post/37677',
|
||||
SITE == 'rdrama.net',
|
||||
),
|
||||
(
|
||||
'Reportmaxxxing Bounties',
|
||||
'Request a redditor be banned.',
|
||||
'fa-gavel', '#dc3545',
|
||||
'/post/215970',
|
||||
SITE == 'rdrama.net',
|
||||
),
|
||||
])-%}
|
||||
{%- endif -%}
|
||||
] -%}
|
||||
|
||||
{% block content %}
|
||||
<div id="directory--wrapper">
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
{% extends "submit_navbar.html" %}
|
||||
{% block pagetitle %}Submit {{kind}}{% if kind == 'Sidebar' %} Images{% else %}s{% endif %}{% endblock %}
|
||||
{% block pagetype %}message{% endblock %}
|
||||
{% block content %}
|
||||
<h2 class="mt-3 mt-md-5">Submit {{kind}} {% if kind == 'Sidebar' %}Image{% endif %}</h2>
|
||||
<div class="settings-section rounded">
|
||||
<div class="d-lg-flex">
|
||||
<div class="body w-lg-100">
|
||||
<form action="/submit/art" method="post" enctype="multipart/form-data" data-nonce="{{g.nonce}}" data-onsubmit="sendFormXHRReload(this)">
|
||||
<input hidden name="formkey" value="{{v|formkey}}" class="notranslate" translate="no">
|
||||
<input hidden name="kind" value="{{kind.lower()}}" class="notranslate" translate="no">
|
||||
|
||||
<div id="image-upload-block">
|
||||
<div><label class="mt-3">Image</label></div>
|
||||
|
||||
<img loading="lazy" id="image-preview" class="d-none" style="max-width:50%;border:5px white solid">
|
||||
<label class="btn btn-secondary m-0" for="file-upload">
|
||||
<div>Select Image</div>
|
||||
<input autocomplete="off" id="file-upload" accept="image/*" type="file" name="image" {% if g.is_tor %}disabled{% endif %} hidden>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<label class="mt-3" for="author">Author</label>
|
||||
<input autocomplete="off" type="text" id="author" class="form-control" name="author" maxlength="30" pattern='[a-zA-Z0-9_\-]{1,30}|\?{3}' placeholder="Required" value="{{username}}" required>
|
||||
|
||||
<div class="footer mt-5">
|
||||
<div class="d-flex">
|
||||
<input id="submit-btn" disabled type="submit" class="btn btn-primary ml-auto" value="Submit {{kind}}">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 class="mt-5 mx-1">Pending Approval</h2>
|
||||
<div class="mt-5">
|
||||
<div class="col px-0">
|
||||
<div class="settings">
|
||||
{% for entry in entries %}
|
||||
<div id="{{entry.id}}-art" class="settings-section rounded">
|
||||
<div class="d-lg-flex">
|
||||
<div class="body w-lg-100">
|
||||
<input hidden value="{{v|formkey}}" class="notranslate" translate="no">
|
||||
|
||||
<div><label class="mt-3">Image</label></div>
|
||||
<img loading="lazy" src="{{SITE_FULL_IMAGES}}/asset_submissions/art/{{entry.id}}.webp?s={{range(1, 10000000)|random}}" style="max-width:50%;border:5px white solid">
|
||||
|
||||
<div><label class="mt-3" for="{{entry.id}}-submitter">Submitter</label></div>
|
||||
<input autocomplete="off" type="text" id="{{entry.id}}-submitter" class="form-control" maxlength="30" value="{{entry.submitter}}" readonly>
|
||||
|
||||
<label class="mt-3" for="{{entry.id}}-author">Author</label>
|
||||
<input autocomplete="off" type="text" id="{{entry.id}}-author" class="form-control" maxlength="30" value="{{entry.author}}" pattern='[a-zA-Z0-9_\-]{1,30}|\?{3}' placeholder="Required" required {% if v.admin_level < PERMS['MODERATE_PENDING_SUBMITTED_ASSETS'] %}readonly{% endif %}>
|
||||
</div>
|
||||
</div>
|
||||
{% if v.admin_level >= PERMS['MODERATE_PENDING_SUBMITTED_ASSETS'] or v.id == entry.submitter_id %}
|
||||
<div class="d-flex my-4 mx-3">
|
||||
<input autocomplete="off" type="text" id="{{entry.id}}-comment" class="form-control mr-4" placeholder="Comment..." maxlength="500" {% if v.admin_level < PERMS['MODERATE_PENDING_SUBMITTED_ASSETS'] %}hidden{% endif %}>
|
||||
|
||||
<button type="button" class="btn btn-danger ml-auto" data-nonce="{{g.nonce}}" data-onclick="remove_art(this, '{{entry.id}}')">Remove</button>
|
||||
{% if v.admin_level >= PERMS['MODERATE_PENDING_SUBMITTED_ASSETS'] %}
|
||||
<button type="button" class="btn btn-success ml-3 mr-1" data-nonce="{{g.nonce}}" data-onclick="approve_art(this, '{{entry.id}}')">Approve</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script defer src="{{'js/submit_art.js' | asset}}"></script>
|
||||
{% endblock %}
|
|
@ -1,9 +1,8 @@
|
|||
{% extends "default.html" %}
|
||||
{% extends "submit_navbar.html" %}
|
||||
{% block pagetitle %}Submit Emojis{% endblock %}
|
||||
{% block pagetype %}message{% endblock %}
|
||||
{% block content %}
|
||||
<div class="mx-4">
|
||||
<h2 class="mt-5">Submit Emoji</h2>
|
||||
<h2 class="mt-3 mt-md-5">Submit Emoji</h2>
|
||||
<div class="settings-section rounded">
|
||||
<div class="d-lg-flex">
|
||||
<div class="body w-lg-100">
|
||||
|
@ -59,10 +58,9 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 class="mt-5 mx-4">Pending Approval</h2>
|
||||
<div class="row mt-5 mx-4">
|
||||
<h2 class="mt-5 mx-1">Pending Approval</h2>
|
||||
<div class="mt-5">
|
||||
<div class="col px-0">
|
||||
<div class="settings">
|
||||
{% for emoji in emojis %}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
{% extends "default.html" %}
|
||||
{% extends "submit_navbar.html" %}
|
||||
{% block pagetitle %}Submit Hats{% endblock %}
|
||||
{% block pagetype %}message{% endblock %}
|
||||
{% block content %}
|
||||
<div class="mx-4">
|
||||
<h2 class="mt-5">Submit Hat</h2>
|
||||
<h2 class="mt-3 mt-md-5">Submit Hat</h2>
|
||||
<div class="settings-section rounded">
|
||||
<div class="d-lg-flex">
|
||||
<div class="body w-lg-100">
|
||||
|
@ -42,10 +41,9 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 class="mt-5 mx-4">Pending Approval</h2>
|
||||
<div class="row mt-5 mx-4">
|
||||
<h2 class="mt-5 mx-1">Pending Approval</h2>
|
||||
<div class="mt-5">
|
||||
<div class="col px-0">
|
||||
<div class="settings">
|
||||
{% for hat in hats %}
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
{%- extends 'root.html' -%}
|
||||
{% block pagetitle %}User List{% endblock %}
|
||||
{% block pagetype %}meta_navbar{% endblock %}
|
||||
{% block body_attributes %}class="has_header"{% endblock %}
|
||||
{% block body %}
|
||||
{% include "header.html" %}
|
||||
{% block subNav %}
|
||||
<div class="container-fluid bg-white sticky ml-2 d-mob-none" style="padding-top: 50px; padding-bottom: 0 !important">
|
||||
<div class="row box-shadow-bottom">
|
||||
<div class="col">
|
||||
<div class="container" style="padding-bottom: 0">
|
||||
<div class="row box-shadow-bottom bg-white">
|
||||
<div class="col">
|
||||
<div class="d-flex flex-row-reverse justify-content-end">
|
||||
<ul class="nav settings-nav" style="margin-left: -15px">
|
||||
{% if FEATURES['ART_SUBMISSIONS'] %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link{% if request.path == '/submit/sidebar' %} active{% endif %}" href="/submit/sidebar">
|
||||
<i class="fas fa-sidebar-flip pr-2"></i>Sidebar Images
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link{% if request.path == '/submit/banners' %} active{% endif %}" href="/submit/banners">
|
||||
<i class="fas fa-landscape pr-2"></i>Banners
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if FEATURES['EMOJI_SUBMISSIONS'] %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link{% if request.path == '/submit/emojis' %} active{% endif %}" href="/submit/emojis">
|
||||
<i class="fas fa-smile-beam pr-2"></i>Emojis
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if FEATURES['HAT_SUBMISSIONS'] %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link{% if request.path == '/submit/hats' %} active{% endif %}" href="/submit/hats">
|
||||
<i class="fas fa-hat-cowboy pr-2"></i>Hats
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if SITE == 'rdrama.net' %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/post/33652">
|
||||
<i class="fas fa-robot pr-2"></i>Snappy Quotes
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-fluid bg-white sticky d-md-none" style="padding-top: 20px; padding-bottom: 0">
|
||||
<div class="row box-shadow-bottom">
|
||||
<div class="col px-0">
|
||||
<div class="d-flex flex-row-reverse justify-content-center">
|
||||
<ul class="nav settings-nav">
|
||||
{% if FEATURES['ART_SUBMISSIONS'] %}
|
||||
<li class="nav-item">
|
||||
<a style="padding: 0.75rem 1.5rem" class="nav-link{% if request.path == '/submit/sidebar' %} active{% endif %}" href="/submit/sidebar"><i class="fas fa-sidebar-flip text-lg mr-0"></i></a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a style="padding: 0.75rem 1.5rem" class="nav-link{% if request.path == '/submit/banners' %} active{% endif %}" href="/submit/banners"><i class="fas fa-landscape text-lg mr-0"></i></a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if FEATURES['EMOJI_SUBMISSIONS'] %}
|
||||
<li class="nav-item">
|
||||
<a style="padding: 0.75rem 1.5rem" class="nav-link{% if request.path == '/submit/emojis' %} active{% endif %}" href="/submit/emojis"><i class="fas fa-smile-beam text-lg mr-0"></i></a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if FEATURES['HAT_SUBMISSIONS'] %}
|
||||
<li class="nav-item">
|
||||
<a style="padding: 0.75rem 1.5rem" class="nav-link{% if request.path == '/submit/hats' %} active{% endif %}" href="/submit/hats"><i class="fas fa-hat-cowboy text-lg mr-0"></i></a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if SITE == 'rdrama.net' %}
|
||||
<li class="nav-item">
|
||||
<a style="padding: 0.75rem 1.5rem" class="nav-link{% if request.path == '/post/33652' %} active{% endif %}" href="/post/33652"><i class="fas fa-robot text-lg mr-0"></i></a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
<div class="pt-3 container">
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,35 @@
|
|||
create table art_submissions (
|
||||
id integer primary key,
|
||||
kind varchar(7) not null,
|
||||
author_id integer not null,
|
||||
submitter_id integer not null,
|
||||
created_utc integer not null,
|
||||
approved bool not null
|
||||
);
|
||||
|
||||
CREATE SEQUENCE public.art_submissions_id_seq
|
||||
AS integer
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
ALTER SEQUENCE public.art_submissions_id_seq OWNED BY public.art_submissions.id;
|
||||
|
||||
ALTER TABLE ONLY public.art_submissions ALTER COLUMN id SET DEFAULT nextval('public.art_submissions_id_seq'::regclass);
|
||||
|
||||
rdrama:
|
||||
SELECT pg_catalog.setval('public.art_submissions_id_seq', 1477, true);
|
||||
|
||||
wpd:
|
||||
SELECT pg_catalog.setval('public.art_submissions_id_seq', 157, true);
|
||||
|
||||
alter table only art_submissions
|
||||
add constraint art_submissions_author_fkey foreign key (author_id) references public.users(id);
|
||||
|
||||
alter table only art_submissions
|
||||
add constraint art_submissions_submitter_fkey foreign key (submitter_id) references public.users(id);
|
||||
|
||||
|
||||
delete from modactions where kind in ('approve_emoji', 'reject_emoji', 'approve_hat', 'reject_hat');
|
Loading…
Reference in New Issue