Exemple #1
0
def destroy_fcreplay(failed=False):
    """Destry the current compute engine

    Checks for the existance of /tmp/destroying. If it exists then
    don't try and destroy fcreplay

    Args:
        failed (bool, optional): Updates the replay to failed. Defaults to False.
    """
    # Create destroying file
    try:
        Path('/tmp/destroying').touch(0o644, exist_ok=False)
    except FileExistsError:
        # File already exists, not running
        sys.exit(0)

    logging.info("Starting destroy_fcreplay")
    RECEIVING_FUNCTION = 'destroy_fcreplay_instance'
    HOSTNAME = socket.gethostname()

    if 'fcreplay-image-' not in HOSTNAME:
        logging.info(f"Not destroying {HOSTNAME}")
        return(False)

    # Only retry if failed is false, by default this is false, but sometimes recording
    # fails. So we don't want to try and re-record them until we work out why they
    # have failed.
    if failed is False:
        try:
            with open('/tmp/fcreplay_status', 'r') as f:
                line = f.readline()
                local_replay_id = line.split()[0].strip()
                local_replay_status = line.split()[1].strip()

            if local_replay_status in ['UPLOADING_TO_IA', 'UPLOADING_TO_YOUTUBE', 'UPLOADED_TO_IA', 'UPLOADED_TO_YOUTUBE']:
                logging.error(f"Not able to safely recover replay {local_replay_id}")
            elif local_replay_status not in ['FINISHED', 'REMOVED_GENERATED_FILES']:
                # Replay was in the middle of processing, going to set replay to be re-recorded
                db = Database()
                db.rerecord_replay(challenge_id=local_replay_id)
        except FileNotFoundError:
            logging.error('/tmp/fcreplay_status not found')

    function_url = f'https://{REGION}-{PROJECT_ID}.cloudfunctions.net/{RECEIVING_FUNCTION}'
    metadata_server_url = \
        f"http://metadata/computeMetadata/v1/instance/service-accounts/{config['gcloud_compute_service_account']}/identity?audience="
    token_full_url = metadata_server_url + function_url
    token_headers = {'Metadata-Flavor': 'Google'}

    # Fetch the token
    token_response = requests.get(token_full_url, headers=token_headers)
    jwt = token_response.text

    # Provide the token in the request to the receiving function
    function_headers = {'Authorization': f'bearer {jwt}'}
    function_response = requests.post(function_url, headers=function_headers, json={'instance_name': HOSTNAME})

    logging.info(f"destroy_fcreplay retruned: {function_response.status_code}")
    status = function_response.status_code
    return(status)
Exemple #2
0
def get_data(query):
    r = requests.post("https://www.fightcade.com/api/", json=query)
    if r.status_code == 500:
        logging.error("500 Code, trying up to 3 times")
        raise IOError("Unable to get data")
    else:
        return r
Exemple #3
0
    def __init__(self):
        config = Config().config

        # Create Engine
        try:
            self.engine = create_engine(config['sql_baseurl'], echo=True)
            Base.metadata.create_all(self.engine)
        except Exception as e:
            logging.error(f"Unable to connect to {config['sql_baseurl']}: {e}")

        self.Session = sessionmaker(bind=self.engine)
Exemple #4
0
        def failed(self, *args, **kwargs):
            try:
                return func(self, *args, **kwargs)
            except Exception as e:
                trace_back = sys.exc_info()[2]
                logging.error(
                    f"Excption: {str(traceback.format_tb(trace_back))},  shutting down"
                )
                logging.info(f"Setting {self.replay.id} to failed")
                self.db.update_failed_replay(challenge_id=self.replay.id)
                self.update_status("FAILED")

                if self.config['gcloud_destroy_on_fail']:
                    destroy_fcreplay(failed=True)
                sys.exit(1)
