This commit is contained in:
Athena Funderburg
2026-05-25 07:05:17 +00:00
commit 4b463a3432
682 changed files with 47796 additions and 0 deletions
View File
+15
View File
@@ -0,0 +1,15 @@
from core import db, stats
from core.conn import Conn
import settings
def main() -> None:
create_dbs()
def create_dbs() -> None:
conn_db = Conn(settings.DB)
db.Base.metadata.create_all(conn_db.engine)
conn_stats = Conn(settings.STATS_DB)
stats.Base.metadata.create_all(conn_stats.engine)
if __name__ == '__main__':
main()
+30
View File
@@ -0,0 +1,30 @@
from core import db
from core.conn import Conn
import settings
# TODO: INS-ize this
def main(*ids: str) -> None:
if not ids:
print("Nothing to do.")
return
print("Deleting {} circles:".format(len(ids)))
for i in ids:
print('=>', i)
ans = input("Are you sure? (y/N) ")
if ans.lower() != 'y':
print("Operation cancelled.")
return
print("Deleting.")
conn = Conn(settings.DB)
with conn.session() as sess:
circles = sess.query(db.Circle).filter(db.Circle.chat_id.in_(ids))
circlememberships = sess.query(db.CircleMembership).filter(db.CircleMembership.chat_id.in_(ids))
print("delete circles", len(ids))
circlememberships.delete(synchronize_session = False)
circles.delete(synchronize_session = False)
sess.flush()
if __name__ == '__main__':
import funcli
funcli.main()
+147
View File
@@ -0,0 +1,147 @@
from typing import Dict, List
from uuid import uuid4
from core.models import ContactList
from core.db import Base, User, UserProfile, UserContact, Circle, CircleMembership, Sound
from core.conn import Conn
from util import misc, hash
import settings, random
usercontacts_by_id_by_uuid = {} # type: Dict[int, Dict[str, UserContact]]
def main() -> None:
U = [] # type: List[User]
for domain in ['example.com', 'yahoo.com', 'hotmail.com', 'live.com', 'aol.com', 'msn.com']:
d = domain[0]
for i in range(1, 5 + 1):
name = "T{}{}".format(i, d)
user = create_user('{}@{}'.format(name.lower(), domain), name.lower(), random.randint(100000,999999), 'Test', 'User', '123456', name, "{} msg".format(name), False, True)
user.id = len(U)
usercontacts_by_id_by_uuid[user.id] = {}
U.append(user)
for i in range(1, 5 + 1):
name = "D{}{}".format(i, d)
user = create_user('{}@{}'.format(name.lower(), domain), name.lower(), random.randint(100000,999999), 'Test', 'User', '123456', name, "{} msg".format(name), False, False)
user.id = len(U)
usercontacts_by_id_by_uuid[user.id] = {}
U.append(user)
for i in range(5):
name = "bot{}".format(i)
user = create_user('{}@crosstalk.net'.format(name.lower()), name.lower(), random.randint(100000,999999), 'Dummy', 'Bot', '123456', name, "{} msg".format(name), False, False)
user.id = len(U)
usercontacts_by_id_by_uuid[user.id] = {}
U.append(user)
for i in range(2):
name = "BannedUser{}".format(i)
user = create_user('{}@banned.net'.format(name.lower()), name.lower(), random.randint(100000,999999), 'Banned', 'Guy', '123456', name, "{} msg".format(name), True, False)
user.id = len(U)
usercontacts_by_id_by_uuid[user.id] = {}
U.append(user)
for i, u in enumerate(U):
contacts_by_group: Dict[str, ContactList[User]] = {}
x = randomish(u)
for j in range(x % 4):
contacts_by_group["" if j == 0 else "U{}G{}".format(i, j)] = []
group_names = list(contacts_by_group.keys())
for uc in U:
y = x ^ randomish(uc)
for k, group_name in enumerate(group_names):
z = y ^ k
if z % 2 < 1:
contacts_by_group[group_name].append(uc)
set_contacts(u, contacts_by_group)
add_profile(u)
tables = []
for u in U:
tables.append(u)
tables.extend(usercontacts_by_id_by_uuid[u.id].values())
conn = Conn(settings.DB)
Base.metadata.create_all(conn.engine)
with conn.session() as sess:
sess.query(User).delete()
sess.query(UserContact).delete()
sess.query(UserProfile).delete()
sess.query(Circle).delete()
sess.query(CircleMembership).delete()
sess.query(Sound).delete()
sess.add_all(tables)
def create_user(email: str, username: str, uin: int, first_name: str, last_name: str, pw: str, name: str, message: str, suspended: bool = False, is_tester: bool = False, is_mvp: bool = False) -> User:
user = User(
uuid = str(uuid4()), email = email, username = username, first_name = first_name, last_name = last_name, uin = uin, verified_to_login = True,
name = name, is_tester = is_tester, is_mvp = is_mvp, show_in_dir = True, friendly_name = name, message = message,
groups = [], settings = {}, suspended = suspended
)
set_passwords(user, pw, support_old_msn = True, support_yahoo = True, support_old_aim = True)
return user
def set_contacts(user: User, contacts_by_group: Dict[str, List[User]]) -> None:
#user.contacts = {}
user.groups = []
for i, (group_name, group_users) in enumerate(contacts_by_group.items()):
group_id = str(i + 1)
group_uuid = str(uuid4())
if group_name:
user.groups.append({ 'id': group_id, 'uuid': group_uuid, 'name': group_name, 'is_favorite': False })
for u in group_users:
contact = add_contact_twosided(user, u)
if group_name:
contact.groups.append({ 'id': group_id, 'uuid': group_uuid })
def randomish(u: User) -> int:
return int(u.uuid[:8], 16)
def add_contact_twosided(user: User, user_contact: User) -> UserContact:
contact = add_contact_onesided(user, user_contact, ContactList.AL | ContactList.FL)
add_contact_onesided(user_contact, user, ContactList.RL)
return contact
def add_contact_onesided(user: User, user_contact: User, lst: ContactList) -> UserContact:
if user_contact.id not in usercontacts_by_id_by_uuid[user.id]:
usercontacts_by_id_by_uuid[user.id][user_contact.uuid] = create_usercontact(user, user_contact)
contact = usercontacts_by_id_by_uuid[user.id][user_contact.uuid]
contact.lists |= lst
return contact
def create_usercontact(user: User, user_contact: User) -> UserContact:
return UserContact(
user_id = user.id, user_uuid = user.uuid, contact_id = user_contact.id, uuid = user_contact.uuid,
index_id = str(len(usercontacts_by_id_by_uuid[user.id]) + 2),
name = user_contact.friendly_name,
lists = ContactList.Empty, groups = [], is_messenger_user = True,
)
def add_profile(user: User) -> UserProfile:
return UserProfile(user_id = user.id, bio = 'I am a dummy!', pronouns = 'it/its', website = 'http://example.com', socials = {}, streetaddr = '', city = '', state = '', zip = '', country = '', interests = {})
def set_passwords(user: User, pw: str, *, support_old_msn: bool = False, support_yahoo: bool = False,
support_old_aim: bool = False) -> None:
user.password = hash.hasher.encode(pw)
if support_old_msn:
pw_md5 = hash.hasher_md5.encode(pw)
user.set_front_data('msn', 'pw_md5', pw_md5)
if support_yahoo:
pw_md5_unsalted = hash.hasher_md5.encode(pw, salt='')
user.set_front_data('ymsg', 'pw_md5_unsalted', pw_md5_unsalted)
pw_md5crypt = hash.hasher_md5crypt.encode(pw, salt='$1$_2S43d5f')
user.set_front_data('ymsg', 'pw_md5crypt', pw_md5crypt)
if support_old_aim:
pw_md5 = hash.hasher_md5.encode(pw, identifier='AOL Instant Messenger (SM)')
user.set_front_data('aim', 'pw_md5', pw_md5)
if __name__ == '__main__':
main()
+19
View File
@@ -0,0 +1,19 @@
from core import db
from core.conn import Conn
import settings
# TODO: INS-ize this
def main(*, verbose: bool = False) -> None:
total = 0
conn = Conn(settings.DB)
with conn.session() as sess:
for circle in sess.query(db.Circle).all():
total += 1
if verbose:
print(circle.chat_id, circle.name)
print("Total:", total)
if __name__ == '__main__':
import funcli
funcli.main()
+27
View File
@@ -0,0 +1,27 @@
from datetime import datetime, timedelta
from core import db
from core.conn import Conn
import settings
# TODO: INS-ize this
def main(*, since: int = 60, verbose: bool = False) -> None:
online_since = datetime.utcnow() - timedelta(minutes = since)
total = 0
total_online = 0
conn = Conn(settings.DB)
with conn.session() as sess:
for u in sess.query(db.User).all():
total += 1
if verbose:
print(u.email)
if online_since is not None and u.date_login is not None:
total_online += (1 if u.date_login >= online_since else 0)
print("Total:", total)
if online_since is not None:
print("Online:", total_online)
if __name__ == '__main__':
import funcli
funcli.main()
+15
View File
@@ -0,0 +1,15 @@
import asyncio, settings
from insclient.cmds import maintenance
async def main(minutes: str):
try:
resp = await maintenance(minutes, b'AzuL-SERV', settings.INS_LINK_PASSWORD)
print("Operation successful!")
except Exception as e:
print("Operation failed:", e)
if __name__ == '__main__':
import sys
_, minutes = sys.argv
asyncio.run(main(minutes))
+105
View File
@@ -0,0 +1,105 @@
from core import db
from core.conn import Conn
import settings
# TODO: INS-ize this
def main(id: str, action: str, *args: str) -> None:
memberships_to_add = []
conn = Conn(settings.DB)
with conn.session() as sess:
circle = sess.query(db.Circle).filter(db.Circle.chat_id == id).one_or_none()
if circle is None:
print('Circle {} does not exist'.format(id))
return
if action.lower() == 'role':
if len(args) < 2:
print('Insufficient arguments for action role')
return
email = args[0]
role = args[1]
user = sess.query(db.User).filter(db.User.email == email).one_or_none()
if user is None:
print('role: User {} does not exist'.format(email))
return
m = sess.query(db.CircleMembership).filter(db.CircleMembership.chat_id == circle.chat_id, db.CircleMembership.member_id == user.id).one_or_none()
if m is None:
print('role: User {} not a member of this circle'.format(user.email))
return
if m.state != 3:
print('role: User {}\'s role in this circle is not set to accepted'.format(user.email))
return
elif m.role == 1:
print('role: User {} is an owner of this circle and cannot be set to any other role. Use "owner" to transfer their ownership to someone else'.format(user.email))
return
if role not in ('2','3'):
if role == '1':
print('role: Cannot set user {}\'s circle role to owner with this command. Use "owner" to perform this action'.format(user.email))
else:
print('role: Role specified is not valid. Accepted values are 2 (co-owner) and 3 (member)')
return
m.role = int(role)
memberships_to_add.append(m)
elif action.lower() == 'owner':
if len(args) < 1:
print('Insufficient arguments for action owner')
return
email = args[0]
user = sess.query(db.User).filter(db.User.email == email).one_or_none()
if user is None:
print('owner: User {} does not exist'.format(email))
return
m = sess.query(db.CircleMembership).filter(db.CircleMembership.chat_id == circle.chat_id, db.CircleMembership.member_id == user.id).one_or_none()
if m is None:
print('role: User {} not a member in this circle'.format(user.email))
return
if m.state != 3:
print('owner: User {}\'s role in circle is not set to accepted'.format(user.email))
return
if m.role == 1:
print('owner: User {} is already owner'.format(user.email))
return
m_owner = sess.query(db.CircleMembership).filter(db.CircleMembership.chat_id == circle.chat_id, db.CircleMembership.role == 1).one_or_none()
if m_owner is not None:
m_owner.role = 3
m.role = 1
memberships_to_add.append(m)
if m_owner is not None:
memberships_to_add.append(m_owner)
elif action.lower() == 'remove':
if len(args) < 1:
print('Insufficient arguments for action remove')
return
email = args[0]
user = sess.query(db.User).filter(db.User.email == email).one_or_none()
if user is None:
print('remove: User {} does not exist'.format(email))
return
m = sess.query(db.CircleMembership).filter(db.CircleMembership.chat_id == circle.chat_id, db.CircleMembership.member_id == user.id).one_or_none()
if m is None or m.state == 0:
print('remove: User {} not a member in this circle'.format(user.email))
return
if m.role == 1:
print('remove: User {} is an owner and cannot be removed from circle'.format(user.email))
return
m.role = 3
m.state = 0
memberships_to_add.append(m)
else:
print('Invalid action')
if memberships_to_add:
sess.add_all(memberships_to_add)
sess.flush()
print('Action successfully performed')
if __name__ == '__main__':
import funcli
funcli.main()
+125
View File
@@ -0,0 +1,125 @@
import asyncio, ast, json, settings
from insclient.cmds import list_sessions, session_detail, session_delete
async def main(action: str, id: str | None):
try:
def _print_sessions(resp):
if not resp or resp[0] != 'ALLTHESESSIONS':
print("No sessions returned or unexpected response format")
return
tokens = resp[2:]
buf = []
sessions = []
i = 0
while i < len(tokens):
tok = tokens[i]
if tok.startswith('"'):
buf = [tok]
while not buf[-1].endswith('"') and i + 1 < len(tokens):
i += 1
buf.append(tokens[i])
raw = " ".join(buf).strip('"')
try:
sid, uuid, email, raw_meta = raw.split('|', 3)
meta = ast.literal_eval(raw_meta)
sessions.append((sid, uuid, email, meta))
except Exception:
pass
else:
buf = [tok]
if tok.endswith('}'):
raw = " ".join(buf)
try:
sid, uuid, email, raw_meta = raw.split('|', 3)
meta = ast.literal_eval(raw_meta)
sessions.append((sid, uuid, email, meta))
except Exception:
pass
i += 1
for sid, uuid, email, meta in sessions:
print(
f" Session ID:\t {sid}\n"
f" UUID:\t\t {uuid}\n"
f" Email:\t {email}\n"
f" Client:\t {meta.get('program')}\n"
f" Version:\t {meta.get('version')}\n"
f" Method:\t {meta.get('via')}\n"
)
if action == 'list_all':
resp = await list_sessions(None, b'AzuL-SERV', settings.INS_LINK_PASSWORD)
_print_sessions(resp)
return
elif action == 'list_by_user':
resp = await list_sessions(id, b'AzuL-SERV', settings.INS_LINK_PASSWORD)
_print_sessions(resp)
return
elif action == 'details':
resp = await session_detail(id, b'AzuL-SERV', settings.INS_LINK_PASSWORD)
if not resp or resp[0] != 'SESSION':
print("No such session or unexpected response")
return
if len(resp) >= 3 and resp[2] == 'KILLED':
print(f"Session {id} was killed")
return
_, ts, sess_id, username, uuid, email, uin = resp[:7]
chat_enabled = resp[-1]
meta_tokens = resp[7:-1]
raw_client = ''
if not meta_tokens:
raw_client = ''
elif len(meta_tokens) == 1:
token = meta_tokens[0]
if token.startswith('"') and token.endswith('"'):
raw_client = token.strip('"')
else:
raw_client = token
else:
combined = " ".join(meta_tokens)
if combined.startswith('"') and combined.endswith('"'):
raw_client = combined.strip('"')
else:
raw_client = combined
try:
client_meta = ast.literal_eval(raw_client) if raw_client else {}
except Exception:
client_meta = {}
print(f" Details for session {sess_id}:")
print(f" Username:\t {username}")
print(f" UUID:\t\t {uuid}")
print(f" Email:\t {email}")
print(f" UIN:\t\t {uin}")
print(f" Chat enabled:\t {chat_enabled}")
print(" Client info:")
for k, v in client_meta.items():
print(f"\t{k}: {v}")
return
elif action in ('close', 'kill'):
await session_delete(id, b'AzuL-SERV', settings.INS_LINK_PASSWORD)
print("Operation successful")
return
else:
print('Unknown action. Valid actions: list_all, list_by_user, details, close, kill')
return
except Exception as e:
print("Operation failed:", e)
if __name__ == '__main__':
import sys
_, action, *rest = sys.argv
id_arg = rest[0] if rest else None
asyncio.run(main(action, id_arg))
+101
View File
@@ -0,0 +1,101 @@
# TODO: holy shit clean this up this is awful
import argparse, asyncio, getpass, settings
from insclient.cmds import usercreate, userupdate, userdelete
from core.conn import Conn
from core import db
def _parse_args():
p = argparse.ArgumentParser(prog='manageuser.py')
sub = p.add_subparsers(dest='cmd', required=True)
sc_create = sub.add_parser('create')
sc_create.add_argument('email')
sc_create.add_argument('username')
sc_create.add_argument('first_name')
sc_create.add_argument('last_name')
sc_create.add_argument('uin', type=int)
sc_create.add_argument('--password', '-p', help='user password (if omitted, prompted)')
sc_create.add_argument('--oldmsn', action='store_true')
sc_create.add_argument('--yahoo', action='store_true')
sc_create.add_argument('--oldaim', action='store_true')
sc_create.add_argument('--msim', action='store_true')
sc_mod = sub.add_parser('modify')
sc_mod.add_argument('email')
sc_mod.add_argument('field')
sc_mod.add_argument('value')
sc_mod.add_argument('--oldmsn', action='store_true', help='also (re)generate legacy MSN MD5 hash when changing password')
sc_mod.add_argument('--yahoo', action='store_true', help='also (re)generate legacy Yahoo hashes when changing password')
sc_mod.add_argument('--oldaim', action='store_true', help='also (re)generate legacy AIM MD5 hash when changing password')
sc_mod.add_argument('--msim', action='store_true', help='also (re)generate legacy MSIM SHA-1 hash when changing password')
sc_del = sub.add_parser('delete')
sc_del.add_argument('email', help='email of the user to delete')
return p.parse_args()
async def _do_create(email: str, username: str, first_name: str, last_name: str, uin: int, user_password: str, oldmsn: bool, yahoo: bool, oldaim: bool, msim: bool) -> None:
try:
await usercreate(
email, username, first_name, last_name, uin, user_password,
oldmsn, yahoo, oldaim, msim, b'AzuL-SERV', settings.INS_LINK_PASSWORD
)
print("Operation successful!")
except Exception as e:
print("Operation failed:", e)
async def _do_modify(email: str, field: str, value: str, oldmsn: bool, yahoo: bool, oldaim: bool, msim: bool) -> None:
conn = Conn(settings.DB)
with conn.session() as sess:
user = sess.query(db.User).filter(db.User.email == email).first()
if not user:
print('User does not exist.')
return
uuid = user.uuid
if field == 'password' and value == '-':
value = getpass.getpass('Password: ')
try:
if field == 'password':
await userupdate(uuid, field, value, b'AzuL-SERV', settings.INS_LINK_PASSWORD, support_old_msn=oldmsn, support_yahoo=yahoo, support_aim=oldaim, support_msim=msim)
else:
await userupdate(uuid, field, value, b'AzuL-SERV', settings.INS_LINK_PASSWORD)
print("Operation successful!")
except Exception as e:
print("Operation failed:", e)
async def _do_delete(email: str) -> None:
conn = Conn(settings.DB)
with conn.session() as sess:
user = sess.query(db.User).filter(db.User.email == email).first()
if not user:
print('User does not exist.')
return
uuid = user.uuid
try:
await userdelete(uuid, b'AzuL-SERV', settings.INS_LINK_PASSWORD)
print("Operation successful!")
except Exception as e:
print("Operation failed:", e)
def main():
args = _parse_args()
if args.cmd == 'create':
pw = args.password
if not pw:
pw = getpass.getpass('Password: ')
asyncio.run(_do_create(
args.email, args.username, args.first_name, args.last_name, args.uin,
pw, args.oldmsn, args.yahoo, args.oldaim, args.msim
))
elif args.cmd == 'modify':
asyncio.run(_do_modify(
args.email, args.field, args.value, args.oldmsn, args.yahoo, args.oldaim, args.msim
))
elif args.cmd == 'delete':
asyncio.run(_do_delete(args.email))
if __name__ == '__main__':
main()
+24
View File
@@ -0,0 +1,24 @@
import asyncio, settings
from insclient.cmds import alert
async def main(emails: str):
message = input('Enter alert message: ').strip()
if not message:
print('Message is required.')
return
url = input('Enter a URL (or leave blank): ').strip() or ''
icon = input('Enter an icon URL (or leave blank): ').strip() or ''
targets = emails if emails.strip() and emails.strip() != '*' else 'all'
try:
await alert(message, b'AzuL-SERV', settings.INS_LINK_PASSWORD, url, icon, targets)
print("Operation successful!")
except Exception as e:
print("Operation failed:", e)
if __name__ == '__main__':
import sys
_, emails = sys.argv
asyncio.run(main(emails))