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