(function() { const extensionName = "Amily-Databin"; const apiBaseUrl = `/api/plugins/${extensionName}`; // ---------------------------------------------------------------- // Private Helper Functions // ---------------------------------------------------------------- /** * Retrieves the current context from SillyTavern and maps it to the expected object name. * This function attempts to get context dynamically from SillyTavern's global objects. */ function _getDynamicObjectName(source) { const { SillyTavern } = window; let context = null; if (SillyTavern && typeof SillyTavern.getContext === 'function') { context = SillyTavern.getContext(); } else { console.error(`[${extensionName}] window.SillyTavern.getContext() not found. Dynamic context resolution is not possible.`); return null; } if (!context) { console.error(`[${extensionName}] SillyTavern context is null or undefined.`); return null; } let resolvedObjectName = null; switch (source) { case AmilyDatabin.SourceType.CHAT_LOG: resolvedObjectName = context.chatId; break; case AmilyDatabin.SourceType.CHARACTER_CARD: resolvedObjectName = context.characterId; break; case AmilyDatabin.SourceType.WORLD_BOOK: // From the provided getContext() structure, there is no direct 'current world book name' key. // The user must provide objName for WORLD_BOOK type, or implement custom logic to detect it. console.warn(`[${extensionName}] 'WORLD_BOOK' type's object name cannot be automatically resolved from SillyTavern.getContext(). Please provide 'objName' explicitly.`); break; default: console.error(`[${extensionName}] Unknown source type for dynamic resolution: ${source}`); return null; } if (!resolvedObjectName) { console.warn(`[${extensionName}] Could not dynamically resolve object name for source type ${source}. Context key might be missing or not active.`); } return resolvedObjectName; } // ---------------------------------------------------------------- // Public API Method Implementations // ---------------------------------------------------------------- async function initialize() { try { const response = await fetch(`${apiBaseUrl}/sourcetype`); if (!response.ok) throw new Error(`Failed to fetch source types: ${response.status}`); this.SourceType = await response.json(); // 'this' refers to AmilyDatabin object console.log(`[${extensionName}] Client initialized with source types:`, this.SourceType); } catch (error) { console.error(`[${extensionName}] Initialization failed:`, error); } } async function getData(source, fileName, objName = null) { const objectName = objName ?? _getDynamicObjectName(source); if (!objectName) { console.error(`[${extensionName}] 'objName' could not be resolved for getData (Source: ${source}, File: ${fileName}).`); return null; } try { const queryParams = new URLSearchParams({ source, objName: objectName, file: fileName }); const response = await fetch(`${apiBaseUrl}/data?${queryParams.toString()}`); if (response.status === 404) return null; if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`); return await response.json(); } catch (error) { console.error(`[${extensionName}] getData failed (Source: ${source}, ObjName: ${objectName}, File: ${fileName}):`, error); return null; } } async function saveData(source, fileName, fileContent, objName = null) { const objectName = objName ?? _getDynamicObjectName(source); if (!objectName) { console.error(`[${extensionName}] 'objName' could not be resolved for saveData (Source: ${source}, File: ${fileName}).`); return false; } try { const response = await fetch(`${apiBaseUrl}/data`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ source, objName: objectName, file: fileName, data: fileContent }), }); if (!response.ok) { const errorText = await response.text(); throw new Error(`HTTP error! status: ${response.status}, message: ${errorText}`); } console.log(`[${extensionName}] Data saved to: ${source}/${objectName}/${fileName}`); return true; } catch (error) { console.error(`[${extensionName}] saveData failed (Source: ${source}, ObjName: ${objectName}, File: ${fileName}):`, error); return false; } } async function deleteData(source, fileName, objName = null) { const objectName = objName ?? _getDynamicObjectName(source); if (!objectName) { console.error(`[${extensionName}] 'objName' could not be resolved for deleteData (Source: ${source}, File: ${fileName}).`); return false; } try { const queryParams = new URLSearchParams({ source, objName: objectName, file: fileName }); const response = await fetch(`${apiBaseUrl}/data?${queryParams.toString()}`, { method: 'DELETE' }); if (!response.ok) { const errorText = await response.text(); throw new Error(`HTTP error! status: ${response.status}, message: ${errorText}`); } console.log(`[${extensionName}] Data deleted from: ${source}/${objectName}/${fileName}`); return true; } catch (error) { console.error(`[${extensionName}] deleteData failed (Source: ${source}, ObjName: ${objectName}, File: ${fileName}):`, error); return false; } } // ---------------------------------------------------------------- // Debug Methods // ---------------------------------------------------------------- function getDebugInstance() { console.log(`[${extensionName}] AmilyDatabin Instance:`, AmilyDatabin); return AmilyDatabin; } function getDebugChatId() { const chatId = _getDynamicObjectName(AmilyDatabin.SourceType.CHAT_LOG); console.log(`[${extensionName}] Current Chat ID (Debug):`, chatId); return chatId; } function getDebugCardId() { const cardId = _getDynamicObjectName(AmilyDatabin.SourceType.CHARACTER_CARD); console.log(`[${extensionName}] Current Character Card ID (Debug):`, cardId); return cardId; } // ---------------------------------------------------------------- // Global Object Definition // ---------------------------------------------------------------- const AmilyDatabin = { SourceType: {}, initialize, getData, saveData, deleteData, // Debug methods getDebugInstance, getDebugChatId, getDebugCardId }; window.AmilyDatabin = AmilyDatabin; // Automatically initialize the module. window.AmilyDatabin.initialize.bind(window.AmilyDatabin)(); })();