Merge pull request #64 from outis1one/claude/read-repo-yLNcT
Claude/read repo y l nc t
This commit is contained in:
@@ -7,3 +7,4 @@ node_modules/
|
|||||||
dist/
|
dist/
|
||||||
.env
|
.env
|
||||||
web-ext-artifacts/
|
web-ext-artifacts/
|
||||||
|
.version-bump-undo
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"manifest_version": 3,
|
"manifest_version": 3,
|
||||||
"name": "Silent Send",
|
"name": "Silent Send",
|
||||||
"version": "0.9.31",
|
"version": "0.9.32",
|
||||||
"description": "Intercepts personal info and substitutes it with user-defined replacements before sending to AI services.",
|
"description": "Intercepts personal info and substitutes it with user-defined replacements before sending to AI services.",
|
||||||
"browser_specific_settings": {
|
"browser_specific_settings": {
|
||||||
"gecko": {
|
"gecko": {
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"manifest_version": 3,
|
"manifest_version": 3,
|
||||||
"name": "Silent Send",
|
"name": "Silent Send",
|
||||||
"version": "0.9.31",
|
"version": "0.9.32",
|
||||||
"description": "Intercepts personal info and substitutes it with user-defined replacements before sending to AI services.",
|
"description": "Intercepts personal info and substitutes it with user-defined replacements before sending to AI services.",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"storage",
|
"storage",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "silent-send",
|
"name": "silent-send",
|
||||||
"version": "0.9.31",
|
"version": "0.9.32",
|
||||||
"private": true,
|
"private": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"description": "Browser extension that substitutes personal data before sending to AI services",
|
"description": "Browser extension that substitutes personal data before sending to AI services",
|
||||||
|
|||||||
+32
-2
@@ -752,12 +752,42 @@ const SilentSendSync = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search the authenticated user's Gists for one containing silent-send-sync.json.
|
||||||
|
* Returns the Gist ID string, or null if not found.
|
||||||
|
*/
|
||||||
|
async _findSyncGistId(token) {
|
||||||
|
try {
|
||||||
|
let page = 1;
|
||||||
|
while (page <= 5) {
|
||||||
|
const resp = await fetch(`https://api.github.com/gists?per_page=100&page=${page}`, {
|
||||||
|
headers: { Authorization: `token ${token}` },
|
||||||
|
});
|
||||||
|
if (!resp.ok) return null;
|
||||||
|
const gists = await resp.json();
|
||||||
|
if (!gists.length) break;
|
||||||
|
for (const gist of gists) {
|
||||||
|
if (gist.files?.['silent-send-sync.json']) return gist.id;
|
||||||
|
}
|
||||||
|
if (gists.length < 100) break;
|
||||||
|
page++;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} catch { return null; }
|
||||||
|
},
|
||||||
|
|
||||||
async pullFromGist(token) {
|
async pullFromGist(token) {
|
||||||
if (!token) return { success: false, reason: 'No GitHub token provided.' };
|
if (!token) return { success: false, reason: 'No GitHub token provided.' };
|
||||||
try {
|
try {
|
||||||
const stored = await api.storage.local.get('ss_gist_id');
|
const stored = await api.storage.local.get('ss_gist_id');
|
||||||
const gistId = stored.ss_gist_id;
|
let gistId = stored.ss_gist_id;
|
||||||
if (!gistId) return { success: false, reason: 'No Gist ID stored. Push first.' };
|
|
||||||
|
if (!gistId) {
|
||||||
|
// No locally-stored Gist ID — search the account for one
|
||||||
|
gistId = await this._findSyncGistId(token);
|
||||||
|
if (!gistId) return { success: false, reason: 'No sync Gist found. Push from the source browser first.' };
|
||||||
|
await api.storage.local.set({ ss_gist_id: gistId });
|
||||||
|
}
|
||||||
|
|
||||||
const resp = await fetch(`https://api.github.com/gists/${gistId}`, {
|
const resp = await fetch(`https://api.github.com/gists/${gistId}`, {
|
||||||
headers: { Authorization: `token ${token}` },
|
headers: { Authorization: `token ${token}` },
|
||||||
|
|||||||
+36
-2
@@ -189,7 +189,24 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||||||
const r = await SilentSendSync.pullFromGist(token);
|
const r = await SilentSendSync.pullFromGist(token);
|
||||||
if (r.needsAuth) {
|
if (r.needsAuth) {
|
||||||
setGistSyncStatus('Authentication required to decrypt.', 'warn');
|
setGistSyncStatus('Authentication required to decrypt.', 'warn');
|
||||||
showSyncAuthPrompt();
|
window.__ssPendingSyncImport = async () => {
|
||||||
|
const r2 = await SilentSendSync.pullFromGist(token);
|
||||||
|
if (r2.needsAuth) {
|
||||||
|
setGistSyncStatus('Authentication failed — wrong password?', 'error');
|
||||||
|
} else if (!r2.success) {
|
||||||
|
setGistSyncStatus('Pull failed: ' + r2.reason, 'error');
|
||||||
|
} else if (r2.imported) {
|
||||||
|
setGistSyncStatus(`Pulled (${r2.time}). Refreshing…`, 'ok');
|
||||||
|
mappings = await Storage.getMappings();
|
||||||
|
settings = await Storage.getSettings();
|
||||||
|
renderMappings();
|
||||||
|
renderDomains();
|
||||||
|
renderLog();
|
||||||
|
} else {
|
||||||
|
setGistSyncStatus('Already up to date.', 'ok');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
showSyncAuthPrompt('decrypt');
|
||||||
} else if (!r.success) {
|
} else if (!r.success) {
|
||||||
setGistSyncStatus('Pull failed: ' + r.reason, 'error');
|
setGistSyncStatus('Pull failed: ' + r.reason, 'error');
|
||||||
} else if (r.imported) {
|
} else if (r.imported) {
|
||||||
@@ -229,7 +246,24 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||||||
const r = await SilentSendSync.pullFromUrl({ url, headers });
|
const r = await SilentSendSync.pullFromUrl({ url, headers });
|
||||||
if (r.needsAuth) {
|
if (r.needsAuth) {
|
||||||
setUrlSyncStatus('Authentication required to decrypt.', 'warn');
|
setUrlSyncStatus('Authentication required to decrypt.', 'warn');
|
||||||
showSyncAuthPrompt();
|
window.__ssPendingSyncImport = async () => {
|
||||||
|
const r2 = await SilentSendSync.pullFromUrl({ url, headers });
|
||||||
|
if (r2.needsAuth) {
|
||||||
|
setUrlSyncStatus('Authentication failed — wrong password?', 'error');
|
||||||
|
} else if (!r2.success) {
|
||||||
|
setUrlSyncStatus('Pull failed: ' + r2.reason, 'error');
|
||||||
|
} else if (r2.imported) {
|
||||||
|
setUrlSyncStatus(`Pulled (${r2.time}). Refreshing…`, 'ok');
|
||||||
|
mappings = await Storage.getMappings();
|
||||||
|
settings = await Storage.getSettings();
|
||||||
|
renderMappings();
|
||||||
|
renderDomains();
|
||||||
|
renderLog();
|
||||||
|
} else {
|
||||||
|
setUrlSyncStatus('Already up to date.', 'ok');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
showSyncAuthPrompt('decrypt');
|
||||||
} else if (!r.success) {
|
} else if (!r.success) {
|
||||||
setUrlSyncStatus('Pull failed: ' + r.reason, 'error');
|
setUrlSyncStatus('Pull failed: ' + r.reason, 'error');
|
||||||
} else if (r.imported) {
|
} else if (r.imported) {
|
||||||
|
|||||||
Reference in New Issue
Block a user