mirror of
https://git.wownero.com/lza_menace/suchwow.git
synced 2024-08-15 01:03:19 +00:00
moving stuff around, cleaning up, adding mod area
This commit is contained in:
parent
0cab370e12
commit
143d08f2f7
20 changed files with 591 additions and 254 deletions
204
suchwow/app.py
204
suchwow/app.py
|
@ -1,22 +1,8 @@
|
||||||
import json
|
from flask import Flask
|
||||||
import click
|
|
||||||
import arrow
|
|
||||||
from math import ceil
|
|
||||||
from datetime import datetime, timedelta
|
|
||||||
from random import choice
|
|
||||||
from os import makedirs, path, remove
|
|
||||||
from flask import Flask, request, session, redirect
|
|
||||||
from flask import render_template, flash, url_for
|
|
||||||
from flask_session import Session
|
from flask_session import Session
|
||||||
from suchwow import config
|
|
||||||
from suchwow.models import Post, Profile, Comment, Notification, db, Moderator, Ban
|
from suchwow.routes import auth, comment, post, profile, leaderboard, api, mod, main
|
||||||
from suchwow.routes import auth, comment, post, profile, leaderboard, api
|
from suchwow import filters, cli
|
||||||
from suchwow.utils.decorators import login_required, moderator_required
|
|
||||||
from suchwow.utils.helpers import post_webhook, get_latest_tipped_posts
|
|
||||||
from suchwow.utils.helpers import get_top_posters, get_top_posts
|
|
||||||
from suchwow.reddit import make_post
|
|
||||||
from suchwow.discord import post_discord_webhook
|
|
||||||
from suchwow import wownero, filters
|
|
||||||
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
@ -30,186 +16,10 @@ app.register_blueprint(profile.bp)
|
||||||
app.register_blueprint(comment.bp)
|
app.register_blueprint(comment.bp)
|
||||||
app.register_blueprint(leaderboard.bp)
|
app.register_blueprint(leaderboard.bp)
|
||||||
app.register_blueprint(api.bp)
|
app.register_blueprint(api.bp)
|
||||||
|
app.register_blueprint(mod.bp)
|
||||||
|
app.register_blueprint(main.bp)
|
||||||
app.register_blueprint(filters.bp)
|
app.register_blueprint(filters.bp)
|
||||||
|
app.register_blueprint(cli.bp)
|
||||||
@app.route("/")
|
|
||||||
def index():
|
|
||||||
itp = 15
|
|
||||||
page = request.args.get("page", 1)
|
|
||||||
submitter = request.args.get("submitter", None)
|
|
||||||
content = request.args.get("content", None)
|
|
||||||
|
|
||||||
if content == 'latest_tipped':
|
|
||||||
posts = get_latest_tipped_posts()
|
|
||||||
return render_template(
|
|
||||||
"index.html",
|
|
||||||
posts=posts[0:30],
|
|
||||||
title="Latest Tipped Memes"
|
|
||||||
)
|
|
||||||
|
|
||||||
try:
|
|
||||||
page = int(page)
|
|
||||||
except:
|
|
||||||
flash("Wow, wtf hackerman. Cool it.", "is-danger")
|
|
||||||
page = 1
|
|
||||||
|
|
||||||
posts = Post.select().where(Post.approved==True).order_by(Post.timestamp.desc())
|
|
||||||
if submitter:
|
|
||||||
posts = posts.where(Post.submitter==submitter)
|
|
||||||
|
|
||||||
paginated_posts = posts.paginate(page, itp)
|
|
||||||
total_pages = ceil(posts.count() / itp)
|
|
||||||
return render_template(
|
|
||||||
"index.html",
|
|
||||||
posts=paginated_posts,
|
|
||||||
page=page,
|
|
||||||
total_pages=total_pages,
|
|
||||||
title="Latest Memes"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/mod")
|
|
||||||
@moderator_required
|
|
||||||
def mod_queue():
|
|
||||||
posts = Post.select().where(Post.approved==False).order_by(Post.timestamp.asc())
|
|
||||||
return render_template("index.html", posts=posts)
|
|
||||||
|
|
||||||
@app.route("/about")
|
|
||||||
def about():
|
|
||||||
mods = Profile.select().join(Moderator, on=(Profile.username == Moderator.username))
|
|
||||||
return render_template("about.html", mods=mods)
|
|
||||||
|
|
||||||
@app.cli.command("init")
|
|
||||||
def init():
|
|
||||||
# create subdirs
|
|
||||||
for i in ["uploads", "db", "wallet"]:
|
|
||||||
makedirs(f"{config.DATA_FOLDER}/{i}", exist_ok=True)
|
|
||||||
|
|
||||||
# init db
|
|
||||||
db.create_tables([Post, Profile, Comment, Notification, Moderator, Ban])
|
|
||||||
|
|
||||||
@app.cli.command("post_reddit")
|
|
||||||
@click.argument('last_hours')
|
|
||||||
def post_reddit(last_hours):
|
|
||||||
posts = Post.select().where(
|
|
||||||
Post.approved==True,
|
|
||||||
Post.to_reddit==False
|
|
||||||
).order_by(Post.timestamp.asc())
|
|
||||||
for p in posts:
|
|
||||||
if p.hours_elapsed() < int(last_hours):
|
|
||||||
if not p.to_reddit:
|
|
||||||
_p = make_post(p)
|
|
||||||
if _p:
|
|
||||||
p.to_reddit = True
|
|
||||||
p.save()
|
|
||||||
return
|
|
||||||
|
|
||||||
@app.cli.command("create_accounts")
|
|
||||||
def create_accounts():
|
|
||||||
wallet = wownero.Wallet()
|
|
||||||
for post in Post.select():
|
|
||||||
if post.account_index not in wallet.accounts():
|
|
||||||
account = wallet.new_account()
|
|
||||||
print(f"Created account {account}")
|
|
||||||
|
|
||||||
@app.cli.command("payout_users")
|
|
||||||
def payout_users():
|
|
||||||
wallet = wownero.Wallet()
|
|
||||||
_fa = wownero.from_atomic
|
|
||||||
_aw = wownero.as_wownero
|
|
||||||
for post in Post.select():
|
|
||||||
try:
|
|
||||||
submitter = Profile.get(username=post.submitter)
|
|
||||||
balances = wallet.balances(post.account_index)
|
|
||||||
url = url_for('post.read', id=post.id, _external=True)
|
|
||||||
if balances[1] > 0.05:
|
|
||||||
print(f"Post #{post.id} has {balances[1]} funds unlocked and ready to send. Sweeping all funds to user's address ({submitter.address}).")
|
|
||||||
sweep = wallet.sweep_all(account=post.account_index, dest_address=submitter.address)
|
|
||||||
print(sweep)
|
|
||||||
if "tx_hash_list" in sweep:
|
|
||||||
amount = 0
|
|
||||||
for amt in sweep["amount_list"]:
|
|
||||||
amount += int(amt)
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Failed because: {e}")
|
|
||||||
|
|
||||||
@app.cli.command("add_admin")
|
|
||||||
@click.argument("username")
|
|
||||||
def add_admin(username):
|
|
||||||
if not Moderator.filter(username=username):
|
|
||||||
m = Moderator(username=username)
|
|
||||||
m.save()
|
|
||||||
print(f"Added {username}")
|
|
||||||
post_webhook(f"Moderator `{username}` added :ship_it_parrot: by console :black_flag:")
|
|
||||||
else:
|
|
||||||
print("That moderator already exists")
|
|
||||||
|
|
||||||
@app.cli.command("remove_admin")
|
|
||||||
@click.argument("username")
|
|
||||||
def remove_admin(username):
|
|
||||||
m = Moderator.filter(username=username).first()
|
|
||||||
if m:
|
|
||||||
m.delete_instance()
|
|
||||||
print(f"Deleted {username}")
|
|
||||||
post_webhook(f"Moderator `{username}` removed :excuseme: by console :black_flag:")
|
|
||||||
else:
|
|
||||||
print("That moderator doesn't exist")
|
|
||||||
|
|
||||||
@app.cli.command("ban_user")
|
|
||||||
@click.argument("username")
|
|
||||||
@click.argument("reason", nargs=-1)
|
|
||||||
def ban_user(username, reason):
|
|
||||||
u = Profile.filter(username=username).first()
|
|
||||||
b = Ban.filter(user=u).first()
|
|
||||||
if b:
|
|
||||||
print("User already banned")
|
|
||||||
return False
|
|
||||||
if u:
|
|
||||||
b = Ban(user=u, reason=' '.join(reason))
|
|
||||||
b.save()
|
|
||||||
print(f"Banned {username}")
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
print("That user doesn't exist")
|
|
||||||
return
|
|
||||||
|
|
||||||
@app.cli.command("unban_user")
|
|
||||||
@click.argument("username")
|
|
||||||
def ban_user(username):
|
|
||||||
u = Profile.filter(username=username).first()
|
|
||||||
if not u:
|
|
||||||
print("That user doesn't exist")
|
|
||||||
return False
|
|
||||||
b = Ban.filter(user=u).first()
|
|
||||||
if b:
|
|
||||||
b.delete_instance()
|
|
||||||
print(f"Unbanned {username}")
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
print("That user isn't banned")
|
|
||||||
return False
|
|
||||||
|
|
||||||
@app.cli.command("show")
|
|
||||||
@click.argument("post_id")
|
|
||||||
def post_id(post_id):
|
|
||||||
p = Post.filter(id=post_id).first()
|
|
||||||
if p:
|
|
||||||
print(p.show())
|
|
||||||
else:
|
|
||||||
print("That post doesn't exist")
|
|
||||||
|
|
||||||
@app.cli.command("load_cache")
|
|
||||||
def load_cache():
|
|
||||||
app.logger.info('loading top posters into cache')
|
|
||||||
get_top_posters()
|
|
||||||
app.logger.info('done')
|
|
||||||
app.logger.info('loading latest tipped into cache')
|
|
||||||
get_latest_tipped_posts()
|
|
||||||
app.logger.info('done')
|
|
||||||
for i in [1, 3, 7, 30, 9999]:
|
|
||||||
app.logger.info(f'loading top posts last {i} days into cache')
|
|
||||||
get_top_posts(i)
|
|
||||||
app.logger.info('done')
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
95
suchwow/cli.py
Normal file
95
suchwow/cli.py
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
from os import makedirs
|
||||||
|
|
||||||
|
import click
|
||||||
|
from flask import Blueprint, url_for, current_app
|
||||||
|
|
||||||
|
from suchwow.models import Post, Profile, Comment, Notification, db, Moderator, Ban
|
||||||
|
from suchwow.utils.helpers import get_latest_tipped_posts
|
||||||
|
from suchwow.utils.helpers import get_top_posters, get_top_posts
|
||||||
|
from suchwow.reddit import make_post
|
||||||
|
from suchwow import wownero
|
||||||
|
from suchwow import config
|
||||||
|
|
||||||
|
bp = Blueprint('cli', 'cli', cli_group=None)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.cli.command("init")
|
||||||
|
def init():
|
||||||
|
# create subdirs
|
||||||
|
for i in ["uploads", "db", "wallet"]:
|
||||||
|
makedirs(f"{config.DATA_FOLDER}/{i}", exist_ok=True)
|
||||||
|
|
||||||
|
# init db
|
||||||
|
db.create_tables([Post, Profile, Comment, Notification, Moderator, Ban])
|
||||||
|
|
||||||
|
|
||||||
|
@bp.cli.command("post_reddit")
|
||||||
|
@click.argument('last_hours')
|
||||||
|
def post_reddit(last_hours):
|
||||||
|
posts = Post.select().where(
|
||||||
|
Post.approved==True,
|
||||||
|
Post.to_reddit==False
|
||||||
|
).order_by(Post.timestamp.asc())
|
||||||
|
for p in posts:
|
||||||
|
if p.hours_elapsed() < int(last_hours):
|
||||||
|
if not p.to_reddit:
|
||||||
|
_p = make_post(p)
|
||||||
|
if _p:
|
||||||
|
p.to_reddit = True
|
||||||
|
p.save()
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@bp.cli.command("create_accounts")
|
||||||
|
def create_accounts():
|
||||||
|
wallet = wownero.Wallet()
|
||||||
|
for post in Post.select():
|
||||||
|
if post.account_index not in wallet.accounts():
|
||||||
|
account = wallet.new_account()
|
||||||
|
print(f"Created account {account}")
|
||||||
|
|
||||||
|
|
||||||
|
@bp.cli.command("payout_users")
|
||||||
|
def payout_users():
|
||||||
|
wallet = wownero.Wallet()
|
||||||
|
_fa = wownero.from_atomic
|
||||||
|
_aw = wownero.as_wownero
|
||||||
|
for post in Post.select():
|
||||||
|
try:
|
||||||
|
submitter = Profile.get(username=post.submitter)
|
||||||
|
balances = wallet.balances(post.account_index)
|
||||||
|
url = url_for('post.read', id=post.id, _external=True)
|
||||||
|
if balances[1] > 0.05:
|
||||||
|
print(f"Post #{post.id} has {balances[1]} funds unlocked and ready to send. Sweeping all funds to user's address ({submitter.address}).")
|
||||||
|
sweep = wallet.sweep_all(account=post.account_index, dest_address=submitter.address)
|
||||||
|
print(sweep)
|
||||||
|
if "tx_hash_list" in sweep:
|
||||||
|
amount = 0
|
||||||
|
for amt in sweep["amount_list"]:
|
||||||
|
amount += int(amt)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Failed because: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
@bp.cli.command("show")
|
||||||
|
@click.argument("post_id")
|
||||||
|
def post_id(post_id):
|
||||||
|
p = Post.filter(id=post_id).first()
|
||||||
|
if p:
|
||||||
|
print(p.show())
|
||||||
|
else:
|
||||||
|
print("That post doesn't exist")
|
||||||
|
|
||||||
|
|
||||||
|
@bp.cli.command("load_cache")
|
||||||
|
def load_cache():
|
||||||
|
current_app.logger.info('loading top posters into cache')
|
||||||
|
get_top_posters()
|
||||||
|
current_app.logger.info('done')
|
||||||
|
current_app.logger.info('loading latest tipped into cache')
|
||||||
|
get_latest_tipped_posts()
|
||||||
|
current_app.logger.info('done')
|
||||||
|
for i in [1, 3, 7, 30, 9999]:
|
||||||
|
current_app.logger.info(f'loading top posts last {i} days into cache')
|
||||||
|
get_top_posts(i)
|
||||||
|
current_app.logger.info('done')
|
|
@ -14,6 +14,7 @@ OIDC_REDIRECT_URL = getenv('OIDC_REDIRECT_URL', 'http://localhost:5000/auth')
|
||||||
SECRET_KEY = getenv('SECRET_KEY', 'yyyyyyyyyyyyy') # whatever you want it to be
|
SECRET_KEY = getenv('SECRET_KEY', 'yyyyyyyyyyyyy') # whatever you want it to be
|
||||||
DATA_FOLDER = getenv('DATA_FOLDER', '/path/to/uploads') # some stable storage path
|
DATA_FOLDER = getenv('DATA_FOLDER', '/path/to/uploads') # some stable storage path
|
||||||
SERVER_NAME = getenv('SERVER_NAME', 'localhost') # name of your DNS resolvable site (.com)
|
SERVER_NAME = getenv('SERVER_NAME', 'localhost') # name of your DNS resolvable site (.com)
|
||||||
|
SUPER_ADMIN = getenv('SUPER_ADMIN', 'lza_menace') # top dawg you cannot delete
|
||||||
WALLET_HOST = getenv('WALLET_HOST', 'localhost') #
|
WALLET_HOST = getenv('WALLET_HOST', 'localhost') #
|
||||||
WALLET_PORT = int(getenv('WALLET_PORT', 8888)) #
|
WALLET_PORT = int(getenv('WALLET_PORT', 8888)) #
|
||||||
WALLET_PROTO = getenv('WALLET_PROTO', 'http') #
|
WALLET_PROTO = getenv('WALLET_PROTO', 'http') #
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
from flask import Blueprint, current_app
|
from flask import Blueprint, current_app
|
||||||
from arrow import get as arrow_get
|
from arrow import get as arrow_get
|
||||||
|
|
||||||
|
from suchwow.models import Moderator
|
||||||
|
|
||||||
|
|
||||||
bp = Blueprint('filters', 'filters')
|
bp = Blueprint('filters', 'filters')
|
||||||
|
|
||||||
|
@ -13,3 +15,10 @@ def shorten_address(a):
|
||||||
@bp.app_template_filter('humanize')
|
@bp.app_template_filter('humanize')
|
||||||
def humanize(d):
|
def humanize(d):
|
||||||
return arrow_get(d).humanize()
|
return arrow_get(d).humanize()
|
||||||
|
|
||||||
|
@bp.app_template_filter('is_moderator')
|
||||||
|
def is_moderator(s):
|
||||||
|
m = Moderator.select().where(Moderator.username == s)
|
||||||
|
if m:
|
||||||
|
return True
|
||||||
|
return False
|
|
@ -1,4 +1,5 @@
|
||||||
from peewee import *
|
from peewee import *
|
||||||
|
from random import choice
|
||||||
from os import path
|
from os import path
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
@ -8,6 +9,16 @@ from suchwow import config
|
||||||
|
|
||||||
db = SqliteDatabase(f"{config.DATA_FOLDER}/sqlite.db")
|
db = SqliteDatabase(f"{config.DATA_FOLDER}/sqlite.db")
|
||||||
|
|
||||||
|
ban_reasons = [
|
||||||
|
'you smell bad',
|
||||||
|
'didnt pass the vibe check, homie',
|
||||||
|
'your memes are bad and you should feel bad',
|
||||||
|
'i just dont like you'
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_ban_reason():
|
||||||
|
return choice(ban_reasons)
|
||||||
|
|
||||||
class Post(Model):
|
class Post(Model):
|
||||||
id = AutoField()
|
id = AutoField()
|
||||||
title = CharField()
|
title = CharField()
|
||||||
|
|
|
@ -21,7 +21,7 @@ def login():
|
||||||
@bp.route("/logout")
|
@bp.route("/logout")
|
||||||
def logout():
|
def logout():
|
||||||
session["auth"] = None
|
session["auth"] = None
|
||||||
return redirect(url_for("index"))
|
return redirect(url_for("main.index"))
|
||||||
|
|
||||||
@bp.route("/auth/")
|
@bp.route("/auth/")
|
||||||
def auth():
|
def auth():
|
||||||
|
@ -66,4 +66,4 @@ def auth():
|
||||||
|
|
||||||
# user can now visit /secret
|
# user can now visit /secret
|
||||||
session["auth"] = user_profile
|
session["auth"] = user_profile
|
||||||
return redirect(url_for("index"))
|
return redirect(url_for("main.index"))
|
|
@ -11,7 +11,7 @@ bp = Blueprint("comment", "comment")
|
||||||
def create(post_id):
|
def create(post_id):
|
||||||
if not Post.filter(id=post_id):
|
if not Post.filter(id=post_id):
|
||||||
flash("WTF, that post doesn't exist. Stop it, hackerman.", "is-danger")
|
flash("WTF, that post doesn't exist. Stop it, hackerman.", "is-danger")
|
||||||
return redirect(url_for("index"))
|
return redirect(url_for("main.index"))
|
||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
comment_text = request.form.get("comment")
|
comment_text = request.form.get("comment")
|
||||||
|
|
50
suchwow/routes/main.py
Normal file
50
suchwow/routes/main.py
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
from math import ceil
|
||||||
|
|
||||||
|
from flask import Blueprint, request, render_template, flash
|
||||||
|
|
||||||
|
from suchwow.models import Post, Profile, Moderator
|
||||||
|
from suchwow.utils.helpers import get_latest_tipped_posts
|
||||||
|
|
||||||
|
bp = Blueprint('main', 'main')
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/")
|
||||||
|
def index():
|
||||||
|
itp = 15
|
||||||
|
page = request.args.get("page", 1)
|
||||||
|
submitter = request.args.get("submitter", None)
|
||||||
|
content = request.args.get("content", None)
|
||||||
|
|
||||||
|
if content == 'latest_tipped':
|
||||||
|
posts = get_latest_tipped_posts()
|
||||||
|
return render_template(
|
||||||
|
"index.html",
|
||||||
|
posts=posts[0:30],
|
||||||
|
title="Latest Tipped Memes"
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
page = int(page)
|
||||||
|
except:
|
||||||
|
flash("Wow, wtf hackerman. Cool it.", "is-danger")
|
||||||
|
page = 1
|
||||||
|
|
||||||
|
posts = Post.select().where(Post.approved==True).order_by(Post.timestamp.desc())
|
||||||
|
if submitter:
|
||||||
|
posts = posts.where(Post.submitter==submitter)
|
||||||
|
|
||||||
|
paginated_posts = posts.paginate(page, itp)
|
||||||
|
total_pages = ceil(posts.count() / itp)
|
||||||
|
return render_template(
|
||||||
|
"index.html",
|
||||||
|
posts=paginated_posts,
|
||||||
|
page=page,
|
||||||
|
total_pages=total_pages,
|
||||||
|
title="Latest Memes"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/about")
|
||||||
|
def about():
|
||||||
|
mods = Profile.select().join(Moderator, on=(Profile.username == Moderator.username))
|
||||||
|
return render_template("about.html", mods=mods)
|
106
suchwow/routes/mod.py
Normal file
106
suchwow/routes/mod.py
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
from flask import Blueprint, render_template, redirect, url_for, flash, request
|
||||||
|
|
||||||
|
from suchwow.models import Post, Profile, Moderator, Ban, get_ban_reason
|
||||||
|
from suchwow.utils.decorators import moderator_required
|
||||||
|
from suchwow.utils.helpers import get_session_user
|
||||||
|
from suchwow import config
|
||||||
|
|
||||||
|
|
||||||
|
bp = Blueprint("mod", "mod")
|
||||||
|
|
||||||
|
@bp.route('/mods')
|
||||||
|
@moderator_required
|
||||||
|
def main():
|
||||||
|
live_posts = Post.select().where(Post.approved == True).count()
|
||||||
|
pending_posts = Post.select().where(Post.approved == False).count()
|
||||||
|
active_posters = Profile.select().join(Post, on=Post.submitter == Profile.username).distinct().count()
|
||||||
|
mods = Moderator.select().count()
|
||||||
|
return render_template(
|
||||||
|
'mod/main.html',
|
||||||
|
live_posts=live_posts,
|
||||||
|
pending_posts=pending_posts,
|
||||||
|
active_posters=active_posters,
|
||||||
|
mods=mods
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/mods/pending')
|
||||||
|
@moderator_required
|
||||||
|
def pending_posts():
|
||||||
|
posts = Post.select().where(Post.approved == False).order_by(Post.timestamp.asc())
|
||||||
|
if not posts:
|
||||||
|
flash('no posts pending', 'is-warning')
|
||||||
|
return redirect(url_for('mod.main'))
|
||||||
|
return render_template('mod/posts.html', posts=posts)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/mods/manage', methods=['GET', 'POST'])
|
||||||
|
@moderator_required
|
||||||
|
def manage_mods():
|
||||||
|
to_delete = request.args.get('delete')
|
||||||
|
if to_delete:
|
||||||
|
m = Moderator.select().where(Moderator.username == to_delete).first()
|
||||||
|
if not m:
|
||||||
|
flash('No moderator exists with that name', 'is-danger')
|
||||||
|
elif m.username == get_session_user():
|
||||||
|
flash('Cannot remove yourself.', 'is-danger')
|
||||||
|
elif m.username == config.SUPER_ADMIN:
|
||||||
|
flash('Cannot delete super admin you son-of-a-bitch.', 'is-danger')
|
||||||
|
else:
|
||||||
|
m.delete_instance()
|
||||||
|
flash(f'Removed {to_delete} from mods!', 'is-success')
|
||||||
|
return redirect(url_for('mod.manage_mods'))
|
||||||
|
if request.method == 'POST':
|
||||||
|
to_add = request.form.get('username', None)
|
||||||
|
if to_add:
|
||||||
|
u = Profile.select().where(Profile.username == to_add).first()
|
||||||
|
if not u:
|
||||||
|
flash('That user does not appear to exist (no profile setup yet)', 'is-danger')
|
||||||
|
elif Moderator.select().where(Moderator.username == to_add).first():
|
||||||
|
flash(f'{to_add} is already a mod, ya dingus.', 'is-warning')
|
||||||
|
else:
|
||||||
|
m = Moderator(username=to_add)
|
||||||
|
m.save()
|
||||||
|
flash(f'Added {to_add} to mods!', 'is-success')
|
||||||
|
mods = Profile.select().join(Moderator, on=(Profile.username == Moderator.username))
|
||||||
|
return render_template('mod/manage.html', mods=mods)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/mods/bans', methods=['GET', 'POST'])
|
||||||
|
@moderator_required
|
||||||
|
def manage_bans():
|
||||||
|
to_delete = request.args.get('delete')
|
||||||
|
if to_delete:
|
||||||
|
ban = Ban.select().join(Profile).where(Profile.username == to_delete).first()
|
||||||
|
if not ban:
|
||||||
|
flash('No ban exists for that user', 'is-danger')
|
||||||
|
elif ban.user == get_session_user():
|
||||||
|
flash('Cannot ban yourself.', 'is-danger')
|
||||||
|
elif ban.user == config.SUPER_ADMIN:
|
||||||
|
flash('Cannot ban super admin you son-of-a-bitch.', 'is-danger')
|
||||||
|
else:
|
||||||
|
ban.delete_instance()
|
||||||
|
flash(f'Unbanned {to_delete}!', 'is-success')
|
||||||
|
return redirect(url_for('mod.manage_bans'))
|
||||||
|
if request.method == 'POST':
|
||||||
|
to_add = request.form.get('username', None)
|
||||||
|
if to_add:
|
||||||
|
u = Profile.select().where(Profile.username == to_add).first()
|
||||||
|
if not u:
|
||||||
|
flash('That user does not appear to exist (no profile setup yet)', 'is-danger')
|
||||||
|
elif Ban.select().join(Profile).where(Profile.username == to_add).first():
|
||||||
|
flash(f'{to_add} is already banned, ya dingus.', 'is-warning')
|
||||||
|
elif to_add == config.SUPER_ADMIN:
|
||||||
|
flash('Cannot ban the super admin you son-of-a-bitch.', 'is-danger')
|
||||||
|
else:
|
||||||
|
reason = request.form.get('reason')
|
||||||
|
if not reason:
|
||||||
|
reason = get_ban_reason()
|
||||||
|
ban = Ban(user=u, reason=reason)
|
||||||
|
ban.save()
|
||||||
|
flash(f'Banned {to_add}!', 'is-success')
|
||||||
|
bans = Ban.select()
|
||||||
|
return render_template('mod/bans.html', bans=bans)
|
||||||
|
|
||||||
|
# audit trail of activity
|
||||||
|
# view wallet rpc logs
|
|
@ -48,7 +48,7 @@ def read(id):
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
flash("No meme there, brah", "is-warning")
|
flash("No meme there, brah", "is-warning")
|
||||||
return redirect(url_for("index"))
|
return redirect(url_for("main.index"))
|
||||||
|
|
||||||
@bp.route("/post/create", methods=["GET", "POST"])
|
@bp.route("/post/create", methods=["GET", "POST"])
|
||||||
@login_required
|
@login_required
|
||||||
|
@ -107,7 +107,7 @@ def create():
|
||||||
url = url_for('post.read', id=post.id, _external=True)
|
url = url_for('post.read', id=post.id, _external=True)
|
||||||
post_webhook(f"New post :doge2: [{post.id}]({url}) by `{submitter}` :neckbeard:")
|
post_webhook(f"New post :doge2: [{post.id}]({url}) by `{submitter}` :neckbeard:")
|
||||||
flash("New post created and pending approval!", "is-success")
|
flash("New post created and pending approval!", "is-success")
|
||||||
return redirect(url_for("index"))
|
return redirect(url_for("main.index"))
|
||||||
return render_template("post/create.html")
|
return render_template("post/create.html")
|
||||||
|
|
||||||
@bp.route("/post/<id>/approve")
|
@bp.route("/post/<id>/approve")
|
||||||
|
@ -122,22 +122,12 @@ def approve(id):
|
||||||
post_webhook(f"Post [{post.id}]({url}) approved :white_check_mark: by `{get_session_user()}` :fieri_parrot:")
|
post_webhook(f"Post [{post.id}]({url}) approved :white_check_mark: by `{get_session_user()}` :fieri_parrot:")
|
||||||
flash("Approved", "is-success")
|
flash("Approved", "is-success")
|
||||||
if current_app.config["DEBUG"] is False:
|
if current_app.config["DEBUG"] is False:
|
||||||
# _r = None
|
|
||||||
# _d = None
|
|
||||||
# if not post.to_reddit:
|
|
||||||
# _r = make_post(post)
|
|
||||||
# if not post.to_discord:
|
|
||||||
# _d = post_discord_webhook(post)
|
|
||||||
# if _r and _d:
|
|
||||||
# post_webhook(f"Post [{post.id}]({url}) submitted :dab_parrot: to Reddit and Discord.")
|
|
||||||
# else:
|
|
||||||
# post_webhook(f"Post [{post.id}]({url}) failed :this-is-fine-fire: to post to socials...Reddit: {_r} - Discord: {_d}")
|
|
||||||
post_discord_webhook(post)
|
post_discord_webhook(post)
|
||||||
post_webhook(f"Post [{post.id}]({url}) submitted :dab_parrot: to Discord.")
|
post_webhook(f"Post [{post.id}]({url}) submitted :dab_parrot: to Discord.")
|
||||||
return redirect(url_for("mod_queue"))
|
return redirect(url_for("mod.pending_posts"))
|
||||||
else:
|
else:
|
||||||
flash("You can't approve this", "is-success")
|
flash("You can't approve this", "is-success")
|
||||||
return redirect(url_for("index"))
|
return redirect(url_for("main.index"))
|
||||||
|
|
||||||
@bp.route("/post/<id>/delete")
|
@bp.route("/post/<id>/delete")
|
||||||
@login_required
|
@login_required
|
||||||
|
@ -155,15 +145,15 @@ def delete(id):
|
||||||
post_webhook(f"Post {post.id} deleted :dumpsterfire: by `{user}` :godmode:")
|
post_webhook(f"Post {post.id} deleted :dumpsterfire: by `{user}` :godmode:")
|
||||||
flash("Deleted that shit, brah!", "is-success")
|
flash("Deleted that shit, brah!", "is-success")
|
||||||
if is_mod:
|
if is_mod:
|
||||||
return redirect(url_for("mod_queue"))
|
return redirect(url_for("mod.pending_posts"))
|
||||||
else:
|
else:
|
||||||
return redirect(url_for("index"))
|
return redirect(url_for("main.index"))
|
||||||
else:
|
else:
|
||||||
flash("You can't delete a meme you don't own, brah", "is-warning")
|
flash("You can't delete a meme you don't own, brah", "is-warning")
|
||||||
return redirect(url_for("post.read", id=post.id))
|
return redirect(url_for("post.read", id=post.id))
|
||||||
else:
|
else:
|
||||||
flash("No meme there, brah", "is-warning")
|
flash("No meme there, brah", "is-warning")
|
||||||
return redirect(url_for("index"))
|
return redirect(url_for("main.index"))
|
||||||
|
|
||||||
@bp.route("/uploads/<path:filename>")
|
@bp.route("/uploads/<path:filename>")
|
||||||
def uploaded_file(filename):
|
def uploaded_file(filename):
|
||||||
|
|
|
@ -70,13 +70,17 @@
|
||||||
<!-- Page Content -->
|
<!-- Page Content -->
|
||||||
{% block content %} {% endblock %}
|
{% block content %} {% endblock %}
|
||||||
|
|
||||||
|
<div style="padding-bottom:10em;"></div>
|
||||||
|
|
||||||
<!-- Footer -->
|
<!-- Footer -->
|
||||||
|
{% block footer %}
|
||||||
<footer class="footer">
|
<footer class="footer">
|
||||||
<div class="content has-text-centered">
|
<div class="content has-text-centered">
|
||||||
<p><strong>SuchWow</strong> by <a href="https://lzahq.tech" target="_blank">lza_menace</a></p>
|
<p><strong>SuchWow</strong> by <a href="https://lzahq.tech" target="_blank">lza_menace</a></p>
|
||||||
<p><a href="https://wownero.org/" target="_blank">Learn more about the infamous shitcoin, Wownero</a>.</p>
|
<p><a href="https://wownero.org/" target="_blank">Learn more about the infamous shitcoin, Wownero</a>.</p>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
<!-- JS -->
|
<!-- JS -->
|
||||||
<script>
|
<script>
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
{% extends 'base.html' %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
<div class="container" style="width:40%;">
|
|
||||||
<div class="submit">
|
|
||||||
<h1>Leave a Comment</h1>
|
|
||||||
<form method=post enctype=multipart/form-data class="form-horizontal">
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="sr-only" for="inlineFormInput">Text</label>
|
|
||||||
<input type="text" class="form-control mb-2 mr-sm-2 mb-sm-0" id="inlineFormInput" placeholder="Comment text (max 300 chars)" name="comment">
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<button type="submit" class="btn btn-success">Submit</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
|
@ -26,7 +26,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
<a href="{{ url_for('index') }}"><button class="btn btn-warning">Go Home</button></a>
|
<a href="{{ url_for('main.index') }}"><button class="btn btn-warning">Go Home</button></a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
57
suchwow/templates/mod/bans.html
Normal file
57
suchwow/templates/mod/bans.html
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<div class="container" style="text-align:center;">
|
||||||
|
<h1 class="title">Manage Mods</h1>
|
||||||
|
<nav class="breadcrumb is-centered" aria-label="breadcrumbs">
|
||||||
|
<ul>
|
||||||
|
<li><a href="/">Home</a></li>
|
||||||
|
<li><a href="{{ url_for('mod.main') }}">Mods</a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
<section class="section">
|
||||||
|
{% for ban in bans %}
|
||||||
|
<article class="message" style="width: 30%; margin: 2em auto;">
|
||||||
|
<div class="message-header">
|
||||||
|
<p>{{ ban.user.username }}</p>
|
||||||
|
<a href="?delete={{ ban.user.username }}" class="delete"></a>
|
||||||
|
</div>
|
||||||
|
<div class="message-body">
|
||||||
|
{{ ban.reason }}
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
{% endfor %}
|
||||||
|
</section>
|
||||||
|
<div class="container" style="text-align:left; width: 30%;">
|
||||||
|
<form method="post">
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Ban User</label>
|
||||||
|
<div class="control">
|
||||||
|
<input class="input" type="text" placeholder="Username" name="username">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Reason</label>
|
||||||
|
<div class="control">
|
||||||
|
<textarea class="textarea" placeholder="Reason for ban" name="reason"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="field is-grouped">
|
||||||
|
<div class="control">
|
||||||
|
<button class="button is-link">Submit</button>
|
||||||
|
</div>
|
||||||
|
<div class="control">
|
||||||
|
<button class="button is-link is-light">Cancel</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block footer %}{% endblock %}
|
72
suchwow/templates/mod/main.html
Normal file
72
suchwow/templates/mod/main.html
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<div class="container content" style="padding-top: 4em;">
|
||||||
|
|
||||||
|
|
||||||
|
<nav class="level">
|
||||||
|
<div class="level-item has-text-centered">
|
||||||
|
<div>
|
||||||
|
<p class="heading">Live Memes</p>
|
||||||
|
<p class="title">{{ live_posts }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="level-item has-text-centered">
|
||||||
|
<div>
|
||||||
|
<p class="heading">Pending Memes</p>
|
||||||
|
<p class="title">{{ pending_posts }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="level-item has-text-centered">
|
||||||
|
<div>
|
||||||
|
<p class="heading">Active Posters</p>
|
||||||
|
<p class="title">{{ active_posters }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="level-item has-text-centered">
|
||||||
|
<div>
|
||||||
|
<p class="heading">Mods</p>
|
||||||
|
<p class="title">{{ mods }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<div class="tabs is-toggle is-fullwidth">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a href="{{ url_for('mod.pending_posts') }}">
|
||||||
|
<span class="icon is-small"></span>
|
||||||
|
<span>Manage Queue</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ url_for('mod.manage_bans') }}">
|
||||||
|
<span class="icon is-small"></span>
|
||||||
|
<span>Manage Bans</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ url_for('mod.manage_mods') }}">
|
||||||
|
<span class="icon is-small"></span>
|
||||||
|
<span>Manage Mods</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a>
|
||||||
|
<span class="icon is-small"></span>
|
||||||
|
<span>View Logs</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<figure>
|
||||||
|
<img src="https://suchwow.xyz/uploads/pg1VwHJWeKT5dWXy-wowcomfysemifinal.gif">
|
||||||
|
</figure>
|
||||||
|
<div style="padding-bottom:10em;"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block footer %}{% endblock %}
|
48
suchwow/templates/mod/manage.html
Normal file
48
suchwow/templates/mod/manage.html
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<div class="container" style="text-align:center;">
|
||||||
|
<h1 class="title">Manage Mods</h1>
|
||||||
|
<nav class="breadcrumb is-centered" aria-label="breadcrumbs">
|
||||||
|
<ul>
|
||||||
|
<li><a href="/">Home</a></li>
|
||||||
|
<li><a href="{{ url_for('mod.main') }}">Mods</a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
<section class="section">
|
||||||
|
{% for mod in mods %}
|
||||||
|
<div class="block">
|
||||||
|
<span class="tag is-large">
|
||||||
|
{{ mod.username }}
|
||||||
|
<a href="?delete={{ mod.username }}" class="delete"></a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</section>
|
||||||
|
<div class="container" style="text-align:left; width: 30%;">
|
||||||
|
<form method="post">
|
||||||
|
<div class="field">
|
||||||
|
<label class="label">Add New Mod</label>
|
||||||
|
<div class="control">
|
||||||
|
<input class="input" type="text" placeholder="Username" name="username">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="field is-grouped">
|
||||||
|
<div class="control">
|
||||||
|
<button class="button is-link">Submit</button>
|
||||||
|
</div>
|
||||||
|
<div class="control">
|
||||||
|
<button class="button is-link is-light">Cancel</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block footer %}{% endblock %}
|
65
suchwow/templates/mod/posts.html
Normal file
65
suchwow/templates/mod/posts.html
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<div class="container" style="text-align:center;">
|
||||||
|
|
||||||
|
<h1 class="title">{% if title %}{{ title }}{% else %}Pending Posts{% endif %}</h1>
|
||||||
|
<nav class="breadcrumb is-centered" aria-label="breadcrumbs">
|
||||||
|
<ul>
|
||||||
|
<li><a href="/">Home</a></li>
|
||||||
|
<li><a href="{{ url_for('mod.main') }}">Mods</a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
<section class="section">
|
||||||
|
{% if posts %}
|
||||||
|
{% for row in posts | batch(4) %}
|
||||||
|
<div class="columns">
|
||||||
|
{% for p in row %}
|
||||||
|
{% set post = p.show() %}
|
||||||
|
<div class="column">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-image">
|
||||||
|
{% if p.get_image_path().endswith('mp4') %}
|
||||||
|
<video style="max-height: 100vh!important;" controls>
|
||||||
|
<source src="{{ url_for('post.uploaded_file', filename=p.image_name) }}" type="video/mp4">
|
||||||
|
Your browser does not support the video tag.
|
||||||
|
</video>
|
||||||
|
{% else %}
|
||||||
|
<img alt="SuchWow #{{ post.id }} - {{ post.title }} by {{ post.submitter }}" src="{{ url_for('post.uploaded_file', filename=post.thumbnail_name) }}" />
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="card-content">
|
||||||
|
<div class="media">
|
||||||
|
<div class="media-content">
|
||||||
|
<p class="title is-4">
|
||||||
|
{{ post.title }}
|
||||||
|
</p>
|
||||||
|
<p class="subtitle is-6"><a href="/?submitter={{ post.submitter }}">{{ post.submitter }}</a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
{{ post.text | truncate(60) }}
|
||||||
|
<time datetime="2016-1-1">{{ post.timestamp.year }}-{{ post.timestamp.month }}-{{ post.timestamp.day }} {{ post.timestamp.hour }}:{{ post.timestamp.minute }} UTC</time>
|
||||||
|
<p>({{ post.timestamp | humanize }})</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<footer class="card-footer">
|
||||||
|
<a href="{{ url_for('post.approve', id=post.id) }}" class="card-footer-item" style="color:green;"><strong>Approve</strong></a>
|
||||||
|
<a href="{{ url_for('post.delete', id=post.id) }}" class="card-footer-item" style="color:red;"><strong>Deny</strong></a>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% else %}
|
||||||
|
<p>No posts pending!</p>
|
||||||
|
{% endif %}
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block footer %}{% endblock %}
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
<div id="navbarBasicExample" class="navbar-menu">
|
<div id="navbarBasicExample" class="navbar-menu">
|
||||||
<div class="navbar-start">
|
<div class="navbar-start">
|
||||||
<a class="navbar-item" href="{{ url_for('index') }}">Home</a>
|
<a class="navbar-item" href="{{ url_for('main.index') }}">Home</a>
|
||||||
<div class="navbar-item has-dropdown is-hoverable">
|
<div class="navbar-item has-dropdown is-hoverable">
|
||||||
<a class="navbar-link">Leaderboards</a>
|
<a class="navbar-link">Leaderboards</a>
|
||||||
|
|
||||||
|
@ -26,10 +26,10 @@
|
||||||
<a class="navbar-item" href="{{ url_for('leaderboard.top_posts') }}?days=9999">Top Memes All Time</a>
|
<a class="navbar-item" href="{{ url_for('leaderboard.top_posts') }}?days=9999">Top Memes All Time</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a class="navbar-item" href="{{ url_for('about') }}">About</a>
|
<a class="navbar-item" href="{{ url_for('main.about') }}">About</a>
|
||||||
<a class="navbar-item" href="{{ url_for('post.create') }}">Submit</a>
|
<a class="navbar-item" href="{{ url_for('post.create') }}">Submit</a>
|
||||||
{% if session.auth %}
|
{% if session.auth.preferred_username | is_moderator %}
|
||||||
<a class="navbar-item" style="color: orange;" href="{{ url_for('mod_queue') }}">Mods!</a>
|
<a class="navbar-item" style="color: orange;" href="{{ url_for('mod.main') }}">Mods!</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@
|
||||||
<a class="nav-link" href="{{ url_for('post.create') }}">Submit</a>
|
<a class="nav-link" href="{{ url_for('post.create') }}">Submit</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="{{ url_for('about') }}">About</a>
|
<a class="nav-link" href="{{ url_for('main.about') }}">About</a>
|
||||||
</li>
|
</li>
|
||||||
{% if session.auth == None %}
|
{% if session.auth == None %}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
|
|
|
@ -9,25 +9,63 @@
|
||||||
<ol>
|
<ol>
|
||||||
<li>no super low effort memes</li>
|
<li>no super low effort memes</li>
|
||||||
<li>no nsfl and nsfw</li>
|
<li>no nsfl and nsfw</li>
|
||||||
<li>must pertain to wownero or crypto in general</li>
|
<!-- <li>must pertain to wownero or crypto in general</li> -->
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
<form method=post enctype=multipart/form-data class="form-horizontal">
|
<form method=post enctype=multipart/form-data class="form-horizontal">
|
||||||
<div class="form-group">
|
<div class="field">
|
||||||
<label class="sr-only" for="inlineFormInput">Title</label>
|
<label class="label">Title</label>
|
||||||
<input type="text" class="form-control mb-2 mr-sm-2 mb-sm-0" id="inlineFormInput" placeholder="Title" name="title">
|
<div class="control">
|
||||||
|
<input class="input" type="text" placeholder="So there I was..." name="title">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
|
||||||
<label class="sr-only" for="inlineFormInput">Text</label>
|
|
||||||
<input type="text" class="form-control mb-2 mr-sm-2 mb-sm-0" id="inlineFormInput" placeholder="Text (optional)" name="text">
|
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="field">
|
||||||
<input type=file name=file>
|
<label class="label">Text</label>
|
||||||
|
<div class="control">
|
||||||
|
<textarea class="textarea" placeholder="balls deep in a jar of mayonnaise" name="text"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="file-js-example" class="file has-name">
|
||||||
|
<label class="file-label">
|
||||||
|
<input class="file-input" type="file" name="file">
|
||||||
|
<span class="file-cta">
|
||||||
|
<span class="file-icon">
|
||||||
|
<i class="fas fa-upload"></i>
|
||||||
|
</span>
|
||||||
|
<span class="file-label">
|
||||||
|
Upload a spicy meme
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<span class="file-name">
|
||||||
|
No file uploaded
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="field mt-4">
|
||||||
|
<div class="control">
|
||||||
|
<label class="checkbox">
|
||||||
|
<input type="checkbox">
|
||||||
|
I agree to be hella based
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="field is-grouped">
|
||||||
|
<div class="control">
|
||||||
|
<button class="button is-link">Submit</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
|
||||||
<button type="submit" class="btn btn-success">Submit</button>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const fileInput = document.querySelector('#file-js-example input[type=file]');
|
||||||
|
fileInput.onchange = () => {
|
||||||
|
if (fileInput.files.length > 0) {
|
||||||
|
const fileName = document.querySelector('#file-js-example .file-name');
|
||||||
|
fileName.textContent = fileInput.files[0].name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ def moderator_required(f):
|
||||||
return f(*args, **kwargs)
|
return f(*args, **kwargs)
|
||||||
else:
|
else:
|
||||||
flash("You are not a moderator", "is-warning")
|
flash("You are not a moderator", "is-warning")
|
||||||
return redirect(url_for("index"))
|
return redirect(url_for("main.index"))
|
||||||
return decorated_function
|
return decorated_function
|
||||||
|
|
||||||
def profile_required(f):
|
def profile_required(f):
|
||||||
|
|
Loading…
Reference in a new issue