
import misskey
import websockets
import json
import asyncio
import requests
from io import BytesIO

MISSKEY_INSTANCE = "misskey.treehousefullofstars.com"
MISSKEY_TOKEN = "JSvVuz1eS2BGq6MagdQC9m109gOllwcO"

msk = misskey.Misskey(address=MISSKEY_INSTANCE, i=MISSKEY_TOKEN)
MY_ID = msk.i()['id']
WS_URL=f"wss://{MISSKEY_INSTANCE}/streaming"

channels = ['localTimeline', 'globalTimeline' 'hybridTimeline', 'main']

discord_webhook = "https://discord.com/api/webhooks/1367836441098326107/fqDmUGd-u2sWXF9ymuAgArHPnmTCU70_pFaqagqFww9cd07ujjQ4S1s8KvVuc1O1xIHX"


async def handleMentions(message: str, mentions):
    for mention in mentions:
        user, discord = await getUserProfile(mention)
        if user and discord:
            misskey_mention_tag = f"@{user['username']}"
            discord_mention_tag = f"<@{discord['user']['id']}>"
            message = message.replace(misskey_mention_tag, discord_mention_tag)

    return message

async def getUserProfile(userID):
    api_endpoint = f"https://{MISSKEY_INSTANCE}/api/users/show"
    bot_token = "MTMyNzcxNDM3MTEyMzgxMDMwNA.GwLjEd.quGP0FA5gHRe1xLyuYq-ANuJ5cRuRQ6dhJiojI"
    guild_id = "954201387770736751"
    params = {
        "i": MISSKEY_TOKEN,
        "userId": userID
    }

    response = requests.post(api_endpoint, json=params)
    user_profile = None
    discord_user = None
    if response.status_code == 200:
        user_profile = response.json()
    else:
        return user_profile, discord_user

    discord_id = None
    if user_profile != {}:
        for field in user_profile.get('fields', []):
            if field['name'] == "Discord":
                discord_id = field['value']
    
    discord_user = {}
    if discord_id:
        headers = {'Authorization': f'Bot {bot_token}'}
        discord_guild_endpoint = f"https://discord.com/api/v10/guilds/{guild_id}/members/{discord_id}"
        response = requests.get(discord_guild_endpoint, headers=headers)
        if response.status_code == 200:
            discord_user = response.json()
        else:
            return user_profile, discord_user
    
    with open('user.json', 'w+') as file:
        file.write(json.dumps({'user': user_profile, 'discord': discord_user}, indent=5))

    return user_profile, discord_user

async def handle_message(websocket, message):
    data = json.loads(message)

    with open('test.json', 'w+') as file:
        file.write(json.dumps(data, indent=5))

    headers={
    'Content-type':'application/json', 
    'Accept':'application/json'
    }   

    response = requests.post("http://127.0.0.1:5000/misskey-connect", json=data, headers=headers)
    print(response)
    guild_id = "954201387770736751"
    user_id = data['body']['body']['userId']
    user, discord = await getUserProfile(userID=user_id)

    with open('user.json', 'w+') as file:
        file.write(json.dumps({'user': user, 'discord': discord}, indent=5))

    if data['body']['type'] == "note":
        print("note")
        if data['body']['body']['renoteId']:
            files = data['body']['body']['renote'].get('files', None)
        else:
            files = data['body']['body'].get('files', None)

        passed_files = {}
        if files != []:
            for i, file in enumerate(files):
                response = requests.get(file['url'])
                file_data = BytesIO(response.content)
                filename = file['name']
                passed_files[f"file{i}"] = (filename, file_data, file['type'])

        if data['body']['body']['renoteId']:
            renote_user = data['body']['body']['renote']['user'].get('name', 'unknown')
            renote_username = data['body']['body']['renote']['user'].get('username', 'unknown')
            renote_user_host = data['body']['body']['renote']['user'].get('hose', 'unknown')
            note_content = f"*Renoted {renote_user} (@{renote_username}@{renote_user_host})*\n{data['body']['body']['renote']['text']}"
        else:
            note_content = data['body']['body'].get('text', 'No text in note')

        username = data['body']['body']['user'].get('name', 'Misskey Bot')
        avatar_url = data['body']['body']['user'].get('avatarUrl', None)

        if discord:
            username = discord['nick']
            if discord['avatar']:
                avatar_url = f"https://cdn.discordapp.com/guilds/{guild_id}/users/{discord['user']['id']}/avatars/{discord['avatar']}.png"
            else:
                avatar_url = f"https://cdn.discordapp.com/avatars/{discord['user']['id']}/{discord['user']['avatar']}.png"


        note_content = await handleMentions(note_content, data['body']['body'].get('mentions', []))

        print(note_content, username, avatar_url)
        if passed_files != {}:
            await send_to_discord(note_content, username=username, avatar_url=avatar_url, files=passed_files)
        else:
            await send_to_discord(note_content, username=username, avatar_url=avatar_url)



async def send_to_discord(message, username="Misskey Bot", avatar_url=None, embeds=None, files=None):
    content = f"{message}"
    
    payload = {
        "content": content,
        "username": username,
        "avatar_url": avatar_url
    }

    if embeds:
        payload['embeds'] = embeds

    print(payload)

    if files:
        response = requests.post(discord_webhook, data=payload, files=files)
    else:
        response = requests.post(discord_webhook, json=payload)
    if response.status_code != 204:
        print(f"Failed to send message to Discord: {response.status_code} {response.text}")

async def connect_and_listen():
    while True:
        try:
            print("Connecting to WebSocket...")
            async with websockets.connect(WS_URL) as websocket:
                print("Connected to WebSocket")
                # Subscribe to the channels
                for channel in channels:
                    subscription_request = {
                        "type": "connect",
                        "body": {
                            "channel": channel,
                            "id": MY_ID,
                            "access_token": MISSKEY_TOKEN
                        }
                    }
                    await websocket.send(json.dumps(subscription_request))
                    print(f"Sent subscription request for {channel} channel with ID: {MY_ID}")
                    response = await websocket.recv()
                    print(f"Received response for {channel} channel: {response}")
                    await handle_message(websocket, response)
                # Listen for messages
                #while True:
                 #   async for message in websocket:
                  #      await handle_message(websocket, message)

        except websockets.exceptions.ConnectionClosedError as e:
            print(f"Connection closed unexpectedly: {e}")
            await asyncio.sleep(5)  # Wait for 5 seconds before retrying
        except Exception as e:
            print(f"An error occurred: {e}")
            await asyncio.sleep(5)  # Wait for 5 seconds before retrying

# Run the client
if __name__ == "__main__":
    asyncio.run(connect_and_listen())