120 lines
3.3 KiB
Python
120 lines
3.3 KiB
Python
#!/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")
|