revamp logging and auditing with webhook events

This commit is contained in:
lza_menace 2020-12-13 22:28:23 -08:00
parent 9a6518c150
commit 09409b80a7
5 changed files with 73 additions and 62 deletions

View file

@ -10,6 +10,7 @@ from suchwow import config
from suchwow.models import Post, Profile, Comment, Notification, db, Moderator from suchwow.models import Post, Profile, Comment, Notification, db, Moderator
from suchwow.routes import auth, comment, post, profile, leaderboard from suchwow.routes import auth, comment, post, profile, leaderboard
from suchwow.utils.decorators import login_required, moderator_required from suchwow.utils.decorators import login_required, moderator_required
from suchwow.utils.helpers import post_webhook
from suchwow.reddit import make_post from suchwow.reddit import make_post
from suchwow.discord import post_discord_webhook from suchwow.discord import post_discord_webhook
from suchwow import wownero from suchwow import wownero
@ -76,57 +77,24 @@ def create_accounts():
account = wallet.new_account() account = wallet.new_account()
print(f"Created account {account}") print(f"Created account {account}")
@app.cli.command("post_new_memes")
def post_new_memes():
# run every 5 mins
all_posts = Post.select().order_by(Post.timestamp.desc()).where(
(Post.to_reddit == False) | (Post.to_discord == False)
)
for post in all_posts:
diff = datetime.now() - post.timestamp
recent_post = diff < timedelta(hours=2)
if recent_post:
if not post.to_reddit:
make_post(post)
if not post.to_discord:
post_discord_webhook(post)
return
@app.cli.command("post_meme")
@click.argument("post_id")
def post_meme(post_id):
post = Post.get(id=post_id)
make_post(post)
post_discord_webhook(post)
return
@app.cli.command("reddit_random")
def reddit_random():
# run every 8 hours
all_posts = Post.select().where(Post.reddit_url == None)
post = choice(all_posts)
make_post(post)
@app.cli.command("payout_users") @app.cli.command("payout_users")
def payout_users(): def payout_users():
wallet = wownero.Wallet() wallet = wownero.Wallet()
_fa = wownero.from_atomic
_aw = wownero.as_wownero
for post in Post.select(): for post in Post.select():
submitter = Profile.get(username=post.submitter) submitter = Profile.get(username=post.submitter)
balances = wallet.balances(post.account_index) balances = wallet.balances(post.account_index)
url = url_for('post.read', id=post.id, _external=True)
if balances[1] > 0: if balances[1] > 0:
print(f"Post #{post.id} has {balances[1]} funds unlocked and ready to send. Sweeping all funds to user's address ({submitter.address}).") 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) sweep = wallet.sweep_all(account=post.account_index, dest_address=submitter.address)
print(sweep) print(sweep)
if "tx_hash_list" in sweep:
@app.cli.command("delete_post") amount = 0
@click.argument("post_id") for amt in sweep["amount_list"]:
def _delete_post(post_id): amount += int(amt)
post = Post.get(id=post_id) post_webhook(f"Paid out :moneybag: {_aw(_fa(amount))} WOW to `{post.submitter}` for post [{post.id}]({url})")
save_path_base = path.join(app.config["DATA_FOLDER"], "uploads")
save_path = path.join(save_path_base, post.image_name)
post.delete_instance()
remove(save_path)
print(f"Deleted post {post_id} and image {save_path}")
@app.cli.command("add_admin") @app.cli.command("add_admin")
@click.argument("username") @click.argument("username")
@ -135,6 +103,7 @@ def add_admin(username):
m = Moderator(username=username) m = Moderator(username=username)
m.save() m.save()
print(f"Added {username}") print(f"Added {username}")
post_webhook(f"Moderator `{username}` added :ship_it_parrot: by console :black_flag:")
else: else:
print("That moderator already exists") print("That moderator already exists")
@ -145,6 +114,7 @@ def remove_admin(username):
if m: if m:
m.delete_instance() m.delete_instance()
print(f"Deleted {username}") print(f"Deleted {username}")
post_webhook(f"Moderator `{username}` removed :excuseme: by console :black_flag:")
else: else:
print("That moderator doesn't exist") print("That moderator doesn't exist")

View file

@ -1,3 +1,6 @@
from os import getenv
OIDC_URL = 'https://login.wownero.com/auth/realms/master/protocol/openid-connect', OIDC_URL = 'https://login.wownero.com/auth/realms/master/protocol/openid-connect',
OIDC_CLIENT_ID = 'suchwowxxx', OIDC_CLIENT_ID = 'suchwowxxx',
OIDC_CLIENT_SECRET = 'xxxxxxxxxx', OIDC_CLIENT_SECRET = 'xxxxxxxxxx',
@ -20,3 +23,8 @@ PRAW_PASSWORD = 'xxxxxxxx'
SERVER_NAME = 'localhost' SERVER_NAME = 'localhost'
DISCORD_URL = 'xxxxxxx' DISCORD_URL = 'xxxxxxx'
BANNED_USERS = {'username': 'reason for the ban'} BANNED_USERS = {'username': 'reason for the ban'}
MM_ICON = getenv('MM_ICON', 'https://funding.wownero.com/static/wowdoge-a.jpg')
MM_CHANNEL = getenv('MM_CHANNEL', 'suchwow')
MM_USERNAME = getenv('MM_USERNAME', 'SuchWow!')
MM_ENDPOINT = getenv('MM_ENDPOINT', 'ppppppppppppppppppppppppp')

