fc3g(ext): cookies extraction + FC backend API client
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* FC backend client. Talks to /api/credentials (FC-3b), /api/sources
|
||||
* (FC-3a), and the new /api/extension/* endpoints (FC-3g).
|
||||
*/
|
||||
|
||||
class FabledCuratorAPI {
|
||||
constructor() {
|
||||
this.baseUrl = null;
|
||||
this.apiKey = null;
|
||||
}
|
||||
|
||||
async init() {
|
||||
const cfg = await browser.storage.local.get(['apiUrl', 'apiKey']);
|
||||
this.baseUrl = cfg.apiUrl || null;
|
||||
this.apiKey = cfg.apiKey || null;
|
||||
return this.isConfigured();
|
||||
}
|
||||
|
||||
isConfigured() {
|
||||
return !!(this.baseUrl && this.apiKey);
|
||||
}
|
||||
|
||||
async request(method, endpoint, data = null) {
|
||||
if (!this.isConfigured()) {
|
||||
throw new Error('Not configured. Set FC URL + API key in settings.');
|
||||
}
|
||||
const url = `${this.baseUrl.replace(/\/+$/, '')}${endpoint}`;
|
||||
const options = {
|
||||
method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Extension-Key': this.apiKey,
|
||||
},
|
||||
};
|
||||
if (data) options.body = JSON.stringify(data);
|
||||
|
||||
let response;
|
||||
try {
|
||||
response = await fetch(url, options);
|
||||
} catch (e) {
|
||||
throw new Error('Cannot connect to FabledCurator. Check URL.');
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
let message;
|
||||
try {
|
||||
const body = await response.json();
|
||||
message = body.error || `HTTP ${response.status}`;
|
||||
if (body.detail) message += `: ${body.detail}`;
|
||||
} catch {
|
||||
message = `HTTP ${response.status}: ${response.statusText}`;
|
||||
}
|
||||
const err = new Error(message);
|
||||
err.status = response.status;
|
||||
throw err;
|
||||
}
|
||||
|
||||
if (response.status === 204) return { success: true };
|
||||
return response.json();
|
||||
}
|
||||
|
||||
// FC-3b — credentials.
|
||||
uploadCredentials(platform, credentialType, data) {
|
||||
return this.request('POST', '/credentials', {
|
||||
platform,
|
||||
credential_type: credentialType,
|
||||
data,
|
||||
});
|
||||
}
|
||||
getCredentials() {
|
||||
return this.request('GET', '/credentials');
|
||||
}
|
||||
|
||||
// FC-3a — sources.
|
||||
listSources() {
|
||||
return this.request('GET', '/sources');
|
||||
}
|
||||
triggerSourceCheck(sourceId) {
|
||||
return this.request('POST', `/sources/${sourceId}/check`);
|
||||
}
|
||||
|
||||
// FC-3g — extension-specific.
|
||||
quickAddSource(url) {
|
||||
return this.request('POST', '/extension/quick-add-source', { url });
|
||||
}
|
||||
|
||||
// Connection test = the cheapest read with auth.
|
||||
testConnection() {
|
||||
return this.request('GET', '/credentials');
|
||||
}
|
||||
}
|
||||
|
||||
const api = new FabledCuratorAPI();
|
||||
Reference in New Issue
Block a user