From 23c5ed30f115c8ee8cb9bf16441c30e0a0e61403 Mon Sep 17 00:00:00 2001
From: ubq323 <ubq323>
Date: Thu, 26 Aug 2021 01:01:15 +0000
Subject: web hook code, and things

---
 apioforum/forum.py    |   4 ++
 apioforum/thread.py   |   7 ++-
 apioforum/webhooks.py | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 132 insertions(+), 2 deletions(-)
 create mode 100644 apioforum/webhooks.py

diff --git a/apioforum/forum.py b/apioforum/forum.py
index 87d4022..3d7611b 100644
--- a/apioforum/forum.py
+++ b/apioforum/forum.py
@@ -225,6 +225,10 @@ def create_thread(forum):
                 (thread_id,g.user,content)
             )
             db.commit()
+
+            from . import webhooks
+            thread = db.execute("select * from threads where id = ?",(thread_id,)).fetchone()
+            webhooks.do_webhooks_thread(forum['id'],thread)
             return redirect(url_for('thread.view_thread',thread_id=thread_id))
         flash(err)
         
diff --git a/apioforum/thread.py b/apioforum/thread.py
index f3bcc59..05abce2 100644
--- a/apioforum/thread.py
+++ b/apioforum/thread.py
@@ -8,6 +8,7 @@ from flask import (
 )
 from .db import get_db
 from .roles import has_permission
+from . import webhooks
 from .forum import get_avail_tags
 
 bp = Blueprint("thread", __name__, url_prefix="/thread")
@@ -38,9 +39,9 @@ def which_page(post_id,return_thread_id=False):
     else:
         return page
 
-def post_jump(post_id):
+def post_jump(post_id,*,external=False):
     page,thread_id=which_page(post_id,True)
-    return url_for("thread.view_thread",thread_id=thread_id,page=page)+"#post_"+str(post_id)
+    return url_for("thread.view_thread",thread_id=thread_id,page=page,_external=external)+"#post_"+str(post_id)
 
 @bp.route("/<int:thread_id>")
 @bp.route("/<int:thread_id>/page/<int:page>")
@@ -255,6 +256,8 @@ def create_post(thread_id):
             (thread_id,)
         )
         db.commit()
+        post = db.execute("select * from posts where id = ?",(post_id,)).fetchone()
+        webhooks.do_webhooks_post(thread['forum'],post)
         flash("post posted postfully")
         return redirect(post_jump(post_id))
     return redirect(url_for('thread.view_thread',thread_id=thread_id))
diff --git a/apioforum/webhooks.py b/apioforum/webhooks.py
new file mode 100644
index 0000000..671100c
--- /dev/null
+++ b/apioforum/webhooks.py
@@ -0,0 +1,123 @@
+import urllib
+import json
+from .db import get_db
+from flask import url_for, flash
+
+def abridge_post(text):
+    MAXLEN = 20
+    if len(text) > MAXLEN+3:
+        return text[:MAXLEN]+"..."
+    else:
+        return text
+
+def send_discord_webhook(url,payload):
+    headers = {
+        "User-Agent":"apioforum (https://f.gh0.pw/apioforum/, v0.0)",
+        "Content-Type":"application/json",
+    }
+    req = urllib.request.Request(
+        url,
+        json.dumps(payload).encode("utf-8"),
+        headers
+    )
+    # todo: read response and things
+    urllib.request.urlopen(req)
+    #try:
+    #    res = urllib.request.urlopen(req)
+    #except urllib.error.HTTPError as e:
+    #    print(f"error {e.code} {e.read()}")
+    #else:
+    #    print(f"succ {res.read()}")
+    
+# todo: object oriented thing for different kinds of webhook (not just discord)
+
+def f(name,value):
+    # discord embed field
+    return {"name":name,"value":value,"inline":True}
+
+def discord_on_new_thread(wh_url, thread):
+    db = get_db()
+    forum = db.execute("select * from forums where id = ?",(thread['forum'],)).fetchone()
+    username = thread['creator']
+    userpage = url_for('user.view_user',username=username,_external=True)
+
+    forumpage = url_for('forum.view_forum',forum_id=forum['id'],_external=True)
+
+    post = db.execute("select * from posts where thread = ? order by id asc limit 1",(thread['id'],)).fetchone()
+    
+    
+    payload = {
+        "username":"apioforum",
+        "avatar_url":"https://d.gh0.pw/lib/exe/fetch.php?media=wiki:logo.png",
+        "embeds":[
+            {
+                "title":thread['title'],
+                "description":abridge_post(post['content']),
+                "url": url_for('thread.view_thread',thread_id=thread['id'],_external=True),
+                "color": 0xff00ff,
+                "fields":[
+                    f('author',f"[{username}]({userpage})"),
+                    f('forum',f"[{forum['name']}]({forumpage})"),
+                ],
+                "footer":{
+                    "text":thread['created'].isoformat(' '),
+                },
+            },
+        ],
+    }
+    send_discord_webhook(wh_url,payload)
+
+def discord_on_new_post(wh_url, post):
+    from .thread import post_jump
+    db = get_db()
+
+    thread = db.execute("select * from threads where id = ?",(post['thread'],)).fetchone()
+    threadpage = url_for('thread.view_thread',thread_id=thread['id'],_external=True)
+
+    forum = db.execute("select * from forums where id = ?",(thread['forum'],)).fetchone()
+    forumpage = url_for('forum.view_forum',forum_id=forum['id'],_external=True)
+
+    username = post['author']
+    userpage = url_for('user.view_user',username=username,_external=True)
+
+    payload = {
+        "username":"apioforum",
+        "avatar_url":"https://d.gh0.pw/lib/exe/fetch.php?media=wiki:logo.png",
+        "embeds":[
+            {
+                "title":"re: "+thread['title'],
+                "description":abridge_post(post['content']),
+                "url": post_jump(post['id'],external=True),
+                "color": 0x00ffff,
+                "fields":[
+                    f('author',f"[{username}]({userpage})"),
+                    f('thread',f"[{thread['title']}]({threadpage})"),
+                    f('forum',f"[{forum['name']}]({forumpage})"),
+                ],
+                "footer":{
+                    "text":post['created'].isoformat(' '),
+                },
+            },
+        ],
+    }
+    send_discord_webhook(wh_url,payload)
+
+def _do_webhooks(forum_id,thing,fn):
+    db = get_db()
+    # todo inheritance
+    webhooks = db.execute("select * from webhooks where forum = ? and type = 'discord'",(forum_id,)).fetchall()
+    for wh in webhooks:
+        wh_url = wh['url']
+        try:
+            fn(wh_url,thing)
+        except:
+            pass # handle probably
+        flash(f"wh {wh['id']}")
+
+def do_webhooks_thread(forum_id,thread):
+    _do_webhooks(forum_id,thread,discord_on_new_thread)
+
+def do_webhooks_post(forum_id,post):
+    _do_webhooks(forum_id,post,discord_on_new_post)
+    
+    
-- 
cgit v1.2.3