discord.js-backup-v13 13.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/LICENSE +21 -0
  2. package/lib/create.d.ts +35 -0
  3. package/lib/create.js +152 -0
  4. package/lib/index.d.ts +34 -0
  5. package/lib/index.js +240 -0
  6. package/lib/load.d.ts +30 -0
  7. package/lib/load.js +256 -0
  8. package/lib/types/AfkData.d.ts +4 -0
  9. package/lib/types/AfkData.js +2 -0
  10. package/lib/types/BackupData.d.ts +25 -0
  11. package/lib/types/BackupData.js +2 -0
  12. package/lib/types/BackupInfos.d.ts +6 -0
  13. package/lib/types/BackupInfos.js +2 -0
  14. package/lib/types/BanData.d.ts +5 -0
  15. package/lib/types/BanData.js +2 -0
  16. package/lib/types/BaseChannelData.d.ts +8 -0
  17. package/lib/types/BaseChannelData.js +2 -0
  18. package/lib/types/CategoryData.d.ts +6 -0
  19. package/lib/types/CategoryData.js +2 -0
  20. package/lib/types/ChannelPermissionData.d.ts +5 -0
  21. package/lib/types/ChannelPermissionData.js +2 -0
  22. package/lib/types/ChannelsData.d.ts +5 -0
  23. package/lib/types/ChannelsData.js +2 -0
  24. package/lib/types/CreateOptions.d.ts +9 -0
  25. package/lib/types/CreateOptions.js +2 -0
  26. package/lib/types/EmojiData.d.ts +5 -0
  27. package/lib/types/EmojiData.js +2 -0
  28. package/lib/types/LoadOptions.d.ts +6 -0
  29. package/lib/types/LoadOptions.js +2 -0
  30. package/lib/types/MemberData.d.ts +9 -0
  31. package/lib/types/MemberData.js +2 -0
  32. package/lib/types/MessageData.d.ts +10 -0
  33. package/lib/types/MessageData.js +2 -0
  34. package/lib/types/RoleData.d.ts +9 -0
  35. package/lib/types/RoleData.js +2 -0
  36. package/lib/types/TextChannelData.d.ts +10 -0
  37. package/lib/types/TextChannelData.js +2 -0
  38. package/lib/types/ThreadChannelData.d.ts +11 -0
  39. package/lib/types/ThreadChannelData.js +2 -0
  40. package/lib/types/VoiceChannelData.d.ts +5 -0
  41. package/lib/types/VoiceChannelData.js +2 -0
  42. package/lib/types/WidgetData.d.ts +4 -0
  43. package/lib/types/WidgetData.js +2 -0
  44. package/lib/types/index.d.ts +17 -0
  45. package/lib/types/index.js +33 -0
  46. package/lib/util.d.ts +27 -0
  47. package/lib/util.js +334 -0
  48. package/package.json +21 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2019 Androz2091
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,35 @@
1
+ import type { BanData, ChannelsData, CreateOptions, EmojiData, RoleData } from './types';
2
+ import type { Guild } from 'discord.js';
3
+ import { MemberData } from './types/MemberData';
4
+ /**
5
+ * Returns an array with the banned members of the guild
6
+ * @param {Guild} guild The Discord guild
7
+ * @returns {Promise<BanData[]>} The banned members
8
+ */
9
+ export declare function getBans(guild: Guild): Promise<BanData[]>;
10
+ /**
11
+ * Returns an array with the members of the guild
12
+ * @param {Guild} guild The Discord guild
13
+ * @returns {Promise<MemberData>}
14
+ */
15
+ export declare function getMembers(guild: Guild): Promise<MemberData[]>;
16
+ /**
17
+ * Returns an array with the roles of the guild
18
+ * @param {Guild} guild The discord guild
19
+ * @returns {Promise<RoleData[]>} The roles of the guild
20
+ */
21
+ export declare function getRoles(guild: Guild): Promise<RoleData[]>;
22
+ /**
23
+ * Returns an array with the emojis of the guild
24
+ * @param {Guild} guild The discord guild
25
+ * @param {CreateOptions} options The backup options
26
+ * @returns {Promise<EmojiData[]>} The emojis of the guild
27
+ */
28
+ export declare function getEmojis(guild: Guild, options: CreateOptions): Promise<EmojiData[]>;
29
+ /**
30
+ * Returns an array with the channels of the guild
31
+ * @param {Guild} guild The discord guild
32
+ * @param {CreateOptions} options The backup options
33
+ * @returns {ChannelData[]} The channels of the guild
34
+ */
35
+ export declare function getChannels(guild: Guild, options: CreateOptions): Promise<ChannelsData>;
package/lib/create.js ADDED
@@ -0,0 +1,152 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getChannels = exports.getEmojis = exports.getRoles = exports.getMembers = exports.getBans = void 0;
4
+ const node_fetch_1 = require("node-fetch");
5
+ const util_1 = require("./util");
6
+ /**
7
+ * Returns an array with the banned members of the guild
8
+ * @param {Guild} guild The Discord guild
9
+ * @returns {Promise<BanData[]>} The banned members
10
+ */
11
+ async function getBans(guild) {
12
+ const bans = [];
13
+ const cases = await guild.bans.fetch();
14
+ cases.forEach((ban) => {
15
+ bans.push({
16
+ id: ban.user.id,
17
+ reason: ban.reason
18
+ });
19
+ });
20
+ return bans;
21
+ }
22
+ exports.getBans = getBans;
23
+ /**
24
+ * Returns an array with the members of the guild
25
+ * @param {Guild} guild The Discord guild
26
+ * @returns {Promise<MemberData>}
27
+ */
28
+ async function getMembers(guild) {
29
+ const members = [];
30
+ guild.members.cache.forEach((member) => {
31
+ members.push({
32
+ userId: member.user.id,
33
+ username: member.user.username,
34
+ discriminator: member.user.discriminator,
35
+ avatarUrl: member.user.avatarURL(),
36
+ joinedTimestamp: member.joinedTimestamp,
37
+ roles: member.roles.cache.map((role) => role.id),
38
+ bot: member.user.bot
39
+ });
40
+ });
41
+ return members;
42
+ }
43
+ exports.getMembers = getMembers;
44
+ /**
45
+ * Returns an array with the roles of the guild
46
+ * @param {Guild} guild The discord guild
47
+ * @returns {Promise<RoleData[]>} The roles of the guild
48
+ */
49
+ async function getRoles(guild) {
50
+ const roles = [];
51
+ guild.roles.cache
52
+ .filter((role) => !role.managed)
53
+ .sort((a, b) => b.position - a.position)
54
+ .forEach((role) => {
55
+ const roleData = {
56
+ name: role.name,
57
+ color: role.hexColor,
58
+ hoist: role.hoist,
59
+ permissions: role.permissions.bitfield.toString(),
60
+ mentionable: role.mentionable,
61
+ position: role.position,
62
+ isEveryone: guild.id === role.id
63
+ };
64
+ roles.push(roleData);
65
+ });
66
+ return roles;
67
+ }
68
+ exports.getRoles = getRoles;
69
+ /**
70
+ * Returns an array with the emojis of the guild
71
+ * @param {Guild} guild The discord guild
72
+ * @param {CreateOptions} options The backup options
73
+ * @returns {Promise<EmojiData[]>} The emojis of the guild
74
+ */
75
+ async function getEmojis(guild, options) {
76
+ const emojis = [];
77
+ guild.emojis.cache.forEach(async (emoji) => {
78
+ const eData = {
79
+ name: emoji.name
80
+ };
81
+ if (options.saveImages && options.saveImages === 'base64') {
82
+ eData.base64 = (await (0, node_fetch_1.default)(emoji.url).then((res) => res.buffer())).toString('base64');
83
+ }
84
+ else {
85
+ eData.url = emoji.url;
86
+ }
87
+ emojis.push(eData);
88
+ });
89
+ return emojis;
90
+ }
91
+ exports.getEmojis = getEmojis;
92
+ /**
93
+ * Returns an array with the channels of the guild
94
+ * @param {Guild} guild The discord guild
95
+ * @param {CreateOptions} options The backup options
96
+ * @returns {ChannelData[]} The channels of the guild
97
+ */
98
+ async function getChannels(guild, options) {
99
+ return new Promise(async (resolve) => {
100
+ const channels = {
101
+ categories: [],
102
+ others: []
103
+ };
104
+
105
+ const categories = guild.channels.cache
106
+ .filter((ch) => ch.type === 'GUILD_CATEGORY')
107
+ .sort((a, b) => a.position - b.position)
108
+
109
+ for (const category of categories.values()) {
110
+
111
+ const categoryData = {
112
+ name: category.name,
113
+ permissions: (0, util_1.fetchChannelPermissions)(category),
114
+ children: []
115
+ };
116
+ const children = guild.channels.cache.filter(c => c.parentId == category.id).sort((a, b) => a.position - b.position)
117
+
118
+ for (const child of children.values()) {
119
+
120
+ if (child.type === 'GUILD_TEXT' || child.type === 'GUILD_NEWS') {
121
+ const channelData = await (0, util_1.fetchTextChannelData)(child, options);
122
+ categoryData.children.push(channelData);
123
+ }
124
+ else {
125
+ const channelData = await (0, util_1.fetchVoiceChannelData)(child);
126
+ categoryData.children.push(channelData);
127
+ }
128
+ }
129
+ channels.categories.push(categoryData);
130
+ }
131
+ const others = guild.channels.cache
132
+ .filter((ch) => {
133
+ return !ch.parent && ch.type !== 'GUILD_CATEGORY'
134
+ && ch.type !== 'GUILD_STORE'
135
+ && ch.type !== 'GUILD_NEWS_THREAD' && ch.type !== 'GUILD_PRIVATE_THREAD' && ch.type !== 'GUILD_PUBLIC_THREAD';
136
+ })
137
+ .sort((a, b) => a.position - b.position)
138
+ .toJSON();
139
+ for (const channel of others.values()) {
140
+ if (channel.type === 'GUILD_TEXT' || channel.type === 'GUILD_NEWS') {
141
+ const channelData = await (0, util_1.fetchTextChannelData)(channel, options);
142
+ channels.others.push(channelData);
143
+ }
144
+ else {
145
+ const channelData = await (0, util_1.fetchVoiceChannelData)(channel);
146
+ channels.others.push(channelData);
147
+ }
148
+ }
149
+ resolve(channels);
150
+ });
151
+ }
152
+ exports.getChannels = getChannels;
package/lib/index.d.ts ADDED
@@ -0,0 +1,34 @@
1
+ import type { BackupData, BackupInfos, CreateOptions, LoadOptions } from './types/';
2
+ import type { Guild } from 'discord.js';
3
+ /**
4
+ * Fetches a backyp and returns the information about it
5
+ */
6
+ export declare const fetch: (backupID: string) => Promise<BackupInfos>;
7
+ /**
8
+ * Creates a new backup and saves it to the storage
9
+ */
10
+ export declare const create: (guild: Guild, options?: CreateOptions) => Promise<BackupData>;
11
+ /**
12
+ * Loads a backup for a guild
13
+ */
14
+ export declare const load: (backup: string | BackupData, guild: Guild, options?: LoadOptions) => Promise<unknown>;
15
+ /**
16
+ * Removes a backup
17
+ */
18
+ export declare const remove: (backupID: string) => Promise<void>;
19
+ /**
20
+ * Returns the list of all backup
21
+ */
22
+ export declare const list: () => Promise<string[]>;
23
+ /**
24
+ * Change the storage path
25
+ */
26
+ export declare const setStorageFolder: (path: string) => void;
27
+ declare const _default: {
28
+ create: (guild: Guild, options?: CreateOptions) => Promise<BackupData>;
29
+ fetch: (backupID: string) => Promise<BackupInfos>;
30
+ list: () => Promise<string[]>;
31
+ load: (backup: string | BackupData, guild: Guild, options?: LoadOptions) => Promise<unknown>;
32
+ remove: (backupID: string) => Promise<void>;
33
+ };
34
+ export default _default;
package/lib/index.js ADDED
@@ -0,0 +1,240 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.setStorageFolder = exports.list = exports.remove = exports.load = exports.create = exports.fetch = void 0;
4
+ const discord_js_1 = require("discord.js-selfbot-v13");
5
+ const node_fetch_1 = require("node-fetch");
6
+ const path_1 = require("path");
7
+ const fs_1 = require("fs");
8
+ const promises_1 = require("fs/promises");
9
+ const createMaster = require("./create");
10
+ const loadMaster = require("./load");
11
+ const utilMaster = require("./util");
12
+ let backups = `${__dirname}/backups`;
13
+ if (!(0, fs_1.existsSync)(backups)) {
14
+ (0, fs_1.mkdirSync)(backups);
15
+ }
16
+ /**
17
+ * Checks if a backup exists and returns its data
18
+ */
19
+ const getBackupData = async (backupID) => {
20
+ return new Promise(async (resolve, reject) => {
21
+ const files = await (0, promises_1.readdir)(backups);
22
+ const file = files.filter((f) => f.split('.').pop() === 'json').find((f) => f === `${backupID}.json`);
23
+ if (file) {
24
+ const backupData = require(`${backups}${path_1.sep}${file}`);
25
+ resolve(backupData);
26
+ }
27
+ else {
28
+ reject('No backup found');
29
+ }
30
+ });
31
+ };
32
+ /**
33
+ * Fetches a backyp and returns the information about it
34
+ */
35
+ const fetch = (backupID) => {
36
+ return new Promise(async (resolve, reject) => {
37
+ getBackupData(backupID)
38
+ .then((backupData) => {
39
+ const size = (0, fs_1.statSync)(`${backups}${path_1.sep}${backupID}.json`).size;
40
+ const backupInfos = {
41
+ data: backupData,
42
+ id: backupID,
43
+ size: Number((size / 1024).toFixed(2))
44
+ };
45
+ resolve(backupInfos);
46
+ })
47
+ .catch(() => {
48
+ reject('No backup found');
49
+ });
50
+ });
51
+ };
52
+ exports.fetch = fetch;
53
+ /**
54
+ * Creates a new backup and saves it to the storage
55
+ */
56
+ const create = async (guild, options = {
57
+ backupID: null,
58
+ maxMessagesPerChannel: 10,
59
+ jsonSave: true,
60
+ jsonBeautify: true,
61
+ doNotBackup: ['bans', 'emojis'],
62
+ backupMembers: false,
63
+ saveImages: ''
64
+ }) => {
65
+ return new Promise(async (resolve, reject) => {
66
+ try {
67
+ const backupData = {
68
+ name: guild.name,
69
+ verificationLevel: guild.verificationLevel,
70
+ explicitContentFilter: guild.explicitContentFilter,
71
+ defaultMessageNotifications: guild.defaultMessageNotifications,
72
+ afk: guild.afkChannel ? { name: guild.afkChannel.name, timeout: guild.afkTimeout } : null,
73
+ widget: {
74
+ enabled: guild.widgetEnabled,
75
+ channel: guild.widgetChannel ? guild.widgetChannel.name : null
76
+ },
77
+ community: {
78
+ enabled: guild.features.includes('COMMUNITY'),
79
+ systemChannelFlags: guild.systemChannelFlags ? guild.systemChannelFlags.bitfield : null,
80
+ systemChannelId: guild.systemChannelId,
81
+ rulesChannelId: guild.rulesChannelId,
82
+ publicUpdatesChannelId: guild.publicUpdatesChannelId,
83
+ safetyAlertsChannelId: guild.safetyAlertsChannelId || null
84
+ },
85
+ channels: { categories: [], others: [] },
86
+ roles: [],
87
+ bans: [],
88
+ emojis: [],
89
+ members: [],
90
+ createdTimestamp: Date.now(),
91
+ guildID: guild.id,
92
+ id: options.backupID ?? discord_js_1.SnowflakeUtil.generate(Date.now())
93
+ };
94
+ if (guild.iconURL()) {
95
+ if (options && options.saveImages && options.saveImages === 'base64') {
96
+ backupData.iconBase64 = (await (0, node_fetch_1.default)(guild.iconURL({ dynamic: true })).then((res) => res.buffer())).toString('base64');
97
+ }
98
+ backupData.iconURL = guild.iconURL({ dynamic: true });
99
+ }
100
+ if (guild.splashURL()) {
101
+ if (options && options.saveImages && options.saveImages === 'base64') {
102
+ backupData.splashBase64 = (await (0, node_fetch_1.default)(guild.splashURL()).then((res) => res.buffer())).toString('base64');
103
+ }
104
+ backupData.splashURL = guild.splashURL();
105
+ }
106
+ if (guild.bannerURL()) {
107
+ if (options && options.saveImages && options.saveImages === 'base64') {
108
+ backupData.bannerBase64 = (await (0, node_fetch_1.default)(guild.bannerURL()).then((res) => res.buffer())).toString('base64');
109
+ }
110
+ backupData.bannerURL = guild.bannerURL();
111
+ }
112
+ if (options && options.backupMembers) {
113
+ backupData.members = await createMaster.getMembers(guild);
114
+ }
115
+ if (!options || !(options.doNotBackup || []).includes('bans')) {
116
+ backupData.bans = await createMaster.getBans(guild);
117
+ }
118
+ if (!options || !(options.doNotBackup || []).includes('roles')) {
119
+ backupData.roles = await createMaster.getRoles(guild);
120
+ }
121
+ if (!options || !(options.doNotBackup || []).includes('emojis')) {
122
+ backupData.emojis = await createMaster.getEmojis(guild, options);
123
+ }
124
+ if (!options || !(options.doNotBackup || []).includes('channels')) {
125
+ backupData.channels = await createMaster.getChannels(guild, options);
126
+ }
127
+ if (!options || options.jsonSave === undefined || options.jsonSave) {
128
+ const backupJSON = options.jsonBeautify
129
+ ? JSON.stringify(backupData, null, 4)
130
+ : JSON.stringify(backupData);
131
+ await (0, promises_1.writeFile)(`${backups}${path_1.sep}${backupData.id}.json`, backupJSON, 'utf-8');
132
+ }
133
+ resolve(backupData);
134
+ }
135
+ catch (e) {
136
+ return reject(e);
137
+ }
138
+ });
139
+ };
140
+ exports.create = create;
141
+ /**
142
+ * Loads a backup for a guild
143
+ */
144
+ const load = async (backup, guild, options = {
145
+ clearGuildBeforeRestore: true,
146
+ maxMessagesPerChannel: 10
147
+ }) => {
148
+ return new Promise(async (resolve, reject) => {
149
+ if (!guild) {
150
+ return reject('Invalid guild');
151
+ }
152
+ try {
153
+ const backupData = typeof backup === 'string' ? await getBackupData(backup) : backup;
154
+ try {
155
+ if (options.clearGuildBeforeRestore === undefined || options.clearGuildBeforeRestore) {
156
+ await utilMaster.clearGuild(guild);
157
+ }
158
+ await Promise.all([
159
+ loadMaster.loadConfig(guild, backupData),
160
+ loadMaster.loadRoles(guild, backupData)
161
+ ]);
162
+
163
+ await new Promise(r => setTimeout(r, 3000));
164
+
165
+ await loadMaster.loadChannels(guild, backupData, options);
166
+
167
+ const restorePromises = [
168
+ loadMaster.loadAFK(guild, backupData),
169
+ loadMaster.loadEmbedChannel(guild, backupData)
170
+ ];
171
+
172
+ if (!options.doNotBackup || !options.doNotBackup.includes('emojis')) {
173
+ restorePromises.push(loadMaster.loadEmojis(guild, backupData));
174
+ }
175
+
176
+ if (!options.doNotBackup || !options.doNotBackup.includes('bans')) {
177
+ restorePromises.push(loadMaster.loadBans(guild, backupData));
178
+ }
179
+
180
+ await Promise.all(restorePromises);
181
+
182
+ await loadMaster.loadCommunity(guild, backupData);
183
+
184
+ await loadMaster.loadRoleChannelPermissions(guild, backupData, options);
185
+ }
186
+ catch (e) {
187
+ return reject(e);
188
+ }
189
+ return resolve(backupData);
190
+ }
191
+ catch (e) {
192
+ return reject('No backup found');
193
+ }
194
+ });
195
+ };
196
+ exports.load = load;
197
+ /**
198
+ * Removes a backup
199
+ */
200
+ const remove = async (backupID) => {
201
+ return new Promise((resolve, reject) => {
202
+ try {
203
+ require(`${backups}${path_1.sep}${backupID}.json`);
204
+ (0, fs_1.unlinkSync)(`${backups}${path_1.sep}${backupID}.json`);
205
+ resolve();
206
+ }
207
+ catch (error) {
208
+ reject('Backup not found');
209
+ }
210
+ });
211
+ };
212
+ exports.remove = remove;
213
+ /**
214
+ * Returns the list of all backup
215
+ */
216
+ const list = async () => {
217
+ const files = await (0, promises_1.readdir)(backups);
218
+ return files.map((f) => f.split('.')[0]);
219
+ };
220
+ exports.list = list;
221
+ /**
222
+ * Change the storage path
223
+ */
224
+ const setStorageFolder = (path) => {
225
+ if (path.endsWith(path_1.sep)) {
226
+ path = path.substr(0, path.length - 1);
227
+ }
228
+ backups = path;
229
+ if (!(0, fs_1.existsSync)(backups)) {
230
+ (0, fs_1.mkdirSync)(backups);
231
+ }
232
+ };
233
+ exports.setStorageFolder = setStorageFolder;
234
+ exports.default = {
235
+ create: exports.create,
236
+ fetch: exports.fetch,
237
+ list: exports.list,
238
+ load: exports.load,
239
+ remove: exports.remove
240
+ };
package/lib/load.d.ts ADDED
@@ -0,0 +1,30 @@
1
+ import type { BackupData, LoadOptions } from './types';
2
+ import type { Emoji, Guild, Role } from 'discord.js';
3
+ /**
4
+ * Restores the guild configuration
5
+ */
6
+ export declare const loadConfig: (guild: Guild, backupData: BackupData) => Promise<Guild[]>;
7
+ /**
8
+ * Restore the guild roles
9
+ */
10
+ export declare const loadRoles: (guild: Guild, backupData: BackupData) => Promise<Role[]>;
11
+ /**
12
+ * Restore the guild channels
13
+ */
14
+ export declare const loadChannels: (guild: Guild, backupData: BackupData, options: LoadOptions) => Promise<unknown[]>;
15
+ /**
16
+ * Restore the afk configuration
17
+ */
18
+ export declare const loadAFK: (guild: Guild, backupData: BackupData) => Promise<Guild[]>;
19
+ /**
20
+ * Restore guild emojis
21
+ */
22
+ export declare const loadEmojis: (guild: Guild, backupData: BackupData) => Promise<Emoji[]>;
23
+ /**
24
+ * Restore guild bans
25
+ */
26
+ export declare const loadBans: (guild: Guild, backupData: BackupData) => Promise<string[]>;
27
+ /**
28
+ * Restore embedChannel configuration
29
+ */
30
+ export declare const loadEmbedChannel: (guild: Guild, backupData: BackupData) => Promise<Guild[]>;