#Atari8BitBot by @KaySavetz. 2020-2021.

import tweepy
import logging
from botConfig import create_api
import time
import os
from shutil import copyfile
import Emulator
from datetime import datetime
from unidecode import unidecode
import re
import GistManager

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger()

def determine_config(full_text, gistUrl):
    config={}
    config['error']=None
    #remove all @ mentions, leaving just the BASIC code
    basiccode = re.sub('^(@.+?\s)+','',full_text, re.ASCII)
    basiccode = unidecode(basiccode)
    #unescape >, <, and &
    basiccode = basiccode.replace("&lt;", "<")
    basiccode = basiccode.replace("&gt;", ">")
    basiccode = basiccode.replace("&amp;", "&")

    #if url, get code from it
    if gistUrl:
        text = GistManager.getGist(gistUrl)
        if text.startswith("Error: "): 
            logger.info(f"unable to retrieve {gistUrl}, {text}")
            config['error']=text
            return config
        else:
            basiccode = unidecode(text)
    #look for Debug command
    exp = "{\w*?D\w*(?:}|\s)" # {B\d\d  D= debug
    result = re.search(exp,basiccode)
    if result:  
        config['debug'] = True
    else:
        config['debug'] = False

    #look for start time command
    exp = "{\w*?B(\d\d?)\w*(?:}|\s)" # {B\d\d  B= Begin
    result = re.search(exp,basiccode)
    if result:  
        starttime = int(result.group(1))
        logger.info(f" Requests start at {starttime} seconds")
    else:
        starttime = 2

    #look for length of time to record command
    exp = "{\w*?S(\d\d?\d?)\w*(?:}|\s)" # {S\d\d  S= Seconds to record
    result=re.search(exp,basiccode)
    if result:
        recordtime = int(result.group(1))
        logger.info(f" Requests record for {recordtime} seconds")
    else:
        recordtime = 20
    if recordtime <1:
        recordtime=1
    if recordtime >140:
        recordtime=140
        
    language = 0 # default to BASIC

    exp = "{\w*?A\w*(?:}|\s)" #{A
    if re.search(exp,basiccode): 
        language=2 #it's Assembly
        logger.info("it's ASM")
        basiccode = "ORG $8000\n" + basiccode

    #remove any { command
    #exp = "{\w*(?:}|\s)" #{anything till space or }
    exp = "{\w*(?:}\s*)" #{anything till } plus trailing whitespace
    basiccode = re.sub(exp,'',basiccode)

    #whitespace
    basiccode = basiccode.strip()
    logger.debug(f"Code: [{basiccode}]")
    
    #halt if string is empty
    if not basiccode:
        logger.info("!!! basiccode string is empty, SKIPPING")
        config['error']="Error: Empty code"
        return config
    
    config['starttime']  =starttime
    config['recordtime'] =recordtime
    config['language']   =language
    config['basiccode']  =basiccode
    return config

def check_mentions(api, since_id):
    logger.info("Retrieving mentions")
    new_since_id = since_id
    for tweet in tweepy.Cursor(api.mentions_timeline, since_id=since_id, 
      tweet_mode='extended', include_entities=True).items():
        new_since_id = max(tweet.id, new_since_id)
        url=None
        
        logger.info(f"Tweet from {tweet.user.name}")
        #if there is an url in text, pass the firs
        if tweet.entities['urls']:
            url=tweet.entities['urls'][0]['expanded_url']
        if not GistManager.validate(url):
            url=None
        config=determine_config(tweet.full_text, url)
        
        if config['error']:
            logger.info(config['error'])
            continue
        
        language    = config['language']
        starttime   = config['starttime']
        basiccode   = config['basiccode']
        recordtime  = config['recordtime']
        debug       = config['debug']

        error=Emulator.compile(language, api, tweet, debug, basiccode)
        if error:
            continue
        Emulator.run_emulator(api, tweet, language, recordtime, starttime)
        logger.info("Done!")
    return new_since_id

def main():
    os.chdir('/home/zxspectrum/bot/')

    api = create_api()

    now = datetime.now()
    logger.info("START TIME:")
    logger.info(now.strftime("%Y %m %d %H:%M:%S")) 

    try:
        sinceFile = open('sinceFile.txt','r')
        since_id = sinceFile.read()
    except:
        sinceFile = open('sinceFile.txt','w')
        sinceFile.write("1")
        logger.info("created new sinceFile")
        since_id = 1

    sinceFile.close()       
    since_id = int(since_id)
    logger.info(f"Starting since_id {since_id}")
    os.environ["DISPLAY"] = ":99"

    while True:
        didatweet=0
        new_since_id = check_mentions(api, since_id)
        if new_since_id != since_id:
            since_id = new_since_id
            logger.info(f"Since_id now {since_id}")     
            sinceFile = open('sinceFile.txt','w')
            sinceFile.write(str(since_id))
            sinceFile.close()
            didatweet=1
        if didatweet==0:
            logger.info("Waiting...")
            time.sleep(120)

if __name__ == "__main__":
    main()
    

#Atari8BitBot by @KaySavetz. 2020-2021.

import tweepy
import logging
from botConfig import create_api
import time
import os
from shutil import copyfile
import Emulator
from datetime import datetime
from unidecode import unidecode
import re
import GistManager

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger()

