-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbackground.js
186 lines (159 loc) · 5.41 KB
/
background.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
// Debug mode flag
const debug_mode = true;
// Debug logger
const debug = (message, data = null) => {
if (debug_mode) {
if (data) {
console.log(`[LinguaSwap Debug] ${message}:`, data);
} else {
console.log(`[LinguaSwap Debug] ${message}`);
}
}
};
// Initialize context menu
chrome.runtime.onInstalled.addListener(() => {
debug('Extension installed/updated');
chrome.contextMenus.create({
id: 'addToLinguaSwap',
title: 'Add to LinguaSwap',
contexts: ['selection']
});
debug('Context menu created');
// Initialize storage with default settings if not exists
chrome.storage.local.get(['settings', 'wordLists'], (result) => {
debug('Initial storage state:', result);
if (!result.settings) {
const initialSettings = {
settings: {
defaultLanguage: '',
targetLanguage: ''
},
wordLists: {}
};
chrome.storage.local.set(initialSettings);
debug('Initialized default settings:', initialSettings);
}
});
});
// Handle context menu clicks: add selected text to LinguaSwap word list, translate it, and notify content script
chrome.contextMenus.onClicked.addListener(async (info, tab) => {
if (info.menuItemId === 'addToLinguaSwap') {
const selectedText = info.selectionText.toLowerCase().trim();
debug('Selected text:', selectedText);
// Get settings and existing word lists
const { settings, wordLists = {} } = await chrome.storage.local.get(['settings', 'wordLists']);
debug('Current settings:', settings);
debug('Current wordLists:', wordLists);
// Translate the word using LinguaSwap API
try {
debug('Attempting translation', {
text: selectedText,
sourceLang: settings.defaultLanguage,
targetLang: settings.targetLanguage
});
const translation = await translateWord(
selectedText,
settings.defaultLanguage,
settings.targetLanguage
);
debug('Translation result:', translation);
// Create language pair key
const langPairKey = `${settings.defaultLanguage}-${settings.targetLanguage}`;
debug('Language pair key:', langPairKey);
// Initialize word list for this language pair if it doesn't exist
if (!wordLists[langPairKey]) {
debug('Creating new word list for language pair');
wordLists[langPairKey] = {};
}
// Add to specific language pair word list
wordLists[langPairKey][selectedText] = translation;
await chrome.storage.local.set({ wordLists });
debug('Updated word lists:', wordLists);
// Notify content script to update the page
chrome.tabs.sendMessage(tab.id, {
type: 'wordAdded',
word: selectedText,
translation,
langPairKey
});
debug('Sent update message to content script');
} catch (error) {
debug('Translation error:', error);
chrome.tabs.sendMessage(tab.id, {
type: 'showNotification',
message: 'Translation failed.'
});
}
}
});
// Function to generate a URL-safe random hash ID
function generateHashId() {
// Generate 16 random bytes
const buffer = crypto.getRandomValues(new Uint8Array(16));
// Convert to Base64
const base64 = btoa(String.fromCharCode.apply(null, buffer));
// Make Base64 URL-safe
const urlSafeHash = base64
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
return urlSafeHash;
}
// Function to translate a word using the LinguaSwap API
async function translateWord(text, sourceLang, targetLang) {
debug('translateWord called with:', { text, sourceLang, targetLang });
// Get settings and caller ID
const { settings, callerId } = await chrome.storage.local.get(['settings', 'callerId']);
let currentCallerId = callerId;
if (!currentCallerId) {
currentCallerId = generateHashId();
await chrome.storage.local.set({ callerId: currentCallerId });
debug('Generated new caller ID:', currentCallerId);
}
const baseUrl = 'https://linguaswap.524619251.xyz/api/translate';
const params = new URLSearchParams({
text,
target_lang: targetLang,
provider: settings.provider,
caller: currentCallerId
});
// Only add source_lang if it's provided (otherwise let API auto-detect)
if (sourceLang) {
params.append('source_lang', sourceLang);
}
debug('API request:', {
url: `${baseUrl}?${params.toString()}`,
method: 'GET',
headers: {
'Accept': 'application/json',
'Origin': `chrome-extension://${chrome.runtime.id}`
}
});
const url = `${baseUrl}?${params.toString()}`;
const response = await fetch(url, {
method: 'GET',
headers: {
'Accept': 'application/json',
'Origin': `chrome-extension://${chrome.runtime.id}`
}
});
debug('API response status:', response.status);
if (!response.ok) {
const errorText = await response.text();
debug('API error response:', errorText);
// More specific error handling based on status codes
switch (response.status) {
case 400:
throw new Error('Invalid parameters or text too long (max 30 characters)');
case 401:
throw new Error('Unauthorized: Origin not allowed');
case 405:
throw new Error('Method not allowed');
default:
throw new Error('Translation failed');
}
}
const data = await response.json();
debug('API success response:', data);
return data.translations[0].text;
}