// Copyright (C) 2023-2025 IITC-CE - GPL-3.0 with Store Exception - see LICENSE and COPYING.STORE
import { isSet, parseMeta, sanitizeFileName } from './helpers.js';
import deepmerge from '@bundled-es-modules/deepmerge';
/**
* Processes the input parameters for backup data retrieval.
*
* This function takes an input object containing parameters for backup data retrieval
* and returns a new object with processed parameters. If the input parameters are not
* an object, an empty object is used as the default value. The function combines the
* input parameters with default parameters to ensure all required properties are present.
*
* @param {BackupParams} params - The parameters for setting the backup data.
* @returns {Object} The processed parameters object.
*/
export function paramsProcessing(params) {
if (typeof params !== 'object') params = {};
// Default parameters
const default_params = {
settings: false,
data: false,
external: false,
};
// Combine the default parameters with the input parameters using spread syntax
return { ...default_params, ...params };
}
/**
* Exports specific IITC settings from the provided storage object.
*
* This function takes a storage object and extracts specific IITC settings based on
* predefined keys. It creates a new object containing only the specified IITC settings
* and returns it.
*
* @param {Object} all_storage - The storage object containing all data.
* @returns {Object} An object containing specific IITC settings.
*/
export const exportIitcSettings = (all_storage) => {
const iitc_settings = {};
// An array of predefined keys for IITC settings
const storage_keys = ['channel', 'network_host', 'release_update_check_interval', 'beta_update_check_interval', 'custom_update_check_interval'];
// Loop through all_storage and check if the keys are present in storage_keys
// If present, add them to the iitc_settings object
for (const key in all_storage) {
if (storage_keys.includes(key) && isSet(all_storage[key])) {
iitc_settings[key] = all_storage[key];
}
}
return iitc_settings;
};
/**
* Exports specific plugin settings from the provided storage object.
*
* This function takes a storage object and extracts plugin settings that have keys starting
* with the prefix 'VMin'. It creates a new object containing only the plugin settings
* and returns it.
*
* @param {Object} all_storage - The storage object containing all data.
* @returns {Object} An object containing specific plugin settings.
*/
export const exportPluginsSettings = (all_storage) => {
const plugins_storage = {};
// Loop through all_storage and check if the keys start with the prefix 'VMin'
// If so, add them to the plugins_storage object
for (const key in all_storage) {
if (key.startsWith('VMin')) {
plugins_storage[key] = all_storage[key];
}
}
return plugins_storage;
};
/**
* Exports external IITC core and plugins from the provided storage object.
*
* This function takes a storage object and extracts external IITC core and plugins based on predefined keys.
* It creates a new object containing the external plugins organized by their channels and filenames,
* and returns it.
*
* @param {Object} all_storage - The storage object containing all data.
* @returns {Object} An object containing external plugins organized by channels and filenames.
*/
export const exportExternalPlugins = (all_storage) => {
const external_plugins = {};
// An array of predefined keys for external plugins
const storage_keys = [
'release_iitc_core_user',
'beta_iitc_core_user',
'custom_iitc_core_user',
'release_plugins_user',
'beta_plugins_user',
'custom_plugins_user',
];
// Loop through all_storage and check if the keys are present in storage_keys
// If present, process and add the external plugins to the external_plugins object
for (const key in all_storage) {
if (storage_keys.includes(key)) {
// Extract the channel name from the key by splitting at '_'
const channel = key.split('_')[0];
const variant = key.split('_')[1];
// Create a channel if it doesn't exist
if (!(channel in external_plugins)) {
external_plugins[channel] = {};
}
// Add a custom IITC core to the external_plugins object
if (variant === 'iitc' && isSet(all_storage[key]) && isSet(all_storage[key]['code'])) {
const plugin_filename = 'total-conversion-build.user.js';
external_plugins[channel][plugin_filename] = all_storage[key]['code'];
continue;
}
// Loop through each plugin UID in the current key's storage data
for (const plugin_uid in all_storage[key]) {
// Get the plugin's filename and code from the storage data and add to the external_plugins object
let plugin_filename = all_storage[key][plugin_uid]['filename'];
if (!plugin_filename) {
plugin_filename = sanitizeFileName(`${all_storage[key][plugin_uid]['name']}.user.js`);
}
external_plugins[channel][plugin_filename] = all_storage[key][plugin_uid]['code'];
}
}
}
return external_plugins;
};
/**
* Imports IITC settings from the provided backup object.
*
* @async
* @param {Object} self - IITC manager object.
* @param {Object} backup - The backup object containing IITC settings to import.
* @returns {Promise<void>} A promise that resolves when the import is complete.
*/
export const importIitcSettings = async (self, backup) => {
const backup_obj = Object.assign({}, backup);
const default_channel = self.channel;
// Set the IITC settings from the backup object into the storage
await self.storage.set(backup_obj);
// Check if the channel in the backup object is different from the original channel
const set_channel = backup_obj.channel;
if (set_channel !== default_channel) {
await self.setChannel(set_channel);
}
};
/**
* Imports plugin settings from the provided backup object.
*
* The function first retrieves all data from the storage object
* using `self.storage.get(null)` and filters out the records with keys starting with 'VMin'
* to create a new object `vMinRecords` containing only plugin-related data. The function then
* merges the `vMinRecords` object with the provided backup object using the `deepmerge` library,
* resulting in a new storage object `new_storage` that contains updated plugin settings. Finally,
* the updated storage object is set into the 'self' object using `self.storage.set()`.
*
* @async
* @param {Object} self - IITC manager object.
* @param {Object} backup - The backup object containing plugin settings to import.
* @returns {Promise<void>} A promise that resolves when the import is complete.
*/
export const importPluginsSettings = async (self, backup) => {
const all_storage = await self.storage.get(null);
// Create a new object containing only plugin-related data (keys starting with 'VMin')
const vMinRecords = {};
Object.keys(all_storage).forEach((key) => {
if (key.startsWith('VMin')) {
vMinRecords[key] = all_storage[key];
}
});
// Merge the 'vMinRecords' object with the provided backup object and set into storage
const new_storage = deepmerge(vMinRecords, backup);
await self.storage.set(new_storage);
};
/**
* Imports external plugins from the provided backup object.
*
* The function iterates through each channel in the backup object,
* sets the current channel using `self.setChannel()`, and then extracts the plugin information
* (metadata and code) for each plugin in the channel. The plugin information is added to the 'scripts'
* array, which is then passed to `self.addUserScripts()` to add the external plugins. After processing
* all channels, the function sets the default channel using `self.setChannel()` if it was changed during
* the import process.
*
* @async
* @param {Object} self - IITC manager object.
* @param {Object} backup - The backup object containing external plugins to import.
* @returns {Promise<void>} A promise that resolves when the import is complete.
*/
export const importExternalPlugins = async (self, backup) => {
const default_channel = self.channel;
// Iterate through each channel in the backup object
for (const channel of Object.keys(backup)) {
// Initialize an empty array to store the plugin information (metadata and code)
const scripts = [];
await self.setChannel(channel);
// Iterate through each plugin in the current channel and extract plugin information
for (const [filename, code] of Object.entries(backup[channel])) {
// Parse the metadata from the plugin code using the 'parseMeta()' function
const meta = parseMeta(code);
meta['filename'] = filename;
// Push the plugin information (metadata and code) to the 'scripts' array
scripts.push({ meta: meta, code: code });
}
// Add the external plugins using the 'self.addUserScripts()' method
await self.addUserScripts(scripts);
}
// If the current channel is different from the default channel,
// set the default channel using the 'self.setChannel()' method
if (self.channel !== default_channel) {
await self.setChannel(default_channel);
}
};