Exemple #5
0
    def record(self):
        """Start recording a replay
        """
        logging.info(
            f"Starting capture with {self.replay.id} and {self.replay.length}")
        time_min = int(self.replay.length / 60)
        logging.info(f"Capture will take {time_min} minutes")

        self.update_status('RECORDING')

        # Star a recording store recording status
        logging.debug(f"""Starting record.main with argumens:
            fc_challange_id={self.replay.id},
            fc_time={self.replay.length},
            kill_time={self.config['record_timeout']},
            fcadefbneo_path={self.config['fcadefbneo_path']},
            fcreplay_path={self.config['fcreplay_dir']},
            game_name={self.replay.game}""")
        record_status = fc_record.main(
            fc_challange_id=self.replay.id,
            fc_time=self.replay.length,
            kill_time=self.config['record_timeout'],
            fcadefbneo_path=self.config['fcadefbneo_path'],
            fcreplay_path=self.config['fcreplay_dir'],
            game_name=self.replay.game)

        # Check recording status
        if not record_status == "Pass":
            logging.error(f"Recording failed on {self.replay.id},"
                          "Status: \"{record_status}\", exiting.")

            if record_status == "FailTimeout":
                raise TimeoutError
            else:
                logging.error(f"Unknown error: ${record_status}, exiting")
                raise ValueError

        logging.info("Capture finished")
        self.update_status('RECORDED')

        return True
Exemple #6
0
    def set_description(self):
        """Set the description of the video

        Returns:
            Boolean: Success or failure
        """
        logging.info("Creating description")

        self.description_text = f"({self.replay.p1_loc}) {self.replay.p1} vs " \
                                f"({self.replay.p2_loc}) {self.replay.p2} - {self.replay.date_replay}" \
                                f"\nFightcade replay id: {self.replay.id}"

        # Read the append file:
        if self.config['description_append_file'][0] is True:
            # Check if file exists:
            if not os.path.exists(self.config['description_append_file'][1]):
                logging.error(
                    f"Description append file {self.config['description_append_file'][1]} doesn't exist"
                )
                return False
            else:
                with open(self.config['description_append_file'][1],
                          'r') as description_append:
                    self.description_text += "\n" + description_append.read()

        self.update_status('DESCRIPTION_CREATED')
        logging.info("Finished creating description")

        # Add description to database
        logging.info('Adding description to database')
        self.db.add_description(challenge_id=self.replay.id,
                                description=self.description_text)

        logging.debug(
            f"Description Text is: {self.description_text.encode('unicode-escape')}"
        )
        return True
Exemple #7
0
    def encode(self):
        logging.info("Encoding file")
        avi_files_list = os.listdir(f"{self.config['fcreplay_dir']}/finished")
        avi_dict = {
            i: int(i.split('_')[1].split('.')[0], 16)
            for i in avi_files_list
        }
        sorted_avi_files_list = []
        for i in sorted(avi_dict.items(), key=lambda x: x[1]):
            sorted_avi_files_list.append(i[0])
        avi_files = [
            f"{self.config['fcreplay_dir']}/finished/" + i
            for i in sorted_avi_files_list
        ]

        logging.info("Running mencoder with:" + " ".join([
            'mencoder', '-oac', 'mp3lame', '-lameopts', 'abr:br=128', '-ovc',
            'x264', '-x264encopts', 'preset=fast:crf=23:subq=1:threads=8',
            '-vf', 'flip,scale=800:600,dsize=4/3', *avi_files, '-o',
            f"{self.config['fcreplay_dir']}/finished/{self.replay.id}.mkv"
        ]))

        mencoder_rc = subprocess.run([
            'mencoder', '-oac', 'mp3lame', '-lameopts', 'abr:br=128', '-ovc',
            'x264', '-x264encopts', 'preset=slow:crf=23:subq=1:threads=8',
            '-vf', 'flip,scale=800:600,dsize=4/3', *avi_files, '-o',
            f"{self.config['fcreplay_dir']}/finished/{self.replay.id}.mkv"
        ],
                                     capture_output=True)

        try:
            mencoder_rc.check_returncode()
        except subprocess.CalledProcessError as e:
            logging.error(
                f"Unable to process avi files. Return code: {e.returncode}, stdout: {mencoder_rc.stdout}, stderr: {mencoder_rc.stderr}"
            )
            raise e
