initial commit
This commit is contained in:
commit
7be12197f0
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
env/
|
1
.tool-versions
Normal file
1
.tool-versions
Normal file
@ -0,0 +1 @@
|
|||||||
|
python 3.11.5
|
119
misskey_scripting.py
Normal file
119
misskey_scripting.py
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
import json
|
||||||
|
import requests
|
||||||
|
|
||||||
|
# Change these configs
|
||||||
|
TOKEN = "misskey-api-token"
|
||||||
|
INSTANCE = "https://your-instance.com"
|
||||||
|
|
||||||
|
|
||||||
|
def post(path, body):
|
||||||
|
"""Sends a post request to the Misskey instance."""
|
||||||
|
return requests.post(
|
||||||
|
f"{INSTANCE}/api{path}",
|
||||||
|
headers={
|
||||||
|
"Authorization": f"Bearer {TOKEN}",
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
data=json.dumps(body),
|
||||||
|
timeout=10,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def fetch_notes(user_id, until_id=None):
|
||||||
|
"""Fetches all notes from a user."""
|
||||||
|
if until_id:
|
||||||
|
notes = post(
|
||||||
|
"/users/notes",
|
||||||
|
{
|
||||||
|
"userId": user_id,
|
||||||
|
"withFiles": False,
|
||||||
|
"withReplies": True,
|
||||||
|
"withChannelNotes": True,
|
||||||
|
"limit": 100,
|
||||||
|
"untilId": until_id
|
||||||
|
},
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
notes = post(
|
||||||
|
"/users/notes",
|
||||||
|
{
|
||||||
|
"userId": user_id,
|
||||||
|
"withFiles": False,
|
||||||
|
"withReplies": True,
|
||||||
|
"withChannelNotes": True,
|
||||||
|
"limit": 100
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return notes.json()
|
||||||
|
|
||||||
|
|
||||||
|
def fetch_users(target_instance, until_id=None):
|
||||||
|
"""Gets all users for a given Misskey instance."""
|
||||||
|
if until_id:
|
||||||
|
users = post(
|
||||||
|
"/federation/users",
|
||||||
|
{"limit": 100, "host": target_instance, "untilId": until_id},
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
users = post("/federation/users", {"limit": 100, "host": target_instance})
|
||||||
|
return users.json()
|
||||||
|
|
||||||
|
|
||||||
|
def destroy(target_instance):
|
||||||
|
"""Destroys all accounts on the given Misskey instance."""
|
||||||
|
users = fetch_users(target_instance)
|
||||||
|
|
||||||
|
while users:
|
||||||
|
for user in users:
|
||||||
|
destroy_notes(user['id'])
|
||||||
|
r1 = post("/admin/delete-account", {"userId": user['id']})
|
||||||
|
r2 = post("/admin/delete-all-files-of-a-user", {"userId": user['id']})
|
||||||
|
if r1.status_code == 204 and r2.status_code == 204:
|
||||||
|
print(f"Deleted @{user['username']}@{user['host']}")
|
||||||
|
else:
|
||||||
|
print(f"Failed to delete @{user['username']}@{user['host']}!!!!!")
|
||||||
|
|
||||||
|
users = fetch_users(target_instance, users[-1]['id'])
|
||||||
|
|
||||||
|
|
||||||
|
def destroy_notes(user_id):
|
||||||
|
"""Destroys all accounts on the given Misskey instance."""
|
||||||
|
notes = fetch_notes(user_id)
|
||||||
|
|
||||||
|
while notes:
|
||||||
|
for note in notes:
|
||||||
|
r = post("/notes/delete", {"noteId": note['id']})
|
||||||
|
if r.status_code == 204:
|
||||||
|
print(f"Deleted {print_name(note)}: {print_note(note)}")
|
||||||
|
else:
|
||||||
|
print(f"Could not delete {print_name(note)}: {print_note(note)}")
|
||||||
|
|
||||||
|
notes = fetch_notes(user_id, notes[-1]['id'])
|
||||||
|
|
||||||
|
def print_note(note):
|
||||||
|
if note.get('renote') and note['renote'].get('reactions'):
|
||||||
|
return "Reaction"
|
||||||
|
elif note.get('renote'):
|
||||||
|
return f"Renote {print_note(note['renote'])}"
|
||||||
|
elif note.get('files') or note.get('fileIds'):
|
||||||
|
return "File"
|
||||||
|
elif note.get('reactions'):
|
||||||
|
return "Reaction"
|
||||||
|
else:
|
||||||
|
if note['text'] is None:
|
||||||
|
print(note)
|
||||||
|
return truncate_text(note['text'])
|
||||||
|
|
||||||
|
def print_name(note):
|
||||||
|
return f"@{note['user']['username']}@{note['user']['host']}"
|
||||||
|
|
||||||
|
def truncate_text(text):
|
||||||
|
if text is None:
|
||||||
|
return "None"
|
||||||
|
else:
|
||||||
|
return text[:75].replace("\n", " ")
|
||||||
|
|
||||||
|
|
||||||
|
destroy("instance-to-destroy.com")
|
1
requirements.txt
Normal file
1
requirements.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
Requests
|
Loading…
x
Reference in New Issue
Block a user