Skip to content

Commit

Permalink
Merge pull request #26 from modos189/backup
Browse files Browse the repository at this point in the history
  • Loading branch information
modos189 authored Jul 28, 2023
2 parents 5a93858 + d288ca7 commit a17e588
Show file tree
Hide file tree
Showing 10 changed files with 500 additions and 5 deletions.
9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "lib-iitc-manager",
"version": "1.6.1",
"version": "1.7.0",
"description": "Library for managing IITC plugins",
"main": "src/index.js",
"type": "module",
Expand All @@ -21,15 +21,16 @@
"homepage": "https://github.com/IITC-CE/lib-iitc-manager#readme",
"devDependencies": {
"chai": "^4.3.6",
"http-server": "^14.1.0",
"mocha": "^9.2.2",
"node-fetch": "^3.2.3",
"eslint": "^8.20.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^4.2.1",
"http-server": "^14.1.0",
"mocha": "^9.2.2",
"node-fetch": "^3.2.3",
"prettier": "^2.7.1"
},
"dependencies": {
"@bundled-es-modules/deepmerge": "^4.3.1",
"xhr2": "^0.2.1"
}
}
212 changes: 212 additions & 0 deletions src/backup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
// @license magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&dn=gpl-3.0.txt GPL-v3

import { parseMeta } 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)) {
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 plugins from the provided storage object.
*
* This function takes a storage object and extracts external 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_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];
external_plugins[channel] = {};

// 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
const plugin_filename = all_storage[key][plugin_uid]['filename'];
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);
}
};
56 changes: 56 additions & 0 deletions src/manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { Worker } from './worker.js';
import * as migrations from './migrations.js';
import { getUID, isSet } from './helpers.js';
import * as backup from './backup.js';

/**
* @classdesc This class contains methods for managing IITC and plugins.
Expand Down Expand Up @@ -298,4 +299,59 @@ export class Manager extends Worker {
if (all_plugins === undefined) return null;
return all_plugins[uid];
}

/**
* Asynchronously retrieves backup data based on the specified parameters.
*
* @async
* @param {BackupParams} params - The parameters for the backup data retrieval.
* @return {Promise<object>} A promise that resolves to the backup data.
*/
async getBackupData(params) {
// Process the input parameters using the 'paramsProcessing' function from the 'backup' module.
params = backup.paramsProcessing(params);

// Initialize the backup_data object with its properties.
const backup_data = {
external_plugins: {},
data: {
iitc_settings: {},
plugins_data: {},
app: 'IITC Button',
},
};

// Retrieve all_storage using the 'get' method of 'storage' module.
const all_storage = await this.storage.get(null);

if (params.settings) backup_data.data.iitc_settings = backup.exportIitcSettings(all_storage);
if (params.data) backup_data.data.plugins_data = backup.exportPluginsSettings(all_storage);
if (params.external) backup_data.external_plugins = backup.exportExternalPlugins(all_storage);

// Return the backup_data object.
return backup_data;
}

/**
* Asynchronously sets backup data based on the specified parameters.
*
* This function takes the provided parameters and backup data object and sets the data
* accordingly. The input parameters are processed using the 'paramsProcessing' function
* from the 'backup' module. Depending on the parameters, the function imports IITC settings,
* plugin data, and external plugins into the 'this' object using appropriate functions from
* the 'backup' module.
*
* @async
* @param {BackupParams} params - The parameters for setting the backup data.
* @param {object} backup_data - The backup data object containing the data to be set.
* @return {Promise<void>} A promise that resolves when the backup data is set.
*/
async setBackupData(params, backup_data) {
// Process the input parameters using the 'paramsProcessing' function from the 'backup' module.
params = backup.paramsProcessing(params);

if (params.settings) await backup.importIitcSettings(this, backup_data.data.iitc_settings);
if (params.data) await backup.importPluginsSettings(this, backup_data.data.plugins_data);
if (params.external) await backup.importExternalPlugins(this, backup_data.external_plugins);
}
}
9 changes: 9 additions & 0 deletions src/worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,15 @@ import { ajaxGet, clearWait, getUID, isSet, parseMeta, wait } from './helpers.js
* @property {string[]} grant
*/

/**
* Parameters for retrieving backup data.
*
* @typedef {Object} BackupParams
* @property {boolean} settings - Whether to import/export IITC settings.
* @property {boolean} data - Whether to import/export plugins' data.
* @property {boolean} external - Whether to import/export external plugins.
*/

/**
* @classdesc This class contains methods for managing IITC and plugins.
*/
Expand Down
1 change: 1 addition & 0 deletions test/manager.0.base.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { expect } from 'chai';
describe('manage.js base integration tests', function () {
let manager = null;
before(function () {
storage.resetStorage();
const params = {
storage: storage,
channel: 'beta',
Expand Down
1 change: 1 addition & 0 deletions test/manager.1.build-in.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { expect } from 'chai';
describe('manage.js build-in plugins integration tests', function () {
let manager = null;
before(function () {
storage.resetStorage();
const params = {
storage: storage,
channel: 'release',
Expand Down
5 changes: 4 additions & 1 deletion test/manager.2.external.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const expectThrowsAsync = async (method, errorMessage) => {
describe('manage.js external plugins integration tests', function () {
let manager = null;
before(function () {
storage.resetStorage();
const params = {
storage: storage,
channel: 'release',
Expand Down Expand Up @@ -387,7 +388,9 @@ describe('manage.js external plugins integration tests', function () {

expect(db_data['release_plugins_flat'][external_1_uid]['status'], "release_plugins_flat['status']: " + external_1_uid).to.equal('off');

expect(db_data['release_plugins_flat'][external_1_uid]['code'], "release_plugins_flat['code']: " + external_1_uid).to.have.lengthOf(578);
expect(db_data['release_plugins_flat'][external_1_uid]['code'], "release_plugins_flat['code']: " + external_1_uid).to.have.lengthOf(
external_code.length
);

expect(db_data['release_plugins_flat'][external_1_uid]['override'], "release_plugins_flat['override']: " + external_1_uid).to.not.be.true;
});
Expand Down
1 change: 1 addition & 0 deletions test/manager.3.repo.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { expect } from 'chai';
describe('manage.js custom repo integration tests', function () {
let manager = null;
before(function () {
storage.resetStorage();
const params = {
storage: storage,
channel: 'release',
Expand Down
Loading

0 comments on commit a17e588

Please sign in to comment.