initial commit of direct message monitoring

This commit is contained in:
jenz 2026-02-26 11:18:16 +01:00
parent fa3405d51b
commit 5e494cf979
6 changed files with 161 additions and 0 deletions

View File

@ -0,0 +1,4 @@
pymongo
requests
simple nsa simulator where we monitor URLS and files send in direct messages to ensure that we can have DM's enabled.

View File

@ -0,0 +1,135 @@
#!/home/nonroot/stoat_view_messages/venv/bin/python3
import pymongo
import requests
import re
import time
import os
import shutil
from settings import stoat_token, stoat_url, MONGO_URI, admin_channel_id
def update_last_msg_id(msg_id):
with open("last_msg_id.txt", 'w') as f:
f.write(msg_id)
def get_last_msg_id_read():
with open("last_msg_id.txt", 'r') as f:
return f.readline()
def send_post_message_to_stoat(report):
headers = {
"x-bot-token": f"{stoat_token}",
"Content-Type": "application/json"
}
data = {
"content": report
}
response = requests.post(stoat_url, headers=headers, json=data)
def get_channel_recipients(db, channel_id):
channel = db.channels.find_one({ "_id": channel_id })
if channel:
return channel.get("recipients", [])
return []
def get_dm_channel_ids(db):
return [c["_id"] for c in db.channels.find({ "channel_type": "DirectMessage" })]
def process_messages(db):
last_msg_id = get_last_msg_id_read()
dm_channels = get_dm_channel_ids(db)
query = {
"channel": { "$in": dm_channels },
"$or": [
{ "content": { "$regex": r"(https?://|www\.)\S+", "$options": "i" } },
{ "attachments": { "$exists": True, "$ne": [] } }
]
}
if last_msg_id:
query["_id"] = { "$gt": last_msg_id }
messages = list(db.messages.find(query).sort("_id", 1))
for msg in messages:
recipients = get_channel_recipients(db, msg["channel"])
content = msg.get("content", "")
attachments = msg.get("attachments", [])
report = f"**DM Flag** | From: <@{msg['author']}> → To: {' '.join([f'<@{r}>' for r in recipients if r != msg['author']])}\n"
if content:
report += f"Content: {content}\n"
extra = ""
if attachments:
#EDIT ME
attachment_links = "\n".join([f"https://yourdomain.com/autumn/attachments/{att['_id']}/{att['filename']}" for att in attachments])
report += attachment_links
extra = "and files"
report += f""" \nto delete the message {extra} from the system type: "Delete {msg['_id']}". After being processed will your delete command be deleted as well. Remember to manually ban the user if they post problematic content and to also delete the bot report if the content is problematic."""
send_post_message_to_stoat(report)
last_msg_id = msg["_id"]
return last_msg_id
def check_if_message_to_delete(db):
delete_requests = db.messages.find({
"channel": admin_channel_id,
"content": { "$regex": "^Delete ", "$options": "" }
})
for cmd_msg in delete_requests:
target_msg_id = cmd_msg["content"].split(" ")[1].strip()
print(f"Processing delete command for message: {target_msg_id}")
target_msg = db.messages.find_one({ "_id": target_msg_id })
if not target_msg:
print(f"Target message {target_msg_id} not found")
# delete the Delete command message from admin channel
db.messages.delete_one({ "_id": cmd_msg["_id"] })
print(f"Cleaned up command message {cmd_msg['_id']}")
continue
attachments = target_msg.get("attachments", [])
hashes = [att["hash"] for att in attachments]
if hashes:
# find all attachment IDs with these hashes
matching_attachments = db.attachments.find({ "hash": { "$in": hashes } })
affected_msg_ids = [att["used_for"]["id"] for att in matching_attachments if att.get("used_for", {}).get("type") == "Message"]
# delete all messages that reference these files
result = db.messages.delete_many({ "_id": { "$in": affected_msg_ids } })
print(f"Deleted {result.deleted_count} message(s) referencing these attachments")
# delete attachment records
db.attachments.delete_many({ "hash": { "$in": hashes } })
# delete physical files
for hash_val in hashes:
#EDIT ME
hash_dir = f"/home/user/server/data/minio/revolt-uploads/{hash_val}"
if os.path.exists(hash_dir):
shutil.rmtree(hash_dir)
print(f"Deleted from disk: {hash_val}")
else:
# no attachments, just delete the single message
db.messages.delete_one({ "_id": target_msg_id })
print(f"Deleted message {target_msg_id}")
# delete the Delete command message from admin channel
db.messages.delete_one({ "_id": cmd_msg["_id"] })
print(f"Cleaned up command message {cmd_msg['_id']}")
def main():
client = pymongo.MongoClient(MONGO_URI)
db = client["revolt"]
while True:
last_msg_id = process_messages(db)
update_last_msg_id(last_msg_id)
check_if_message_to_delete(db)
time.sleep(60)
if __name__ == '__main__':
main()

View File

@ -0,0 +1,4 @@
stoat_token = ""
stoat_url = ""
MONGO_URI = ""
admin_channel_id = ""

View File

@ -0,0 +1,10 @@
[Unit]
Description=monitors Direct Messages for urls and attachments to make sure people dont post problematic shit
[Service]
Type=simple
User=root
Environment=PYTHONUNBUFFERED=1
Environment=PATH=/home/nonroot/stoat_view_messages/venv/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/snap/bin
WorkingDirectory=/home/nonroot/stoat_view_messages
ExecStart=/home/nonroot/stoat_view_messages/main.py

View File

@ -0,0 +1,8 @@
[Unit]
Description=restart message viewing service once every day at midnight
[Timer]
OnCalendar=*-*-1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 00:00:00
[Install]
WantedBy=multi-user.target