Merge pull request #254 from micz/auto_tags

Auto tags
This commit is contained in:
Mic 2025-02-09 23:29:38 +01:00 committed by GitHub
commit 5cb60b8f99
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 382 additions and 115 deletions

View file

@ -7,6 +7,10 @@
<h2>Version 3.2.0 - ??/??/2025</h2>
<ul>
<li>Added an option to automatically tag incoming emails [<a href="https://github.com/micz/ThunderAI/issues/237">#237</a>].</li>
<li>Added the <i>{%thunderai_def_sign%}</i> placeholder to get the default signature as defined in the options [<a href="https://github.com/micz/ThunderAI/issues/248">#248</a>].</li>
<li>Added the <i>{%thunderai_def_lang%}</i> placeholder to get the default language as defined in the options [<a href="https://github.com/micz/ThunderAI/issues/248">#248</a>].</li>
<li>Various minor improvements.</li>
<li>...</li>
</ul>
<h2>Version 3.1.2 - 29/01/2025</h2>

View file

@ -1018,5 +1018,37 @@
"sparks_not_installed": {
"message": "ThunderAI Sparks not installed!",
"description": ""
},
"prefs_OptionText_add_tags_auto": {
"message": "Add tags automatically",
"description": ""
},
"prefs_OptionText_add_tags_auto_Info": {
"message": "If checked, the AI will automatically add tags to newly received emails.",
"description": ""
},
"prefs_OptionText_add_tags_auto_force_existing": {
"message": "Force existing tags when autotagging",
"description": ""
},
"prefs_OptionText_add_tags_auto_force_existing_Info": {
"message": "If checked, the AI will add only existing tags to newly received emails, and won't create new tags.",
"description": ""
},
"prefs_OptionText_add_tags_auto_only_inbox": {
"message": "Only add tags to inbox emails",
"description": ""
},
"prefs_OptionText_add_tags_auto_only_inbox_Info": {
"message": "If checked, the AI will only add tags to emails received in the inbox folder.",
"description": ""
},
"placeholder_thunderai_def_sign": {
"message": "Default signature as defined in ThunderAI options.",
"description": ""
},
"thunderai_def_lang": {
"message": "Default language as defined in ThunderAI options.",
"description": ""
}
}

View file

@ -19,7 +19,8 @@
// Some original methods are derived from https://github.com/ali-raheem/Aify/blob/cfadf52f576b7be3720b5b73af7c8d3129c054da/plugin/html/actions.js
import { getPrompts } from './mzta-prompts.js';
import { getLanguageDisplayName, getMenuContextCompose, getMenuContextDisplay, i18nConditionalGet, getMailSubject, getTagsList, transformTagsLabels } from './mzta-utils.js'
import { getLanguageDisplayName, getMenuContextCompose, getMenuContextDisplay, i18nConditionalGet, getMailSubject, getTagsList } from './mzta-utils.js'
import { taPromptUtils } from './mzta-utils-prompt.js';
import { taLogger } from './mzta-logger.js';
import { placeholdersUtils } from './mzta-placeholders.js';
import { mzta_specialCommand } from './mzta-special-commands.js';
@ -106,18 +107,8 @@ export class mzta_Menus {
only_typed_text = msg_text.only_typed_text.replace(/\s+/g, ' ').trim();
//open chatgpt window
//console.log("Click menu item...");
let chatgpt_lang = '';
if(String(curr_prompt.define_response_lang) == "1"){
let prefs = await browser.storage.sync.get({default_chatgpt_lang: ''});
chatgpt_lang = prefs.default_chatgpt_lang;
//console.log(" >>>>>>>>>>>> chatgpt_lang: " + chatgpt_lang);
if(chatgpt_lang === ''){
chatgpt_lang = browser.i18n.getMessage("reply_same_lang");
}else{
chatgpt_lang = browser.i18n.getMessage("prompt_lang") + " " + chatgpt_lang + ".";
}
}
let chatgpt_lang = taPromptUtils.getDefaultLang(curr_prompt);
let fullPrompt = '';
let tags_full_list = await getTagsList();
@ -137,65 +128,7 @@ export class mzta_Menus {
break;
}
if(!placeholdersUtils.hasPlaceholder(curr_prompt.text)){
// no placeholders, do as usual
fullPrompt = curr_prompt.text + (String(curr_prompt.need_signature) == "1" ? " " + await this.getDefaultSignature():"") + " " + chatgpt_lang + " \"" + (selection_text=='' ? body_text : selection_text) + "\" ";
}else{
// we have at least a placeholder, do the magic!
let currPHs = await placeholdersUtils.extractPlaceholders(curr_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'] = body_text;
break;
case 'mail_html_body':
finalSubs['mail_html_body'] = msg_text.html;
break;
case 'mail_typed_text':
finalSubs['mail_typed_text'] = only_typed_text;
break;
case 'mail_subject':
let mail_subject = await getMailSubject(tabs[0]);
finalSubs['mail_subject'] = mail_subject;
break;
case 'selected_text':
finalSubs['selected_text'] = selection_text;
break;
case 'author':
finalSubs['author'] = curr_message.author;
break;
case 'recipients':
finalSubs['recipients'] = curr_message.recipients.join(", ");
break;
case 'cc_list':
finalSubs['cc_list'] = curr_message.ccList.join(", ");
break;
case 'junk_score':
finalSubs['junk_score'] = curr_message.junkScore;
break;
case 'mail_datetime':
finalSubs['mail_datetime'] = curr_message.date;
break;
case 'current_datetime':
finalSubs['current_datetime'] = new Date().toString();
break;
case 'tags_current_email':
let tags_current_email_array = await transformTagsLabels(curr_message.tags, tags_full_list[1]);
finalSubs['tags_current_email'] = tags_current_email_array.join(", ");
break;
case 'tags_full_list':
finalSubs['tags_full_list'] = tags_full_list[0];
break;
default: // TODO Manage custom placeholders https://github.com/micz/ThunderAI/issues/156
break;
}
}
// console.log(">>>>>>>>>> finalSubs: " + JSON.stringify(finalSubs));
let prefs_ph = await browser.storage.sync.get({placeholders_use_default_value: false});
fullPrompt = (placeholdersUtils.replacePlaceholders(curr_prompt.text, finalSubs, prefs_ph.placeholders_use_default_value, true) + (String(curr_prompt.need_signature) == "1" ? " " + await this.getDefaultSignature():"") + " " + chatgpt_lang).trim();
}
fullPrompt = await taPromptUtils.preparePrompt(curr_prompt, curr_message, chatgpt_lang, selection_text, body_text, await getMailSubject(tabs[0]), msg_text, only_typed_text, tags_full_list);
switch(curr_prompt.id){
case 'prompt_translate_this':
@ -220,26 +153,20 @@ export class mzta_Menus {
switch(curr_prompt.id){
case 'prompt_add_tags': { // Add tags to the email
let tags_current_email = '';
let prefs_at = await browser.storage.sync.get({add_tags_maxnum: 3, connection_type: '', add_tags_force_lang: true, default_chatgpt_lang: ''});
let prefs_at = await browser.storage.sync.get({add_tags_maxnum: 3, connection_type: '', add_tags_force_lang: true, default_chatgpt_lang: '', do_debug: false});
if((prefs_at.connection_type === '')||(prefs_at.connection_type === null)||(prefs_at.connection_type === undefined)||(prefs_at.connection_type === 'chatgpt_web')){
console.error("[ThunderAI | AddTags] Invalid connection type: " + prefs_at.connection_type);
return {ok:'0'};
}
let add_tags_maxnum = prefs_at.add_tags_maxnum;
if(add_tags_maxnum > 0){
fullPrompt += " " + browser.i18n.getMessage("prompt_add_tags_maxnum") + " " + add_tags_maxnum +".";
}
if(prefs_at.add_tags_force_lang && prefs_at.default_chatgpt_lang !== ''){
fullPrompt += " " + browser.i18n.getMessage("prompt_add_tags_force_lang") + " " + prefs_at.default_chatgpt_lang + ".";
}
fullPrompt = taPromptUtils.finalizePrompt_add_tags(fullPrompt, prefs_at.add_tags_maxnum, prefs_at.add_tags_force_lang, prefs_at.default_chatgpt_lang);
this.logger.log("fullPrompt: " + fullPrompt);
// TODO: use the current API, abort if using chatgpt web
// COMMENTED TO DO TESTS
// tags_current_email = "recipients, TEST, home, work, CAR, light";
let cmd_addTags = new mzta_specialCommand(fullPrompt,prefs_at.connection_type,true);
let cmd_addTags = new mzta_specialCommand(fullPrompt,prefs_at.connection_type,prefs_at.do_debug);
await cmd_addTags.initWorker();
try{
tags_current_email = await cmd_addTags.sendPrompt();
tags_current_email = (await cmd_addTags.sendPrompt()).trim();
// console.log(">>>>>>>>>>> tags_current_email: " + tags_current_email);
}catch(err){
console.error("[ThunderAI] Error getting tags: ", err);
@ -306,15 +233,6 @@ export class mzta_Menus {
this.rootMenu.push(curr_menu_entry);
};
async getDefaultSignature(){
let prefs = await browser.storage.sync.get({default_sign_name: ''});
if(prefs.default_sign_name===''){
return '';
}else{
return browser.i18n.getMessage("sign_msg_as") + " " + prefs.default_sign_name + ".";
}
}
loadShortcutMenu() {
this.shortcutMenu = [];
this.allPrompts.forEach((prompt) => {

View file

@ -131,6 +131,20 @@ const defaultPlaceholders = [
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",
},
];
@ -246,4 +260,64 @@ export const placeholdersUtils = {
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'] = body_text;
break;
case 'mail_html_body':
finalSubs['mail_html_body'] = msg_text.html;
break;
case 'mail_typed_text':
finalSubs['mail_typed_text'] = only_typed_text;
break;
case 'mail_subject':
finalSubs['mail_subject'] = mail_subject;
break;
case 'selected_text':
finalSubs['selected_text'] = selection_text;
break;
case 'author':
finalSubs['author'] = curr_message.author;
break;
case 'recipients':
finalSubs['recipients'] = curr_message.recipients.join(", ");
break;
case 'cc_list':
finalSubs['cc_list'] = curr_message.ccList.join(", ");
break;
case 'junk_score':
finalSubs['junk_score'] = curr_message.junkScore;
break;
case 'mail_datetime':
finalSubs['mail_datetime'] = curr_message.date;
break;
case 'current_datetime':
finalSubs['current_datetime'] = new Date().toString();
break;
case 'tags_current_email':
let tags_current_email_array = await transformTagsLabels(curr_message.tags, tags_full_list[1]);
finalSubs['tags_current_email'] = tags_current_email_array.join(", ");
break;
case 'tags_full_list':
finalSubs['tags_full_list'] = 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'] = 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'] = prefs_def_lang.default_chatgpt_lang;
break;
default: // TODO Manage custom placeholders https://github.com/micz/ThunderAI/issues/156
break;
}
}
}
}

74
js/mzta-utils-prompt.js Normal file
View file

@ -0,0 +1,74 @@
/*
* 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/>.
*/
import { placeholdersUtils } from './mzta-placeholders.js';
export const taPromptUtils = {
async getDefaultSignature(){
let prefs = await browser.storage.sync.get({default_sign_name: ''});
if(prefs.default_sign_name===''){
return '';
}else{
return browser.i18n.getMessage("sign_msg_as") + " " + prefs.default_sign_name + ".";
}
},
async preparePrompt(curr_prompt, curr_message, chatgpt_lang, selection_text, body_text, subject_text, msg_text, only_typed_text, tags_full_list){
let fullPrompt = '';
if(!placeholdersUtils.hasPlaceholder(curr_prompt.text)){
// no placeholders, do as usual
fullPrompt = curr_prompt.text + (String(curr_prompt.need_signature) == "1" ? " " + await taPromptUtils.getDefaultSignature():"") + " " + chatgpt_lang + " \"" + (selection_text=='' ? body_text : selection_text) + "\" ";
}else{
// we have at least a placeholder, do the magic!
let finalSubs = placeholdersUtils.getPlaceholdersValues(curr_prompt.text, curr_message, subject_text, body_text, msg_text, only_typed_text, selection_text, tags_full_list);
// console.log(">>>>>>>>>> finalSubs: " + JSON.stringify(finalSubs));
let prefs_ph = await browser.storage.sync.get({placeholders_use_default_value: false});
fullPrompt = (placeholdersUtils.replacePlaceholders(curr_prompt.text, finalSubs, prefs_ph.placeholders_use_default_value, true) + (String(curr_prompt.need_signature) == "1" ? " " + await taPromptUtils.getDefaultSignature():"") + " " + chatgpt_lang).trim();
}
return fullPrompt;
},
finalizePrompt_add_tags(fullPrompt, add_tags_maxnum, add_tags_force_lang, default_chatgpt_lang){
if(add_tags_maxnum > 0){
fullPrompt += " " + browser.i18n.getMessage("prompt_add_tags_maxnum") + " " + add_tags_maxnum +".";
}
if(add_tags_force_lang && default_chatgpt_lang !== ''){
fullPrompt += " " + browser.i18n.getMessage("prompt_add_tags_force_lang") + " " + default_chatgpt_lang + ".";
}
return fullPrompt;
},
async getDefaultLang(curr_prompt){
let chatgpt_lang = '';
if(String(curr_prompt.define_response_lang) == "1"){
let prefs = await browser.storage.sync.get({default_chatgpt_lang: ''});
chatgpt_lang = prefs.default_chatgpt_lang;
if(chatgpt_lang === ''){
chatgpt_lang = browser.i18n.getMessage("reply_same_lang");
}else{
chatgpt_lang = browser.i18n.getMessage("prompt_lang") + " " + chatgpt_lang + ".";
}
}
return chatgpt_lang;
},
};

View file

@ -83,6 +83,29 @@ export async function getMailSubject(tab){
}
}
export async function getMailBody(fullMessage){
let text = '';
let html = '';
if (fullMessage.contentType.trim().toLowerCase() === "text/plain") {
text = fullMessage.body;
}
if (fullMessage.contentType.trim().toLowerCase() === "text/html") {
html = fullMessage.body;
}
for (let part of fullMessage.parts) {
if (part.contentType.trim().toLowerCase() === "text/plain") {
text = part.body;
}
if (part.contentType.trim().toLowerCase() === "text/html") {
html = part.body;
}
}
return {text, html};
}
export async function reloadBody(tabId){
let composeDetails = await messenger.compose.getComposeDetails(tabId);
let originalHtmlBody = composeDetails.body + " ";
@ -403,3 +426,17 @@ export async function migrateDefaultPromptsPropStorage(){
await browser.storage.sync.remove("_default_prompts_properties");
// console.log("migrateDefaultPromptsPropStorage: migrated default prompts properties from storage.sync to storage.local");
}
export async function* getMessages(list) {
let page = await list;
for (let message of page.messages) {
yield message;
}
while (page.id) {
page = await messenger.messages.continueList(page.id);
for (let message of page.messages) {
yield message;
}
}
}

View file

@ -20,7 +20,9 @@ import { mzta_script } from './js/mzta-chatgpt.js';
import { prefs_default } from './options/mzta-options-default.js';
import { mzta_Menus } from './js/mzta-menus.js';
import { taLogger } from './js/mzta-logger.js';
import { getCurrentIdentity, getOriginalBody, replaceBody, setBody, i18nConditionalGet, generateCallID, migrateCustomPromptsStorage, migrateDefaultPromptsPropStorage, getGPTWebModelString, getTagsList, createTag, assignTagsToMessage, checkIfTagExists, getActiveSpecialPromptsIDs, checkSparksPresence } from './js/mzta-utils.js';
import { getCurrentIdentity, getOriginalBody, replaceBody, setBody, i18nConditionalGet, generateCallID, migrateCustomPromptsStorage, migrateDefaultPromptsPropStorage, getGPTWebModelString, getTagsList, createTag, assignTagsToMessage, checkIfTagExists, getActiveSpecialPromptsIDs, checkSparksPresence, getMessages, getMailBody } from './js/mzta-utils.js';
import { taPromptUtils } from './js/mzta-utils-prompt.js';
import { mzta_specialCommand } from './js/mzta-special-commands.js';
await migrateCustomPromptsStorage();
await migrateDefaultPromptsPropStorage();
@ -28,7 +30,9 @@ await migrateDefaultPromptsPropStorage();
var original_html = '';
var modified_html = '';
let prefs_init = await browser.storage.sync.get({do_debug: false, add_tags: true, get_calendar_event: true, connection_type: 'chatgpt_web'});
let prefs_init = {};
await reload_pref_init();
let taLog = new taLogger("mzta-background",prefs_init.do_debug);
let special_prompts_ids = getActiveSpecialPromptsIDs(prefs_init.add_tags, await doGetCalendarEvent(prefs_init.get_calendar_event), (prefs_init.connection_type === "chatgpt_web"));
@ -134,6 +138,24 @@ async function _reload_menus() {
return true;
}
async function _assign_tags(_data, create_new_tags = true) {
let all_tags_list = await getTagsList();
all_tags_list = all_tags_list[1];
// console.log(">>>>>>>>>>>>>>> all_tags_list: " + JSON.stringify(all_tags_list));
taLog.log("assign_tags data: " + JSON.stringify(_data));
let new_tags = [];
for (const tag of _data.tags) {
// console.log(">>>>>>>>>>>>>>> tag: " + tag);
if (create_new_tags && !checkIfTagExists(tag, all_tags_list)) {
taLog.log("Creating tag: " + tag);
await createTag(tag);
}
new_tags.push(tag);
}
await assignTagsToMessage(_data.messageId, new_tags);
taLog.log("Assigned tags: " + JSON.stringify(new_tags));
}
messenger.runtime.onMessage.addListener((message, sender, sendResponse) => {
// Check what type of message we have received and invoke the appropriate
// handler function.
@ -240,24 +262,7 @@ messenger.runtime.onMessage.addListener((message, sender, sendResponse) => {
return _popup_menu_ready();
break;
case 'assign_tags':
async function _assign_tags() {
let all_tags_list = await getTagsList();
all_tags_list = all_tags_list[1];
// console.log(">>>>>>>>>>>>>>> all_tags_list: " + JSON.stringify(all_tags_list));
taLog.log("assign_tags data: " + JSON.stringify(message));
let new_tags = [];
for (const tag of message.tags) {
// console.log(">>>>>>>>>>>>>>> tag: " + tag);
if (!checkIfTagExists(tag, all_tags_list)) {
taLog.log("Creating tag: " + tag);
await createTag(tag);
}
new_tags.push(tag);
}
await assignTagsToMessage(message.messageId, new_tags);
taLog.log("Assigned tags: " + JSON.stringify(new_tags));
}
return _assign_tags();
return _assign_tags(message);
break;
default:
break;
@ -596,7 +601,7 @@ async function doGetCalendarEvent(get_calendar_event) {
}
async function reload_pref_init(){
prefs_init = await browser.storage.sync.get({do_debug: false, add_tags: true, get_calendar_event: true, connection_type: 'chatgpt_web'});
prefs_init = await browser.storage.sync.get({do_debug: false, add_tags: true, get_calendar_event: true, connection_type: 'chatgpt_web', add_tags_auto: false, add_tags_auto_force_existing: false, add_tags_auto_only_inbox: true});
}
@ -639,7 +644,85 @@ function setupStorageChangeListener() {
// Call the function to set up the listener
setupStorageChangeListener();
// Menus handling
const menus = new mzta_Menus(openChatGPT, prefs_init.do_debug);
menus.loadMenus(special_prompts_ids);
menus.loadMenus(special_prompts_ids);
// Listening for new received emails
const newEmailListener = (folder, messagesList) => {
taLog.log("New mail received");
taLog.log(`Folder: ${folder.name}`);
async function _newEmailListener(){
let messages = getMessages(messagesList);
for await (let message of messages) {
let fullMessage = await browser.messages.getFull(message.id);
taLog.log(`From: ${fullMessage.headers.from}`);
taLog.log(`Subject: ${fullMessage.headers.subject}`);
taLog.log(`Name: ${fullMessage.name}`);
taLog.log(`Body: ${fullMessage.body}`);
taLog.log(`contentType: [${fullMessage.contentType}]`);
taLog.log(`fullMessage.parts.length: ${fullMessage.parts.length}`);
if (fullMessage.parts.length > 0) {
for (let part of fullMessage.parts) {
taLog.log(`From: ${part.headers.from}`);
taLog.log(`Subject: ${part.headers.subject}`);
taLog.log(`Name: ${part.name}`);
taLog.log(`Body: ${part.body}`);
taLog.log(`contentType: [${part.contentType}]`);
taLog.log('contentType JSON: '+JSON.stringify(part.contentType));
if (part.contentType.trim().toLowerCase() === "text/plain") {
taLog.log("Body (text/plain):" + part.body);
// return part.body;
}
if (part.contentType.trim().toLowerCase() === "text/html") {
taLog.log("Body (text/html):" + part.body);
// return part.body;
}
}
}
let specialFullPrompt = '';
let curr_fullMessage = null;
// if some auto feature is active prepare some data
// this will be used when will be implemented the spam filter (https://github.com/micz/ThunderAI/issues/231)
// or the auto translator https://github.com/micz/ThunderAI/issues/247
if(prefs_init.add_tags_auto){
curr_fullMessage = await browser.messages.getFull(message.id);
}
// Auto add_tags
if(prefs_init.add_tags_auto){
let curr_prompt_add_tags = menus.allPrompts.find(p => p.id === 'prompt_add_tags');
let chatgpt_lang = taPromptUtils.getDefaultLang(curr_prompt_add_tags);
let msg_text = await getMailBody(curr_fullMessage);
let body_text = msg_text.text.replace(/\s+/g, ' ').trim();
let tags_full_list = await getTagsList();
specialFullPrompt = await taPromptUtils.preparePrompt(curr_prompt_add_tags, message, chatgpt_lang, /*selection_text*/ '', body_text, curr_fullMessage.headers.subject, msg_text, /*only_typed_text*/ '', tags_full_list);
let prefs_aat = await browser.storage.sync.get({add_tags_maxnum: 3, connection_type: '', add_tags_force_lang: true, default_chatgpt_lang: '', add_tags_auto_force_existing: false});
specialFullPrompt = taPromptUtils.finalizePrompt_add_tags(specialFullPrompt, prefs_aat.add_tags_maxnum, prefs_aat.add_tags_force_lang, prefs_aat.default_chatgpt_lang);
taLog.log("Special prompt: " + specialFullPrompt);
let cmd_addTags = new mzta_specialCommand(specialFullPrompt,prefs_aat.connection_type,prefs_init.do_debug);
await cmd_addTags.initWorker();
let tags_current_email = '';
try{
tags_current_email = (await cmd_addTags.sendPrompt()).trim();
}catch(err){
console.error("[ThunderAI | Auto add_tags] Error getting tags: ", err);
}
taLog.log("tags_current_email: " + tags_current_email);
let _data = {messageId: message.id, tags: tags_current_email.split(/,\s*/)};
_assign_tags(_data, !prefs_aat.add_tags_auto_force_existing);
}
}
}
return _newEmailListener();
}
browser.messages.onNewMailReceived.addListener(newEmailListener, !prefs_init.add_tags_auto_only_inbox);

View file

@ -21,6 +21,7 @@ export const prefs_default = {
chatgpt_win_height: 800,
chatgpt_win_width: 700,
default_chatgpt_lang: '',
default_sign_name: '',
connection_type: 'chatgpt_web', //Other values: 'chatgpt_api', 'ollama_api', 'openai_comp_api', 'google_gemini_api'
chatgpt_web_model: '',
chatgpt_web_tempchat: false,
@ -46,5 +47,8 @@ export const prefs_default = {
add_tags_hide_exclusions: false,
add_tags_first_uppercase: true,
add_tags_force_lang: true,
add_tags_auto: false,
add_tags_auto_force_existing: false,
add_tags_auto_only_inbox: true,
get_calendar_event: true,
}

View file

@ -9,6 +9,10 @@
<div id="miczRelNotes"><h1>ThunderAI Release Notes</h1>
<h2>Version 3.2.0 - ??/??/2025</h2>
<ul>
<li>Added an option to automatically tag incoming emails [<a href="https://github.com/micz/ThunderAI/issues/237">#237</a>].</li>
<li>Added the <i>{%thunderai_def_sign%}</i> placeholder to get the default signature as defined in the options [<a href="https://github.com/micz/ThunderAI/issues/248">#248</a>].</li>
<li>Added the <i>{%thunderai_def_lang%}</i> placeholder to get the default language as defined in the options [<a href="https://github.com/micz/ThunderAI/issues/248">#248</a>].</li>
<li>Various minor improvements.</li>
<li>...</li>
</ul>
<h2>Version 3.1.2 - 29/01/2025</h2>

View file

@ -27,7 +27,7 @@
justify-content: space-between;
}
#addtags_info_additional_statements{
#addtags_info_additional_statements, #add_tags_auto_force_existing_tr, #add_tags_auto_only_inbox_tr{
display: none;
}

View file

@ -49,6 +49,33 @@
</label>
</td>
</tr>
<tr class="add_tags_tr">
<td><span>__MSG_prefs_OptionText_add_tags_auto__</span></td>
<td>
<label>
<input type="checkbox" id="add_tags_auto" name="add_tags_auto" class="option-input" />
__MSG_prefs_OptionText_add_tags_auto_Info__
</label>
</td>
</tr>
<tr class="add_tags_tr" id="add_tags_auto_force_existing_tr">
<td><span>__MSG_prefs_OptionText_add_tags_auto_force_existing__</span></td>
<td>
<label>
<input type="checkbox" id="add_tags_auto_force_existing" name="add_tags_auto_force_existing" class="option-input" />
__MSG_prefs_OptionText_add_tags_auto_force_existing_Info__
</label>
</td>
</tr>
<tr class="add_tags_tr" id="add_tags_auto_only_inbox_tr">
<td><span>__MSG_prefs_OptionText_add_tags_auto_only_inbox__</span></td>
<td>
<label>
<input type="checkbox" id="add_tags_auto_only_inbox" name="add_tags_auto_only_inbox" class="option-input" />
__MSG_prefs_OptionText_add_tags_auto_only_inbox_Info__
</label>
</td>
</tr>
</table>
<div id="addtags_prompt_container">
<span class="section_title">__MSG_AddTags_prompt_text_title__</span><span id="addtags_prompt_unsaved" class="unsaved hidden"> __MSG_customPrompts_unsaved_changes__</span>

View file

@ -53,6 +53,16 @@ document.addEventListener('DOMContentLoaded', async () => {
}
});
let add_tags_auto_el = document.getElementById('add_tags_auto');
let add_tags_auto_force_existing_tr = document.getElementById('add_tags_auto_force_existing_tr');
let add_tags_auto_only_inbox_tr = document.getElementById('add_tags_auto_only_inbox_tr');
add_tags_auto_el.addEventListener('click', (event) => {
add_tags_auto_force_existing_tr.style.display = event.target.checked ? 'table-row' : 'none';
add_tags_auto_only_inbox_tr.style.display = event.target.checked ? 'table-row' : 'none';
});
add_tags_auto_force_existing_tr.style.display = add_tags_auto_el.checked ? 'table-row' : 'none';
add_tags_auto_only_inbox_tr.style.display = add_tags_auto_el.checked ? 'table-row' : 'none';
addtags_reset_btn.addEventListener('click', () => {
addtags_textarea.value = browser.i18n.getMessage('prompt_add_tags_full_text');
addtags_reset_btn.disabled = true;