Initial Commit
This commit is contained in:
2
modules/board/__init__.py
Normal file
2
modules/board/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from flask import Blueprint
|
||||
board_bp = Blueprint("board", __name__, template_folder="templates")
|
||||
52
modules/board/routes.py
Normal file
52
modules/board/routes.py
Normal file
@@ -0,0 +1,52 @@
|
||||
import os, time, requests
|
||||
GUILD = os.getenv("DISCORD_GUILD_ID","")
|
||||
CHANNEL = os.getenv("DISCORD_CHANNEL_ID","")
|
||||
WEBHOOK = os.getenv("DISCORD_WEBHOOK_URL","")
|
||||
|
||||
|
||||
_cache = {"ts":0, "messages":[]}
|
||||
TTL = 10
|
||||
|
||||
|
||||
def _headers():
|
||||
if not BOT: raise RuntimeError("Missing DISCORD_BOT_TOKEN")
|
||||
return {"Authorization": f"Bot {BOT}"}
|
||||
|
||||
|
||||
@board_bp.get("/")
|
||||
@require_perms("board.view")
|
||||
def index():
|
||||
return render_template("board/index.html")
|
||||
|
||||
|
||||
@board_bp.get("/api/messages")
|
||||
@require_perms("board.view")
|
||||
def api_messages():
|
||||
now = time.time()
|
||||
if now - _cache["ts"] < TTL and _cache["messages"]:
|
||||
return jsonify(_cache["messages"])
|
||||
url = f"{DISCORD_API}/channels/{CHANNEL}/messages"
|
||||
r = requests.get(url, headers=_headers(), params={"limit":40}, timeout=10)
|
||||
msgs = []
|
||||
if r.status_code == 200:
|
||||
for m in reversed(r.json()):
|
||||
a = m.get("author", {})
|
||||
msgs.append({
|
||||
"id": m.get("id"),
|
||||
"content": m.get("content",""),
|
||||
"username": a.get("global_name") or a.get("username","user"),
|
||||
"timestamp": m.get("timestamp"),
|
||||
})
|
||||
_cache.update({"ts":now, "messages":msgs})
|
||||
return jsonify(msgs)
|
||||
|
||||
|
||||
@board_bp.post("/api/post")
|
||||
@require_perms("board.post")
|
||||
def api_post():
|
||||
data = request.get_json(force=True)
|
||||
content = (data.get("content") or "").strip()
|
||||
if not content: return jsonify({"ok":False,"error":"Empty"}),400
|
||||
if not WEBHOOK: return jsonify({"ok":False,"error":"No webhook"}),500
|
||||
r = requests.post(WEBHOOK, json={"content": content[:1800]}, timeout=10)
|
||||
return (jsonify({"ok":True}), 200) if r.status_code in (200,204) else (jsonify({"ok":False}), 502)
|
||||
41
modules/board/templates/board/index.html
Normal file
41
modules/board/templates/board/index.html
Normal file
@@ -0,0 +1,41 @@
|
||||
{% extends 'core/base.html' %}
|
||||
{% block title %}Intercom — Portal{% endblock %}
|
||||
{% block content %}
|
||||
<section class="max-w-4xl mx-auto">
|
||||
<header class="flex items-center justify-between mb-4">
|
||||
<h1 class="text-2xl font-bold">Discord Intercom</h1>
|
||||
<button id="refresh" class="btn">Refresh</button>
|
||||
</header>
|
||||
<div id="list" class="space-y-3"></div>
|
||||
|
||||
|
||||
<div class="mt-6 card glass p-4">
|
||||
<textarea id="composer" rows="3" class="w-full"></textarea>
|
||||
<div class="mt-2 text-right"><button id="send" class="btn bg-accent font-semibold">Post</button></div>
|
||||
</div>
|
||||
</section>
|
||||
<script>
|
||||
async function load(){
|
||||
const r = await fetch('/board/api/messages');
|
||||
const data = await r.json();
|
||||
const root = document.getElementById('list');
|
||||
root.innerHTML = data.map(m=>`
|
||||
<article class="card glass p-4">
|
||||
<div class="text-sm text-white/60">${(m.timestamp||'').replace('T',' ').replace('Z',' UTC')}</div>
|
||||
<div class="font-semibold">${m.username||'user'}</div>
|
||||
<div class="mt-1 whitespace-pre-wrap">${m.content||''}</div>
|
||||
</article>`).join('');
|
||||
}
|
||||
async function post(){
|
||||
const v = document.getElementById('composer').value.trim();
|
||||
if(!v) return;
|
||||
const r = await fetch('/board/api/post',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({content:v})});
|
||||
if(r.ok){ document.getElementById('composer').value=''; load(); }
|
||||
else alert('Not allowed or failed');
|
||||
}
|
||||
load();
|
||||
setInterval(load,15000);
|
||||
refresh.onclick = load;
|
||||
send.onclick = post;
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user