Initial commit
This commit is contained in:
commit
ae59e020d8
3 changed files with 139 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
__pycache__/
|
||||||
|
secret.py
|
||||||
|
blocked.json
|
81
main.py
Normal file
81
main.py
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
import json
|
||||||
|
import time
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import flask
|
||||||
|
import requests
|
||||||
|
|
||||||
|
from secret import token
|
||||||
|
|
||||||
|
REVERSE_PROXY = False # if True: uses X-Real-IP header instead of remote addr
|
||||||
|
BASE_DIR = Path(__file__).parent
|
||||||
|
TIMEOUT = 15 * 60
|
||||||
|
CONTENT_WARNING = "test post ignore" # "Post from a random person - trinkey is not responsible for the content!!"
|
||||||
|
POST_URL = "https://is.trinkey.com/api/iceshrimp/notes"
|
||||||
|
RUN_CONF = {
|
||||||
|
"debug": True,
|
||||||
|
"host": "127.0.0.1",
|
||||||
|
"port": "8000"
|
||||||
|
}
|
||||||
|
|
||||||
|
app = flask.Flask(__file__)
|
||||||
|
|
||||||
|
data: dict[str, int] = {}
|
||||||
|
|
||||||
|
try:
|
||||||
|
data = json.load(open(BASE_DIR / "blocked.json", "r"))
|
||||||
|
except FileNotFoundError:
|
||||||
|
...
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
...
|
||||||
|
|
||||||
|
def save():
|
||||||
|
with open(BASE_DIR / "blocked.json", "w") as f:
|
||||||
|
json.dump(data, f)
|
||||||
|
|
||||||
|
def get_ip() -> str:
|
||||||
|
return (flask.request.headers.get("X-Real-IP") if REVERSE_PROXY else flask.request.remote_addr) or "0.0.0.0"
|
||||||
|
|
||||||
|
app.route("/about/")(lambda: open(BASE_DIR / "public/about.html", "rb").read())
|
||||||
|
|
||||||
|
@app.route("/", methods=["POST", "GET"])
|
||||||
|
def index() -> bytes:
|
||||||
|
ip = get_ip()
|
||||||
|
cant_post = ip in data and data[ip] > time.time()
|
||||||
|
message = ""
|
||||||
|
|
||||||
|
if flask.request.method == "POST":
|
||||||
|
if not cant_post:
|
||||||
|
content = (flask.request.form.get("text") or "").strip()
|
||||||
|
|
||||||
|
if content:
|
||||||
|
resp = requests.post(POST_URL, json={
|
||||||
|
"text": content,
|
||||||
|
"cw": CONTENT_WARNING,
|
||||||
|
"replyId": None,
|
||||||
|
"renoteId": None,
|
||||||
|
"mediaIds": None,
|
||||||
|
"visibility": "home",
|
||||||
|
"idempotencyKey": None
|
||||||
|
}, headers={
|
||||||
|
"Authorization": f"Bearer {token}"
|
||||||
|
})
|
||||||
|
|
||||||
|
if resp.status_code == 200:
|
||||||
|
data[ip] = int(time.time() + TIMEOUT)
|
||||||
|
save()
|
||||||
|
message = "Success!"
|
||||||
|
else:
|
||||||
|
message = f"Got non-200 status code ({resp})"
|
||||||
|
else:
|
||||||
|
message = "Enter some text!"
|
||||||
|
else:
|
||||||
|
message = "You can't post yet!"
|
||||||
|
|
||||||
|
return open(BASE_DIR / "public/index.html", "rb").read() \
|
||||||
|
.replace(b"{{ IP }}", str.encode(ip)) \
|
||||||
|
.replace(b"{{ EXPIRE }}", str.encode(str(data[ip] if cant_post else 0))) \
|
||||||
|
.replace(b"{{ ERROR }}", str.encode(message))
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.run(**RUN_CONF)
|
55
public/index.html
Normal file
55
public/index.html
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>EveryoneBot</title>
|
||||||
|
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
|
<meta name="pronouns" content="she/her">
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta name="twitter:card" content="summary_large_image">
|
||||||
|
<meta name="author" content="EveryoneBot">
|
||||||
|
<meta name="description" content="The fedi bot anyone can post to">
|
||||||
|
<meta property="og:title" content="EveryoneBot">
|
||||||
|
<meta property="og:description" content="The fedi bot anyone can post to">
|
||||||
|
<meta name="twitter:title" content="EveryoneBot">
|
||||||
|
<meta name="twitter:description" content="The fedi bot anyone can post to">
|
||||||
|
|
||||||
|
<style>
|
||||||
|
body { font-family: sans-serif; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<h1>EveryoneBot</h1>
|
||||||
|
<h3>The fedi bot anyone can post to</h3>
|
||||||
|
<a href="https://git.trinkey.com/trinkey/everyonebot" target="_blank">Source Code</a> - Fedi: <b>@everyonebot@is.trinkey.com</b>
|
||||||
|
<p>{{ ERROR }}</p>
|
||||||
|
<hr>
|
||||||
|
<p>Enter your post below. Anyone can post anything, once every 15 minutes per IP address.</p>
|
||||||
|
<form method="POST" action="/">
|
||||||
|
<div><textarea name="text" id="text" required placeholder="a stupid fedi post"></textarea></div>
|
||||||
|
<div><input type="submit" value="Post!"></div>
|
||||||
|
</form>
|
||||||
|
<small>Moderation enforced at trinkey's discretion. This service can go down temporarily or permanently at any time. All posts are viewable by anyone and cannot be deleted.</small>
|
||||||
|
<p>You can post <span id="until-post">in <i>Please enable JavaScript for this to work!</i></span></p>
|
||||||
|
<p><details>
|
||||||
|
<summary>Your IP address:</summary> {{ IP }}
|
||||||
|
</details></p>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
let expire = +"{{ EXPIRE }}" * 1000;
|
||||||
|
|
||||||
|
function updateTimestamp() {
|
||||||
|
let remaining = Math.floor((expire - Date.now()) / 1000);
|
||||||
|
|
||||||
|
document.getElementById("until-post").innerHTML = remaining <= 0 ? "<b>now!</b>" : (remaining < 60 ? `in <b>${remaining}s</b>` : `in <b>${Math.floor(remaining / 60)}m${remaining % 60}s</b>`);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateTimestamp();
|
||||||
|
|
||||||
|
setInterval(updateTimestamp, 500);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in a new issue