Merge pull request #66 from micz/new_1.1

Version 1.1.0
This commit is contained in:
Mic 2024-05-21 21:25:02 +02:00 committed by GitHub
commit bbd0186849
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
25 changed files with 4453 additions and 123 deletions

View file

@ -2,25 +2,40 @@
<h2>Version 1.1.0 - ??/??/2024</h2>
<ul>
<li>A prompt can be configured to request additional text from the user.</li>
<li>Added custom prompts. See more info <a href="https://micz.it/thunderdbird-addon-thunderai/custom-prompts/">here</a>.</li>
<li>Dark mode added.</li>
<li>Added some error messages to handle potential changes in the ChatGPT web interface.</li>
<li>German translation added.</li>
<li>French translation added.</li>
<li>Log messages improved.</li>
</ul>
<h2>Version 1.0.10 - 17/05/2024</h2>
<ul>
<li>Now using the new URL chatgpt.com.</li>
<li>More improvements in handling the ChatGPT web interface.</li>
</ul>
<h2>Version 1.0.9 - 16/05/2024</h2>
<ul>
<li>Improved handling of different versions of the ChatGPT web interface.</li>
</ul>
<h2>Version 1.0.8 - 15/05/2024</h2>
<ul>
<li>Fixed changes in the ChatGPT web interface, see <a href="https://github.com/micz/ThunderAI/issues/57">#57</a> and <a href="https://github.com/micz/ThunderAI/issues/62">#62</a>.</li>
<li>Fixed changes in the ChatGPT web interface [<a href="https://github.com/micz/ThunderAI/issues/57">#57</a>, <a href="https://github.com/micz/ThunderAI/issues/62">#62</a>].</li>
<li>Correctly handling the model ChatGPT-4o.</li>
</ul>
<h2>Version 1.0.7 - 09/05/2024</h2>
<ul>
<li>Improved the reply prompt to exclude comments and other text beside the mail text.</li>
<li>Correctly keeping the signature in a reply even if it's above the quoted email [<a href="https://github.com/micz/ThunderAI/issues/45">#45</a>].</li>
</ul>
<h2>Version 1.0.6 - 08/05/2024</h2>
<ul>
<li>Correctly handling a change in the ChatGPT web interface [<a href="https://github.com/micz/ThunderAI/issues/43">#43</a>].</li>

View file

@ -16,9 +16,15 @@ ThunderAI is a tool for anyone looking to improve their email quality, both in c
There is no need for an API key and is possibile to use this extension even with a free account!
Starting from version 1.1.0, you can also define your own **custom prompts**! Find out how [here](https://micz.it/thunderdbird-addon-thunderai/custom-prompts/)!
<br>
## Changelog
ThunderAI's changes are logged [here](CHANGELOG.md).
<br>
<br>Thanks to:
<ul><li><a href="https://github.com/KudoAI/chatgpt.js">chatgpt.js</a> for providing methods to interact with the ChatGTP frontend.</li>
<li><a href="https://github.com/ali-raheem/Aify">Aify</a> for inspiration and certains methods to process the text from ChatGPT.</li>

407
_locales/de/messages.json Normal file
View file

@ -0,0 +1,407 @@
{
"extensionDescription": {
"message": "Verwenden Sie ChatGPT, um Ihre E-Mails zu verbessern!",
"description": "Beschreibung der Erweiterung."
},
"menu_title": {
"message": "KI",
"description": ""
},
"prompt_lang": {
"message": "Antwort in ",
"description": ""
},
"prompt_reply": {
"message": "Darauf antworten",
"description": ""
},
"prompt_rewrite_polite": {
"message": "Höflich umschreiben",
"description": ""
},
"prompt_rewrite_formal": {
"message": "Formal umschreiben",
"description": ""
},
"prompt_classify": {
"message": "Klassifizieren",
"description": ""
},
"prompt_summarize_this": {
"message": "Zusammenfassen",
"description": ""
},
"prompt_translate_this": {
"message": "Übersetzen",
"description": ""
},
"prompt_this": {
"message": "Auffordern",
"description": ""
},
"prompt_selection_needed": {
"message": "Um fortzufahren, müssen Sie einen Text auswählen!",
"description": ""
},
"customPrompts_managePrompts": {
"message": "Eingabeaufforderungen verwalten",
"description": ""
},
"customPrompts_managePrompts_help": {
"message": "Informationen",
"description": ""
},
"customPrompts_start_saving": {
"message": "Eingabeaufforderungen werden gespeichert...",
"description": ""
},
"customPrompts_reindexing_list": {
"message": "Liste wird neu indiziert...",
"description": ""
},
"customPrompts_filtering_prompts": {
"message": "Eingabeaufforderungen werden gefiltert...",
"description": ""
},
"customPrompts_saving_default_prompts": {
"message": "Standard-Eingabeaufforderungen werden gespeichert...",
"description": ""
},
"customPrompts_saving_custom_prompts": {
"message": "Benutzerdefinierte Eingabeaufforderungen werden gespeichert...",
"description": ""
},
"customPrompts_reloading_menus": {
"message": "Menüs werden neu geladen...",
"description": ""
},
"customPrompts_saved": {
"message": "Eingabeaufforderungen gespeichert!",
"description": ""
},
"customPrompts_form_label_ID": {
"message": "ID",
"description": ""
},
"customPrompts_form_label_ID_rules": {
"message": "Muss eindeutig, kleingeschrieben und ohne Leerzeichen sein",
"description": ""
},
"customPrompts_form_label_Name": {
"message": "Name",
"description": ""
},
"customPrompts_form_label_Text": {
"message": "Eingabeaufforderungstext",
"description": ""
},
"customPrompts_form_label_Action": {
"message": "Aktion",
"description": ""
},
"customPrompts_form_label_need_selected": {
"message": "Textauswahl erforderlich",
"description": ""
},
"customPrompts_form_label_need_signature": {
"message": "Immer die Signatur hinzufügen",
"description": ""
},
"customPrompts_form_label_need_custom_text": {
"message": "Nach zusätzlichem Text fragen",
"description": ""
},
"customPrompts_form_label_enabled": {
"message": "Aktiviert",
"description": ""
},
"customPrompts_form_required_fields": {
"message": "Erforderliche Felder",
"description": ""
},
"customPrompts_btnEdit": {
"message": "Bearbeiten",
"description": ""
},
"customPrompts_btnCancel": {
"message": "Abbrechen",
"description": ""
},
"customPrompts_btnOK": {
"message": "OK",
"description": ""
},
"customPrompts_btnDelete": {
"message": "Löschen",
"description": ""
},
"customPrompts_btnDelete_confirmText": {
"message": "Sind Sie sicher, dass Sie dieses Element löschen möchten?",
"description": ""
},
"customPrompts_unsaved_changes": {
"message": "Es gibt ungespeicherte Änderungen!",
"description": ""
},
"customPrompts_btnSaveAll": {
"message": "Alle speichern",
"description": ""
},
"customPrompts_save_button": {
"message": "Speichern",
"description": ""
},
"customPrompts_btnNew": {
"message": "Neu hinzufügen",
"description": ""
},
"customPrompts_btnAddNewCommit": {
"message": "Eingabeaufforderung hinzufügen",
"description": ""
},
"customPrompts_add_to_menu": {
"message": "Zum Menü hinzufügen",
"description": ""
},
"customPrompts_add_to_menu_always": {
"message": "Immer",
"description": ""
},
"customPrompts_add_to_menu_reading": {
"message": "E-Mail lesen",
"description": ""
},
"customPrompts_add_to_menu_composing": {
"message": "E-Mail verfassen",
"description": ""
},
"customPrompts_close_button": {
"message": "Schließen",
"description": ""
},
"customPrompts_do_reply": {
"message": "Antworten",
"description": ""
},
"customPrompts_substitute_text": {
"message": "Text ersetzen",
"description": ""
},
"chatgpt_win_working": {
"message": "Arbeit in Arbeit...",
"description": ""
},
"chatgpt_win_job_completed": {
"message": "Abgeschlossen!",
"description": ""
},
"chatgpt_win_get_answer": {
"message": "Letzte Antwort verwenden",
"description": ""
},
"chatgpt_win_close": {
"message": "Schließen",
"description": ""
},
"chatgpt_textarea_not_found_error": {
"message": "Es gibt einen Fehler beim Senden der Eingabeaufforderung an ChatGPT. Bitte versuchen Sie es erneut. Wenn das Problem weiterhin besteht, überprüfen Sie bitte den <a href=\"https://micz.it/thunderdbird-addon-thunderai/status/\">Dienststatus</a>.",
"description": ""
},
"chatgpt_sendbutton_not_found_error": {
"message": "Klicken Sie auf die Schaltfläche „Senden“, um die Eingabeaufforderung zu übermitteln.",
"description": ""
},
"chatgpt_user_not_logged_in": {
"message": "Sie sind nicht bei ChatGPT angemeldet. Bitte melden Sie sich mit Ihren Anmeldeinformationen an, schließen Sie das ChatGPT-Fenster und wiederholen Sie dann die Aktion, die Sie versucht haben. Danach bleiben Sie angemeldet.",
"description": ""
},
"chatgpt_win_model_warning": {
"message": "Sie haben die Option zur Verwendung von ChatGPT-4 eingestellt, aber es scheint, dass es nicht korrekt geladen wird. Haben Sie das richtige Modell oben ausgewählt?",
"description": ""
},
"chatgpt_win_custom_text": {
"message": "Fügen Sie hier den zusätzlichen Text für die Eingabeaufforderung ein.",
"description": ""
},
"chatgpt_win_send": {
"message": "Senden",
"description": ""
},
"chatgpt_use_gpt35": {
"message": "Verwenden Sie GPT3.5",
"description": ""
},
"chatgpt_force_completion": {
"message": "Abschluss erzwingen",
"description": ""
},
"chatgpt_force_completion_title": {
"message": "Klicken Sie hier, um die Schaltfläche „Letzte Antwort verwenden“ anzuzeigen, wenn ChatGPT seine Arbeit abgeschlossen hat, die Schaltfläche jedoch nicht erschienen ist.",
"description": ""
},
"msg_prompt_too_long": {
"message": "Der eingegebene Text ist zu lang. Sie müssen ihn verkürzen, um ChatGPT zu verwenden.",
"description": ""
},
"prefs_OptionText_release_notes": {
"message": "Versionshinweise",
"description": ""
},
"prefs_status_page": {
"message": "Dienststatus",
"description": ""
},
"prefs_OptionText_chatgpt_win_text": {
"message": "ChatGPT-Fensterabmessungen",
"description": ""
},
"prefs_OptionText_chatgpt_win_height": {
"message": "Höhe",
"description": ""
},
"prefs_OptionText_chatgpt_win_width": {
"message": "Breite",
"description": ""
},
"prefs_OptionText_default_sign_name": {
"message": "Standard-Signaturname",
"description": ""
},
"prefs_OptionText_default_chatgpt_lang": {
"message": "Standardsprache für ChatGPT-Antworten",
"description": ""
},
"prefs_OptionText_reply_all": {
"message": "Allen antworten",
"description": ""
},
"prefs_OptionText_reply_sender": {
"message": "Absender antworten",
"description": ""
},
"prefs_OptionText_reply_type": {
"message": "Antworttyp",
"description": ""
},
"prefs_OptionText_chatpgt_use_gpt4": {
"message": "Verwenden Sie ChatGPT-4",
"description": ""
},
"prefs_OptionText_chatpgt_use_gpt4_info": {
"message": "Nachdem Sie diese Option geändert haben, müssen Sie beim ersten Gebrauch das richtige Modell auswählen.",
"description": ""
},
"prefs_OptionText_btnManagePrompts": {
"message": "Verwalten Sie Ihre Eingabeaufforderungen",
"description": ""
},
"prefsInfoTitle": {
"message": "Wichtige Informationen",
"description": ""
},
"prefsInfoDesc_1": {
"message": "Es ist nicht mehr möglich, den Verlauf der ChatGPT-Chats zu deaktivieren. Daher gibt es keine Möglichkeit, zu verhindern, dass Anfragen, die über dieses Addon gestellt werden, in Ihrem ChatGPT-Chatverlauf erscheinen.",
"description": ""
},
"prefsInfoDesc_2": {
"message": "Wenn eine weiße Seite erscheint, wenn das ChatGPT-Fenster geöffnet wird, bedeutet dies, dass es ein Problem beim Laden der ChatGPT-Seite gibt, das nicht mit der Verwendung dieses Add-Ons zusammenhängt.",
"description": ""
},
"prefsInfoDesc_3": {
"message": " ",
"description": ""
},
"prefsDonation_1": {
"message": "Gefällt Ihnen dieses Addon?",
"description": ""
},
"prefsDonation_2": {
"message": "Überlegen Sie, eine Spende zu machen!",
"description": ""
},
"backToOptionsText": {
"message": "Optionen",
"description": ""
}
}

View file

@ -54,6 +54,186 @@
"description": ""
},
"customPrompts_managePrompts": {
"message": "Manage Prompts",
"description": ""
},
"customPrompts_managePrompts_help": {
"message": "More info",
"description": ""
},
"customPrompts_start_saving": {
"message": "Saving prompts...",
"description": ""
},
"customPrompts_reindexing_list": {
"message": "Reindexing list...",
"description": ""
},
"customPrompts_filtering_prompts": {
"message": "Filtering prompts...",
"description": ""
},
"customPrompts_saving_default_prompts": {
"message": "Saving default prompts...",
"description": ""
},
"customPrompts_saving_custom_prompts": {
"message": "Saving custom prompts...",
"description": ""
},
"customPrompts_reloading_menus": {
"message": "Reloading menus...",
"description": ""
},
"customPrompts_saved": {
"message": "Prompts saved!",
"description": ""
},
"customPrompts_form_label_ID": {
"message": "ID",
"description": ""
},
"customPrompts_form_label_ID_rules": {
"message": "Must be unique, lowercase and without spaces",
"description": ""
},
"customPrompts_form_label_Name": {
"message": "Name",
"description": ""
},
"customPrompts_form_label_Text": {
"message": "Prompt Text",
"description": ""
},
"customPrompts_form_label_Action": {
"message": "Action",
"description": ""
},
"customPrompts_form_label_need_selected": {
"message": "Text selection needed",
"description": ""
},
"customPrompts_form_label_need_signature": {
"message": "Always add the signature",
"description": ""
},
"customPrompts_form_label_need_custom_text": {
"message": "Ask for additional text",
"description": ""
},
"customPrompts_form_label_enabled": {
"message": "Enabled",
"description": ""
},
"customPrompts_form_required_fields": {
"message": "Required fields",
"description": ""
},
"customPrompts_btnEdit": {
"message": "Edit",
"description": ""
},
"customPrompts_btnCancel": {
"message": "Cancel",
"description": ""
},
"customPrompts_btnOK": {
"message": "OK",
"description": ""
},
"customPrompts_btnDelete": {
"message": "Delete",
"description": ""
},
"customPrompts_btnDelete_confirmText": {
"message": "Are you sure you want to delete this item?",
"description": ""
},
"customPrompts_unsaved_changes": {
"message": "There are unsaved changes!",
"description": ""
},
"customPrompts_btnSaveAll": {
"message": "Save All",
"description": ""
},
"customPrompts_save_button": {
"message": "Save",
"description": ""
},
"customPrompts_btnNew": {
"message": "Add New",
"description": ""
},
"customPrompts_btnAddNewCommit": {
"message": "Add the Prompt",
"description": ""
},
"customPrompts_add_to_menu": {
"message": "Add to menu",
"description": ""
},
"customPrompts_add_to_menu_always": {
"message": "Always",
"description": ""
},
"customPrompts_add_to_menu_reading": {
"message": "Reading an email",
"description": ""
},
"customPrompts_add_to_menu_composing": {
"message": "Composing an email",
"description": ""
},
"customPrompts_close_button": {
"message": "Close button",
"description": ""
},
"customPrompts_do_reply": {
"message": "Do reply",
"description": ""
},
"customPrompts_substitute_text": {
"message": "Substitute text",
"description": ""
},
"chatgpt_win_working": {
"message": "Work in progress...",
"description": ""
@ -74,6 +254,16 @@
"description": ""
},
"chatgpt_textarea_not_found_error": {
"message": "There is an error sending the prompt to ChatGPT, please retry. If the problem persists, please <a href=\"https://micz.it/thunderdbird-addon-thunderai/status/\">check the service status</a>.",
"description": ""
},
"chatgpt_sendbutton_not_found_error": {
"message": "Click the send button to submit the prompt.",
"description": ""
},
"chatgpt_user_not_logged_in": {
"message": "You are not logged in to ChatGPT. Please log in with your credentials, close the ChatGPT window, and then repeat the action you attempted. You will remain logged in afterwards.",
"description": ""
@ -84,6 +274,16 @@
"description": ""
},
"chatgpt_win_custom_text": {
"message": "Insert here the additional text for the prompt.",
"description": ""
},
"chatgpt_win_send": {
"message": "Send",
"description": ""
},
"chatgpt_use_gpt35": {
"message": "Use GPT3.5",
"description": ""
@ -164,6 +364,11 @@
"description": ""
},
"prefs_OptionText_btnManagePrompts": {
"message": "Manage your prompts",
"description": ""
},
"prefsInfoTitle": {
"message": "Important Information",
"description": ""

407
_locales/fr/messages.json Normal file
View file

@ -0,0 +1,407 @@
{
"extensionDescription": {
"message": "Utilisez ChatGPT pour améliorer vos emails!",
"description": "Description de l'extension."
},
"menu_title": {
"message": "IA",
"description": ""
},
"prompt_lang": {
"message": "Répondre en ",
"description": ""
},
"prompt_reply": {
"message": "Répondre à ceci",
"description": ""
},
"prompt_rewrite_polite": {
"message": "Réécrire de manière polie",
"description": ""
},
"prompt_rewrite_formal": {
"message": "Réécrire de manière formelle",
"description": ""
},
"prompt_classify": {
"message": "Classer",
"description": ""
},
"prompt_summarize_this": {
"message": "Résumer ceci",
"description": ""
},
"prompt_translate_this": {
"message": "Traduire ceci",
"description": ""
},
"prompt_this": {
"message": "Proposer ceci",
"description": ""
},
"prompt_selection_needed": {
"message": "Pour continuer, vous devez sélectionner du texte!",
"description": ""
},
"customPrompts_managePrompts": {
"message": "Gérer les prompts",
"description": ""
},
"customPrompts_managePrompts_help": {
"message": "Informations",
"description": ""
},
"customPrompts_start_saving": {
"message": "Enregistrement des prompts...",
"description": ""
},
"customPrompts_reindexing_list": {
"message": "Réindexation de la liste...",
"description": ""
},
"customPrompts_filtering_prompts": {
"message": "Filtrage des prompts...",
"description": ""
},
"customPrompts_saving_default_prompts": {
"message": "Enregistrement des prompts par défaut...",
"description": ""
},
"customPrompts_saving_custom_prompts": {
"message": "Enregistrement des prompts personnalisées...",
"description": ""
},
"customPrompts_reloading_menus": {
"message": "Rechargement des menus...",
"description": ""
},
"customPrompts_saved": {
"message": "prompts enregistrées!",
"description": ""
},
"customPrompts_form_label_ID": {
"message": "ID",
"description": ""
},
"customPrompts_form_label_ID_rules": {
"message": "Doit être unique, en minuscules et sans espaces",
"description": ""
},
"customPrompts_form_label_Name": {
"message": "Nom",
"description": ""
},
"customPrompts_form_label_Text": {
"message": "Texte de la proposition",
"description": ""
},
"customPrompts_form_label_Action": {
"message": "Action",
"description": ""
},
"customPrompts_form_label_need_selected": {
"message": "Sélection de texte nécessaire",
"description": ""
},
"customPrompts_form_label_need_signature": {
"message": "Toujours ajouter la signature",
"description": ""
},
"customPrompts_form_label_need_custom_text": {
"message": "Demander du texte supplémentaire",
"description": ""
},
"customPrompts_form_label_enabled": {
"message": "Activé",
"description": ""
},
"customPrompts_form_required_fields": {
"message": "Champs obligatoires",
"description": ""
},
"customPrompts_btnEdit": {
"message": "Modifier",
"description": ""
},
"customPrompts_btnCancel": {
"message": "Annuler",
"description": ""
},
"customPrompts_btnOK": {
"message": "OK",
"description": ""
},
"customPrompts_btnDelete": {
"message": "Supprimer",
"description": ""
},
"customPrompts_btnDelete_confirmText": {
"message": "Êtes-vous sûr de vouloir supprimer cet élément?",
"description": ""
},
"customPrompts_unsaved_changes": {
"message": "Il y a des modifications non enregistrées!",
"description": ""
},
"customPrompts_btnSaveAll": {
"message": "Tout enregistrer",
"description": ""
},
"customPrompts_save_button": {
"message": "Enregistrer",
"description": ""
},
"customPrompts_btnNew": {
"message": "Ajouter nouveau",
"description": ""
},
"customPrompts_btnAddNewCommit": {
"message": "Ajouter la proposition",
"description": ""
},
"customPrompts_add_to_menu": {
"message": "Ajouter au menu",
"description": ""
},
"customPrompts_add_to_menu_always": {
"message": "Toujours",
"description": ""
},
"customPrompts_add_to_menu_reading": {
"message": "Lors de la lecture d'un email",
"description": ""
},
"customPrompts_add_to_menu_composing": {
"message": "Lors de la rédaction d'un email",
"description": ""
},
"customPrompts_close_button": {
"message": "Bouton de fermeture",
"description": ""
},
"customPrompts_do_reply": {
"message": "Faire une réponse",
"description": ""
},
"customPrompts_substitute_text": {
"message": "Remplacer le texte",
"description": ""
},
"chatgpt_win_working": {
"message": "Travail en cours...",
"description": ""
},
"chatgpt_win_job_completed": {
"message": "Terminé!",
"description": ""
},
"chatgpt_win_get_answer": {
"message": "Utiliser la dernière réponse",
"description": ""
},
"chatgpt_win_close": {
"message": "Fermer",
"description": ""
},
"chatgpt_textarea_not_found_error": {
"message": "Il y a une erreur lors de l'envoi de la proposition à ChatGPT, veuillez réessayer. Si le problème persiste, veuillez <a href=\"https://micz.it/thunderdbird-addon-thunderai/status/\">vérifier le statut du service</a>.",
"description": ""
},
"chatgpt_sendbutton_not_found_error": {
"message": "Cliquez sur le bouton d'envoi pour soumettre la proposition.",
"description": ""
},
"chatgpt_user_not_logged_in": {
"message": "Vous n'êtes pas connecté à ChatGPT. Veuillez vous connecter avec vos identifiants, fermer la fenêtre ChatGPT, puis répéter l'action que vous avez tentée. Vous resterez connecté par la suite.",
"description": ""
},
"chatgpt_win_model_warning": {
"message": "Vous avez choisi l'option d'utiliser ChatGPT-4, mais il semble qu'il ne se charge pas correctement. Avez-vous choisi le bon modèle en haut?",
"description": ""
},
"chatgpt_win_custom_text": {
"message": "Insérez ici le texte supplémentaire pour la proposition.",
"description": ""
},
"chatgpt_win_send": {
"message": "Envoyer",
"description": ""
},
"chatgpt_use_gpt35": {
"message": "Utiliser GPT3.5",
"description": ""
},
"chatgpt_force_completion": {
"message": "forcer l'achèvement",
"description": ""
},
"chatgpt_force_completion_title": {
"message": "Cliquez ici pour afficher le bouton 'Utiliser la dernière réponse' si ChatGPT a terminé son travail mais que le bouton n'est pas apparu.",
"description": ""
},
"msg_prompt_too_long": {
"message": "Le texte que vous avez fourni est trop long. Vous devez le réduire pour utiliser ChatGPT.",
"description": ""
},
"prefs_OptionText_release_notes": {
"message": "Notes de version",
"description": ""
},
"prefs_status_page": {
"message": "statut du service",
"description": ""
},
"prefs_OptionText_chatgpt_win_text": {
"message": "Dimensions de la fenêtre ChatGPT",
"description": ""
},
"prefs_OptionText_chatgpt_win_height": {
"message": "Hauteur",
"description": ""
},
"prefs_OptionText_chatgpt_win_width": {
"message": "Largeur",
"description": ""
},
"prefs_OptionText_default_sign_name": {
"message": "Nom de la signature par défaut",
"description": ""
},
"prefs_OptionText_default_chatgpt_lang": {
"message": "Langue par défaut pour les réponses de ChatGPT",
"description": ""
},
"prefs_OptionText_reply_all": {
"message": "Répondre à tous",
"description": ""
},
"prefs_OptionText_reply_sender": {
"message": "Répondre à l'expéditeur",
"description": ""
},
"prefs_OptionText_reply_type": {
"message": "Type de réponse",
"description": ""
},
"prefs_OptionText_chatpgt_use_gpt4": {
"message": "Utiliser ChatGPT-4",
"description": ""
},
"prefs_OptionText_chatpgt_use_gpt4_info": {
"message": "Après avoir changé cette option, vous devez choisir le bon modèle la première fois que vous l'utilisez.",
"description": ""
},
"prefs_OptionText_btnManagePrompts": {
"message": "Gérer vos prompts",
"description": ""
},
"prefsInfoTitle": {
"message": "Informations importantes",
"description": ""
},
"prefsInfoDesc_1": {
"message": "Il n'est plus possible de désactiver l'historique des chats ChatGPT. Par conséquent, il n'y a aucun moyen d'empêcher les demandes effectuées via cet addon d'apparaître dans l'historique de vos chats ChatGPT.",
"description": ""
},
"prefsInfoDesc_2": {
"message": "Si une page blanche apparaît lors de l'ouverture de la fenêtre ChatGPT, cela signifie qu'il y a un problème de chargement de la page ChatGPT, non lié à l'utilisation de cet addon.",
"description": ""
},
"prefsInfoDesc_3": {
"message": " ",
"description": ""
},
"prefsDonation_1": {
"message": "Aimez-vous cet addon?",
"description": ""
},
"prefsDonation_2": {
"message": "Envisagez de faire un don!",
"description": ""
},
"backToOptionsText": {
"message": "Options",
"description": ""
}
}

View file

@ -1,201 +1,326 @@
{
"extensionDescription": {
"message": "Usa ChatGPT per migliorare le tue email!",
"description": "Descrizione dell'estensione."
"description": "Description of the extension."
},
"menu_title": {
"message": "IA",
"description": ""
},
"prompt_lang": {
"message": "Rispondi in ",
"description": ""
},
"prompt_reply": {
"message": "Rispondi",
"description": ""
},
"prompt_rewrite_polite": {
"message": "Riscrivi cortese",
"description": ""
},
"prompt_rewrite_formal": {
"message": "Riscrivi formale",
"description": ""
},
"prompt_classify": {
"message": "Classifica",
"description": ""
},
"prompt_summarize_this": {
"message": "Riassumi",
"description": ""
},
"prompt_translate_this": {
"message": "Traduci",
"description": ""
},
"prompt_this": {
"message": "Chedi a ChatGPT",
"description": ""
},
"prompt_selection_needed": {
"message": "Per procedere è necessario che selezioni del testo!",
"description": ""
},
"customPrompts_managePrompts": {
"message": "Gestisci i prompt",
"description": ""
},
"customPrompts_managePrompts_help": {
"message": "Informazioni",
"description": ""
},
"customPrompts_start_saving": {
"message": "Salvataggio prompt in corso...",
"description": ""
},
"customPrompts_reindexing_list": {
"message": "Indicizzazione lista...",
"description": ""
},
"customPrompts_filtering_prompts": {
"message": "Applicazione filtro in corso...",
"description": ""
},
"customPrompts_saving_default_prompts": {
"message": "Salvataggio prompt di base...",
"description": ""
},
"customPrompts_saving_custom_prompts": {
"message": "Salvataggio prompt personalizzati...",
"description": ""
},
"customPrompts_reloading_menus": {
"message": "Caricamento menu aggiornati...",
"description": ""
},
"customPrompts_saved": {
"message": "Prompt salvati!",
"description": ""
},
"customPrompts_form_label_ID": {
"message": "ID",
"description": ""
},
"customPrompts_form_label_ID_rules": {
"message": "Deve essere univoco, minuscolo e senza spazi.",
"description": ""
},
"customPrompts_form_label_Name": {
"message": "Nome",
"description": ""
},
"customPrompts_form_label_Text": {
"message": "Testo del prompt",
"description": ""
},
"customPrompts_form_label_Action": {
"message": "Azione",
"description": ""
},
"customPrompts_form_label_need_selected": {
"message": "Necessaria la selezione di testo",
"description": ""
},
"customPrompts_form_label_need_signature": {
"message": "Aggiungi sempre la firma",
"description": ""
},
"customPrompts_form_label_need_custom_text": {
"message": "Chiedi un testo aggiuntivo",
"description": ""
},
"customPrompts_form_label_enabled": {
"message": "Attivo",
"description": ""
},
"customPrompts_form_required_fields": {
"message": "Campi obbligatori",
"description": ""
},
"customPrompts_btnEdit": {
"message": "Modifica",
"description": ""
},
"customPrompts_btnCancel": {
"message": "Annulla",
"description": ""
},
"customPrompts_btnOK": {
"message": "OK",
"description": ""
},
"customPrompts_btnDelete": {
"message": "Cancella",
"description": ""
},
"customPrompts_btnDelete_confirmText": {
"message": "Sei sicuro di voler cancellare questo elemento?",
"description": ""
},
"customPrompts_unsaved_changes": {
"message": "Ci sono modifiche non salvate!",
"description": ""
},
"customPrompts_btnSaveAll": {
"message": "Salva Tutto",
"description": ""
},
"customPrompts_save_button": {
"message": "Salva",
"description": ""
},
"customPrompts_btnNew": {
"message": "Aggiungi Nuovo",
"description": ""
},
"customPrompts_btnAddNewCommit": {
"message": "Aggiungi il Prompt",
"description": ""
},
"customPrompts_add_to_menu": {
"message": "Aggiungi al menu",
"description": ""
},
"customPrompts_add_to_menu_always": {
"message": "Sempre",
"description": ""
},
"customPrompts_add_to_menu_reading": {
"message": "In lettura di una mail",
"description": ""
},
"customPrompts_add_to_menu_composing": {
"message": "In composizione di una mail",
"description": ""
},
"customPrompts_close_button": {
"message": "Pulsante chiudi",
"description": ""
},
"customPrompts_do_reply": {
"message": "Rispondi",
"description": ""
},
"customPrompts_substitute_text": {
"message": "Sostituisci il testo",
"description": ""
},
"chatgpt_win_working": {
"message": "Elaborazione in corso...",
"description": ""
},
"chatgpt_win_job_completed": {
"message": "Completato!",
"description": ""
},
"chatgpt_win_get_answer": {
"message": "Usa l'ultima risposta",
"description": ""
},
"chatgpt_win_close": {
"message": "Chiudi",
"description": ""
},
"chatgpt_user_not_logged_in": {
"message": "Non sei connesso a ChatGPT. Effettua l'accesso con le tue credenziali, chiudi la finestra di ChatGPT e poi ripeti l'azione che avevi tentato. Rimarrai connesso in seguito.",
"description": ""
},
"chatgpt_win_model_warning": {
"message": "Hai impostato l'opzione per utilizzare ChatGPT-4, ma sembra che non si stia caricando. Hai selezionato correttamente il modello in alto?",
"description": ""
},
"chatgpt_win_custom_text": {
"message": "Inserisci qui il testo aggiuntivo per il prompt.",
"description": ""
},
"chatgpt_win_send": {
"message": "Invia",
"description": ""
},
"chatgpt_use_gpt35": {
"message": "Usa GPT3.5",
"description": ""
},
"chatgpt_force_completion": {
"message": "forza il completamento",
"description": ""
},
"chatgpt_force_completion_title": {
"message": "Fai clic qui per visualizzare il pulsante 'Usa l'ultima risposta' se ChatGPT ha terminato il suo lavoro ma il pulsante non è apparso.",
"description": ""
},
"msg_prompt_too_long": {
"message": "Il testo che vuoi inviare a ChatGPT è troppo lungo. Devi ridurlo per poter procedere.",
"description": ""
},
"prefs_OptionText_release_notes": {
"message": "Note di rilascio",
"description": ""
},
"prefs_status_page": {
"message": "stato del servizio",
"description": ""
},
"prefs_OptionText_chatgpt_win_text": {
"message": "Dimensioni della finestra di ChatGPT",
"description": ""
},
"prefs_OptionText_chatgpt_win_height": {
"message": "Altezza",
"description": ""
},
"prefs_OptionText_chatgpt_win_width": {
"message": "Larghezza",
"description": ""
},
"chatgpt_textarea_not_found_error": {
"message": "C'è stato un errore nell'invio del prompt a ChatGPT, per favore riprova. Se il problema persiste, per favore <a href=\"https://micz.it/thunderdbird-addon-thunderai/status/\">controlla lo stato del servizio</a>.",
"description": ""
},
"chatgpt_sendbutton_not_found_error": {
"message": "Premi il pulsante per inviare il prompt a ChatGPT.",
"description": ""
},
"prefs_OptionText_default_sign_name": {
"message": "Nome da utilizzare per la firma",
"description": ""
},
"prefs_OptionText_default_chatgpt_lang": {
"message": "Lingua predefinita per le risposte di ChatGPT",
"description": ""
},
"prefs_OptionText_reply_all": {
"message": "Rispondi a tutti",
"description": ""
},
"prefs_OptionText_reply_sender": {
"message": "Rispondi al mittente",
"description": ""
},
"prefs_OptionText_reply_type": {
"message": "Modalità di risposta",
"description": ""
},
"prefs_OptionText_chatpgt_use_gpt4": {
"message": "Usa il modello ChatGPT-4",
"description": ""
},
"prefs_OptionText_chatpgt_use_gpt4_info": {
"message": "Dopo aver modificato questa opzione, devi scegliere il modello corretto la prima volta che lo usi.",
"description": ""
},
"prefs_OptionText_btnManagePrompts": {
"message": "Gestisci i tuoi prompts",
"description": ""
},
"prefsInfoTitle": {
"message": "Informazioni Importanti",
"description": ""
},
"prefsInfoDesc_1": {
"message": "Non è più possibile disabilitare la cronologia delle chat di ChatGPT. Pertanto, non c'è modo di impedire che le richieste effettuate tramite questo componente aggiuntivo appaiano nella cronologia delle chat di ChatGPT.",
"description": ""
},
"prefsInfoDesc_2": {
"message": "Se all'apertura della finestra di ChatGPT, viene mostrata una pagina bianca, significa che c'è un problema di caricamento della pagina di ChatGPT, non relativo all'utilizzo di questo componente aggiuntivo.",
"description": ""
},
"prefsInfoDesc_3": {
"message": " ",
"description": ""
},
"prefsDonation_1": {
"message": "Ti piace questo componente aggiuntivo?",
"description": ""
},
"prefsDonation_2": {
"message": "Considera di fare una donazione!",
"description": ""
},
"backToOptionsText": {
"message": "Opzioni",
"description": ""
}
}
}

2020
customprompts/list.js Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,172 @@
@media (prefers-color-scheme: light) {
table th {
background-color: #ffffff;
}
#command_palette{
background-color: #ffffff;
}
table.prompts_list tr:nth-child(even) {
background-color: #e9e9e9;
}
table.prompts_list tr:nth-child(odd) {
background-color: #f3f3f3;
}
}
@media (prefers-color-scheme: dark) {
body {
background-color: #1C1B22;
color: rgb(251, 251, 254);
}
a:link { color: #409EFF; }
a:visited { color: #409EFF; }
a:hover { color: #66B1FF; }
a:active { color: #66B1FF; }
table {
background-color: #1C1B22;
border: 1px solid #ccc;
}
table.prompts_list th {
background-color: #4c4e58;
border: 1px solid rgb(251, 251, 254);
color: rgb(194, 194, 194);
}
#command_palette{
background-color: inherit;
}
table.prompts_list tr:nth-child(even) {
background-color: #2E2F36;
}
}
table {
border-collapse: collapse;
border-spacing: 0;
border: 1px solid #ccc;
}
thead {
position: sticky;
top: 26px;
}
#command_palette{
position: sticky;
top: 0;
padding-top: 1px;
height: 26px;
width: 100%;
}
#btnNew{
float: right;
}
#btnSaveAll{
float: left;
}
#msgDisplay{
padding-left: 40px;
}
table tr {
border-bottom: 1px solid #ccc;
}
table.prompts_list th {
padding: 8px;
text-align: left;
}
table td {
border: 1px solid #ddd;
padding: 8px;
}
table td.w08{
width: 8vw;
}
table td.w17{
width: 17vw;
}
table td.w19{
width: 19vw;
}
table td.w25{
width: 25vw;
}
table td.w40{
width: 40vw;
}
table.prompts_list td.properties{
white-space: nowrap;
}
table .sort {
background-image: url(../images/listjs-arrow-sort-inactive.png);
background-repeat: no-repeat;
background-position: right center;
padding-right: 14px;
cursor: pointer;
cursor: hand;
}
table .sort.asc {
background-image: url(../images/listjs-arrow-sort-active-down.png);
}
table .sort.desc {
background-image: url(../images/listjs-arrow-sort-active-up.png);
}
.hiddendata{
display: none;
}
#formNew{
display: none;
width: 100%;
padding-bottom: 7px;
}
.text_output{
width: 98%;
height: 9em;
}
.go_right_float{
float: right;
}
.go_right{
width: 100%;
text-align: right;
}
.width_all{
width: 100%;
}
.small_label{
font-size: small;
font-style: italic;
}
#txtIdNew, .id_output{
text-transform: lowercase;
}