def determine_config(full_text, gistUrl):
    config={}
    config['error']=None
    #remove all @ mentions, leaving just the BASIC code
    basiccode = re.sub('^(@.+?\s)+','',full_text, re.ASCII)
    basiccode = unidecode(basiccode)
    #unescape >, <, and &
    basiccode = basiccode.replace("&lt;", "<")
    basiccode = basiccode.replace("&gt;", ">")
    basiccode = basiccode.replace("&amp;", "&")

    #if url, get code from it
    if gistUrl:
        text = GistManager.getGist(gistUrl)
        if text.startswith("Error: "): 
            logger.info(f"unable to retrieve {gistUrl}, {text}")
            config['error']=text
            return config
        else:
            basiccode = unidecode(text)
    #look for Debug command
    exp = "{\w*?D\w*(?:}|\s)" # {B\d\d  D= debug
    result = re.search(exp,basiccode)
    if result:  
        config['debug'] = True
    else:
        config['debug'] = False

    #look for start time command
    exp = "{\w*?B(\d\d?)\w*(?:}|\s)" # {B\d\d  B= Begin
    result = re.search(exp,basiccode)
    if result:  
        starttime = int(result.group(1))
        logger.info(f" Requests start at {starttime} seconds")
    else:
        starttime = 2

    #look for length of time to record command
    exp = "{\w*?S(\d\d?\d?)\w*(?:}|\s)" # {S\d\d  S= Seconds to record
    result=re.search(exp,basiccode)
    if result:
        recordtime = int(result.group(1))
        logger.info(f" Requests record for {recordtime} seconds")
    else:
        recordtime = 20
    if recordtime <1:
        recordtime=1
    if recordtime >140:
        recordtime=140
        
    language = 0 # default to BASIC

    exp = "{\w*?A\w*(?:}|\s)" #{A
    if re.search(exp,basiccode): 
        language=2 #it's Assembly
        logger.info("it's ASM")
        basiccode = "ORG $8000\n" + basiccode

    #remove any { command
    #exp = "{\w*(?:}|\s)" #{anything till space or }
    exp = "{\w*(?:}\s*)" #{anything till } plus trailing whitespace
    basiccode = re.sub(exp,'',basiccode)

    #whitespace
    basiccode = basiccode.strip()
    logger.debug(f"Code: [{basiccode}]")
    
    #halt if string is empty
    if not basiccode:
        logger.info("!!! basiccode string is empty, SKIPPING")
        config['error']="Error: Empty code"
        return config
    
    config['starttime']  =starttime
    config['recordtime'] =recordtime
    config['language']   =language
    config['basiccode']  =basiccode
    return config

def check_mentions(api, since_id):
    logger.info("Retrieving mentions")
    new_since_id = since_id
    for tweet in tweepy.Cursor(api.mentions_timeline, since_id=since_id, 
      tweet_mode='extended', include_entities=True).items():
        new_since_id = max(tweet.id, new_since_id)
        url=None
        
        logger.info(f"Tweet from {tweet.user.name}")
        #if there is an url in text, pass the firs
        if tweet.entities['urls']:
            url=tweet.entities['urls'][0]['expanded_url']
        if not GistManager.validate(url):
            url=None
        config=determine_config(tweet.full_text, url)
        
        if config['error']:
            logger.info(config['error'])
            continue
        
        language    = config['language']
        starttime   = config['starttime']
        basiccode   = config['basiccode']
        recordtime  = config['recordtime']
        debug       = config['debug']

        error=Emulator.compile(language, api, tweet, debug, basiccode)
        if error:
            continue
        Emulator.run_emulator(api, tweet, language, recordtime, starttime)
        logger.info("Done!")
    return new_since_id

def main():
    os.chdir('/home/zxspectrum/bot/')

    api = create_api()

    now = datetime.now()
    logger.info("START TIME:")
    logger.info(now.strftime("%Y %m %d %H:%M:%S")) 

    try:
        sinceFile = open('sinceFile.txt','r')
        since_id = sinceFile.read()
    except:
        sinceFile = open('sinceFile.txt','w')
        sinceFile.write("1")
        logger.info("created new sinceFile")
        since_id = 1

    sinceFile.close()       
    since_id = int(since_id)
    logger.info(f"Starting since_id {since_id}")
    os.environ["DISPLAY"] = ":99"

    while True:
        didatweet=0
        new_since_id = check_mentions(api, since_id)
        if new_since_id != since_id:
            since_id = new_since_id
            logger.info(f"Since_id now {since_id}")     
            sinceFile = open('sinceFile.txt','w')
            sinceFile.write(str(since_id))
            sinceFile.close()
            didatweet=1
        if didatweet==0:
            logger.info("Waiting...")
            time.sleep(120)

if __name__ == "__main__":
    main()
    

#Atari8BitBot by @KaySavetz. 2020-2021. #remove all @ mentions, leaving just the BASIC code #unescape >, <, and & #if url, get code from it #look for Debug command # {B\d\d  D= debug #look for start time command # {B\d\d  B= Begin #look for length of time to record command # {S\d\d  S= Seconds to record # default to BASIC #{A #it's Assembly #remove any { command #exp = "{\w*(?:}|\s)" #{anything till space or } #{anything till } plus trailing whitespace #whitespace #halt if string is empty #if there is an url in text, pass the firs