CoolFace
Apppublic

deepsync/translator-admin-dashboard

sourceHugging Facebsdupdated 3y agoView on Hugging Face
0likes
app.py481 linesDownload Raw Back to root
1import os2import gradio as gr3import pymongo4import pandas as pd5from bson import ObjectId6from dotenv import load_dotenv7import requests8from datetime import timedelta9from collections import defaultdict10 11load_dotenv()12 13video_status = {14    "Not Assigned": "NOT_STARTED",15    "Under Review": "NOT_STARTED",16    "Dubbing Started": "DUBBING_STARTED",17    "Waiting QA": "WAITING_QA",18    "Sent to Client": "SENT_TO_CLIENT",19    "Approved": "APPROVED",20    "Rejected": "REJECTED",21    "Churned": "CHURNED",22    "Re-review Requested": "RE_REVIEW_REQUESTED"23}24 25HEADERS = {"x-api-key": os.environ.get('X-API-KEY'), "Content-Type": "application/json"}26 27ALL_LANGUAGES = ['Hindi', 'English', 'Bengali', 'Kannada', 'Spanish', 'French', 'German', 'Italian', 'Tamil', 'Telugu']28 29language_maps = {30    "Hindi": "hi",31    "English": "en",32    "Spanish": "es",33    "French": "fr",34    "German": "de",35    "Italian": "it",36    "Tamil": "ta",37    "Telugu": "te",38    "Bengali": "bn",39    "Kannada": "kn",40    "hi": "Hindi",41    "en": "English",42    "es": "Spanish",43    "fr": "French",44    "de": "German",45    "it": "Italian",46    "ta": "Tamil",47    "te": "Telugu",48    "bn": "Bengali",49    "kn": "Kannada"50}51 52 53def print_slack(platform, video_id, translator_name, assignment="translator"):54    if platform == "dev":55        return56    else:57        client = pymongo.MongoClient(os.environ.get("MONGO_URI"))58        source_db = client.deepsync_prod59    60    headers = {61        'Content-type': 'application/json',62    }63 64    video = source_db.dubbedvideos.find_one({"_id": ObjectId(video_id)})65    video_name = video['title']66    source_language = language_maps[video['sourceLanguage'][:2]]67    target_language = language_maps[video['targetLanguage'][:2]]68    video_duration = str(timedelta(seconds=video['duration']))69    translator_details = "/".join(translator_name.split("/")[:3])70 71    message = f"""```{'Translator' if assignment == 'translator' else 'QA'} Assigned72Video Name : {video_name}73Source Language : {source_language}74Target Language : {target_language}75Video Duration : {video_duration} hours76Details : {translator_details}77```78"""79 80    json_data = {81        'text': message,82    }83 84    response = requests.post(85        os.environ.get('SLACK_WEBHOOK'),86        headers=headers,87        json=json_data,88    )89    client.close()90 91 92def get_translators(platform):93    if platform == "dev":94        api_url = "https://api.dev-env.deepsync.co/api/v1"95        client = pymongo.MongoClient(os.environ.get("MONGO_DEV_URI"))96        source_db = client.deepsync_stage97    else:98        api_url = "https://api.deepsync.co/api/v1"99        client = pymongo.MongoClient(os.environ.get("MONGO_URI"))100        source_db = client.deepsync_prod101 102    response = requests.get(f"{api_url}/dashboard/translators", headers=HEADERS)103    translators = list(filter(lambda x: not x.get('isDeleted', False), response.json()['data']))104    translators_data = []105 106    if len(translators):107        desired_ids = [ObjectId(t["translator"]) for t in translators]108        companies_cursor = source_db.companies.find({'_id': {'$in': desired_ids}})109        companies = {c["_id"]: c for c in companies_cursor}110    for translator in translators:111        try:112            data = companies[ObjectId(translator["translator"])]113            translators_data.append({114                "_id": str(translator["_id"]),115                "Name": data["name"],116                "Email": data["email"],117                "Source Language": ", ".join(list(map(lambda x: language_maps[x], translator["sourceAccent"]))),118                "Target Language": ", ".join(list(map(lambda x: language_maps[x], translator["targetAccent"])))119            })120        except Exception as e:121            print(e)122            pass123    client.close()124    return pd.DataFrame(translators_data)125 126 127def add_translator(platform, email_id, source_langs, target_langs, contact_num, pricing):128    if platform == "dev":129        api_url = "https://api.dev-env.deepsync.co/api/v1"130        client = pymongo.MongoClient(os.environ.get("MONGO_DEV_URI"))131        source_db = client.deepsync_stage132    else:133        api_url = "https://api.deepsync.co/api/v1"134        client = pymongo.MongoClient(os.environ.get("MONGO_URI"))135        source_db = client.deepsync_prod136    137    try:138        company_id_validity = source_db.companies.find_one({"email": email_id})139    except:140        company_id_validity = None141    if company_id_validity is None:142        return "Invalid Company ID. Unable to add translator."143    144    if source_langs is None:145        source_accents = []146    else:147        source_accents = [language_maps[l] for l in source_langs]148    if target_langs is None:149        target_accents = []150    else:151        target_accents = [language_maps[l] for l in target_langs]152 153    main_data = {154        "targetAccent": target_accents,155        "sourceAccent": source_accents,156        "contactNum": None if len(contact_num.strip()) == 0 else contact_num.strip(),157        "pricing": None if pricing is None or pricing == -1 else pricing158    }159 160    data = {"translator": str(company_id_validity["_id"]), **main_data}161 162    response = requests.post(f"{api_url}/dashboard/translator", json=data, headers=HEADERS)163 164    if str(response.status_code).startswith('4') or str(response.status_code).startswith('5'):165        if response.json()['message'].strip() == "Translator already exists":166            translator_main_id = source_db.translators.find_one({"translator": company_id_validity['_id']})167            response = requests.patch(f"{api_url}/dashboard/translators/{translator_main_id['_id']}", json={"isDeleted": False,  **main_data}, headers=HEADERS)168            if str(response.status_code).startswith('4') or str(response.status_code).startswith('5'):169                return f"{response.json()['message']} ({response.status_code})"170            return f"Translator added succesfully, ID : {response.json()['data']['_id']}"171        return f"{response.json()['message']} ({response.status_code})"172 173    client.close()174    return f"Translator added succesfully, ID : {response.json()['data']['_id']}"175 176 177def get_translator_names(platform):178    if platform == "dev":179        api_url = "https://api.dev-env.deepsync.co/api/v1"180        client = pymongo.MongoClient(os.environ.get("MONGO_DEV_URI"))181        source_db = client.deepsync_stage182    else:183        api_url = "https://api.deepsync.co/api/v1"184        client = pymongo.MongoClient(os.environ.get("MONGO_URI"))185        source_db = client.deepsync_prod186 187    response = requests.get(f"{api_url}/dashboard/translators", headers=HEADERS)188    translators = list(filter(lambda x: not x.get('isDeleted', False), response.json()['data']))189    translators_names = []190 191    if len(translators):192        desired_ids = [ObjectId(t["translator"]) for t in translators]193        companies_cursor = source_db.companies.find({'_id': {'$in': desired_ids}})194        companies = {c["_id"]: c for c in companies_cursor}195    for translator in translators:196        try:197            data = companies[ObjectId(translator["translator"])]198            translators_names.append(f'{data["name"]} / {data["email"]} / {translator["_id"]}')199        except Exception as e:200            print(e)201            pass202    client.close()203    return gr.Dropdown.update(choices=translators_names)204 205 206def select_current_data(platform, translator_name):207    if translator_name is None:208        return "Please select a translator."209 210    name, email, translator_id = list(map(lambda x: x.strip(), translator_name.split("/")))211 212    if platform == "dev":213        api_url = "https://api.dev-env.deepsync.co/api/v1"214    else:215        api_url = "https://api.deepsync.co/api/v1"216 217    response = requests.get(f"{api_url}/dashboard/translators", headers=HEADERS)218    translators = list(filter(lambda x: not x.get('isDeleted', False) and x["_id"] == translator_id, response.json()['data']))219    if len(translators):220        translator = translators[0]221    else:222        raise Exception("Translator", translator_name, "not found.")223    return gr.CheckboxGroup.update(value=[language_maps[l] for l in translator["sourceAccent"]]), gr.CheckboxGroup.update(value=[language_maps[l] for l in translator["targetAccent"]]), gr.Textbox.update(value="" if translator["contactNum"] is None else translator["contactNum"]), gr.Textbox.update(value=-1 if translator["pricing"] is None else translator["pricing"])224 225 226def update_translator(platform, translator_name, source_languages, target_languages, contact_num, pricing):227    if translator_name is None:228        return "Please select a translator."229    230    name, email, translator_id = list(map(lambda x: x.strip(), translator_name.split("/")))231 232    if platform == "dev":233        api_url = "https://api.dev-env.deepsync.co/api/v1"234    else:235        api_url = "https://api.deepsync.co/api/v1"236 237    response = requests.get(f"{api_url}/dashboard/translators", headers=HEADERS)238    translators = list(filter(lambda x: not x.get('isDeleted', False), response.json()['data']))239    if len(translators):240        translator = translators[0]241    else:242        raise Exception("Translator", translator_name, "not found.")243 244    source_accents = [language_maps[l] for l in source_languages]245    target_accents = [language_maps[l] for l in target_languages]246 247    updateable_data = {248        "sourceAccent": source_accents,249        "targetAccent": target_accents,250        "contactNum": "" if contact_num is None else contact_num.strip(),251        "pricing": 0 if pricing is None else pricing252    }253 254    response = requests.patch(f"{api_url}/dashboard/translators/{translator_id}", json=updateable_data, headers=HEADERS)255    if str(response.status_code).startswith('4') or str(response.status_code).startswith('5'):256        return response.json()['message']257 258    return f"Updated translator details succesfully."259 260 261def get_videos_under_review(platform, status_key):262    status_keys = [status_key]263    if platform == "dev":264        api_url = "https://api.dev-env.deepsync.co/api/v1"265    else:266        api_url = "https://api.deepsync.co/api/v1"267 268    if status_keys is None or len(status_keys) == 0:269        API_URL = f"{api_url}/dashboard/dubbed/videos/review/requested"270        response = requests.get(API_URL, headers=HEADERS)271        if response.status_code == 200:272            options = [f"{str(v['_id'])} / {v['title']}" for v in response.json()['data'] if 'title' in v]273            return gr.Dropdown.update(choices=options, value=None), ""274        else:275            return gr.Dropdown.update(choices=[], value=None), ""276    else:277        options = []278        count = {}279        for status in status_keys:280            API_URL = f"{api_url}/dashboard/dubbed/videos/review/requested/{video_status[status]}"281            response = requests.get(API_URL, headers=HEADERS)282            if response.status_code == 200:283                response_data = response.json()['data']284                if status == "Not Assigned":285                    response_data = list(filter(lambda x: x["videoReviewInformation"].get("assignedTranslator") is None, response_data))286                if status == "Under Review":287                    response_data = list(filter(lambda x: x["videoReviewInformation"].get("assignedTranslator") is not None, response_data))288                current_options = [f"{str(v['_id'])} / {v['title']}" for v in response_data if 'title' in v]289                290                count[status] = len(current_options)291                options.extend(current_options)292        data_text = "\n".join([f"{k} : {v} videos" for k,v in count.items()])293        return gr.Dropdown.update(choices=options, value=None), data_text294 295 296def delete_translator_func(platform, translator_name):297    if translator_name is None:298        return "Please select a translator."299    300    name, email, translator_id = list(map(lambda x: x.strip(), translator_name.split("/")))301 302    if platform == "dev":303        api_url = "https://api.dev-env.deepsync.co/api/v1"304    else:305        api_url = "https://api.deepsync.co/api/v1"306    307    response = requests.patch(f"{api_url}/dashboard/translators/{translator_id}", json={"isDeleted": True}, headers=HEADERS)308    if str(response.status_code).startswith('4') or str(response.status_code).startswith('5'):309        return response.json()['message']310    return "Translator deleted."311 312 313 314def get_traslators_assign(platform, video):315    video_id = video.split("/", maxsplit=1)[0].strip()316 317    if platform == "dev":318        api_url = "https://api.dev-env.deepsync.co/api/v1"319        client = pymongo.MongoClient(os.environ.get("MONGO_DEV_URI"))320        source_db = client.deepsync_stage321    else:322        api_url = "https://api.deepsync.co/api/v1"323        client = pymongo.MongoClient(os.environ.get("MONGO_URI"))324        source_db = client.deepsync_prod325        326    video = source_db.dubbedvideos.find_one({"_id": ObjectId(video_id)})327    source_language = video["sourceLanguage"].split("-")[0]328    target_language = video["targetLanguage"].split("-")[0]329 330    translators = list(source_db.translators.find({"sourceAccent": {"$elemMatch": {"$eq": source_language}}, "targetAccent": {"$elemMatch": {"$eq": target_language}}}))331    translators_list = []332 333    pending_videos = []334    for status in ["NOT_STARTED", "DUBBING_STARTED", "WAITING_QA"]:335        API_URL = f"{api_url}/dashboard/dubbed/videos/review/requested/{status}"336        response = requests.get(API_URL, headers=HEADERS)337        if response.status_code == 200:338            response_data = response.json()['data']339            pending_videos.extend(response_data)340    translator_pv_count = defaultdict(lambda: 0)341    for pv in pending_videos:342        if pv.get("videoReviewInformation", {}).get("assignedTranslator") is not None:343            trs = str(pv.get("videoReviewInformation", {}).get("assignedTranslator"))344            translator_pv_count[trs] += 1345 346    if len(translators):347        desired_ids = [t["translator"] for t in translators]348        companies_cursor = source_db.companies.find({'_id': {'$in': desired_ids}})349        companies = {c["_id"]: c for c in companies_cursor}350    for translator in translators:351        company = companies[translator["translator"]]352        translators_list.append(f"{company['name']} / {company['email']} / {str(translator['_id'])} / Pending Videos: {translator_pv_count[str(translator['_id'])]}")353    354    button = gr.Button.update(interactive=False)355    current_translator = None 356    current_qa = None357    if "videoReviewInformation" in video:358        if video["videoReviewInformation"]["status"] in {"NOT_STARTED", "DUBBING_STARTED", "WAITING_QA"}:359            button = gr.Button.update(interactive=True)360        if video["videoReviewInformation"].get("assignedTranslator") is not None:361            str_id = str(video["videoReviewInformation"].get("assignedTranslator"))362            value = [v for v in translators_list if str_id in v]363            current_translator = value[0] if len(value) else None364        if video["videoReviewInformation"].get("assignedQA") is not None:365            str_id = str(video["videoReviewInformation"].get("assignedQA"))366            value = [v for v in translators_list if str_id in v]367            current_qa = value[0] if len(value) else None368    client.close()369    return gr.Dropdown.update(choices=translators_list, value=current_translator), gr.Dropdown.update(choices=translators_list, value=current_qa), language_maps[source_language], language_maps[target_language], button, button370 371 372def assign_translator(platform, translator, video):373    translator_id = translator.split("/")[2].strip()374    video_id = video.split("/", maxsplit=1)[0].strip()375    role = "translator"376    if platform == "dev":377        api_url = "https://api.dev-env.deepsync.co/api/v1"378    else:379        api_url = "https://api.deepsync.co/api/v1"380    data = {381        "videoId": video_id,382        "userId": translator_id383    }384    response = requests.post(f"{api_url}/dashboard/dubbed/video/assign/{role}", json=data, headers=HEADERS)385    if str(response.status_code).startswith('2'):386        print_slack(platform, video_id, translator, "translator")387        return "Successfully assigned."388    else:389        return str(response.status_code)390 391 392def assign_qa(platform, qa, video):393    translator_id = qa.split("/")[2].strip()394    video_id = video.split("/", maxsplit=1)[0].strip()395    role = "QA"396    if platform == "dev":397        api_url = "https://api.dev-env.deepsync.co/api/v1"398    else:399        api_url = "https://api.deepsync.co/api/v1"400    data = {401        "videoId": video_id,402        "userId": translator_id403    }404    response = requests.post(f"{api_url}/dashboard/dubbed/video/assign/{role}", json=data, headers=HEADERS)405    if str(response.status_code).startswith('2'):406        print_slack(platform, video_id, qa, "qa")407        return "Successfully assigned."408    else:409        return str(response.status_code)410 411 412with gr.Blocks() as demo:413    gr.Markdown("# Translators Admin Dashboard")414    with gr.Tab("List"):415        source_platform = gr.Radio(["dev", "prod"], value="prod", label="Source Platform")416        refresh_list = gr.Button("Load")417        translators_list = gr.Dataframe(label="Translators", interactive=False, max_rows=20, overflow_row_behaviour="paginate")418    with gr.Tab("Add"):419        gr.Markdown("Add a new translator")420        source_platform_add = gr.Radio(["dev", "prod"], value="prod", label="Source Platform")421        email_id = gr.Textbox(label="Email ID", lines=1)422        source_languages = gr.CheckboxGroup(ALL_LANGUAGES, label="Source Languages")423        target_languages = gr.CheckboxGroup(ALL_LANGUAGES, label="Target Languages")424        contact_num_box = gr.Textbox(label="Contact Number", lines=1)425        pricing_box = gr.Number(label="Pricing", value=-1)426        submit = gr.Button("Submit")427        result = gr.Textbox(label="Logs")428    with gr.Tab("Update"):429        gr.Markdown("Update Translator")430        source_platform_update = gr.Radio(["dev", "prod"], value="prod", label="Source Platform")431        refresh_update_platform = gr.Button("Load")432        translator_name = gr.Dropdown([], label="Translators")433        source_languages_update = gr.CheckboxGroup(ALL_LANGUAGES, label="Source Languages")434        target_languages_update = gr.CheckboxGroup(ALL_LANGUAGES, label="Target Languages")435        contact_num_update = gr.Textbox(label="Contact Number", lines=1)436        pricing_update = gr.Number(label="Pricing")437        update_language = gr.Button("Update")438        delete_translator = gr.Button("Delete Translator")439        result_update = gr.Textbox(label="Logs")440    with gr.Tab("Assign"):441        gr.Markdown("Assign Translator / QA")442        source_platform_assign = gr.Radio(["dev", "prod"], value="prod", label="Source Platform")443        filter_videos_assign = gr.Radio(['Not Assigned', 'Under Review', 'Dubbing Started', 'Waiting QA', 'Sent to Client', 'Approved', 'Rejected', 'Churned', 'Re-review Requested'], label="Filter videos. Do not select any of them for videos without request info.")444        video_details = gr.Textbox(label="Video Details")445        refresh_assign = gr.Button("Load Videos")446        under_review_videos_list = gr.Dropdown([], label="Video IDs")447        with gr.Row():448            source_language_box = gr.Textbox(label="Source Language")449            target_language_box = gr.Textbox(label="Target Language")450        with gr.Row():451            translator_name_assign = gr.Dropdown([], label="Translator")452            submit_tr_assign_button = gr.Button("Assign Translator")453        with gr.Row():454            qa_name_assign = gr.Dropdown([], label="QA")455            submit_qa_assign_button = gr.Button("Assign QA")456        assign_logs = gr.Textbox(label="Logs")457 458    459    # For list460    refresh_list.click(get_translators, source_platform, translators_list)461    source_platform.change(get_translators, source_platform, translators_list)462 463    # For add464    submit.click(add_translator, [source_platform_add, email_id, source_languages, target_languages, contact_num_box, pricing_box], result)465 466    # For Update467    refresh_update_platform.click(get_translator_names, source_platform_update, translator_name)468    source_platform_update.change(get_translator_names, source_platform_update, translator_name)469    translator_name.change(select_current_data, [source_platform_update, translator_name], [source_languages_update, target_languages_update, contact_num_update, pricing_update])470    update_language.click(update_translator, [source_platform_update, translator_name, source_languages_update, target_languages_update, contact_num_update, pricing_update], result_update)471    delete_translator.click(delete_translator_func, [source_platform_update, translator_name], result_update)472 473    # For Assign474    refresh_assign.click(get_videos_under_review, [source_platform_assign, filter_videos_assign], [under_review_videos_list, video_details])475    under_review_videos_list.change(get_traslators_assign, [source_platform_assign, under_review_videos_list], [translator_name_assign, qa_name_assign, source_language_box, target_language_box, submit_tr_assign_button, submit_qa_assign_button])476    submit_tr_assign_button.click(assign_translator, [source_platform_assign, translator_name_assign, under_review_videos_list], assign_logs)477    submit_qa_assign_button.click(assign_qa, [source_platform_assign, qa_name_assign, under_review_videos_list], assign_logs)478 479 480if __name__=="__main__":481    demo.launch(auth=(os.environ.get("GRADIO_USERNAME"), os.environ.get("GRADIO_PASSWORD")))