View file

@ -0,0 +1,91 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>ThunderAI - __MSG_customPrompts_managePrompts__</title>
<link rel="stylesheet" href="mzta-custom-prompts.css">
</head>
<body>
<div>
<h1>__MSG_customPrompts_managePrompts__</h1>
<p><a href="https://micz.it/thunderdbird-addon-thunderai/custom-prompts/">__MSG_customPrompts_managePrompts_help__</a></p>
</div>
<div id="command_palette">
<button id="btnSaveAll" disabled>__MSG_customPrompts_btnSaveAll__</button>
<span id="msgDisplay"></span>
<button id="btnNew">__MSG_customPrompts_btnNew__</button>
</div>
<div id="formNew">
<table class="width_all">
<tr>
<td class="w19">
<label for="txtIdNew">*__MSG_customPrompts_form_label_ID__:</label>
<br>
<input type="text" id="txtIdNew" name="id" class="input_new" tabindex="1">
<br><span class="small_label">[__MSG_customPrompts_form_label_ID_rules__]</span>
</td>
<td rowspan="2" class="w25">
<label for="txtTextNew">*__MSG_customPrompts_form_label_Text__:</label>
<br>
<textarea id="txtTextNew" name="text" class="input_new text_output" tabindex="3"></textarea>
</td>
<td class="w19">
<label for="selectTypeNew">__MSG_customPrompts_add_to_menu__:</label>
<br>
<select id="selectTypeNew" name="type" tabindex="4">
<option value="0">__MSG_customPrompts_add_to_menu_always__</option>
<option value="1">__MSG_customPrompts_add_to_menu_reading__</option>
<option value="2">__MSG_customPrompts_add_to_menu_composing__</option>
</select>
</td>
<td rowspan="2" class="w19">
<input type="checkbox" id="checkboxNeedSelectedNew" name="need_selected" value="1" tabindex="6"> <label for="checkboxNeedSelectedNew">__MSG_customPrompts_form_label_need_selected__</label>
<br>
<input type="checkbox" id="checkboxNeedSignatureNew" name="need_signature" value="1" tabindex="7"> <label for="checkboxNeedSignatureNew">__MSG_customPrompts_form_label_need_signature__</label>
<br>
<input type="checkbox" id="checkboxNeedCustomTextNew" name="need_custom_text" value="1" tabindex="8"> <label for="checkboxNeedCustomTextNew">__MSG_customPrompts_form_label_need_custom_text__</label>
</td>
</tr>
<tr>
<td class="w19">
<label for="txtNameNew">*__MSG_customPrompts_form_label_Name__:</label>
<br>
<input type="text" id="txtNameNew" name="name" class="input_new" tabindex="2">
</td>
<td class="w19">
<label for="selectActionNew">__MSG_customPrompts_form_label_Action__:</label>
<br>
<select id="selectActionNew" name="action" tabindex="5">
<option value="0">__MSG_customPrompts_close_button__</option>
<option value="1">__MSG_customPrompts_do_reply__</option>
<option value="2">__MSG_customPrompts_substitute_text__</option>
</select>
</td>
</tr>
</table>
<div class="go_right_float">* __MSG_customPrompts_form_required_fields__</div>
<br>
<div class="go_right"><button id="btnAddNew" disabled>__MSG_customPrompts_btnAddNewCommit__</button></div>
</div>
<div id="all_prompts">
<table class="prompts_list">
<thead>
<tr>
<th class="sort" data-sort="id">__MSG_customPrompts_form_label_ID__</th>
<th class="sort" data-sort="name">__MSG_customPrompts_form_label_Name__</th>
<th class="sort" data-sort="text">__MSG_customPrompts_form_label_Text__</th>
<th class="sort" data-sort="type">__MSG_customPrompts_add_to_menu__</th>
<th>Properties</th>
<th>__MSG_customPrompts_form_label_Action__</th>
</tr>
</thead>
<tbody class="list">
</tbody>
</table>
</div>
<script src="list.js"></script>
<script src="mzta-custom-prompts.js" type="module"></script>
<script src="../js/mzta-i18n.js"></script>
</body>
</html>