View file

@ -10,13 +10,16 @@ insults = ["fart sacks", "dick lips", "shit stains", "chodes", "dipshits", "dick
def post_discord_webhook(post): def post_discord_webhook(post):
wallet = wownero.Wallet() try:
post_wow_address = wallet.get_address(account=post.account_index) wallet = wownero.Wallet()
content = f"{choice(intro)} {choice(insults)}, new SuchWow post #{post.id} by {post.submitter} is up! Tip WOW to `{post_wow_address}` to show support! {url_for('post.uploaded_file', filename=post.image_name, _external=True)}" post_wow_address = wallet.get_address(account=post.account_index)
msg = {"content": content} content = f"{choice(intro)} {choice(insults)}, new SuchWow post #{post.id} by {post.submitter} is up! Tip WOW to `{post_wow_address}` to show support! {url_for('post.uploaded_file', filename=post.image_name, _external=True)}"
discord_webhook_url = config.DISCORD_URL msg = {"content": content}
r = requests.post(discord_webhook_url, data=msg) discord_webhook_url = config.DISCORD_URL
r.raise_for_status() r = requests.post(discord_webhook_url, data=msg)
post.to_discord = True r.raise_for_status()
post.save() post.to_discord = True
print(f"Posted #{post.id} to Discord") post.save()
return True
except:
return False

View file

@ -7,7 +7,7 @@ from suchwow import wownero
from suchwow import config from suchwow import config
from suchwow.models import Post, Comment from suchwow.models import Post, Comment
from suchwow.utils.decorators import login_required, profile_required, moderator_required from suchwow.utils.decorators import login_required, profile_required, moderator_required
from suchwow.utils.helpers import allowed_file, is_moderator, get_session_user from suchwow.utils.helpers import allowed_file, is_moderator, get_session_user, post_webhook
from suchwow.reddit import make_post from suchwow.reddit import make_post
from suchwow.discord import post_discord_webhook from suchwow.discord import post_discord_webhook
@ -100,21 +100,31 @@ def create():
address_index=0 address_index=0
) )
post.save() post.save()
return redirect(url_for("post.read", id=post.id)) url = url_for('post.read', id=post.id, _external=True)
post_webhook(f"New post :doge2: [{post.id}]({url}) by `{submitter}` :neckbeard:")
return redirect(url)
return render_template("post/create.html") return render_template("post/create.html")
@bp.route("/post/<id>/approve") @bp.route("/post/<id>/approve")
@moderator_required @moderator_required
def approve(id): def approve(id):
post = Post.get(id=id) post = Post.get(id=id)
url = url_for('post.read', id=post.id, _external=True)
if post: if post:
post.approved = True if not post.approved:
post.save() post.approved = True
if not post.to_reddit: post.save()
make_post(post) post_webhook(f"Post [{post.id}]({url}) approved :white_check_mark: by `{get_session_user()}` :fieri_parrot:")
if not post.to_discord: flash("Approved")
post_discord_webhook(post) if current_app.config["DEBUG"] is False:
flash("Approved") 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}")
return redirect(url_for("mod_queue")) return redirect(url_for("mod_queue"))
else: else:
flash("You can't approve this") flash("You can't approve this")
@ -133,6 +143,7 @@ def delete(id):
save_path = path.join(save_path_base, post.image_name) save_path = path.join(save_path_base, post.image_name)
remove(save_path) remove(save_path)
post.delete_instance() post.delete_instance()
post_webhook(f"Post {post.id} deleted :dumpsterfire: by `{user}` :godmode:")
flash("Deleted that shit, brah!") flash("Deleted that shit, brah!")
if is_mod: if is_mod:
return redirect(url_for("mod_queue")) return redirect(url_for("mod_queue"))

View file

@ -1,10 +1,13 @@
from flask import current_app, session from requests import post as r_post
from json import dumps
from flask import session, current_app
from suchwow.models import Moderator from suchwow.models import Moderator
from suchwow import config
def allowed_file(filename): def allowed_file(filename):
return "." in filename and \ return "." in filename and \
filename.rsplit(".", 1)[1].lower() in current_app.config["ALLOWED_EXTENSIONS"] filename.rsplit(".", 1)[1].lower() in config.ALLOWED_EXTENSIONS
def is_moderator(username): def is_moderator(username):
m = Moderator.filter(username=username) m = Moderator.filter(username=username)
@ -17,3 +20,19 @@ def get_session_user():
if "auth" not in session or not session["auth"]: if "auth" not in session or not session["auth"]:
return None return None
return session["auth"]["preferred_username"] return session["auth"]["preferred_username"]
def post_webhook(msg):
try:
if current_app.config["DEBUG"]:
msg = "[DEBUG] " + msg
data = {
"text": msg,
"channel": config.MM_CHANNEL,
"username": config.MM_USERNAME,
"icon_url": config.MM_ICON
}
res = r_post(config.MM_ENDPOINT, data=dumps(data))
res.raise_for_status()
return True
except:
return False