corretor.py 9.03 KB
# -*- coding: utf-8 -*-

from flask import request, make_response
from werkzeug import secure_filename
import pbclient
import os
import pyutil
import checkout
import requests
import shutil
import tempfile


class Corretor:

    def __init__(self, configuration, template_env):
        self.config = configuration
        self.env = template_env
        self.__setup_pb_client()
        self.__setup_upload_folder()

    def __setup_pb_client(self):
        pbclient.set('endpoint', self.config['PYBOSSA_ENDPOINT'])
        pbclient.set('api_key', self.config['PYBOSSA_API_KEY'])

    def __setup_upload_folder(self):
        upload_folder = self.config['UPLOAD_FOLDER']
        if not os.path.exists(upload_folder):
            os.makedirs(upload_folder)

    def __find_project(self, app_short_name):
        projects = pbclient.find_project(short_name=app_short_name)
        return projects[0] if len(projects) > 0 else None

    def __setup_project(self, project):
        self.__update_project_info(project)

    def __create_tasks(self, project):
        test_signs = ["ENSINADO", "ENTANTO", "ENTENDIDO"]
        for sign in test_signs:
            video_ref = "/videos/" + sign + "_REF.webm"
            video_ava = "/videos/" + sign + "_AVATAR.webm"
            blend = "/videos/" + sign + "_AVATAR.blend"
            task = dict(sign_name=sign, submission_date=pyutil.get_date_now(),
                        video_ref=video_ref, video_ava=video_ava, blend=blend)
            pbclient.create_task(project.id, task)

    def __update_project_info(self, project):
        template = self.env.get_template('index.html')
        project.info['task_presenter'] = template.render(
            server=self.config['HOST_STATIC_FILES_ENDPOINT'],
            server_backend=self.config['HOST_ENDPOINT'],
            app_shortname=self.config['PYBOSSA_APP_SHORT_NAME'],
            api_db_host=self.config['API_DB_HOST'])
        project.info['thumbnail'] = self.config['HOST_STATIC_FILES_ENDPOINT'] + "/img/thumbnail.png"
        project.info['sched'] = "incremental"
        project.info['published'] = True
        project.allow_anonymous_contributors = False
        pbclient.update_project(project)

    def __find_task(self, project_id, task_id):
        tasks = pbclient.find_tasks(project_id, id=task_id)
        return tasks[0] if len(tasks) > 0 else None

    def __find_taskruns(self, project_id, task_id):
        return pbclient.find_taskruns(project_id, task_id=task_id)

    def __number_of_taskruns(self, project_id, task_id):
        taskruns = self.__find_taskruns(project_id, task_id)
        return len(taskruns)

    def __close_task(self, project_id, task_id):
        pyutil.log("Closing the task with ID=" + str(task_id) + ".")
        task = self.__find_task(project_id, task_id)
        number_of_taskruns = self.__number_of_taskruns(project_id, task_id)
        task.n_answers = number_of_taskruns + 1
        pbclient.update_task(task)
        return "The task with ID=" + str(task_id) + " was closed."

    def finish_task(self):
        user_id = request.form['upload_session_id']
        pyutil.log(str(user_id))
        task_id = request.form['task_id']
        api_host = self.config['SERVER_HOST']
        api_dbhost = self.config['API_DB_HOST']
        sign_name = request.form['sign_name']
        project_id = request.form['project_id']
        number_of_approval = int(request.form['number_of_approval'])
        agreement_number = self.config['AGREEMENT_NUMBER']
        result_msg = ""
        code = 200
        if (number_of_approval >= agreement_number):
            tmp_dir = tempfile.NamedTemporaryFile().name
            if not os.path.exists(tmp_dir):
                os.makedirs(tmp_dir)
            blend_path = os.path.join(tmp_dir, sign_name + ".blend")
            video_path = os.path.join(tmp_dir, sign_name + ".webm")
            blend_url = ('http://%s/corretor/uploads/%s/%s.blend' % (api_host, user_id, sign_name))
            video_url = ('http://%s/corretor/uploads/%s/%s.webm' % (api_host, user_id, sign_name))
            blend_downloaded = self.get_file(blend_url, blend_path)
            video_downloaded = self.get_file(video_url, video_path)
            if (not blend_downloaded):
                pyutil.log("blend file: %s was not downloaded" % (blend_url))
            elif (not video_downloaded):
                pyutil.log("video file: %s was not downloaded" % (video_url))
            else:
                files_to_upload = [
                    ("video", (video_path, open(video_path, "rb"))),
                    ("video", (blend_path, open(blend_path, "rb")))
                ]
                body = {
                    "nome": sign_name,
                    "idtask": task_id,
                    "selo": 5
                }
                r = requests.post(("%s/updatesinal" % (api_dbhost)), files=files_to_upload, data=body)
                code = r.status_code
                if (code == 200):
                    result_msg = self.__close_task(project_id, task_id)
                else:
                    result_msg = r.text
            shutil.rmtree(tmp_dir)
        else:
            result_msg = "The task with ID=" + str(task_id) + " didn't reach the agreement number yet."
        pyutil.log(str(result_msg).encode("UTF-8", errors="ignore"))
        return make_response(result_msg, code)

    def render_video(self):
        upload_session_id = request.form['upload_session_id']
        sign_name = request.form['sign_name']
        upload_dir = os.path.join(self.config['UPLOAD_FOLDER'], upload_session_id)
        blend_file = os.path.join(upload_dir, sign_name + ".blend")
        checkout_result = checkout.render_video(upload_dir, blend_file, sign_name)
        pyutil.log("render_video code: " + str(checkout_result))
        code = 0
        result_msg = ""
        if(checkout_result == 0):
            result_msg = "Successfully rendered the video."
            code = 200
        else:
           result_msg = "Error while rendering the video."
           code = 400
        pyutil.log(result_msg)
        return make_response(result_msg, code)

    def create_project(self):
        app_short_name = self.config['PYBOSSA_APP_SHORT_NAME']
        project = self.__find_project(app_short_name)
        result_msg = ""
        if (project):
            result_msg = "The project " + app_short_name + " was already created."
        else:
            project = pbclient.create_project(self.config['PYBOSSA_APP_NAME'], app_short_name, self.config['PYBOSSA_APP_DESCRIPTION'])
            if (project):
                self.__setup_project(project)
                result_msg = "The project " + app_short_name + " was created."
            else:
                result_msg = "The project " + app_short_name + " couldn't be created. Check the server log for details."
        pyutil.log(result_msg)
        return result_msg

    def update_project(self):
        app_short_name = self.config['PYBOSSA_APP_SHORT_NAME']
        project = self.__find_project(app_short_name)
        # self.__create_tasks(project)
        self.__update_project_info(project)
        result_msg = "The project " + app_short_name + " was updated."
        pyutil.log(result_msg)
        return result_msg

    def __allowed_file(self, filename):
        allowed_extensions = set(['blend'])
        return '.' in filename and filename.rsplit('.', 1)[1] in allowed_extensions

    def get_file(self, url, filename):
        r = requests.get(url, stream=True)
        if (r.status_code == 200):
            with open(filename, 'wb') as f:
                for chunk in r.iter_content(chunk_size=1024):
                    if chunk:
                        f.write(chunk)
            return True
        return False

    def upload_file(self):
        upload_session_id = request.form['upload_session_id']
        sign_name = request.form['sign_name']
        file = request.files['file']
        result_msg = ""
        code = 400
        if (not pyutil.is_int(upload_session_id)):
            result_msg = "Invalid upload session id: " + upload_session_id
        elif file and not self.__allowed_file(file.filename):
            result_msg = file.filename + " extension is not acceptable."
        else:
            filename = secure_filename(file.filename)
            upload_dir = os.path.join(self.config['UPLOAD_FOLDER'], upload_session_id)
            if not os.path.exists(upload_dir):
                os.makedirs(upload_dir)
            uploaded_file = os.path.join(upload_dir, filename)
            file.save(uploaded_file)
            renamed_file = os.path.join(upload_dir, secure_filename(sign_name + ".blend"))
            os.rename(uploaded_file, renamed_file)
            checkout_result = checkout.check_action(renamed_file, sign_name)
            pyutil.log("checkout_result code: " + str(checkout_result))
            if (checkout_result == 0):
                result_msg = "File " + filename + " was uploaded."
                code = 200
            else:
                result_msg = "File " + filename + " has not expected structure of blend file. "
                code = 400
        pyutil.log(result_msg)
        return make_response(result_msg, code)