View file

@ -0,0 +1,525 @@
/*
* ThunderAI [https://micz.it/thunderdbird-addon-thunderai/]
* Copyright (C) 2024 Mic (m@micz.it)
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { getPrompts, setDefaultPromptsProperties, setCustomPrompts } from "../js/mzta-prompts.js";
var promptsList = null;
var somethingChanged = false;
var positionMax_compose = 0;
var positionMax_display = 0;
var idnumMax = 0;
var msgTimeout = null;
document.addEventListener('DOMContentLoaded', async () => {
let options = {
valueNames: [ { data: ['idnum'] }, 'is_default', 'id', 'name', 'text', 'type', 'action', 'position_compose', 'position_display', { name: 'need_selected', attr: 'checked_val'}, { name: 'need_signature', attr: 'checked_val'}, { name: 'need_custom_text', attr: 'checked_val'}, { name: 'enabled', attr: 'checked_val'} ],
item: function(values) {
let type_output = '';
switch(String(values.type)){
case "0":
type_output = `__MSG_customPrompts_add_to_menu_always__`;
break;
case "1":
type_output = `__MSG_customPrompts_add_to_menu_reading__`;
break;
case "2":
type_output = `__MSG_customPrompts_add_to_menu_composing__`;
break;
}
let action_output = '';
switch(String(values.action)){
case "0":
action_output = `__MSG_customPrompts_close_button__`;
break;
case "1":
action_output = `__MSG_customPrompts_do_reply__`;
break;
case "2":
action_output = `__MSG_customPrompts_substitute_text__`;
break;
}
//console.log('>>>>>>>>>>>>> action_output: ' + JSON.stringify(action_output));
let output = `<tr ` + ((values.is_default == 1) ? 'class="is_default"':'') + `>
<td class="w08"><span class="id id_show"></span><input type="text" class="hiddendata id_output" value="` + values.id + `" /></td>
<td class="w08"><span class="name name_show"></span><input type="text" class="hiddendata name_output" value="` + values.name + `" /></td>
<td class="w40"><span class="text text_show"></span><textarea class="hiddendata text_output">` + values.text + `</textarea></td>
<td class="w08"><span class="type_show">` + type_output + `</span>
<select class="type_output hiddendata">
<option value="0"` + ((values.type == "0") ? ' selected':'') + `>__MSG_customPrompts_add_to_menu_always__</option>
<option value="1"` + ((values.type == "1") ? ' selected':'') + `>__MSG_customPrompts_add_to_menu_reading__</option>
<option value="2"` + ((values.type == "2") ? ' selected':'') + `>__MSG_customPrompts_add_to_menu_composing__</option>
</select>` +
`<span class="type hiddendata"></span>
</td>
<td class="w17">
Action: <span class="action_show">` + action_output + `</span>
<select class="action_output hiddendata">
<option value="0"` + ((values.action == "0") ? ' selected':'') + `>__MSG_customPrompts_close_button__</option>
<option value="1"` + ((values.action == "1") ? ' selected':'') + `>__MSG_customPrompts_do_reply__</option>
<option value="2"` + ((values.action == "2") ? ' selected':'') + `>__MSG_customPrompts_substitute_text__</option>
</select>` +
`<span class="action hiddendata"></span>
<br>
<input type="checkbox" class="need_selected" disabled> __MSG_customPrompts_form_label_need_selected__
<br>
<input type="checkbox" class="need_signature" disabled> __MSG_customPrompts_form_label_need_signature__
<br>
<input type="checkbox" class="need_custom_text" disabled> __MSG_customPrompts_form_label_need_custom_text__
<br>
<input type="checkbox" class="enabled input_mod"> __MSG_customPrompts_form_label_enabled__
<span class="is_default hiddendata"></span>
<span class="position_compose hiddendata"></span>
<span class="position_display hiddendata"></span>
</td>
<td>
<button class="btnEditItem"` + ((values.is_default == 1) ? ' disabled':'') + `>__MSG_customPrompts_btnEdit__</button>
<button class="btnCancelItem hiddendata"` + ((values.is_default == 1) ? ' disabled':'') + `>__MSG_customPrompts_btnCancel__</button>
<br><br>
<button class="btnConfirmItem hiddendata"` + ((values.is_default == 1) ? ' disabled':'') + `>__MSG_customPrompts_btnOK__</button>
<button class="btnDeleteItem"` + ((values.is_default == 1) ? ' disabled':'') + `>__MSG_customPrompts_btnDelete__</button>
</td>
</tr>`;
//console.log('>>>>>>>> values.name: ' + JSON.stringify(values.name));
positionMax_compose = Math.max(positionMax_compose, values.position_compose);
positionMax_display = Math.max(positionMax_display, values.position_display);
idnumMax = Math.max(idnumMax, values.idnum);
return output;
}
};
let values = await getPrompts();
//console.log('>>>>>>>>>>>>>>>> values: ' + JSON.stringify(values));
promptsList = new List('all_prompts', options, values);
checkSelectedBoxes();
const btnSaveAll = document.getElementById('btnSaveAll');
btnSaveAll.disabled = true;
// Disable save button and handle save actions
function handleSaveAllClick(e) {
e.preventDefault();
saveAll();
clearFields();
}
btnSaveAll.addEventListener('click', handleSaveAllClick);
const btnNew = document.getElementById('btnNew');
// Show the new item form
function handleNewClick(e) {
e.preventDefault();
e.target.disabled = true;
document.getElementById('formNew').style.display = 'block';
window.scrollTo({
top: 0,
behavior: 'smooth'
});
}
btnNew.addEventListener('click', handleNewClick);
// Enable save button on input change
function handleInputChange(e) {
e.preventDefault();
setSomethingChanged();
}
document.querySelectorAll('.input_mod').forEach(element => {
element.addEventListener('change', handleInputChange);
});
// Display selected value next to select input
// function handleSelectChange(e) {
// e.preventDefault();
// const spanElement = e.target.nextElementSibling;
// spanElement.textContent = e.target.value;
// }
// document.querySelectorAll('select.input_mod').forEach(element => {
// element.addEventListener('change', handleSelectChange);
// });
// Log data ID number from item row and prepare for edit action
function handleEditClick(e) {
e.preventDefault();
const tr = e.target.parentNode.parentNode;
//console.log('>>>>>>>> tr: ' + tr.getAttribute('data-idnum'));
e.target.style.display = 'none'; // Edit btn
tr.querySelector('.btnConfirmItem').style.display = 'inline'; // Save btn
tr.querySelector('.btnCancelItem').style.display = 'inline'; // Cancel btn
// tr.querySelector('.btnEditItem').style.display = 'none'; // Edit btn
tr.querySelector('.btnDeleteItem').style.display = 'none'; // Delete btn
showItemRowEditor(tr);
}
let btnEditItem_elements = document.querySelectorAll(".btnEditItem");
btnEditItem_elements.forEach(element => {
element.addEventListener('click', handleEditClick);
});
function showItemRowEditor(tr) {
tr.querySelector('.id_output').style.display = 'inline';
tr.querySelector('.id_show').style.display = 'none';
tr.querySelector('.name_output').style.display = 'inline';
tr.querySelector('.name_show').style.display = 'none';
tr.querySelector('.text_output').style.display = 'inline';
tr.querySelector('.text_show').style.display = 'none';
tr.querySelector('.type_output').style.display = 'inline';
tr.querySelector('.type_show').style.display = 'none';
tr.querySelector('.action_output').style.display = 'inline';
tr.querySelector('.action_show').style.display = 'none';
tr.querySelector('input.need_selected').disabled = false;
tr.querySelector('input.need_signature').disabled = false;
tr.querySelector('input.need_custom_text').disabled = false;
}
function hideItemRowEditor(tr) {
tr.querySelector('.id_output').style.display = 'none';
tr.querySelector('.id_show').style.display = 'inline';
tr.querySelector('.name_output').style.display = 'none';
tr.querySelector('.name_show').style.display = 'inline';
tr.querySelector('.text_output').style.display = 'none';
tr.querySelector('.text_show').style.display = 'inline';
tr.querySelector('.type_output').style.display = 'none';
tr.querySelector('.type_show').style.display = 'inline';
tr.querySelector('.action_output').style.display = 'none';
tr.querySelector('.action_show').style.display = 'inline';
tr.querySelector('input.need_selected').disabled = true;
tr.querySelector('input.need_signature').disabled = true;
tr.querySelector('input.need_custom_text').disabled = true;
}
// Confirm and log deletion action
function handleDeleteClick(e) {
e.preventDefault();
const checkConfirm = window.confirm(browser.i18n.getMessage("customPrompts_btnDelete_confirmText"));
if (!checkConfirm) {
return;
}
const tr = e.target.parentNode.parentNode;
//console.log('>>>>>>>> tr: ' + tr.getAttribute('data-idnum'));
promptsList.remove("id", tr.querySelector('span.id').innerText);
setSomethingChanged();
}
let btnDeleteItem_elements = document.querySelectorAll(".btnDeleteItem");
btnDeleteItem_elements.forEach(element => {
element.addEventListener('click', handleDeleteClick);
});
function handleCancelClick(e) {
e.preventDefault();
const tr = e.target.parentNode.parentNode;
e.target.style.display = 'none'; // Cancel btn
tr.querySelector('.btnConfirmItem').style.display = 'none'; // Save btn
// tr.querySelector('.btnCancelItem').style.display = 'none'; // Cancel btn
tr.querySelector('.btnEditItem').style.display = 'inline'; // Edit btn
tr.querySelector('.btnDeleteItem').style.display = 'inline'; // Delete btn
hideItemRowEditor(tr);
}
let btnCancelItem_elements = document.querySelectorAll(".btnCancelItem");
btnCancelItem_elements.forEach(element => {
element.addEventListener('click', handleCancelClick);
});
function handleConfirmClick(e) {
e.preventDefault();
const tr = e.target.parentNode.parentNode;
e.target.style.display = 'none'; // Ok btn
// tr.querySelector('.btnConfirmItem').style.display = 'none'; // Ok btn
tr.querySelector('.btnCancelItem').style.display = 'none'; // Cancel btn
tr.querySelector('.btnEditItem').style.display = 'inline'; // Edit btn
tr.querySelector('.btnDeleteItem').style.display = 'inline'; // Delete btn
// Update item data
tr.querySelector('.id_show').innerText = String(tr.querySelector('.id_output').value).toLocaleLowerCase();
tr.querySelector('.name_show').innerText = tr.querySelector('.name_output').value;
tr.querySelector('.text_show').innerText = tr.querySelector('.text_output').value;
tr.querySelector('.type').innerText = tr.querySelector('.type_output').value;
tr.querySelector('.type_show').innerText = tr.querySelector('.type_output').selectedOptions[0].text;
tr.querySelector('.action').innerText = tr.querySelector('.action_output').value;
tr.querySelector('.action_show').innerText = tr.querySelector('.action_output').selectedOptions[0].text;
// the checkboxes update is handled directly by themselves
hideItemRowEditor(tr);
setSomethingChanged();
}
let btnConfirmItem_elements = document.querySelectorAll(".btnConfirmItem");
btnConfirmItem_elements.forEach(element => {
element.addEventListener('click', handleConfirmClick);
});
// Handle checkbox changes and log new state
function handleCheckboxChange(e) {
e.preventDefault();
e.target.setAttribute('checked_val', e.target.checked ? '1' : '0');
//console.log('>>>>>>>> checked_val: ' + e.target.getAttribute('checked_val'));
}
let checkbox_elements = document.querySelectorAll("input[type='checkbox']");
checkbox_elements.forEach(element => {
element.addEventListener('change', handleCheckboxChange);
});
// Handle "type" select changes and log new state
// function handleTypeSelectChange(e) {
// e.preventDefault();
// const spanElement = e.target.nextElementSibling;
// spanElement.textContent = e.target.value;
// }
// let type_select_elements = document.querySelectorAll("select.type_output");
// type_select_elements.forEach(element => {
// element.addEventListener('change', handleTypeSelectChange);
// });
// Handle "action" select changes and log new state
// function handleActionSelectChange(e) {
// e.preventDefault();
// const spanElement = e.target.nextElementSibling;
// spanElement.textContent = e.target.value;
// }
// let action_select_elements = document.querySelectorAll("select.action_output");
// action_select_elements.forEach(element => {
// element.addEventListener('change', handleActionSelectChange);
// });
// for the new prompt form
let btnNew_elements = document.querySelectorAll(".input_new");
if(btnNew_elements) {
btnNew_elements.forEach(element => {
element.addEventListener('change', (e) => {
e.preventDefault();
checkFields();
});
});
}
i18n.updateDocument();
//To add a new item
var txtIdNew = document.getElementById('txtIdNew');
var txtNameNew = document.getElementById('txtNameNew');
var txtTextNew = document.getElementById('txtTextNew');
var selectTypeNew = document.getElementById('selectTypeNew');
var selectActionNew = document.getElementById('selectActionNew');
var checkboxNeedSelectedNew = document.getElementById('checkboxNeedSelectedNew');
var checkboxNeedSignatureNew = document.getElementById('checkboxNeedSignatureNew');
var checkboxNeedCustomTextNew = document.getElementById('checkboxNeedCustomTextNew');
const btnAddNew = document.getElementById('btnAddNew');
btnAddNew.addEventListener('click', (e) => {
e.preventDefault();
if(!checkFields()) {
return;
}
let newItem = promptsList.add({
id: String(txtIdNew.value.trim()).toLocaleLowerCase(),
name: txtNameNew.value.trim(),
text: txtTextNew.value.trim(),
type: selectTypeNew.value,
action: selectActionNew.value,
need_selected: (checkboxNeedSelectedNew.checked) ? 1 : 0,
need_signature: (checkboxNeedSignatureNew.checked) ? 1 : 0,
need_custom_text: (checkboxNeedCustomTextNew.checked) ? 1 : 0,
enabled: 1,
position_compose: positionMax_compose + 1,
position_display: positionMax_display + 1,
is_default: 0,
idnum: idnumMax + 1,
});
idnumMax++;
let curr_idnum = newItem[0].values().idnum;
let checkboxes = document.querySelectorAll(`tr[data-idnum="${curr_idnum}"] input[type="checkbox"]`);
checkSelectedBoxes(checkboxes);
let editBtn = document.querySelector(`tr[data-idnum="${curr_idnum}"] button.btnEditItem`);
//console.log(`>>>>>>>>>>>> tr[data-idnum="${curr_idnum}"] button.btnEditItem`);
editBtn.addEventListener('click', handleEditClick);
//console.log('>>>>>>>>>>>>> editBtn: ' + JSON.stringify(editBtn));
let deleteBtn = document.querySelector(`tr[data-idnum="${curr_idnum}"] button.btnDeleteItem`);
//console.log(`>>>>>>>>>>>> tr[data-idnum="${curr_idnum}"] button.btnDeleteItem`);
deleteBtn.addEventListener('click', handleDeleteClick);
let okBtn = document.querySelector(`tr[data-idnum="${curr_idnum}"] button.btnConfirmItem`);
okBtn.addEventListener('click', handleConfirmClick);
let cancelBtn = document.querySelector(`tr[data-idnum="${curr_idnum}"] button.btnCancelItem`);
cancelBtn.addEventListener('click', handleCancelClick);
// console.log('>>>>>>>>>>>>> deleteBtn: ' + JSON.stringify(deleteBtn));
// console.log('>>>>>>>>>>>>> newItem: ' + JSON.stringify(newItem));
document.getElementById('btnNew').disabled = false;
clearFields();
setSomethingChanged();
i18n.updateDocument();
window.scrollTo({
top: document.body.scrollHeight,
behavior: 'smooth'
});
});
}, { once: true });
function checkFields() {
//console.log('>>>>>>>>>>>>> typeof promptsList: ' + typeof promptsList);
//console.log('>>>>>>>>>>>>> Array.isArray(promptsList): ' + Array.isArray(promptsList));
// the id must be unique and without spaces
let is_error = false;
let id_value = document.getElementById('txtIdNew').value.trim();
if ((id_value == '')||
(/\s/.test(id_value))) {
inputSetError('txtIdNew');
is_error = true;
} else {
let exists = promptsList.get("id", id_value);
//console.log('>>>>>>>>>>>>> exists: ' + JSON.stringify(exists));
if(exists && exists.length > 0) {
inputSetError('txtIdNew');
is_error = true;
} else {
inputClearError('txtIdNew');
}
}
if (document.getElementById('txtNameNew').value.trim() == '') {
inputSetError('txtNameNew');
is_error = true;
} else {
inputClearError('txtNameNew');
}
if (document.getElementById('txtTextNew').value.trim() == '') {
inputSetError('txtTextNew');
is_error = true;
} else {
inputClearError('txtTextNew');
}
document.getElementById('btnAddNew').disabled = is_error;
return !is_error;
}
function clearFields() {
document.getElementById('txtIdNew').value = '';
document.getElementById('txtNameNew').value = '';
document.getElementById('txtTextNew').value = '';
document.getElementById('selectTypeNew').value = '0';
document.getElementById('selectActionNew').value = '0';
document.getElementById('checkboxNeedSelectedNew').value = '0';
document.getElementById('checkboxNeedSignatureNew').value = '0';
document.getElementById('checkboxNeedCustomTextNew').value = '0';
document.getElementById('formNew').style.display = 'none';
}
function inputSetError(input) {
document.getElementById(input).style.borderColor = 'red';
}
function inputClearError(input) {
document.getElementById(input).style.borderColor = 'green';
}
function setSomethingChanged(){
clearTimeout(msgTimeout);
somethingChanged = true;
document.getElementById('btnSaveAll').disabled = false;
let msgDisplay = document.getElementById('msgDisplay');
msgDisplay.innerHTML = browser.i18n.getMessage('customPrompts_unsaved_changes');
msgDisplay.style.display = 'inline';
msgDisplay.style.color = 'red';
}
function setNothingChanged(){
somethingChanged = false;
document.getElementById('btnSaveAll').disabled = true;
let msgDisplay = document.getElementById('msgDisplay');
msgDisplay.disabled = true;
msgDisplay.innerHTML = ''
msgDisplay.style.display = 'none';
msgDisplay.style.color = '';
}
function checkSelectedBoxes(checkboxes = null) {
if(checkboxes == null){
checkboxes = [
...document.querySelectorAll('.need_selected[type="checkbox"]'),
...document.querySelectorAll('.need_signature[type="checkbox"]'),
...document.querySelectorAll('.need_custom_text[type="checkbox"]'),
...document.querySelectorAll('.enabled[type="checkbox"]'),
];
}
// Iterate through the checkboxes
checkboxes.forEach(checkbox => {
// Check if the 'checked' attribute is "0"
if (checkbox.getAttribute('checked_val') == "0") {
// Uncheck the checkbox
checkbox.checked = false;
} else {
checkbox.checked = true;
}
});
}
//Save all prompts
async function saveAll() {
setMessage(browser.i18n.getMessage('customPrompts_start_saving'));
setNothingChanged();
if(promptsList != null) {
setMessage(browser.i18n.getMessage('customPrompts_reindexing_list'));
promptsList.reIndex();
let newPrompts = promptsList.items.map(item => {
// For each item in the array, return only the '_values' part
return item.values();
});
// newPrompts.forEach(prompt => {
// console.log('>>>>>>>>>>>>> id: ' + JSON.stringify(prompt));
// });
//console.log('>>>>>>>>>>>>> saveAll: ' + JSON.stringify(newPrompts));
setMessage(browser.i18n.getMessage('customPrompts_filtering_prompts'));
let newDefaultPrompts = newPrompts.filter(item => item.is_default == 1);
//console.log('>>>>>>>>>>>>> newDefaultPrompts: ' + JSON.stringify(newDefaultPrompts));
let newCustomPrompts = newPrompts.filter(item => item.is_default == 0);
setMessage(browser.i18n.getMessage('customPrompts_saving_default_prompts'));
await setDefaultPromptsProperties(newDefaultPrompts);
setMessage(browser.i18n.getMessage('customPrompts_saving_custom_prompts'));
await setCustomPrompts(newCustomPrompts);
setMessage(browser.i18n.getMessage('customPrompts_reloading_menus'));
browser.runtime.sendMessage({command: "reload_menus"});
setMessage(browser.i18n.getMessage('customPrompts_saved'),'green');
msgTimeout = setTimeout(() => {
clearMessage();
}, 10000)
}
}
function setMessage(msg, color = '') {
clearTimeout(msgTimeout);
let msgDisplay = document.getElementById('msgDisplay');
msgDisplay.innerHTML = msg;
msgDisplay.style.display = 'inline';
msgDisplay.style.color = color;
}
function clearMessage() {
let msgDisplay = document.getElementById('msgDisplay');
msgDisplay.innerHTML = '';
msgDisplay.style.display = 'none';
msgDisplay.style.color = '';
}
// window.addEventListener('beforeunload', function (event) {
// // Check if any changes have been made
// if (somethingChanged) {
// event.preventDefault();
// }
// });

Binary file not shown.

After

Width:  |  Height:  |  Size: 515 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 560 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 629 B

View file

@ -22,13 +22,22 @@
export const mzta_script = `
let force_go = false;
let current_message = null;
async function chatgpt_sendMsg(msg, method ='') {
async function chatgpt_sendMsg(msg, method ='') { // return -1 send button not found, -2 textarea not found
const textArea = document.querySelector('form textarea'),
sendButton = document.querySelector('path[d*="M15.192 8.906a1.143"]')?.parentNode.parentNode // post-GPT-4o;
|| document.querySelector('[data-testid="send-button"]'); // pre-GPT-4o
sendButton = document.querySelector('path[d*="M15.192 8.906a1.143"]')?.parentNode.parentNode // post-GPT-4o;
|| document.querySelector('[data-testid="send-button"]'); // pre-GPT-4o
//check if the textarea has been found
if(!textArea) {
return -2;
}
textArea.value = msg;
textArea.dispatchEvent(new Event('input', { bubbles: true })); // enable send button
//check if the sendbutton has been found
if (!sendButton) {
return -1;
}
const delaySend = setInterval(() => {
if (!sendButton?.hasAttribute('disabled')) { // send msg
method.toLowerCase() == 'click' ? sendButton.click()
@ -36,6 +45,7 @@ async function chatgpt_sendMsg(msg, method ='') {
clearInterval(delaySend);
}
}, 25);
return 0; //everything is ok
}
async function chatgpt_isIdle() {
@ -106,22 +116,27 @@ async function chatgpt_getFromDOM(pos) {
function chatpgt_scrollToBottom () {
try { document.querySelector('button[class*="cursor"][class*="bottom"]').click(); }
catch (err) { console.error('', err); }
catch (err) { console.error('[ThunderAI] ', err); }
}
function addCustomDiv(prompt_action,tabId) {
// Create <style> element for the CSS
var style = document.createElement('style');
style.innerHTML = ".mzta-header-fixed {position: fixed;bottom: 0;left: 0;height:100px;width: 100%;background-color: #333;color: white;text-align: center;padding: 10px 0;z-index: 1000;}"
style.innerHTML = ".mzta-header-fixed {position: fixed;bottom: 0;left: 0;height:100px;width: 100%;background-color: #333;color: white;text-align: center;padding: 10px 0;z-index: 1000;border-top: 3px solid white;}"
style.innerHTML += "body {padding-bottom: 100px;} [id^='headlessui-dialog-panel-:r']{padding-bottom: 100px;}";
style.innerHTML += "#mzta-btn_ok {background-color: #007bff;border: none;color: white;padding: 8px 15px;text-align: center;text-decoration: none;display: inline-block;font-size: 16px;margin: 4px 2px;transition-duration: 0.4s;cursor: pointer;border-radius: 5px;}";
style.innerHTML += "#mzta-btn_ok:hover {background-color: #0056b3;color: white;}";
style.innerHTML += ".mzta-btn {background-color: #007bff;border: none;color: white;padding: 8px 15px;text-align: center;text-decoration: none;display: inline-block;font-size: 16px;margin: 4px 2px;transition-duration: 0.4s;cursor: pointer;border-radius: 5px;}";
style.innerHTML += ".mzta-btn:hover {background-color:#0056b3;color:white;}";
style.innerHTML += "#mzta-loading{height:50px;display:inline-block;}";
style.innerHTML += "#mzta-model_warn{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);max-height:100%px;min-width:30%;max-width:50%;padding:3px;border-radius:5px;text-align:center;background-color:#FFBABA;border:1px solid;font-size:13px;color:#D8000C;display:none;}";
style.innerHTML += "#mzta-model_warn{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);max-height:100%px;min-width:30%;max-width:50%;padding:3px;border-radius:5px;text-align:center;background-color:#FFBABA;border:1px solid;font-size:13px;color:#D8000C;display:none;}#mzta-model_warn a{color:blue;text-decoration: underline;}";
style.innerHTML += "#mzta-btn_gpt35 {background-color: #007bff;border: none;color: white;padding: 2px 4px;text-align: center;text-decoration: none;display: none;font-size: 13px;margin-left: 4px;transition-duration: 0.4s;cursor: pointer;border-radius: 2px;}";
style.innerHTML += "#mzta-status-page{position:fixed;bottom:0;left:0;padding-left:5px;font-size:13px;font-style:italic;text-decoration:underline;color:#919191;}";
style.innerHTML += "#mzta-force-completion{cursor:pointer;position:fixed;bottom:0;right:0;padding-right:5px;font-size:13px;font-style:italic;text-decoration:underline;color:#919191;}";
style.innerHTML += "#mzta-status-page:hover, #mzta-force-completion:hover{color:#007bff;}";
style.innerHTML += "#mzta-custom_text{padding:10px;width:auto;max-width:80%;height:auto;max-height:80%;border-radius:5px;overflow:auto;position:fixed;top:50%;left:50%;display:none;transform:translate(-50%,-50%);text-align:center;background:#333;color:white;border:3px solid white;}";
style.innerHTML += "#mzta-custom_loading{height:50px;display:none;}";
style.innerHTML += "#mzta-custom_textarea{color:black;padding:1px;font-size:15px;width:100%;}";
style.innerHTML += "#mzta-custom_info{text-align:center;width:100%;padding-bottom:10px;font-size:15px;}";
// Add <style> to the page's <head>
document.head.appendChild(style);
@ -175,16 +190,17 @@ function addCustomDiv(prompt_action,tabId) {
var btn_ok = document.createElement('button');
btn_ok.id="mzta-btn_ok";
btn_ok.classList.add('mzta-btn');
//console.log('default: '+prompt_action)
switch(prompt_action){
switch(String(prompt_action)){
default:
case 0: // close window
case "0": // close window
btn_ok.innerHTML = browser.i18n.getMessage("chatgpt_win_close");
btn_ok.onclick = async function() {
browser.runtime.sendMessage({command: "chatgpt_close"});
};
break;
case 1: // do reply
case "1": // do reply
btn_ok.innerHTML = browser.i18n.getMessage("chatgpt_win_get_answer");
btn_ok.onclick = async function() {
const response = await chatgpt_getFromDOM('last');
@ -193,7 +209,7 @@ function addCustomDiv(prompt_action,tabId) {
browser.runtime.sendMessage({command: "chatgpt_close"});
};
break;
case 2: // replace text
case "2": // replace text
btn_ok.innerHTML = browser.i18n.getMessage("chatgpt_win_get_answer");
btn_ok.onclick = async function() {
const response = await chatgpt_getFromDOM('last');
@ -207,12 +223,45 @@ function addCustomDiv(prompt_action,tabId) {
btn_ok.style.display = 'none';
fixedDiv.appendChild(btn_ok);
//div per custom text
let customDiv = document.createElement('div');
customDiv.id = 'mzta-custom_text';
let customInfo = document.createElement('div');
customInfo.id = 'mzta-custom_info';
customInfo.innerHTML = browser.i18n.getMessage("chatgpt_win_custom_text");
customDiv.appendChild(customInfo);
let customTextArea = document.createElement('textarea');
customTextArea.id = 'mzta-custom_textarea';
customDiv.appendChild(customTextArea);
let customLoading = document.createElement('img');
customLoading.src = browser.runtime.getURL("/images/loading.gif");
customLoading.id = "mzta-custom_loading";
customDiv.appendChild(customLoading);
let customBtn = document.createElement('button');
customBtn.id = 'mzta-custom_btn';
customBtn.innerHTML = browser.i18n.getMessage("chatgpt_win_send");
customBtn.classList.add('mzta-btn');
customBtn.addEventListener("click", () => { customTextBtnClick({customBtn:customBtn,customLoading:customLoading,customDiv:customDiv}) });
customTextArea.addEventListener("keydown", (event) => { if(event.code == "Enter" && event.ctrlKey) customTextBtnClick({customBtn:customBtn,customLoading:customLoading,customDiv:customDiv}) });
customDiv.appendChild(customBtn);
fixedDiv.appendChild(customDiv);
document.body.insertBefore(fixedDiv, document.body.firstChild);
}
function customTextBtnClick(args) {
const customText = document.getElementById('mzta-custom_textarea').value;
args.customBtn.disabled = true;
args.customBtn.classList.add('disabled');
args.customLoading.style.display = 'inline-block';
args.customLoading.style.display = 'none';
doProceed(current_message,customText);
args.customDiv.style.display = 'none';
}
function checkGPT4Model() {
return new Promise((resolve, reject) => {
// Set up an interval that shows the waring after 2 seconds
// Set up an interval that shows the warning after 2 seconds
const intervalId2 = setTimeout(() => {
document.getElementById('mzta-model_warn').style.display = 'inline-block';
document.getElementById('mzta-btn_gpt35').style.display = 'inline';
@ -226,7 +275,7 @@ function checkGPT4Model() {
for(element of elements){
// Check if the element exists and its content is '4' or '4o'
if ((element && element.textContent === '4')||(element && element.textContent === '4o')||(force_go)) {
console.log("The GPT Model is now '4' or '4o'");
console.log("[ThunderAI] The GPT Model is now '4' or '4o'");
clearInterval(intervalId);
clearTimeout(intervalId2);
document.getElementById('mzta-model_warn').style.display = 'none';
@ -234,7 +283,7 @@ function checkGPT4Model() {
resolve("GPT4");
break;
} else if (!element) {
console.log("Element not found!");
console.log("[ThunderAI] Element not found!");
clearInterval(intervalId);
reject("Element not found.");
}
@ -256,6 +305,33 @@ function checkLoggedIn(){
return !window.location.href.startsWith('https://chatgpt.com/auth/');
}
function showCustomTextField(){
document.getElementById('mzta-custom_text').style.display = 'block';
}
async function doProceed(message, customText = ''){
let prefs = await browser.storage.sync.get({chatpgt_use_gpt4:false});
if(prefs.chatpgt_use_gpt4){
await checkGPT4Model();
}
//await chatgpt.isLoaded();
let send_result = await chatgpt_sendMsg(message.prompt+' '+customText,'click');
switch(send_result){
case -1: // send button not found
document.getElementById('mzta-curr_msg').style.display = 'block';
document.getElementById('mzta-curr_msg').innerHTML = browser.i18n.getMessage("chatgpt_sendbutton_not_found_error");
break;
case -2: // textarea not found
document.getElementById('mzta-model_warn').innerHTML = browser.i18n.getMessage("chatgpt_textarea_not_found_error");
document.getElementById('mzta-model_warn').style.display = 'inline-block';
document.getElementById('mzta-curr_msg').innerHTML = "";
document.getElementById('mzta-loading').style.display = 'none';
break;
}
await chatgpt_isIdle();
operation_done();
}
// Nello script di contenuto
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.command === "chatgpt_send") {
@ -265,15 +341,12 @@ browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
}else{
addCustomDiv(message.action,message.tabId);
(async () => {
let prefs = await browser.storage.sync.get({chatpgt_use_gpt4:false});
if(prefs.chatpgt_use_gpt4){
await checkGPT4Model();
if(mztaDoCustomText === 1){
current_message = message;
showCustomTextField();
} else {
await doProceed(message);
}
//await chatgpt.isLoaded();
await chatgpt_sendMsg(message.prompt,'click');
await chatgpt_isIdle();
// console.log(response);
operation_done();
})();
}
}

View file

@ -18,14 +18,15 @@
// Some original methods are derived from https://github.com/ali-raheem/Aify/blob/cfadf52f576b7be3720b5b73af7c8d3129c054da/plugin/html/actions.js
import { defaultPrompts } from './mzta-prompts.js';
import { getLanguageDisplayName } from './mzta-utils.js'
import { getPrompts } from './mzta-prompts.js';
import { getLanguageDisplayName, getMenuContextCompose, getMenuContextDisplay } from './mzta-utils.js'
export class mzta_Menus {
allPrompts = [];
openChatGPT = null;
menu_context_compose = 'compose_action_menu';
menu_context_display = 'message_display_action_menu';
menu_context_compose = null;
menu_context_display = null;
menu_listeners = {};
rootMenu = [
@ -33,16 +34,36 @@ export class mzta_Menus {
];
constructor(openChatGPT) {
this.menu_context_compose = getMenuContextCompose();
this.menu_context_display = getMenuContextDisplay();
this.openChatGPT = openChatGPT;
defaultPrompts.forEach((prompt) => {
this.allPrompts = [];
this.listener = this.listener.bind(this);
}
async initialize() {
this.allPrompts = [];
this.rootMenu = [];
this.menu_listeners = {};
this.allPrompts = await getPrompts(true);
this.allPrompts.sort((a, b) => a.name.localeCompare(b.name));
this.allPrompts.forEach((prompt) => {
this.addAction(prompt)
});
//this.addMenu(this.rootMenu);
}
async reload(){
await browser.menus.removeAll().catch(error => {
console.error("[ThunderAI] ERROR removing the menus: ", error);
});
this.removeClickListener();
this.loadMenus();
}
addAction = (curr_prompt) => {
let curr_menu_entry = {id: curr_prompt.id };
let curr_menu_entry = {id: curr_prompt.id, is_default: curr_prompt.is_default, name: curr_prompt.name};
const getHighlight = async () => {
const tabs = await browser.tabs.query({ active: true, currentWindow: true });
@ -56,7 +77,7 @@ export class mzta_Menus {
const msg_text = await getHighlight();
//check if a selection is needed
if(curr_prompt.need_selected && (msg_text.selection==='')){
if(String(curr_prompt.need_selected) == "1" && (msg_text.selection==='')){
//A selection is needed, but nothing is selected!
//alert(browser.i18n.getMessage('prompt_selection_needed'));
const tabs = await browser.tabs.query({ active: true, currentWindow: true });
@ -75,7 +96,7 @@ export class mzta_Menus {
let prefs = await browser.storage.sync.get({default_chatgpt_lang: getLanguageDisplayName(browser.i18n.getUILanguage())});
let chatgpt_lang = prefs.default_chatgpt_lang;
var fullPrompt = curr_prompt.text + (curr_prompt.need_signature ? " " + await this.getDefaultSignature():"") + " " + browser.i18n.getMessage("prompt_lang") + chatgpt_lang + ". \"" + body_text + "\" ";
var fullPrompt = curr_prompt.text + (String(curr_prompt.need_signature) == "1" ? " " + await this.getDefaultSignature():"") + " " + browser.i18n.getMessage("prompt_lang") + chatgpt_lang + ". \"" + body_text + "\" ";
switch(curr_prompt.id){
case 'prompt_translate_this':
@ -87,14 +108,15 @@ export class mzta_Menus {
default:
break;
}
const tabs = await browser.tabs.query({ active: true, currentWindow: true });
// add custom text if needed
//browser.runtime.sendMessage({command: "chatgpt_open", prompt: fullPrompt, action: curr_prompt.action, tabId: tabs[0].id});
this.openChatGPT(fullPrompt, curr_prompt.action, tabs[0].id);
this.openChatGPT(fullPrompt, curr_prompt.action, tabs[0].id, curr_prompt.need_custom_text);
};
this.rootMenu.push(curr_menu_entry);
};
async getDefaultSignature(){
let prefs = await browser.storage.sync.get({default_sign_name: ''});
if(prefs.default_sign_name===''){
@ -104,53 +126,83 @@ export class mzta_Menus {
}
}
loadMenus() {
this.addMenu(this.rootMenu);
let listeners = this.menu_listeners;
browser.menus.onClicked.addListener((info, tab) => {
listeners[info.menuItemId] && listeners[info.menuItemId] (info, tab);
});
async loadMenus() {
await this.initialize();
await this.addMenu(this.rootMenu);
this.addClickListener();
}
addMenu = (menu, root = null) => {
for (let item of menu) {
let {id, menu, act} = item;
listener(info, tab) {
let listeners = this.menu_listeners;
if (listeners[info.menuItemId]) {
listeners[info.menuItemId](info, tab);
}
}
browser.menus.create({
id: id,
title: browser.i18n.getMessage(id),
contexts: this.getContexts(id),
parentId: root
});
addClickListener() {
browser.menus.onClicked.addListener(this.listener);
}
removeClickListener() {
browser.menus.onClicked.removeListener(this.listener);
}
addMenu = async (menu, root = null) => {
for (let item of menu) {
let {id, is_default, name, menu, act} = item;
await new Promise(resolve =>
browser.menus.create({
id: id,
title: this.getCustomTextAttribute(id) + is_default == 1 ? (browser.i18n.getMessage(id) || name) : name,
contexts: this.getContexts(id),
parentId: root
},
resolve
)
);
if (act) {
this.menu_listeners[id] = act;
}
if (menu) {
this.addMenu(menu, id);
await this.addMenu(menu, id);
}
}
};
getContexts(id){
const curr_prompt = defaultPrompts.find(p => p.id === id);
//console.log(">>>>>>>>> id: " + id);
const curr_prompt = this.allPrompts.find(p => p.id === id);
//console.log(">>>>>>>>>> curr_prompt: " + JSON.stringify(curr_prompt));
if (!curr_prompt) {
return [];
}
switch(curr_prompt.type){
case 0:
switch(String(curr_prompt.type)){
case "0":
return [this.menu_context_compose, this.menu_context_display];
case 1:
case "1":
return [this.menu_context_display];
case 2:
case "2":
return [this.menu_context_compose];
default:
return [];
}
}
getCustomTextAttribute(id){
const curr_prompt = this.allPrompts.find(p => p.id === id);
if (!curr_prompt) {
return "";
}
if(String(curr_prompt.need_custom_text) === "1"){
return "*";
}else{
return "";
}
}
}

View file

@ -16,9 +16,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Modified version derived from https://github.com/ali-raheem/Aify/blob/13ff87583bc520fb80f555ab90a90c5c9df797a7/plugin/html/globals.js
// Modified prompts text derived from https://github.com/ali-raheem/Aify/blob/13ff87583bc520fb80f555ab90a90c5c9df797a7/plugin/html/globals.js
/* Types (type attribute):
/* ================= PROMPTS PROPERTIES ========================================
================ BASE PROPERTIES
Types (type attribute):
0: always show (when composing a part of the text must be selected if need_selected = 1)
1: show when reading an email
2: show when composing a mail (a part of the text must be selected if need_selected = 1)
@ -28,21 +32,178 @@
1: do reply
2: substitute text
Only if text selected (attribute need_selected):
Only if text selected (need_selected attribute):
0: no selection needed (use all the message body)
1: need a selection
Signature
Signature (need_signature attribute):
0: No signature needed
1: Signature needed
Custom Text (need_custom_text attribute):
0: No custom text needed
1: Custom text needed
================ USER PROPERTIES
Enabled (enabled attribute):
0: Disabled
1: Enabled
Position Display Message (position_display attribute):
<num>: position number
Position Compose Message (position_compose attribute):
<num>: position number
*/
export const defaultPrompts = [
{ id: 'prompt_reply', name: "__MSG_prompt_reply__", text: "Reply to the following email. Reply with only the mail text, with greetings and signature, and with no extra comments.", type: 1, action: 1, need_selected: 0, need_signature: 1 },
{ id: 'prompt_rewrite_polite', name: "__MSG_prompt_rewrite_polite__", text: "Rewrite the following text to be more polite. Reply with only the re-written text and with no extra comments or other text.", type: 2, action: 2, need_selected: 1, need_signature: 0 },
{ id: 'prompt_rewrite_formal', name: "__MSG_prompt_rewrite_formal__", text: "Rewrite the following text to be more formal. Reply with only the re-written text and with no extra comments or other text.", type: 2, action: 2, need_selected: 1, need_signature: 0 },
{ id: 'prompt_classify', name: "__MSG_prompt_classify__", text: "Classify the following text in terms of Politeness, Warmth, Formality, Assertiveness, Offensiveness giving a percentage for each category. Reply with only the category and score with no extra comments or other text.", type: 0, action: 0, need_selected: 0, need_signature: 0 },
{ id: 'prompt_summarize_this', name: "__MSG_prompt_summarize_this__", text: "Summarize the following email into a bullet point list.", type: 0, action: 0, need_selected: 0, need_signature: 0 },
{ id: 'prompt_translate_this', name: "__MSG_prompt_translate_this__", text: "Translate the following email in ", type: 0, action: 0, need_selected: 0, need_signature: 0 },
{ id: 'prompt_this', name: "__MSG_prompt_this__", text: "Reply with only the needed text and with no extra comments or other text.", type: 2, action: 2, need_selected: 1, need_signature: 0 },
const defaultPrompts = [
{
id: 'prompt_reply',
name: "__MSG_prompt_reply__",
text: "Reply to the following email.",
type: "1",
action: "1",
need_selected: "0",
need_signature: "1",
need_custom_text: "0",
is_default: "1",
},
{
id: 'prompt_rewrite_polite',
name: "__MSG_prompt_rewrite_polite__",
text: "Rewrite the following text to be more polite. Reply with only the re-written text and with no extra comments or other text.",
type: "2",
action: "2",
need_selected: "1",
need_signature: "0",
need_custom_text: "0",
is_default: "1",
},
{
id: 'prompt_rewrite_formal',
name: "__MSG_prompt_rewrite_formal__",
text: "Rewrite the following text to be more formal. Reply with only the re-written text and with no extra comments or other text.",
type: "2",
action: "2",
need_selected: "1",
need_signature: "0",
need_custom_text: "0",
is_default: "1",
},
{
id: 'prompt_classify',
name: "__MSG_prompt_classify__",
text: "Classify the following text in terms of Politeness, Warmth, Formality, Assertiveness, Offensiveness giving a percentage for each category. Reply with only the category and score with no extra comments or other text.",
type: "0",
action: "0",
need_selected: "0",
need_signature: "0",
need_custom_text: "0",
is_default: "1",
},
{
id: 'prompt_summarize_this',
name: "__MSG_prompt_summarize_this__",
text: "Summarize the following email into a bullet point list.",
type: "0",
action: "0",
need_selected: "0",
need_signature: "0",
need_custom_text: "0",
is_default: "1",
},
{
id: 'prompt_translate_this',
name: "__MSG_prompt_translate_this__",
text: "Translate the following email in ",
type: "0",
action: "0",
need_selected: "0",
need_signature: "0",
need_custom_text: "0",
is_default: "1",
},
{
id: 'prompt_this',
name: "__MSG_prompt_this__",
text: "Reply with only the needed text and with no extra comments or other text.",
type: "2",
action: "2",
need_selected: "1",
need_signature: "0",
need_custom_text: "0",
is_default: "1",
},
];
export async function getPrompts(onlyEnabled = false){
const defaultPrompts = await getDefaultPrompts_withProps();
const customPrompts = await getCustomPrompts();
let output = defaultPrompts.concat(customPrompts);
if(onlyEnabled){
output = output.filter(obj => obj.enabled != 0);
}else{ // order only if we are not filtering, the filtering is for the menus and we are ordering there after i18n
output.sort((a, b) => a.id.localeCompare(b.id));
}
for(let i=1; i<=output.length; i++){
output[i-1].idnum = i;
}
return output;
}
async function getDefaultPrompts_withProps() {
let prefs = await browser.storage.sync.get({_default_prompts_properties: null}); //production
let defaultPrompts_prop = [...defaultPrompts];
if(prefs._default_prompts_properties === null){ // no default prompts properties saved
let pos = 1;
defaultPrompts_prop.forEach((prompt) => {
prompt.position_display = pos;
prompt.position_compose = pos;
prompt.enabled = 1;
pos++;
})
} else { // we have saved default prompts properties
let pos = 1000;
defaultPrompts_prop.forEach((prompt) => {
if(prefs._default_prompts_properties?.[prompt.id]){
prompt.position_compose = prefs._default_prompts_properties[prompt.id].position_compose;
prompt.position_display = prefs._default_prompts_properties[prompt.id].position_display;
prompt.enabled = prefs._default_prompts_properties[prompt.id].enabled;
}else{
prompt.position_display = pos;
prompt.position_compose = pos;
prompt.enabled = 1;
pos++;
}
})
}
return defaultPrompts_prop;
}
async function getCustomPrompts() {
let prefs = await browser.storage.sync.get({_custom_prompt: null});
if(prefs._custom_prompt === null){
return [];
} else {
return prefs._custom_prompt;
}
}
export async function setDefaultPromptsProperties(prompts) {
let default_prompts_properties = {};
prompts.forEach((prompt) => {
default_prompts_properties[prompt.id] = {position_compose: prompt.position_compose, position_display: prompt.position_display, enabled: prompt.enabled};
});
//console.log('>>>>>>>>>>>>>> default_prompts_properties: ' + JSON.stringify(default_prompts_properties));
await browser.storage.sync.set({_default_prompts_properties: default_prompts_properties});
}
export async function setCustomPrompts(prompts) {
await browser.storage.sync.set({_custom_prompt: prompts});
}

View file

@ -16,6 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
export const getMenuContextCompose = () => 'compose_action_menu';
export const getMenuContextDisplay = () => 'message_display_action_menu';
export function getLanguageDisplayName(languageCode) {
const languageDisplay = new Intl.DisplayNames([languageCode], {type: 'language'});

View file

@ -2,7 +2,7 @@
"manifest_version": 2,
"name": "ThunderAI",
"description": "__MSG_extensionDescription__",
"version": "1.0.10",
"version": "1.1.0pre4",
"author": "Mic (m@micz.it)",
"homepage_url": "https://micz.it/thunderdbird-addon-thunderai/",
"browser_specific_settings": {

View file

@ -55,10 +55,10 @@ messenger.runtime.onMessage.addListener(async (message, sender, sendResponse) =>
return true;
case 'chatgpt_close':
browser.windows.remove(createdWindowID).then(() => {
console.log("ChatGPT window closed successfully.");
console.log("[ThunderAI] ChatGPT window closed successfully.");
return true;
}).catch((error) => {
console.error("Error closing ChatGPT window:", error);
console.error("[ThunderAI] Error closing ChatGPT window:", error);
return false;
});
break;
@ -113,6 +113,10 @@ messenger.runtime.onMessage.addListener(async (message, sender, sendResponse) =>
await setBody(message.tabId, original_html);
await setBody(message.tabId, modified_html);
break;
case 'reload_menus':
await menus.reload();
console.log('[ThunderAI] Reloaded menus');
break;
default:
break;
}
@ -122,10 +126,10 @@ messenger.runtime.onMessage.addListener(async (message, sender, sendResponse) =>
});
async function openChatGPT(promptText, action, curr_tabId) {
async function openChatGPT(promptText, action, curr_tabId, do_custom_text = 0) {
let prefs = await browser.storage.sync.get(prefs_default);
prefs = checkScreenDimensions(prefs);
console.log('Prompt length: ' + promptText.length);
console.log('[ThunderAI] Prompt length: ' + promptText.length);
if(promptText.length > 30000 ){
// Prompt too long for ChatGPT
browser.tabs.sendMessage(curr_tabId, { command: "promptTooLong" });
@ -138,7 +142,7 @@ async function openChatGPT(promptText, action, curr_tabId) {
height: prefs.chatgpt_win_height
});
console.log("Script started...");
console.log("[ThunderAI] Script started...");
createdWindowID = newWindow.id;
const createdTab = newWindow.tabs[0];
@ -164,15 +168,16 @@ async function openChatGPT(promptText, action, curr_tabId) {
let pre_script = `let mztaStatusPageDesc="`+ browser.i18n.getMessage("prefs_status_page") +`";
let mztaForceCompletionDesc="`+ browser.i18n.getMessage("chatgpt_force_completion") +`";
let mztaForceCompletionTitle="`+ browser.i18n.getMessage("chatgpt_force_completion_title") +`";
let mztaDoCustomText=`+ do_custom_text +`;
`;
browser.tabs.executeScript(createdTab.id, { code: pre_script + mzta_script, matchAboutBlank: false })
.then(async () => {
console.log("Script injected successfully");
console.log("[ThunderAI] Script injected successfully");
browser.tabs.sendMessage(createdTab.id, { command: "chatgpt_send", prompt: promptText, action: action, tabId: curr_tabId });
})
.catch(err => {
console.error("Error injecting the script: ", err);
console.error("[ThunderAI] Error injecting the script: ", err);
});
}

View file

@ -1,3 +1,16 @@
@media (prefers-color-scheme: dark) {
body {
background-color: rgb(35, 34, 43);
color: rgb(251, 251, 254);
}
a:link { color: #409EFF; }
a:visited { color: #409EFF; }
a:hover { color: #66B1FF; }
a:active { color: #66B1FF; }
}
div#miczDescription{
padding:0px 15px 0px 15px;
font-size: 13px;
@ -71,4 +84,10 @@ input#chatgpt_win_height{
span.dims_label{
width: 75px;
display: inline-block;
}
#btn_custom_prompts{
text-align: center;
width: 100%;
margin: 10px 0px;
}

View file

@ -71,6 +71,9 @@
</td>
</tr>
</table>
<div id="btn_custom_prompts">
<button id="btnManagePrompts">__MSG_prefs_OptionText_btnManagePrompts__</button>
</div>
<div id="miczDescription">
<h1>__MSG_prefsInfoTitle__</h1>
<p>__MSG_prefsInfoDesc_1__<br/>

View file

@ -39,7 +39,7 @@ function saveOptions(e) {
if (element.tagName === 'SELECT') {
options[element.id] = element.value;
}else{
console.log('Unhandled input type:', element.type);
console.log('[ThunderAI] Unhandled input type:', element.type);
}
}
@ -73,14 +73,14 @@ function restoreOptions() {
element.selectedIndex = -1;
}
}else{
console.log('Unhandled input type:', element.type);
console.log('[ThunderAI] Unhandled input type:', element.type);
}
}
});
}
function onError(error) {
console.log(`Error: ${error}`);
console.log(`[ThunderAI] Error: ${error}`);
}
let getting = browser.storage.sync.get(null);
@ -93,4 +93,16 @@ document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll(".option-input").forEach(element => {
element.addEventListener("change", saveOptions);
});
document.getElementById('btnManagePrompts').addEventListener('click', () => {
// check if the tab is already there
browser.tabs.query({url: browser.runtime.getURL('../customprompts/mzta-custom-prompts.html')}).then((tabs) => {
if (tabs.length > 0) {
// if the tab is already there, focus it
browser.tabs.update(tabs[0].id, {active: true});
} else {
// if the tab is not there, create it
browser.tabs.create({url: browser.runtime.getURL('../customprompts/mzta-custom-prompts.html')});
}
})
});
}, { once: true });

View file

@ -1,3 +1,16 @@
@media (prefers-color-scheme: dark) {
body {
background-color: rgb(35, 34, 43);
color: rgb(251, 251, 254);
}
a:link { color: #409EFF; }
a:visited { color: #409EFF; }
a:hover { color: #66B1FF; }
a:active { color: #66B1FF; }
}
div#miczRelNotes{
padding: 10px;
}

View file

@ -7,25 +7,40 @@
<body>
<div id="miczBackPrefs"><a href="mzta-options.html">__MSG_backToOptionsText__</a></div>
<div id="miczRelNotes"><h1>ThunderAI Release Notes</h1>
<h2>Version 1.1.0 - ??/??/2024</h2>
<ul>
<li>A prompt can be configured to request additional text from the user.</li>
<li>Added custom prompts. See more info <a href="https://micz.it/thunderdbird-addon-thunderai/custom-prompts/">here</a>.</li>
<li>Dark mode added.</li>
<li>Added some error messages to handle potential changes in the ChatGPT web interface.</li>
<li>German translation added.</li>
<li>French translation added.</li>
<li>Log messages improved.</li>
</ul>
<h2>Version 1.0.10 - 17/05/2024</h2>
<ul>
<li>Now using the new URL chatgpt.com.</li>
<li>More improvements in handling the ChatGPT web interface.</li>
</ul>
<h2>Version 1.0.9 - 16/05/2024</h2>
<ul>
<li>Improved handling of different versions of the ChatGPT web interface.</li>
</ul>
<h2>Version 1.0.8 - 15/05/2024</h2>
<ul>
<li>Fixed changes in the ChatGPT web interface, see <a href="https://github.com/micz/ThunderAI/issues/57">#57</a> and <a href="https://github.com/micz/ThunderAI/issues/62">#62</a>.</li>
<li>Fixed changes in the ChatGPT web interface [<a href="https://github.com/micz/ThunderAI/issues/57">#57</a>, <a href="https://github.com/micz/ThunderAI/issues/62">#62</a>].</li>
<li>Correctly handling the model ChatGPT-4o.</li>
</ul>
<h2>Version 1.0.7 - 09/05/2024</h2>
<ul>
<li>Improved the reply prompt to exclude comments and other text beside the mail text.</li>
<li>Correctly keeping the signature in a reply even if it's above the quoted email [<a href="https://github.com/micz/ThunderAI/issues/45">#45</a>].</li>
</ul>
<h2>Version 1.0.6 - 08/05/2024</h2>
<ul>
<li>Correctly handling a change in the ChatGPT web interface [<a href="https://github.com/micz/ThunderAI/issues/43">#43</a>].</li>