Exemple #8
0
    def upload_to_yt(self):
        """Upload video to youtube
        """
        self.update_status('UPLOADING_TO_YOUTUBE')
        title = f"{self.config['supported_games'][self.replay.game]['game_name']}: ({self.replay.p1_loc}) {self.replay.p1} vs "\
                f"({self.replay.p2_loc}) {self.replay.p2} - {self.replay.date_replay}"
        filename = f"{self.replay.id}.mkv"
        import_format = '%Y-%m-%d %H:%M:%S'
        date_raw = datetime.datetime.strptime(str(self.replay.date_replay),
                                              import_format)

        # YYYY-MM-DDThh:mm:ss.sZ
        youtube_date = date_raw.strftime('%Y-%m-%dT%H:%M:%S.0Z')

        # Check if youtube-upload is installed
        if shutil.which('youtube-upload') is not None:
            # Check if credentials file exists
            if not os.path.exists(self.config['youtube_credentials']):
                logging.error("Youtube credentials don't exist exist")
                return False

            if not os.path.exists(self.config['youtube_secrets']):
                logging.error("Youtube secrets don't exist")
                return False

            # Check min and max length:
            if (int(self.replay.length) / 60) < int(
                    self.config['yt_min_length']):
                logging.info("Replay is too short. Not uploading to youtube")
                return False
            if (int(self.replay.length) / 60) > int(
                    self.config['yt_max_length']):
                logging.info("Replay is too long. Not uploading to youtube")
                return False

            # Find number of uploads today
            day_log = self.db.get_youtube_day_log()

            # Check max uploads
            # Get todays date, dd-mm-yyyy
            today = datetime.date.today()

            # Check the log is for today
            if day_log.date.date() == today:
                # Check number of uploads
                if day_log.count >= int(
                        self.config['youtube_max_daily_uploads']):
                    logging.info("Maximum uploads reached for today")
                    return False
            else:
                # It's a new day, update the counter
                logging.info("New day for youtube uploads")
                self.db.update_youtube_day_log_count(count=1, date=today)

            # Create description file
            with open(f"{self.config['fcreplay_dir']}/tmp/description.txt",
                      'w') as description_file:
                description_file.write(self.description_text)

            # Do upload
            logging.info("Uploading to youtube")
            yt_rc = subprocess.run([
                'youtube-upload',
                '--credentials-file',
                self.config['youtube_credentials'],
                '--client-secrets',
                self.config['youtube_secrets'],
                '-t',
                title,
                '-c',
                'Gaming',
                '--description-file',
                f"{self.config['fcreplay_dir']}/tmp/description.txt",
                '--recording-date',
                youtube_date,
                '--default-language',
                'en',
                '--thumbnail',
                f"{self.config['fcreplay_dir']}/tmp/thumbnail.jpg",
                f"{self.config['fcreplay_dir']}/finished/{filename}",
            ],
                                   stderr=subprocess.PIPE,
                                   stdout=subprocess.PIPE)

            logging.info(yt_rc.stdout.decode())
            logging.info(yt_rc.stderr.decode())

            if not self.replay.player_requested:
                logging.info('Updating day_log')
                logging.info("Updating counter")
                self.db.update_youtube_day_log_count(count=day_log.count + 1,
                                                     date=today)

            # Remove description file
            os.remove(f"{self.config['fcreplay_dir']}/tmp/description.txt")

            self.update_status('UPLOADED_TO_YOUTUBE')
            logging.info('Finished uploading to Youtube')
        else:
            raise ModuleNotFoundError