1. 1 : // Copyright (C) 2023-2025 IITC-CE - GPL-3.0 with Store Exception - see LICENSE and COPYING.STORE
  2. 2 :
  3. 3 : import { isSet, parseMeta, sanitizeFileName } from './helpers.js';
  4. 4 : import deepmerge from '@bundled-es-modules/deepmerge';
  5. 5 :
  6. 6 : /**
  7. 7 : * Processes the input parameters for backup data retrieval.
  8. 8 : *
  9. 9 : * This function takes an input object containing parameters for backup data retrieval
  10. 10 : * and returns a new object with processed parameters. If the input parameters are not
  11. 11 : * an object, an empty object is used as the default value. The function combines the
  12. 12 : * input parameters with default parameters to ensure all required properties are present.
  13. 13 : *
  14. 14 : * @param {BackupParams} params - The parameters for setting the backup data.
  15. 15 : * @returns {Object} The processed parameters object.
  16. 16 : */
  17. 17 : export function paramsProcessing(params) {
  18. 18 : if (typeof params !== 'object') params = {};
  19. 19 :
  20. 20 : // Default parameters
  21. 21 : const default_params = {
  22. 22 : settings: false,
  23. 23 : data: false,
  24. 24 : external: false,
  25. 25 : };
  26. 26 :
  27. 27 : // Combine the default parameters with the input parameters using spread syntax
  28. 28 : return { ...default_params, ...params };
  29. 29 : }
  30. 30 :
  31. 31 : /**
  32. 32 : * Exports specific IITC settings from the provided storage object.
  33. 33 : *
  34. 34 : * This function takes a storage object and extracts specific IITC settings based on
  35. 35 : * predefined keys. It creates a new object containing only the specified IITC settings
  36. 36 : * and returns it.
  37. 37 : *
  38. 38 : * @param {Object} all_storage - The storage object containing all data.
  39. 39 : * @returns {Object} An object containing specific IITC settings.
  40. 40 : */
  41. 41 : export const exportIitcSettings = (all_storage) => {
  42. 42 : const iitc_settings = {};
  43. 43 :
  44. 44 : // An array of predefined keys for IITC settings
  45. 45 : const storage_keys = ['channel', 'network_host', 'release_update_check_interval', 'beta_update_check_interval', 'custom_update_check_interval'];
  46. 46 :
  47. 47 : // Loop through all_storage and check if the keys are present in storage_keys
  48. 48 : // If present, add them to the iitc_settings object
  49. 49 : for (const key in all_storage) {
  50. 50 : if (storage_keys.includes(key) && isSet(all_storage[key])) {
  51. 51 : iitc_settings[key] = all_storage[key];
  52. 52 : }
  53. 53 : }
  54. 54 : return iitc_settings;
  55. 55 : };
  56. 56 :
  57. 57 : /**
  58. 58 : * Exports specific plugin settings from the provided storage object.
  59. 59 : *
  60. 60 : * This function takes a storage object and extracts plugin settings that have keys starting
  61. 61 : * with the prefix 'VMin'. It creates a new object containing only the plugin settings
  62. 62 : * and returns it.
  63. 63 : *
  64. 64 : * @param {Object} all_storage - The storage object containing all data.
  65. 65 : * @returns {Object} An object containing specific plugin settings.
  66. 66 : */
  67. 67 : export const exportPluginsSettings = (all_storage) => {
  68. 68 : const plugins_storage = {};
  69. 69 :
  70. 70 : // Loop through all_storage and check if the keys start with the prefix 'VMin'
  71. 71 : // If so, add them to the plugins_storage object
  72. 72 : for (const key in all_storage) {
  73. 73 : if (key.startsWith('VMin')) {
  74. 74 : plugins_storage[key] = all_storage[key];
  75. 75 : }
  76. 76 : }
  77. 77 : return plugins_storage;
  78. 78 : };
  79. 79 :
  80. 80 : /**
  81. 81 : * Exports external IITC core and plugins from the provided storage object.
  82. 82 : *
  83. 83 : * This function takes a storage object and extracts external IITC core and plugins based on predefined keys.
  84. 84 : * It creates a new object containing the external plugins organized by their channels and filenames,
  85. 85 : * and returns it.
  86. 86 : *
  87. 87 : * @param {Object} all_storage - The storage object containing all data.
  88. 88 : * @returns {Object} An object containing external plugins organized by channels and filenames.
  89. 89 : */
  90. 90 : export const exportExternalPlugins = (all_storage) => {
  91. 91 : const external_plugins = {};
  92. 92 :
  93. 93 : // An array of predefined keys for external plugins
  94. 94 : const storage_keys = [
  95. 95 : 'release_iitc_core_user',
  96. 96 : 'beta_iitc_core_user',
  97. 97 : 'custom_iitc_core_user',
  98. 98 : 'release_plugins_user',
  99. 99 : 'beta_plugins_user',
  100. 100 : 'custom_plugins_user',
  101. 101 : ];
  102. 102 :
  103. 103 : // Loop through all_storage and check if the keys are present in storage_keys
  104. 104 : // If present, process and add the external plugins to the external_plugins object
  105. 105 : for (const key in all_storage) {
  106. 106 : if (storage_keys.includes(key)) {
  107. 107 : // Extract the channel name from the key by splitting at '_'
  108. 108 : const channel = key.split('_')[0];
  109. 109 : const variant = key.split('_')[1];
  110. 110 :
  111. 111 : // Create a channel if it doesn't exist
  112. 112 : if (!(channel in external_plugins)) {
  113. 113 : external_plugins[channel] = {};
  114. 114 : }
  115. 115 :
  116. 116 : // Add a custom IITC core to the external_plugins object
  117. 117 : if (variant === 'iitc' && isSet(all_storage[key]) && isSet(all_storage[key]['code'])) {
  118. 118 : const plugin_filename = 'total-conversion-build.user.js';
  119. 119 : external_plugins[channel][plugin_filename] = all_storage[key]['code'];
  120. 120 : continue;
  121. 121 : }
  122. 122 :
  123. 123 : // Loop through each plugin UID in the current key's storage data
  124. 124 : for (const plugin_uid in all_storage[key]) {
  125. 125 : // Get the plugin's filename and code from the storage data and add to the external_plugins object
  126. 126 : let plugin_filename = all_storage[key][plugin_uid]['filename'];
  127. 127 : if (!plugin_filename) {
  128. 128 : plugin_filename = sanitizeFileName(`${all_storage[key][plugin_uid]['name']}.user.js`);
  129. 129 : }
  130. 130 : external_plugins[channel][plugin_filename] = all_storage[key][plugin_uid]['code'];
  131. 131 : }
  132. 132 : }
  133. 133 : }
  134. 134 :
  135. 135 : return external_plugins;
  136. 136 : };
  137. 137 :
  138. 138 : /**
  139. 139 : * Imports IITC settings from the provided backup object.
  140. 140 : *
  141. 141 : * @async
  142. 142 : * @param {Object} self - IITC manager object.
  143. 143 : * @param {Object} backup - The backup object containing IITC settings to import.
  144. 144 : * @returns {Promise<void>} A promise that resolves when the import is complete.
  145. 145 : */
  146. 146 : export const importIitcSettings = async (self, backup) => {
  147. 147 : const backup_obj = Object.assign({}, backup);
  148. 148 : const default_channel = self.channel;
  149. 149 :
  150. 150 : // Set the IITC settings from the backup object into the storage
  151. 151 : await self.storage.set(backup_obj);
  152. 152 :
  153. 153 : // Check if the channel in the backup object is different from the original channel
  154. 154 : const set_channel = backup_obj.channel;
  155. 155 : if (set_channel !== default_channel) {
  156. 156 : await self.setChannel(set_channel);
  157. 157 : }
  158. 158 : };
  159. 159 :
  160. 160 : /**
  161. 161 : * Imports plugin settings from the provided backup object.
  162. 162 : *
  163. 163 : * The function first retrieves all data from the storage object
  164. 164 : * using `self.storage.get(null)` and filters out the records with keys starting with 'VMin'
  165. 165 : * to create a new object `vMinRecords` containing only plugin-related data. The function then
  166. 166 : * merges the `vMinRecords` object with the provided backup object using the `deepmerge` library,
  167. 167 : * resulting in a new storage object `new_storage` that contains updated plugin settings. Finally,
  168. 168 : * the updated storage object is set into the 'self' object using `self.storage.set()`.
  169. 169 : *
  170. 170 : * @async
  171. 171 : * @param {Object} self - IITC manager object.
  172. 172 : * @param {Object} backup - The backup object containing plugin settings to import.
  173. 173 : * @returns {Promise<void>} A promise that resolves when the import is complete.
  174. 174 : */
  175. 175 : export const importPluginsSettings = async (self, backup) => {
  176. 176 : const all_storage = await self.storage.get(null);
  177. 177 :
  178. 178 : // Create a new object containing only plugin-related data (keys starting with 'VMin')
  179. 179 : const vMinRecords = {};
  180. 180 : Object.keys(all_storage).forEach((key) => {
  181. 181 : if (key.startsWith('VMin')) {
  182. 182 : vMinRecords[key] = all_storage[key];
  183. 183 : }
  184. 184 : });
  185. 185 :
  186. 186 : // Merge the 'vMinRecords' object with the provided backup object and set into storage
  187. 187 : const new_storage = deepmerge(vMinRecords, backup);
  188. 188 : await self.storage.set(new_storage);
  189. 189 : };
  190. 190 :
  191. 191 : /**
  192. 192 : * Imports external plugins from the provided backup object.
  193. 193 : *
  194. 194 : * The function iterates through each channel in the backup object,
  195. 195 : * sets the current channel using `self.setChannel()`, and then extracts the plugin information
  196. 196 : * (metadata and code) for each plugin in the channel. The plugin information is added to the 'scripts'
  197. 197 : * array, which is then passed to `self.addUserScripts()` to add the external plugins. After processing
  198. 198 : * all channels, the function sets the default channel using `self.setChannel()` if it was changed during
  199. 199 : * the import process.
  200. 200 : *
  201. 201 : * @async
  202. 202 : * @param {Object} self - IITC manager object.
  203. 203 : * @param {Object} backup - The backup object containing external plugins to import.
  204. 204 : * @returns {Promise<void>} A promise that resolves when the import is complete.
  205. 205 : */
  206. 206 : export const importExternalPlugins = async (self, backup) => {
  207. 207 : const default_channel = self.channel;
  208. 208 :
  209. 209 : // Iterate through each channel in the backup object
  210. 210 : for (const channel of Object.keys(backup)) {
  211. 211 : // Initialize an empty array to store the plugin information (metadata and code)
  212. 212 : const scripts = [];
  213. 213 : await self.setChannel(channel);
  214. 214 :
  215. 215 : // Iterate through each plugin in the current channel and extract plugin information
  216. 216 : for (const [filename, code] of Object.entries(backup[channel])) {
  217. 217 : // Parse the metadata from the plugin code using the 'parseMeta()' function
  218. 218 : const meta = parseMeta(code);
  219. 219 : meta['filename'] = filename;
  220. 220 :
  221. 221 : // Push the plugin information (metadata and code) to the 'scripts' array
  222. 222 : scripts.push({ meta: meta, code: code });
  223. 223 : }
  224. 224 :
  225. 225 : // Add the external plugins using the 'self.addUserScripts()' method
  226. 226 : await self.addUserScripts(scripts);
  227. 227 : }
  228. 228 :
  229. 229 : // If the current channel is different from the default channel,
  230. 230 : // set the default channel using the 'self.setChannel()' method
  231. 231 : if (self.channel !== default_channel) {
  232. 232 : await self.setChannel(default_channel);
  233. 233 : }
  234. 234 : };