diff --git a/_locales/en/messages.json b/_locales/en/messages.json index d77738c4..48cd1b80 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -1127,8 +1127,24 @@ "message": "If checked, the AI will add only existing tags and won't create new tags.", "description": "" }, + "prefs_OptionText_add_tags_auto_uselist": { + "message": "Use only these tags", + "description": "" + }, + "prefs_OptionText_add_tags_auto_uselist_Info": { + "message": "If checked, the AI will add only tags from the list below.", + "description": "" + }, + "prefs_OptionText_add_tags_auto_uselist_list_Info": { + "message": "The list must contain at least one tag. Add a tag per line, or separated by a comma.", + "description": "" + }, + "prompt_add_tags_use_list": { + "message": "Use only these tags, that are comma separated in the list", + "description": "" + }, "prefs_OptionText_add_tags_auto_only_inbox": { - "message": "Only add tags to inbox emails", + "message": "Only add tags to emails in the inbox", "description": "" }, "prefs_OptionText_add_tags_auto_only_inbox_Info": { diff --git a/js/mzta-utils-prompt.js b/js/mzta-utils-prompt.js index 60c9076b..57098416 100644 --- a/js/mzta-utils-prompt.js +++ b/js/mzta-utils-prompt.js @@ -80,13 +80,16 @@ export const taPromptUtils = { return fullPrompt; }, - finalizePrompt_add_tags(fullPrompt, add_tags_maxnum, add_tags_force_lang, default_chatgpt_lang){ + finalizePrompt_add_tags(fullPrompt, add_tags_maxnum, add_tags_force_lang, default_chatgpt_lang, add_tags_auto_uselist = false, add_tags_auto_uselist_list = ''){ if(add_tags_maxnum > 0){ fullPrompt += " \n" + browser.i18n.getMessage("prompt_add_tags_maxnum") + " " + add_tags_maxnum +"."; } if(add_tags_force_lang && default_chatgpt_lang !== ''){ fullPrompt += " \n" + browser.i18n.getMessage("prompt_add_tags_force_lang") + " " + default_chatgpt_lang + "."; } + if(add_tags_auto_uselist && add_tags_auto_uselist_list && add_tags_auto_uselist_list.length > 0){ + fullPrompt += " \n" + browser.i18n.getMessage("prompt_add_tags_use_list") + " " + add_tags_auto_uselist_list + "."; + } return fullPrompt; }, @@ -126,7 +129,7 @@ export const taPromptUtils = { * For backwords compatibility, if the response text is not a valid JSON, * it will try to split the text by commas and return the resulting array. */ - getTagsFromResponse(response_text){ + getTagsFromResponse(response_text, filter_tags = false, filter_tags_list = ''){ let tags = []; if(response_text && response_text.length > 0){ try { @@ -143,6 +146,10 @@ export const taPromptUtils = { tags = response_text.split(/,\s*/).map(tag => tag.trim()); } } + if(filter_tags && filter_tags_list && filter_tags_list.length > 0){ + const allowedTags = filter_tags_list.split(',').map(tag => tag.trim().toLowerCase()).filter(tag => tag.length > 0); + tags = tags.filter(tag => allowedTags.includes(tag.toLowerCase())); + } return tags; } }; \ No newline at end of file diff --git a/js/mzta-utils.js b/js/mzta-utils.js index d5549624..bf41319a 100644 --- a/js/mzta-utils.js +++ b/js/mzta-utils.js @@ -477,6 +477,26 @@ function sanitizeString(input) { return sanitized; } +/* returnType: + 0: string comma separated (default) + 1: string \n separated + 2: array +*/ +export function normalizeStringList(list, returnType = 0) { + let _array_new = list.split(/[\n,]+/); + _array_new = Array.from(new Set(_array_new.map(item => item.trim().toLowerCase()))).sort(); + switch(returnType) { + case 0: + return _array_new.join(', '); + case 1: + return _array_new.join('\n'); + case 2: + return _array_new; + default: + return _array_new.join(', '); + } +} + function generateHexColorForTag() { const red = Math.floor(Math.random() * 256); const green = Math.floor(Math.random() * 256); diff --git a/mzta-background.js b/mzta-background.js index b82438e1..4046b52a 100644 --- a/mzta-background.js +++ b/mzta-background.js @@ -973,6 +973,8 @@ async function processEmails(messages, addTagsAuto, spamFilter) { add_tags_auto_force_existing: prefs_default.add_tags_auto_force_existing, add_tags_enabled_accounts: prefs_default.add_tags_enabled_accounts, add_tags_exclusions_exact_match: prefs_default.add_tags_exclusions_exact_match, + add_tags_auto_uselist: prefs_default.add_tags_auto_uselist, + add_tags_auto_uselist_list: prefs_default.add_tags_auto_uselist_list, spamfilter_enabled_accounts: prefs_default.spamfilter_enabled_accounts, }); @@ -1007,20 +1009,20 @@ async function processEmails(messages, addTagsAuto, spamFilter) { let chatgpt_lang = await taPromptUtils.getDefaultLang(curr_prompt_add_tags); specialFullPrompt_add_tags = await taPromptUtils.preparePrompt({ curr_prompt: curr_prompt_add_tags, - curr_message: curr_message, + curr_message: message, chatgpt_lang: chatgpt_lang, body_text: body_text, subject_text: curr_fullMessage.headers.subject, msg_text: msg_text, tags_full_list: tags_full_list }); - specialFullPrompt_add_tags = taPromptUtils.finalizePrompt_add_tags(specialFullPrompt_add_tags, prefs_aats.add_tags_maxnum, prefs_aats.add_tags_force_lang, prefs_aats.default_chatgpt_lang); + specialFullPrompt_add_tags = taPromptUtils.finalizePrompt_add_tags(specialFullPrompt_add_tags, prefs_aats.add_tags_maxnum, prefs_aats.add_tags_force_lang, prefs_aats.default_chatgpt_lang, prefs_aats.add_tags_auto_uselist, prefs_aats.add_tags_auto_uselist_list); taLog.log("Special prompt: " + specialFullPrompt_add_tags); let cmd_addTags = new mzta_specialCommand(specialFullPrompt_add_tags, prefs_aats.connection_type, prefs_init.do_debug); await cmd_addTags.initWorker(); let tags_current_email = []; try { - tags_current_email = taPromptUtils.getTagsFromResponse(await cmd_addTags.sendPrompt()); + tags_current_email = taPromptUtils.getTagsFromResponse(await cmd_addTags.sendPrompt(), prefs_aats.add_tags_auto_uselist, prefs_aats.add_tags_auto_uselist_list); } catch (err) { console.error("[ThunderAI | Auto add_tags] Error getting tags: ", err); } diff --git a/options/mzta-options-default.js b/options/mzta-options-default.js index 16530072..e1aeb908 100644 --- a/options/mzta-options-default.js +++ b/options/mzta-options-default.js @@ -62,6 +62,8 @@ export const prefs_default = { add_tags_auto: false, add_tags_auto_force_existing: false, add_tags_auto_only_inbox: true, + add_tags_auto_uselist: false, + add_tags_auto_uselist_list: '', add_tags_context_menu: true, add_tags_enabled_accounts: [], get_calendar_event: true, diff --git a/pages/addtags/mzta-add-tags.css b/pages/addtags/mzta-add-tags.css index 198b6896..070f3bdf 100644 --- a/pages/addtags/mzta-add-tags.css +++ b/pages/addtags/mzta-add-tags.css @@ -17,10 +17,16 @@ margin: 40px auto; } -#addtags_excl_list{ +#addtags_excl_list, #add_tags_auto_uselist_list{ width: 30em; } +#add_tags_auto_uselist_list:disabled { + background-color: #eee; + color: #888; + cursor: not-allowed; +} + #account_selector_container{ display: none; } @@ -37,13 +43,17 @@ background-color: #e9ffdf; } +tr.add_tags_auto_sub td{ + padding-left: 0.8em !important; +} + .btn_div{ width: 100%; display: flex; justify-content: space-between; } -#addtags_info_additional_statements, #add_tags_auto_only_inbox_tr{ +#addtags_info_additional_statements, #add_tags_auto_only_inbox_tr, #add_tags_auto_uselist_tr{ display: none; } diff --git a/pages/addtags/mzta-add-tags.html b/pages/addtags/mzta-add-tags.html index ef5d2488..bf9d8c53 100644 --- a/pages/addtags/mzta-add-tags.html +++ b/pages/addtags/mzta-add-tags.html @@ -68,7 +68,7 @@ - + __MSG_prefs_OptionText_add_tags_auto_only_inbox__ + + __MSG_prefs_OptionText_add_tags_auto_uselist__ + + + + __MSG_prefs_OptionText_add_tags_context_menu__ diff --git a/pages/addtags/mzta-add-tags.js b/pages/addtags/mzta-add-tags.js index 8da2bae2..7205bc28 100644 --- a/pages/addtags/mzta-add-tags.js +++ b/pages/addtags/mzta-add-tags.js @@ -22,7 +22,7 @@ import { getSpecialPrompts, setSpecialPrompts } from "../../js/mzta-prompts.js"; import { getPlaceholders } from "../../js/mzta-placeholders.js"; import { textareaAutocomplete } from "../../js/mzta-placeholders-autocomplete.js"; import { addTags_getExclusionList, addTags_setExclusionList } from "../../js/mzta-addatags-exclusion-list.js"; -import { getAccountsList } from "../../js/mzta-utils.js"; +import { getAccountsList, normalizeStringList } from "../../js/mzta-utils.js"; let autocompleteSuggestions = []; let taLog = new taLogger("mzta-addtags-page",true); @@ -57,14 +57,25 @@ document.addEventListener('DOMContentLoaded', async () => { let add_tags_auto_only_inbox_tr = document.getElementById('add_tags_auto_only_inbox_tr'); let account_selector_container = document.getElementById('account_selector_container'); let add_tags_auto_infoline = document.getElementById('add_tags_auto_infoline'); + let add_tags_auto_uselist_tr = document.getElementById('add_tags_auto_uselist_tr'); add_tags_auto_el.addEventListener('click', (event) => { add_tags_auto_only_inbox_tr.style.display = event.target.checked ? 'table-row' : 'none'; account_selector_container.style.display = event.target.checked ? 'block' : 'none'; add_tags_auto_infoline.style.display = event.target.checked ? 'inline' : 'none'; + add_tags_auto_uselist_tr.style.display = event.target.checked ? 'table-row' : 'none'; + }); add_tags_auto_only_inbox_tr.style.display = add_tags_auto_el.checked ? 'table-row' : 'none'; account_selector_container.style.display = add_tags_auto_el.checked ? 'block' : 'none'; add_tags_auto_infoline.style.display = add_tags_auto_el.checked ? 'inline' : 'none'; + add_tags_auto_uselist_tr.style.display = add_tags_auto_el.checked ? 'table-row' : 'none'; + + let add_tags_auto_uselist = document.getElementById('add_tags_auto_uselist'); + let add_tags_auto_uselist_list = document.getElementById('add_tags_auto_uselist_list'); + add_tags_auto_uselist.addEventListener('click', (event) => { + add_tags_auto_uselist_list.disabled = !event.target.checked; + }); + add_tags_auto_uselist_list.disabled = !add_tags_auto_uselist.checked; addtags_reset_btn.addEventListener('click', () => { addtags_textarea.value = browser.i18n.getMessage('prompt_add_tags_full_text'); @@ -89,6 +100,8 @@ document.addEventListener('DOMContentLoaded', async () => { document.getElementById('add_tags_maxnum').addEventListener('change', updateAdditionalPromptStatements); document.getElementById('add_tags_force_lang').addEventListener('change', updateAdditionalPromptStatements); + document.getElementById('add_tags_auto_uselist').addEventListener('change', updateAdditionalPromptStatements); + document.getElementById('add_tags_auto_uselist_list').addEventListener('change', updateAdditionalPromptStatements); updateAdditionalPromptStatements(); @@ -113,8 +126,7 @@ document.addEventListener('DOMContentLoaded', async () => { }); excl_list_save_btn.addEventListener('click', () => { - let excl_array_new = excl_list_textarea.value.split(/[\n,]+/); - excl_array_new = Array.from(new Set(excl_array_new.map(item => item.trim().toLowerCase()))).sort(); + let excl_array_new = normalizeStringList(excl_list_textarea.value, 2); addTags_setExclusionList(excl_array_new); excl_list_save_btn.disabled = true; excl_list_textarea.value = excl_array_new.join('\n'); @@ -179,19 +191,26 @@ document.addEventListener('DOMContentLoaded', async () => { async function updateAdditionalPromptStatements(){ - let prefs_ = await browser.storage.sync.get({add_tags_maxnum: 3, add_tags_force_lang: true, default_chatgpt_lang: ''}); + let prefs_ = await browser.storage.sync.get({ + add_tags_maxnum: prefs_default.add_tags_maxnum, + add_tags_force_lang: prefs_default.add_tags_force_lang, + default_chatgpt_lang: prefs_default.default_chatgpt_lang, + add_tags_auto_uselist: prefs_default.add_tags_auto_uselist, + add_tags_auto_uselist_list: prefs_default.add_tags_auto_uselist_list, + }); let el_tag_limit = document.getElementById('addtags_info_additional_statements'); - if((prefs_.add_tags_maxnum > 0)||(prefs_.add_tags_force_lang && prefs_.default_chatgpt_lang !== '')){ + if((prefs_.add_tags_maxnum > 0)||(prefs_.add_tags_force_lang && prefs_.default_chatgpt_lang !== '')||(prefs_.add_tags_auto_uselist && prefs_.add_tags_auto_uselist_list.trim() !== '')){ el_tag_limit.textContent = browser.i18n.getMessage("addtags_info_additional_statements") + " \"" if(prefs_.add_tags_maxnum > 0){ - el_tag_limit.textContent += browser.i18n.getMessage("prompt_add_tags_maxnum") + " " + prefs_.add_tags_maxnum +"." + el_tag_limit.textContent += browser.i18n.getMessage("prompt_add_tags_maxnum") + " " + prefs_.add_tags_maxnum +". " } if(prefs_.add_tags_force_lang && prefs_.default_chatgpt_lang !== ''){ - if(prefs_.add_tags_maxnum > 0){ - el_tag_limit.textContent += " " - } - el_tag_limit.textContent += browser.i18n.getMessage("prompt_add_tags_force_lang") + " " + prefs_.default_chatgpt_lang + "." + el_tag_limit.textContent += browser.i18n.getMessage("prompt_add_tags_force_lang") + " " + prefs_.default_chatgpt_lang + ". " } + if(prefs_.add_tags_auto_uselist && prefs_.add_tags_auto_uselist_list.trim() !== ''){ + el_tag_limit.textContent += browser.i18n.getMessage("prompt_add_tags_use_list") + ": " + prefs_.add_tags_auto_uselist_list + "."; + } + el_tag_limit.textContent = el_tag_limit.textContent.trim(); el_tag_limit.textContent += "\"."; el_tag_limit.style.display = 'block'; }else{ @@ -221,6 +240,12 @@ function saveOptions(e) { case 'select-one': options[element.id] = element.value; break; + case 'textarea': + if(element.id === 'add_tags_auto_uselist_list') { + element.value = normalizeStringList(element.value, 1); + } + options[element.id] = normalizeStringList(element.value); + break; default: console.error("[ThunderAI] Unhandled input type:", element.type); } @@ -243,9 +268,13 @@ async function restoreOptions() { element.value = result[element.id] ?? default_number_value; break; case 'text': + case 'textarea': case 'password': let default_text_value = ''; if(element.id == 'default_chatgpt_lang') default_text_value = prefs_default.default_chatgpt_lang; + if(element.id === 'add_tags_auto_uselist_list') { + result[element.id] = normalizeStringList(result[element.id], 1); + } element.value = result[element.id] || default_text_value; break; default: