365 lines
No EOL
14 KiB
JavaScript
365 lines
No EOL
14 KiB
JavaScript
/*
|
|
* ThunderAI [https://micz.it/thunderbird-addon-thunderai/]
|
|
* Copyright (C) 2024 - 2025 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/>.
|
|
*/
|
|
|
|
/* ================= PLACEHOLDERS 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)
|
|
|
|
================ USER PROPERTIES
|
|
Enabled (enabled attribute):
|
|
0: Disabled
|
|
1: Enabled
|
|
|
|
*/
|
|
|
|
import { transformTagsLabels, getCurrentIdentity } from './mzta-utils.js';
|
|
|
|
const defaultPlaceholders = [
|
|
{
|
|
id: 'mail_text_body',
|
|
name: "__MSG_placeholder_mail_text_body__",
|
|
default_value: "",
|
|
type: 0,
|
|
is_default: "1",
|
|
},
|
|
{
|
|
id: 'mail_html_body',
|
|
name: "__MSG_placeholder_mail_html_body__",
|
|
default_value: "",
|
|
type: 0,
|
|
is_default: "1",
|
|
},
|
|
{
|
|
id: 'mail_typed_text',
|
|
name: "__MSG_placeholder_mail_typed_text__",
|
|
default_value: "",
|
|
type: 2,
|
|
is_default: "1",
|
|
},
|
|
{
|
|
id: 'mail_subject',
|
|
name: "__MSG_placeholder_mail_subject__",
|
|
default_value: "",
|
|
type: 0,
|
|
is_default: "1",
|
|
},
|
|
{
|
|
id: 'mail_folder_name',
|
|
name: "__MSG_placeholder_folder_name__",
|
|
default_value: "",
|
|
type: 1,
|
|
is_default: "1",
|
|
},
|
|
{
|
|
id: 'mail_folder_path',
|
|
name: "__MSG_placeholder_folder_path__",
|
|
default_value: "",
|
|
type: 1,
|
|
is_default: "1",
|
|
},
|
|
{
|
|
id: 'selected_text',
|
|
name: "__MSG_placeholder_selected_text__",
|
|
default_value: "",
|
|
type: 0,
|
|
is_default: "1",
|
|
},
|
|
{
|
|
id: 'additional_text',
|
|
name: "__MSG_placeholder_additional_text__",
|
|
default_value: "",
|
|
type: 0,
|
|
is_default: "1",
|
|
},
|
|
{
|
|
id: 'junk_score',
|
|
name: "__MSG_placeholder_junk_score__",
|
|
default_value: "0",
|
|
type: 1,
|
|
is_default: "1",
|
|
},
|
|
{
|
|
id: 'recipients',
|
|
name: "__MSG_placeholder_recipients__",
|
|
default_value: "",
|
|
type: 0,
|
|
is_default: "1",
|
|
},
|
|
{
|
|
id: 'cc_list',
|
|
name: "__MSG_placeholder_cc_list__",
|
|
default_value: "",
|
|
type: 0,
|
|
is_default: "1",
|
|
},
|
|
{
|
|
id: 'author',
|
|
name: "__MSG_placeholder_author__",
|
|
default_value: "",
|
|
type: 0,
|
|
is_default: "1",
|
|
},
|
|
{
|
|
id: 'mail_datetime',
|
|
name: "__MSG_placeholder_mail_datetime__",
|
|
default_value: "",
|
|
type: 1,
|
|
is_default: "1",
|
|
},
|
|
{
|
|
id: 'current_datetime',
|
|
name: "__MSG_placeholder_current_datetime__",
|
|
default_value: "",
|
|
type: 0,
|
|
is_default: "1",
|
|
},
|
|
{
|
|
id: 'account_email_address',
|
|
name: "__MSG_placeholder_account_email_address__",
|
|
default_value: "",
|
|
type: 0,
|
|
is_default: "1",
|
|
},
|
|
{
|
|
id: 'tags_current_email',
|
|
name: "__MSG_placeholder_tags_current_email__",
|
|
default_value: "",
|
|
type: 0,
|
|
is_default: "1",
|
|
},
|
|
{
|
|
id: 'tags_full_list',
|
|
name: "__MSG_placeholder_tags_full_list__",
|
|
default_value: "",
|
|
type: 0,
|
|
is_default: "1",
|
|
},
|
|
{
|
|
id: 'thunderai_def_sign',
|
|
name: "__MSG_placeholder_thunderai_def_sign__",
|
|
default_value: "",
|
|
type: 0,
|
|
is_default: "1",
|
|
},
|
|
{
|
|
id: 'thunderai_def_lang',
|
|
name: "__MSG_placeholder_thunderai_def_lang__",
|
|
default_value: "",
|
|
type: 0,
|
|
is_default: "1",
|
|
},
|
|
];
|
|
|
|
|
|
export async function getPlaceholders(onlyEnabled = false){
|
|
const _defaultPlaceholders = await getDefaultPlaceholders_withProps();
|
|
// console.log('>>>>>>>>>>>> getPlaceholders _defaultPlaceholders: ' + JSON.stringify(_defaultPlaceholders));
|
|
const customPlaceholders = await getCustomPlaceholders();
|
|
// console.log('>>>>>>>>>>>> getPlaceholders customPlaceholders: ' + JSON.stringify(customPlaceholders));
|
|
let output = _defaultPlaceholders.concat(customPlaceholders);
|
|
if(onlyEnabled){
|
|
output = output.filter(obj => obj.enabled != 0);
|
|
}else{ // order only if we are not filtering, the filtering is for the automplete and we are ordering there after i18n
|
|
output.sort((a, b) => a.id.localeCompare(b.id));
|
|
}
|
|
// console.log('>>>>>>>>>>>> getPlaceholders output: ' + JSON.stringify(output));
|
|
let prefs = await browser.storage.local.get({ add_tags: false });
|
|
return output;
|
|
}
|
|
|
|
async function getDefaultPlaceholders_withProps() {
|
|
let prefs = await browser.storage.local.get({_default_placeholders_properties: null});
|
|
// console.log('>>>>>>>>>>>> getDefaultPlaceholders_withProps prefs: ' + JSON.stringify(prefs));
|
|
//let defaultPlaceholders_prop = [...defaultPlaceholders];
|
|
let defaultPlaceholders_prop = JSON.parse(JSON.stringify(defaultPlaceholders));
|
|
// console.log('>>>>>>>>>>>> getDefaultPlaceholders_withProps defaultPlaceholders: ' + JSON.stringify(defaultPlaceholders));
|
|
// console.log('>>>>>>>>>>>> getDefaultPlaceholders_withProps defaultPlaceholders_prop: ' + JSON.stringify(defaultPlaceholders_prop));
|
|
if(prefs._default_placeholders_properties === null){ // no default Placeholders properties saved
|
|
defaultPlaceholders_prop.forEach((placeholder) => {
|
|
placeholder.enabled = 1;
|
|
})
|
|
// console.log('>>>>>>>>>>>> getDefaultPlaceholders_withProps [no prop saved] defaultPlaceholders_prop: ' + JSON.stringify(defaultPlaceholders_prop));
|
|
} else { // we have saved default Placeholders properties
|
|
defaultPlaceholders_prop.forEach((placeholder) => {
|
|
if(prefs._default_Placeholders_properties?.[placeholder.id]){
|
|
placeholder.enabled = prefs._default_Placeholders_properties[placeholder.id].enabled;
|
|
}else{
|
|
placeholder.enabled = 1;
|
|
}
|
|
})
|
|
// console.log('>>>>>>>>>>>> getDefaultPlaceholders_withProps [prop saved] defaultPlaceholders_prop: ' + JSON.stringify(defaultPlaceholders_prop));
|
|
}
|
|
return defaultPlaceholders_prop;
|
|
}
|
|
|
|
async function getCustomPlaceholders() {
|
|
let prefs = await browser.storage.local.get({_custom_placeholder: null});
|
|
if(prefs._custom_placeholder === null){
|
|
return [];
|
|
} else {
|
|
return prefs._custom_placeholder;
|
|
}
|
|
}
|
|
|
|
export async function setDefaultPlaceholdersProperties(placeholders) {
|
|
let default_placeholders_properties = {};
|
|
placeholders.forEach((placeholder) => {
|
|
default_placeholders_properties[placeholder.id] = {enabled: placeholder.enabled};
|
|
});
|
|
//console.log('>>>>>>>>>>>>>> default_placeholders_properties: ' + JSON.stringify(default_placeholders_properties));
|
|
await browser.storage.local.set({_default_placeholders_properties: default_placeholders_properties});
|
|
}
|
|
|
|
export async function setCustomPlaceholders(placeholders) {
|
|
await browser.storage.local.set({_custom_placeholder: placeholders});
|
|
}
|
|
|
|
|
|
export const placeholdersUtils = {
|
|
|
|
async extractPlaceholders(text) {
|
|
// Regular expression to match patterns like {%...%}
|
|
const regex = /{%\s*(.*?)\s*%}/g;
|
|
let matches = [];
|
|
let match;
|
|
|
|
let activePHs = await getPlaceholders(true);
|
|
|
|
// Use exec to find all matches
|
|
while ((match = regex.exec(text)) !== null) {
|
|
const foundPH = activePHs.find(ph => ph.id === match[1].trim());
|
|
if (foundPH) {
|
|
matches.push(foundPH);
|
|
}
|
|
}
|
|
|
|
return matches;
|
|
},
|
|
|
|
replacePlaceholders(text, replacements, use_default_value = false, skip_additional_text = false) {
|
|
// Regular expression to match patterns like {%...%}
|
|
return text.replace(/{%\s*(.*?)\s*%}/g, function(match, p1) {
|
|
// p1 contains the key inside {% %}
|
|
if (skip_additional_text && (p1 === 'additional_text')) {
|
|
return match;
|
|
}
|
|
// Replace if found, otherwise keep the original or substitute with default value
|
|
return replacements[p1] || (use_default_value ? defaultPlaceholders.find(ph => ph.id === p1).default_value : match);
|
|
});
|
|
},
|
|
|
|
hasPlaceholder(text, placeholder = "") {
|
|
let regex;
|
|
|
|
// If a specific placeholder is provided, we search for it
|
|
if (placeholder !== "") {
|
|
// Dynamically build the regex for the specific placeholder
|
|
regex = new RegExp(`{%\s*${placeholder}\s*%}`);
|
|
} else {
|
|
// Otherwise, we search for any placeholder in the format {% ... %}
|
|
regex = /{%\s*(.*?)\s*%}/;
|
|
}
|
|
|
|
// Check if the specific or any placeholder is present in the text
|
|
return regex.test(text);
|
|
},
|
|
|
|
async getPlaceholdersValues(prompt_text, curr_message, mail_subject, body_text, msg_text, only_typed_text, selection_text, tags_full_list) {
|
|
let currPHs = await placeholdersUtils.extractPlaceholders(prompt_text);
|
|
// console.log(">>>>>>>>>> currPHs: " + JSON.stringify(currPHs));
|
|
let finalSubs = {};
|
|
for(let currPH of currPHs){
|
|
switch(currPH.id){
|
|
case 'mail_text_body':
|
|
finalSubs['mail_text_body'] = placeholdersUtils.failSafePlaceholders(body_text);
|
|
break;
|
|
case 'mail_html_body':
|
|
finalSubs['mail_html_body'] = placeholdersUtils.failSafePlaceholders(msg_text?.html);
|
|
break;
|
|
case 'mail_typed_text':
|
|
finalSubs['mail_typed_text'] = placeholdersUtils.failSafePlaceholders(only_typed_text);
|
|
break;
|
|
case 'mail_subject':
|
|
finalSubs['mail_subject'] = placeholdersUtils.failSafePlaceholders(mail_subject);
|
|
break;
|
|
case 'mail_folder_name':
|
|
finalSubs['mail_folder_name'] = placeholdersUtils.failSafePlaceholders(curr_message.folder?.name);
|
|
break;
|
|
case 'mail_folder_path':
|
|
finalSubs['mail_folder_path'] = placeholdersUtils.failSafePlaceholders(curr_message.folder?.path);
|
|
break;
|
|
case 'selected_text':
|
|
finalSubs['selected_text'] = placeholdersUtils.failSafePlaceholders(selection_text);
|
|
break;
|
|
case 'author':
|
|
finalSubs['author'] = placeholdersUtils.failSafePlaceholders(curr_message.author);
|
|
break;
|
|
case 'recipients':
|
|
finalSubs['recipients'] = placeholdersUtils.failSafePlaceholders(curr_message.recipients?.join(", "));
|
|
break;
|
|
case 'cc_list':
|
|
finalSubs['cc_list'] = placeholdersUtils.failSafePlaceholders(curr_message.ccList?.join(", "));
|
|
break;
|
|
case 'junk_score':
|
|
finalSubs['junk_score'] = placeholdersUtils.failSafePlaceholders(curr_message.junkScore);
|
|
break;
|
|
case 'mail_datetime':
|
|
finalSubs['mail_datetime'] = placeholdersUtils.failSafePlaceholders(curr_message.date);
|
|
break;
|
|
case 'current_datetime':
|
|
finalSubs['current_datetime'] = placeholdersUtils.failSafePlaceholders(new Date().toString());
|
|
break;
|
|
case 'account_email_address':
|
|
let current_identity = await getCurrentIdentity(curr_message, true);
|
|
finalSubs['account_email_address'] = placeholdersUtils.failSafePlaceholders(current_identity.email);
|
|
break;
|
|
case 'tags_current_email':
|
|
let tags_current_email_array = await transformTagsLabels(curr_message.tags, tags_full_list[1]);
|
|
finalSubs['tags_current_email'] = placeholdersUtils.failSafePlaceholders(tags_current_email_array.join(", "));
|
|
break;
|
|
case 'tags_full_list':
|
|
finalSubs['tags_full_list'] = placeholdersUtils.failSafePlaceholders(tags_full_list[0]);
|
|
break;
|
|
case 'thunderai_def_sign':
|
|
let prefs_def_sign = await browser.storage.sync.get({default_sign_name: ''});
|
|
finalSubs['thunderai_def_sign'] = placeholdersUtils.failSafePlaceholders(prefs_def_sign.default_sign_name);
|
|
break;
|
|
case 'thunderai_def_lang':
|
|
let prefs_def_lang = await browser.storage.sync.get({default_chatgpt_lang: ''});
|
|
finalSubs['thunderai_def_lang'] = placeholdersUtils.failSafePlaceholders(prefs_def_lang.default_chatgpt_lang);
|
|
break;
|
|
default: // TODO Manage custom placeholders https://github.com/micz/ThunderAI/issues/156
|
|
break;
|
|
}
|
|
}
|
|
|
|
return finalSubs;
|
|
},
|
|
|
|
failSafePlaceholders(element){
|
|
if(element === null || element === undefined){
|
|
return '';
|
|
}
|
|
}
|
|
|
|
} |