forked from rDrama/rDrama
add Marsey Submission UI
parent
d75fcc4bdc
commit
47890d771d
|
@ -38,7 +38,7 @@
|
|||
border-color: var(--primary) !important;
|
||||
}
|
||||
|
||||
.form-control:disabled, .form-control[readonly] {
|
||||
.form-control:disabled, [readonly] {
|
||||
background: transparent;
|
||||
border-color: var(--primary) !important;
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
border-color: var(--primary) !important;
|
||||
}
|
||||
|
||||
.form-control:disabled, .form-control[readonly] {
|
||||
.form-control:disabled, [readonly] {
|
||||
background: transparent;
|
||||
border-color: var(--primary) !important;
|
||||
}
|
||||
|
|
|
@ -487,7 +487,7 @@ pre code {
|
|||
color: #6c757d;
|
||||
opacity: 1;
|
||||
}
|
||||
.form-control:disabled, .form-control[readonly] {
|
||||
.form-control:disabled, [readonly] {
|
||||
background-color: #e9ecef;
|
||||
opacity: 1;
|
||||
}
|
||||
|
@ -2965,7 +2965,7 @@ label.color-radio span {
|
|||
background-color: var(--gray-900);
|
||||
color: var(--black);
|
||||
}
|
||||
.form-inline.search .form-control, .form-control[readonly] {
|
||||
.form-inline.search .form-control, [readonly] {
|
||||
background-color: var(--gray-800);
|
||||
font-size: 1rem;
|
||||
color: var(--white);
|
||||
|
@ -2998,8 +2998,8 @@ label.color-radio span {
|
|||
background: #dee2e6;
|
||||
transition: none;
|
||||
}
|
||||
.form-control:disabled, .form-control[readonly] {
|
||||
background-color: var(--dark);
|
||||
.form-control:disabled, [readonly] {
|
||||
background-color: var(--dark) !important;
|
||||
}
|
||||
.form-control:hover {
|
||||
color: var(--black);
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
border-color: var(--primary) !important;
|
||||
}
|
||||
|
||||
.form-control:disabled, .form-control[readonly] {
|
||||
.form-control:disabled, [readonly] {
|
||||
border-color: var(--primary) !important;
|
||||
}
|
||||
|
||||
|
|
|
@ -215,7 +215,7 @@
|
|||
border: 1px solid var(--primary) !important;
|
||||
}
|
||||
|
||||
#frontpage .pseudo-submit-form.card, .form-inline.search .form-control, .form-control[readonly] {
|
||||
#frontpage .pseudo-submit-form.card, .form-inline.search .form-control, [readonly] {
|
||||
border: 2px solid var(--gray-200) !important;
|
||||
}
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ blockquote {
|
|||
background-color: var(--white) !important;
|
||||
}
|
||||
|
||||
.form-control, .form-control:disabled, .form-control[readonly] {
|
||||
.form-control, .form-control:disabled, [readonly] {
|
||||
background: white !important;
|
||||
color: black !important
|
||||
}
|
||||
|
|
|
@ -240,6 +240,63 @@ function post_toast(t, url, button1, button2, classname, extra_actions) {
|
|||
|
||||
}
|
||||
|
||||
function post_toast_callback(url, data, callback) {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", url);
|
||||
xhr.setRequestHeader('xhr', 'xhr');
|
||||
const form = new FormData()
|
||||
form.append("formkey", formkey());
|
||||
|
||||
if(typeof data === 'object' && data !== null) {
|
||||
for(let k of Object.keys(data)) {
|
||||
form.append(k, data[k]);
|
||||
}
|
||||
}
|
||||
|
||||
form.append("formkey", formkey());
|
||||
xhr.onload = function() {
|
||||
let result = callback(xhr);
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
var myToast = bootstrap.Toast.getOrCreateInstance(document.getElementById('toast-post-error'));
|
||||
myToast.hide();
|
||||
|
||||
var myToast = bootstrap.Toast.getOrCreateInstance(document.getElementById('toast-post-success'));
|
||||
myToast.show();
|
||||
|
||||
try {
|
||||
if(typeof result == "string") {
|
||||
document.getElementById('toast-post-success-text').innerText = result;
|
||||
} else {
|
||||
document.getElementById('toast-post-success-text').innerText = JSON.parse(xhr.response)["message"];
|
||||
}
|
||||
} catch(e) {
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
var myToast = bootstrap.Toast.getOrCreateInstance(document.getElementById('toast-post-success'));
|
||||
myToast.hide();
|
||||
|
||||
var myToast = bootstrap.Toast.getOrCreateInstance(document.getElementById('toast-post-error'));
|
||||
myToast.show();
|
||||
|
||||
try {
|
||||
if(typeof result == "string") {
|
||||
document.getElementById('toast-post-error-text').innerText = result;
|
||||
} else {
|
||||
document.getElementById('toast-post-error-text').innerText = JSON.parse(xhr.response)["error"];
|
||||
}
|
||||
return false
|
||||
} catch(e) {console.log(e)}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
xhr.send(form);
|
||||
|
||||
}
|
||||
|
||||
function escapeHTML(unsafe) {
|
||||
return unsafe.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
||||
}
|
||||
|
|
|
@ -1,60 +1,3 @@
|
|||
function post_toast_callback(url, data, callback) {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", url);
|
||||
xhr.setRequestHeader('xhr', 'xhr');
|
||||
const form = new FormData()
|
||||
form.append("formkey", formkey());
|
||||
|
||||
if(typeof data === 'object' && data !== null) {
|
||||
for(let k of Object.keys(data)) {
|
||||
form.append(k, data[k]);
|
||||
}
|
||||
}
|
||||
|
||||
form.append("formkey", formkey());
|
||||
xhr.onload = function() {
|
||||
let result = callback(xhr);
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
var myToast = bootstrap.Toast.getOrCreateInstance(document.getElementById('toast-post-error'));
|
||||
myToast.hide();
|
||||
|
||||
var myToast = bootstrap.Toast.getOrCreateInstance(document.getElementById('toast-post-success'));
|
||||
myToast.show();
|
||||
|
||||
try {
|
||||
if(typeof result == "string") {
|
||||
document.getElementById('toast-post-success-text').innerText = result;
|
||||
} else {
|
||||
document.getElementById('toast-post-success-text').innerText = JSON.parse(xhr.response)["message"];
|
||||
}
|
||||
} catch(e) {
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
var myToast = bootstrap.Toast.getOrCreateInstance(document.getElementById('toast-post-success'));
|
||||
myToast.hide();
|
||||
|
||||
var myToast = bootstrap.Toast.getOrCreateInstance(document.getElementById('toast-post-error'));
|
||||
myToast.show();
|
||||
|
||||
try {
|
||||
if(typeof result == "string") {
|
||||
document.getElementById('toast-post-error-text').innerText = result;
|
||||
} else {
|
||||
document.getElementById('toast-post-error-text').innerText = JSON.parse(xhr.response)["error"];
|
||||
}
|
||||
return false
|
||||
} catch(e) {console.log(e)}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
xhr.send(form);
|
||||
|
||||
}
|
||||
|
||||
function toggleElement(id, id2) {
|
||||
for(let el of document.getElementsByClassName('toggleable')) {
|
||||
if(el.id != id) {
|
||||
|
|
|
@ -14,7 +14,6 @@ from .subscriptions import *
|
|||
from files.__main__ import app
|
||||
from .mod_logs import *
|
||||
from .award import *
|
||||
from .marsey import *
|
||||
from .sub_block import *
|
||||
from .sub_subscription import *
|
||||
from .sub_join import *
|
||||
|
@ -25,3 +24,4 @@ from .follows import *
|
|||
from .lottery import *
|
||||
from .casino_game import *
|
||||
from .hats import *
|
||||
from .marsey import *
|
|
@ -1,4 +1,5 @@
|
|||
from sqlalchemy import *
|
||||
from sqlalchemy.orm import relationship
|
||||
from files.__main__ import Base
|
||||
|
||||
class Marsey(Base):
|
||||
|
@ -8,6 +9,7 @@ class Marsey(Base):
|
|||
author_id = Column(Integer, ForeignKey("users.id"))
|
||||
tags = Column(String)
|
||||
count = Column(Integer, default=0)
|
||||
submitter_id = Column(Integer, ForeignKey("users.id"))
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Marsey(name={self.name})>"
|
|
@ -212,7 +212,6 @@ SIDEBAR_THREAD = 0
|
|||
BANNER_THREAD = 0
|
||||
BADGE_THREAD = 0
|
||||
SNAPPY_THREAD = 0
|
||||
MARSEY_THREAD = 0
|
||||
HAT_THREAD = 0
|
||||
|
||||
if SITE == 'rdrama.net':
|
||||
|
@ -223,7 +222,6 @@ if SITE == 'rdrama.net':
|
|||
BANNER_THREAD = 37697
|
||||
BADGE_THREAD = 37833
|
||||
SNAPPY_THREAD = 37749
|
||||
MARSEY_THREAD = 37838
|
||||
HAT_THREAD = 100210
|
||||
|
||||
HOLE_COST = 50000
|
||||
|
@ -313,7 +311,6 @@ elif SITE == 'watchpeopledie.co':
|
|||
SNAKES_ID = 32
|
||||
|
||||
SIDEBAR_THREAD = 5403
|
||||
MARSEY_THREAD = 5743
|
||||
else: # localhost or testing environment implied
|
||||
FEATURES['PRONOUNS'] = True
|
||||
FEATURES['HOUSES'] = True
|
||||
|
@ -920,10 +917,10 @@ christian_emojis = [':#marseyjesus:',':#marseyimmaculate:',':#marseymothermary:'
|
|||
':#marseyorthodoxsmug:',':#marseypastor:',':#marseypope:',]
|
||||
|
||||
db = db_session()
|
||||
marseys_const = [x[0] for x in db.query(Marsey.name).filter(Marsey.name!='chudsey').all()]
|
||||
marseys_const = [x[0] for x in db.query(Marsey.name).filter(Marsey.submitter_id==None, Marsey.name!='chudsey').all()]
|
||||
marseys_const2 = marseys_const + ['chudsey','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9','exclamationpoint','period','questionmark']
|
||||
|
||||
marseys = db.query(Marsey).all()
|
||||
marseys = db.query(Marsey).filter(Marsey.submitter_id==None).all()
|
||||
marsey_mappings = {}
|
||||
for marsey in marseys:
|
||||
for tag in marsey.tags.split():
|
||||
|
@ -944,7 +941,7 @@ if path.isfile(f'snappy_{SITE_NAME}.txt'):
|
|||
|
||||
YOUTUBE_KEY = environ.get("YOUTUBE_KEY", "").strip()
|
||||
|
||||
ADMIGGERS = {SIDEBAR_THREAD,BANNER_THREAD,BADGE_THREAD,SNAPPY_THREAD,MARSEY_THREAD,HAT_THREAD}
|
||||
ADMIGGERS = {SIDEBAR_THREAD, BANNER_THREAD, BADGE_THREAD, SNAPPY_THREAD, HAT_THREAD}
|
||||
|
||||
proxies = {"http":"http://127.0.0.1:18080","https":"http://127.0.0.1:18080"}
|
||||
|
||||
|
|
|
@ -327,7 +327,7 @@ def sanitize(sanitized, edit=False, limit_pings=0, showmore=True, marsified=Fals
|
|||
sanitized = audio_sub_regex.sub(r'\1<audio controls preload="metadata" src="\2"></audio>', sanitized)
|
||||
|
||||
if not edit and not marsified:
|
||||
for marsey in g.db.query(Marsey).filter(Marsey.name.in_(marseys_used)).all():
|
||||
for marsey in g.db.query(Marsey).filter(Marsey.submitter_id==None, Marsey.name.in_(marseys_used)).all():
|
||||
marsey.count += 1
|
||||
g.db.add(marsey)
|
||||
|
||||
|
@ -416,7 +416,7 @@ def filter_emojis_only(title, edit=False, graceful=False, torture=False):
|
|||
title = render_emoji(title, emoji_regex3, edit, marseys_used)
|
||||
|
||||
if not edit:
|
||||
for marsey in g.db.query(Marsey).filter(Marsey.name.in_(marseys_used)).all():
|
||||
for marsey in g.db.query(Marsey).filter(Marsey.submitter_id==None, Marsey.name.in_(marseys_used)).all():
|
||||
marsey.count += 1
|
||||
g.db.add(marsey)
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ def stats(site=None):
|
|||
active_users = set(posters) | set(commenters) | set(voters) | set(commentvoters)
|
||||
|
||||
stats = {
|
||||
"marseys": g.db.query(Marsey).count(),
|
||||
"marseys": g.db.query(Marsey).filter(Marsey.submitter_id==None).count(),
|
||||
"users": g.db.query(User).count(),
|
||||
"private users": g.db.query(User).filter_by(is_private=True).count(),
|
||||
"banned users": g.db.query(User).filter(User.is_banned > 0).count(),
|
||||
|
|
|
@ -10,7 +10,6 @@ from files.helpers.actions import *
|
|||
from files.helpers.get import *
|
||||
from files.classes import *
|
||||
from files.routes.front import comment_idlist
|
||||
from files.routes.static import marsey_list
|
||||
from flask import *
|
||||
from files.__main__ import app, limiter
|
||||
from files.helpers.sanitize import filter_emojis_only
|
||||
|
@ -232,44 +231,6 @@ def comment(v):
|
|||
data=f'{{"files": ["https://{SITE}/assets/images/badges/{badge.id}.webp"]}}', timeout=5)
|
||||
except Exception as e:
|
||||
return {"error": str(e)}, 400
|
||||
elif v.admin_level > 2 and parent_post.id == MARSEY_THREAD:
|
||||
try:
|
||||
marsey = loads(body.lower())
|
||||
|
||||
name = marsey["name"]
|
||||
if not marsey_regex.fullmatch(name): return {"error": "Invalid name!"}, 400
|
||||
existing = g.db.query(Marsey.name).filter_by(name=name).one_or_none()
|
||||
if existing: return {"error": "A marsey with this name already exists!"}, 403
|
||||
|
||||
tags = marsey["tags"]
|
||||
if not tags_regex.fullmatch(tags): return {"error": "Invalid tags!"}, 400
|
||||
|
||||
if "author" in marsey: user = get_user(marsey["author"])
|
||||
elif "author_id" in marsey: user = get_account(marsey["author_id"])
|
||||
else: abort(400)
|
||||
|
||||
filename = f'files/assets/images/emojis/{name}.webp'
|
||||
copyfile(oldname, filename)
|
||||
process_image(filename, 200)
|
||||
|
||||
marsey = Marsey(name=name, author_id=user.id, tags=tags, count=0)
|
||||
g.db.add(marsey)
|
||||
|
||||
all_by_author = g.db.query(Marsey).filter_by(author_id=user.id).count()
|
||||
|
||||
# off-by-one: newly added marsey isn't counted
|
||||
if all_by_author >= 99:
|
||||
badge_grant(badge_id=143, user=user)
|
||||
elif all_by_author >= 9:
|
||||
badge_grant(badge_id=16, user=user)
|
||||
else:
|
||||
badge_grant(badge_id=17, user=user)
|
||||
|
||||
requests.post(f'https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/purge_cache', headers=CF_HEADERS,
|
||||
data=f'{{"files": ["https://{SITE}/e/{name}.webp"]}}', timeout=5)
|
||||
cache.delete_memoized(marsey_list)
|
||||
except Exception as e:
|
||||
return {"error": str(e)}, 400
|
||||
elif v.admin_level > 2 and parent_post.id == HAT_THREAD:
|
||||
try:
|
||||
hat = loads(body)
|
||||
|
|
|
@ -2,12 +2,14 @@ from files.mail import *
|
|||
from files.__main__ import app, limiter, mail
|
||||
from files.helpers.alerts import *
|
||||
from files.helpers.const import *
|
||||
from files.helpers.actions import *
|
||||
from files.classes.award import AWARDS
|
||||
from sqlalchemy import func
|
||||
import os
|
||||
from files.classes.mod_logs import ACTIONTYPES, ACTIONTYPES2
|
||||
from files.classes.badges import BadgeDef
|
||||
import files.helpers.stats as statshelper
|
||||
from shutil import move
|
||||
|
||||
@app.get("/r/drama/comments/<id>/<title>")
|
||||
@app.get("/r/Drama/comments/<id>/<title>")
|
||||
|
@ -20,12 +22,13 @@ def rdrama(id, title):
|
|||
@auth_required
|
||||
def marseys(v):
|
||||
if SITE == 'rdrama.net':
|
||||
marseys = g.db.query(Marsey, User).join(User)
|
||||
marseys = g.db.query(Marsey, User).join(User, Marsey.author_id == User.id).filter(Marsey.submitter_id==None)
|
||||
sort = request.values.get("sort", "usage")
|
||||
if sort == "usage": marseys = marseys.order_by(Marsey.count.desc(), User.username)
|
||||
else: marseys = marseys.order_by(User.username, Marsey.count.desc())
|
||||
else:
|
||||
marseys = g.db.query(Marsey).order_by(Marsey.count.desc())
|
||||
marseys = g.db.query(Marsey).filter(Marsey.submitter_id==None).order_by(Marsey.count.desc())
|
||||
|
||||
return render_template("marseys.html", v=v, marseys=marseys)
|
||||
|
||||
@app.get("/marsey_list.json")
|
||||
|
@ -43,7 +46,7 @@ def marsey_list():
|
|||
if emoji.name.startswith("marsey") else emoji.name],
|
||||
"count": emoji.count,
|
||||
"class": "Marsey"
|
||||
} for emoji, author in g.db.query(Marsey, User.username).join(User) \
|
||||
} for emoji, author in g.db.query(Marsey, User.username).join(User, Marsey.author_id == User.id).filter(Marsey.submitter_id==None) \
|
||||
.order_by(Marsey.count.desc())]
|
||||
|
||||
# Static shit
|
||||
|
@ -178,11 +181,12 @@ def api(v):
|
|||
return render_template("api.html", v=v)
|
||||
|
||||
@app.get("/contact")
|
||||
@app.get("/contactus")
|
||||
@app.get("/contact_us")
|
||||
@app.get("/press")
|
||||
@app.get("/media")
|
||||
@auth_required
|
||||
def contact(v):
|
||||
|
||||
return render_template("contact.html", v=v)
|
||||
|
||||
@app.post("/send_admin")
|
||||
|
@ -433,3 +437,107 @@ def categories_json():
|
|||
data.update({sub: sub_cats})
|
||||
|
||||
return jsonify(data)
|
||||
|
||||
|
||||
@app.get("/submit/marseys")
|
||||
@auth_required
|
||||
def submit_marseys(v):
|
||||
if v.admin_level > 2:
|
||||
marseys = g.db.query(Marsey).filter(Marsey.submitter_id != None).all()
|
||||
else:
|
||||
marseys = g.db.query(Marsey).filter(Marsey.submitter_id == v.id).all()
|
||||
|
||||
for marsey in marseys:
|
||||
marsey.author = g.db.query(User.username).filter_by(id=marsey.author_id).one()[0]
|
||||
marsey.submitter = g.db.query(User.username).filter_by(id=marsey.submitter_id).one()[0]
|
||||
|
||||
return render_template("submit_marseys.html", v=v, marseys=marseys)
|
||||
|
||||
|
||||
@app.post("/submit/marsey")
|
||||
@auth_required
|
||||
def submit_marsey(v):
|
||||
if request.headers.get("cf-ipcountry") == "T1":
|
||||
return {"error":"Image uploads are not allowed through TOR."}
|
||||
|
||||
file = request.files["image"]
|
||||
if not file: return {"error": "You need to submit an image!"}
|
||||
|
||||
name = request.values.get('name').lower()
|
||||
if not marsey_regex.fullmatch(name):
|
||||
return {"error": "Invalid name!"}
|
||||
|
||||
existing = g.db.query(Marsey.name).filter_by(name=name).one_or_none()
|
||||
if existing:
|
||||
return {"error": "A marsey with this name already exists!"}
|
||||
|
||||
tags = request.values.get('tags').lower()
|
||||
if not tags_regex.fullmatch(tags):
|
||||
return {"error": "Invalid tags!"}
|
||||
|
||||
author = request.values.get('author')
|
||||
author = get_user(author)
|
||||
|
||||
filename = f'/asset_submissions/{name}.webp'
|
||||
file.save(filename)
|
||||
process_image(filename, 200)
|
||||
|
||||
marsey = Marsey(name=name, author_id=author.id, tags=tags, count=0, submitter_id=v.id)
|
||||
g.db.add(marsey)
|
||||
|
||||
return redirect('/submit/marseys')
|
||||
|
||||
|
||||
@app.post("/admin/approve/marsey/<name>")
|
||||
@admin_level_required(3)
|
||||
def approve_marsey(v, name):
|
||||
marsey = g.db.query(Marsey).filter_by(name=name).one_or_none()
|
||||
if not marsey: abort(404)
|
||||
|
||||
tags = request.values.get('tags')
|
||||
if not tags: abort(400)
|
||||
|
||||
marsey.submitter_id = None
|
||||
marsey.tags = tags
|
||||
g.db.add(marsey)
|
||||
|
||||
move(f"/asset_submissions/{name}.webp", f"files/assets/images/emojis/{name}.webp")
|
||||
|
||||
author = get_account(marsey.author_id)
|
||||
all_by_author = g.db.query(Marsey).filter_by(author_id=author.id).count()
|
||||
|
||||
if all_by_author >= 99:
|
||||
badge_grant(badge_id=143, user=author)
|
||||
elif all_by_author >= 9:
|
||||
badge_grant(badge_id=16, user=author)
|
||||
else:
|
||||
badge_grant(badge_id=17, user=author)
|
||||
|
||||
requests.post(f'https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/purge_cache', headers=CF_HEADERS,
|
||||
data=f'{{"files": ["https://{SITE}/e/{name}.webp"]}}', timeout=5)
|
||||
cache.delete_memoized(marsey_list)
|
||||
|
||||
return {"message": f"{name} approved!"}
|
||||
|
||||
@app.post("/admin/reject/marsey/<name>")
|
||||
@admin_level_required(3)
|
||||
def reject_marsey(v, name):
|
||||
marsey = g.db.query(Marsey).filter_by(name=name).one_or_none()
|
||||
if not marsey: abort(404)
|
||||
|
||||
g.db.delete(marsey)
|
||||
os.remove(f"/asset_submissions/{name}.webp")
|
||||
|
||||
return {"message": f"{name} rejected!"}
|
||||
|
||||
|
||||
@app.get('/asset_submissions/<image>')
|
||||
@limiter.exempt
|
||||
def asset_submissions(image):
|
||||
if not image.endswith('.webp'): abort(404)
|
||||
resp = make_response(send_from_directory('/asset_submissions', image))
|
||||
resp.headers.remove("Cache-Control")
|
||||
resp.headers.add("Cache-Control", "public, max-age=3153600")
|
||||
resp.headers.remove("Content-Type")
|
||||
resp.headers.add("Content-Type", "image/webp")
|
||||
return resp
|
|
@ -566,7 +566,7 @@ def leaderboard(v):
|
|||
users11 = users11.limit(25).all()
|
||||
|
||||
if SITE_NAME == 'rDrama':
|
||||
sq = g.db.query(Marsey.author_id, func.count(Marsey.author_id).label("count"), func.rank().over(order_by=func.count(Marsey.author_id).desc()).label("rank")).group_by(Marsey.author_id).subquery()
|
||||
sq = g.db.query(Marsey.author_id, func.count(Marsey.author_id).label("count"), func.rank().over(order_by=func.count(Marsey.author_id).desc()).label("rank")).filter(Marsey.submitter_id==None).group_by(Marsey.author_id).subquery()
|
||||
users12 = g.db.query(User, sq.c.count).join(sq, User.id==sq.c.author_id).order_by(sq.c.count.desc())
|
||||
pos12 = g.db.query(User.id, sq.c.rank, sq.c.count).join(sq, User.id==sq.c.author_id).filter(User.id == v.id).one_or_none()
|
||||
if pos12: pos12 = (pos12[1],pos12[2])
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
{% extends "default.html" %}
|
||||
|
||||
{% block title %}
|
||||
<title>Submit Marseys</title>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="mx-4">
|
||||
<h2 class="mt-5">Submit Marsey</h2>
|
||||
<div class="settings-section rounded">
|
||||
<div class="d-lg-flex">
|
||||
<div class="body w-lg-100">
|
||||
<form action="/submit/marsey" method="post" enctype="multipart/form-data">
|
||||
<input type="hidden" name="formkey" value="{{v.formkey}}">
|
||||
|
||||
<div id="image-upload-block">
|
||||
<div><label class="mt-3">Image</label></div>
|
||||
|
||||
<img loading="lazy" id="image-preview" style="max-width:50%">
|
||||
<label class="btn btn-secondary m-0" for="file-upload">
|
||||
<div id="filename-show">Select File</div>
|
||||
<input autocomplete="off" id="file-upload" accept="image/*" type="file" name="image" {% if request.headers.get('cf-ipcountry')=="T1" %}disabled{% endif %} hidden>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<label class="mt-3" for="name">Name</label>
|
||||
<input autocomplete="off" type="text" id="name" class="form-control" name="name" maxlength="30" required>
|
||||
|
||||
<label class="mt-3" for="author">Author</label>
|
||||
<input autocomplete="off" type="text" id="author" class="form-control" name="author" value="{{v.username}}" maxlength="30" required>
|
||||
|
||||
<label class="mt-3" for="tags">Tags</label>
|
||||
<input autocomplete="off" type="text" id="tags" class="form-control" name="tags" maxlength="200" required>
|
||||
|
||||
<div class="footer mt-5">
|
||||
<div class="d-flex">
|
||||
<input id="submit-marsey" disabled type="submit" onclick="disable(this)" class="btn btn-primary ml-auto" value="Submit Marsey">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.onpaste = function(event) {
|
||||
files = event.clipboardData.files
|
||||
|
||||
filename = files[0]
|
||||
|
||||
if (filename)
|
||||
{
|
||||
filename = filename.name.toLowerCase()
|
||||
if (document.activeElement.id == 'post-text') {
|
||||
let filename = ''
|
||||
for (const file of files)
|
||||
filename += file.name + ', '
|
||||
filename = filename.toLowerCase().slice(0, -2)
|
||||
document.getElementById('file-upload-submit').files = files;
|
||||
document.getElementById('filename-show-submit').textContent = filename;
|
||||
}
|
||||
else {
|
||||
f=document.getElementById('file-upload');
|
||||
f.files = files;
|
||||
document.getElementById('filename-show').textContent = filename;
|
||||
document.getElementById('urlblock').classList.add('d-none');
|
||||
if (filename.endsWith(".jpg") || filename.endsWith(".jpeg") || filename.endsWith(".png") || filename.endsWith(".gif") || filename.endsWith(".webp"))
|
||||
{
|
||||
var fileReader = new FileReader();
|
||||
fileReader.readAsDataURL(f.files[0]);
|
||||
fileReader.addEventListener("load", function () {document.getElementById('image-preview').setAttribute('src', this.result);});
|
||||
}
|
||||
document.getElementById('file-upload').setAttribute('required', 'false');
|
||||
}
|
||||
document.getElementById('post-url').value = null;
|
||||
localStorage.setItem("post-url", "")
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('file-upload').addEventListener('change', function(){
|
||||
f=document.getElementById('file-upload');
|
||||
document.getElementById('filename-show').textContent = document.getElementById('file-upload').files[0].name.substr(0, 20);
|
||||
filename = f.files[0].name.toLowerCase()
|
||||
if (filename.endsWith(".jpg") || filename.endsWith(".jpeg") || filename.endsWith(".png") || filename.endsWith(".gif") || filename.endsWith(".webp"))
|
||||
{
|
||||
var fileReader = new FileReader();
|
||||
fileReader.readAsDataURL(f.files[0]);
|
||||
fileReader.addEventListener("load", function () {document.getElementById('image-preview').setAttribute('src', this.result);});
|
||||
document.getElementById('submit-marsey').disabled = false;
|
||||
}
|
||||
})
|
||||
|
||||
function approve_marsey(t, name) {
|
||||
t.disabled = true;
|
||||
t.classList.add("disabled");
|
||||
post_toast_callback(`/admin/approve/marsey/${name}`,
|
||||
{
|
||||
"tags": document.getElementById(`${name}-tags`).value,
|
||||
},
|
||||
(xhr) => {
|
||||
if(xhr.status == 200) {
|
||||
document.getElementById(`${name}-marsey`).classList.add('d-none')
|
||||
}
|
||||
}
|
||||
);
|
||||
setTimeout(() => {
|
||||
t.disabled = false;
|
||||
t.classList.remove("disabled");
|
||||
}, 2000);
|
||||
}
|
||||
</script>
|
||||
|
||||
<h2 class="mt-5 mx-4">Current Applications</h2>
|
||||
<div class="row mt-5 mx-4">
|
||||
<div class="col px-0">
|
||||
<div class="settings">
|
||||
{% for marsey in marseys %}
|
||||
<div id="{{marsey.name}}-marsey" class="settings-section rounded">
|
||||
<div class="d-lg-flex">
|
||||
<div class="body w-lg-100">
|
||||
<input type="hidden" name="formkey" value="{{v.formkey}}">
|
||||
|
||||
<div><label class="mt-3">Image</label></div>
|
||||
<img loading="lazy" src="/asset_submissions/{{marsey.name}}.webp" style="max-width:50%">
|
||||
|
||||
<div><label class="mt-3" for="{{marsey.name}}-name">Name</label></div>
|
||||
<input autocomplete="off" type="text" id="{{marsey.name}}-name" class="form-control" maxlength="30" value="{{marsey.name}}" readonly>
|
||||
|
||||
<label class="mt-3" for="{{marsey.name}}-author">Author</label>
|
||||
<input autocomplete="off" type="text" id="{{marsey.name}}-author" class="form-control" maxlength="30" value="{{marsey.author}}" readonly>
|
||||
|
||||
<label class="mt-3" for="{{marsey.name}}-tags">Tags</label>
|
||||
<input autocomplete="off" type="text" id="{{marsey.name}}-tags" class="form-control" name="tags" maxlength="200" value="{{marsey.tags}}" required>
|
||||
|
||||
<label class="mt-3" for="{{marsey.name}}-submitter">Submitter</label>
|
||||
<input autocomplete="off" type="text" id="{{marsey.name}}-submitter" class="form-control" maxlength="30" value="{{marsey.submitter}}" readonly>
|
||||
</div>
|
||||
</div>
|
||||
{% if v.admin_level > 2 %}
|
||||
<div class="d-flex my-4 mx-3">
|
||||
<a role="button" class="btn btn-primary ml-auto mr-2" onclick="approve_marsey(this, '{{marsey.name}}')">Approve</a>
|
||||
<a role="button" class="btn btn-secondary mr-0" onclick="post_toast(this,'/admin/reject/marsey/{{marsey.name}}', true)">Reject</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -1,22 +1,22 @@
|
|||
{%-
|
||||
set CACHE_VER = {
|
||||
'css/main.css': 4020,
|
||||
'css/catalog.css': 4004,
|
||||
'css/4chan.css': 4004,
|
||||
'css/main.css': 4021,
|
||||
'css/catalog.css': 4005,
|
||||
'css/4chan.css': 4005,
|
||||
'css/classic.css': 4005,
|
||||
'css/classic_dark.css': 4005,
|
||||
'css/coffee.css': 4004,
|
||||
'css/dark.css': 4004,
|
||||
'css/dramblr.css': 4004,
|
||||
'css/light.css': 4004,
|
||||
'css/midnight.css': 4004,
|
||||
'css/reddit.css': 4004,
|
||||
'css/transparent.css': 4004,
|
||||
'css/tron.css': 4004,
|
||||
'css/win98.css': 4004,
|
||||
'css/coffee.css': 4005,
|
||||
'css/dark.css': 4005,
|
||||
'css/dramblr.css': 4005,
|
||||
'css/light.css': 4005,
|
||||
'css/midnight.css': 4005,
|
||||
'css/reddit.css': 4005,
|
||||
'css/transparent.css': 4005,
|
||||
'css/tron.css': 4005,
|
||||
'css/win98.css': 4005,
|
||||
|
||||
'js/award_modal.js': 4001,
|
||||
'js/bootstrap.js': 4002,
|
||||
'js/bootstrap.js': 4003,
|
||||
'js/category_modal.js': 4000,
|
||||
'js/comments_admin.js': 4000,
|
||||
'js/comments_v.js': 4001,
|
||||
|
@ -28,7 +28,7 @@ set CACHE_VER = {
|
|||
'js/search.js': 4000,
|
||||
'js/submit.js': 4000,
|
||||
'js/userpage.js': 4000,
|
||||
'js/userpage_v.js': 4000,
|
||||
'js/userpage_v.js': 4001,
|
||||
'js/lozad.js': 4000,
|
||||
'js/sort_table.js': 4000,
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
alter table marseys add column submitter_id int;
|
||||
|
||||
ALTER TABLE ONLY public.marseys
|
||||
ADD CONSTRAINT marsey_submitter_fkey FOREIGN KEY (submitter_id) REFERENCES public.users(id);
|
||||
|
||||
CREATE INDEX marseys_idx4 ON public.marseys USING btree (submitter_id);
|
|
@ -35,6 +35,7 @@ mkdir /songs
|
|||
mkdir /images
|
||||
mkdir /videos
|
||||
mkdir /audio
|
||||
mkdir /asset_submissions
|
||||
git config --global --add safe.directory /songs
|
||||
git config --global --add safe.directory /images
|
||||
git config --global --add safe.directory /videos
|
||||
|
|
Loading…
Reference in New Issue