spacecommands 3.1.0 → 3.2.0
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.
- package/README.md +2 -1
- package/dist/CommandHandler.js +1 -1
- package/dist/SlashCommands.js +1 -1
- package/dist/command-checks/has-entitlement.js +15 -2
- package/dist/command-checks/has-permissions.js +1 -1
- package/dist/commands/mylanguage.js +60 -0
- package/dist/handlers/ContextMenuHandler.js +4 -4
- package/dist/handlers/EntitlementHandler.js +11 -0
- package/dist/index.js +10 -0
- package/dist/message-handler.js +22 -6
- package/dist/models/user-languages.js +65 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -55,6 +55,7 @@ client.on('ready', () => {
|
|
|
55
55
|
featuresDir: path.join(__dirname, 'features'),
|
|
56
56
|
testServers: ['YOUR_TEST_SERVER_ID'],
|
|
57
57
|
botOwners: ['YOUR_USER_ID'],
|
|
58
|
+
premiumServers: ['YOUR_PREMIUM_SERVER_ID'],
|
|
58
59
|
// Database (optional - Supabase recommended)
|
|
59
60
|
supabaseUrl: process.env.SUPABASE_URL,
|
|
60
61
|
supabaseKey: process.env.SUPABASE_KEY,
|
|
@@ -66,7 +67,7 @@ client.login(process.env.BOT_TOKEN);
|
|
|
66
67
|
|
|
67
68
|
## Supabase Setup (Recommended)
|
|
68
69
|
|
|
69
|
-
SpaceCommands
|
|
70
|
+
SpaceCommands uses Supabase for data persistence. Here's how to set it up:
|
|
70
71
|
|
|
71
72
|
### 1. Create a Supabase Project
|
|
72
73
|
|
package/dist/CommandHandler.js
CHANGED
|
@@ -137,7 +137,7 @@ class CommandHandler {
|
|
|
137
137
|
});
|
|
138
138
|
}
|
|
139
139
|
else {
|
|
140
|
-
message.reply(instance.messageHandler.get(guild, 'EXCEPTION'));
|
|
140
|
+
message.reply(instance.messageHandler.get(guild, 'EXCEPTION', {}, message.author));
|
|
141
141
|
console.error(e);
|
|
142
142
|
}
|
|
143
143
|
instance.emit(Events_1.default.COMMAND_EXCEPTION, command, message, e);
|
package/dist/SlashCommands.js
CHANGED
|
@@ -72,7 +72,7 @@ class SlashCommands {
|
|
|
72
72
|
const command = this._instance.commandHandler.getCommand(commandName);
|
|
73
73
|
if (!command) {
|
|
74
74
|
interaction.reply({
|
|
75
|
-
content: this._instance.messageHandler.get(guild, 'INVALID_SLASH_COMMAND'),
|
|
75
|
+
content: this._instance.messageHandler.get(guild, 'INVALID_SLASH_COMMAND', {}, interaction.user),
|
|
76
76
|
ephemeral: this._instance.ephemeral,
|
|
77
77
|
});
|
|
78
78
|
return;
|
|
@@ -5,6 +5,9 @@ module.exports = async (guild, command, instance, member, user, reply) => {
|
|
|
5
5
|
if (!requiredEntitlements.length && !premiumOnly) {
|
|
6
6
|
return true;
|
|
7
7
|
}
|
|
8
|
+
if (guild && instance.premiumServers.includes(guild.id)) {
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
8
11
|
const entitlementHandler = instance.entitlementHandler;
|
|
9
12
|
if (!entitlementHandler) {
|
|
10
13
|
console.warn('SpaceCommands > Command requires entitlements but EntitlementHandler is not initialized.');
|
|
@@ -13,7 +16,12 @@ module.exports = async (guild, command, instance, member, user, reply) => {
|
|
|
13
16
|
// Check if user has required entitlements
|
|
14
17
|
if (requiredEntitlements.length > 0) {
|
|
15
18
|
const { hasEntitlement } = await entitlementHandler.hasAnyEntitlement(user.id, requiredEntitlements);
|
|
16
|
-
|
|
19
|
+
let hasAccess = hasEntitlement;
|
|
20
|
+
if (!hasAccess && guild) {
|
|
21
|
+
const { hasEntitlement: hasGuildEntitlement } = await entitlementHandler.hasAnyGuildEntitlement(guild.id, requiredEntitlements);
|
|
22
|
+
hasAccess = hasGuildEntitlement;
|
|
23
|
+
}
|
|
24
|
+
if (!hasAccess) {
|
|
17
25
|
reply(instance.messageHandler.get(guild, 'MISSING_ENTITLEMENT') ||
|
|
18
26
|
'You need a premium subscription to use this command.').then((message) => {
|
|
19
27
|
if (!message) {
|
|
@@ -32,7 +40,12 @@ module.exports = async (guild, command, instance, member, user, reply) => {
|
|
|
32
40
|
// If premiumOnly is set, check for any active entitlement
|
|
33
41
|
if (premiumOnly) {
|
|
34
42
|
const allEntitlements = await entitlementHandler.getUserEntitlements(user.id);
|
|
35
|
-
|
|
43
|
+
let hasPremium = allEntitlements.length > 0;
|
|
44
|
+
if (!hasPremium && guild) {
|
|
45
|
+
const guildEntitlements = await entitlementHandler.getGuildEntitlements(guild.id);
|
|
46
|
+
hasPremium = guildEntitlements.length > 0;
|
|
47
|
+
}
|
|
48
|
+
if (!hasPremium) {
|
|
36
49
|
reply(instance.messageHandler.get(guild, 'PREMIUM_ONLY') ||
|
|
37
50
|
'This command is only available to premium subscribers.').then((message) => {
|
|
38
51
|
if (!message) {
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
// @ts-nocheck
|
|
6
|
+
const user_languages_1 = __importDefault(require("../models/user-languages"));
|
|
7
|
+
const Events_1 = __importDefault(require("../enums/Events"));
|
|
8
|
+
module.exports = {
|
|
9
|
+
description: 'Displays or sets your personal language preference',
|
|
10
|
+
category: 'Configuration',
|
|
11
|
+
aliases: ['mylang'],
|
|
12
|
+
maxArgs: 1,
|
|
13
|
+
expectedArgs: '[language]',
|
|
14
|
+
cooldown: '2s',
|
|
15
|
+
options: [
|
|
16
|
+
{
|
|
17
|
+
name: 'language',
|
|
18
|
+
description: 'The language to set for yourself',
|
|
19
|
+
type: 3, // STRING
|
|
20
|
+
required: false,
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
slash: 'both',
|
|
24
|
+
callback: async (options) => {
|
|
25
|
+
const { channel, text, instance, user } = options;
|
|
26
|
+
const { guild } = channel;
|
|
27
|
+
// Allow in DMs
|
|
28
|
+
// if (!guild) {
|
|
29
|
+
// return
|
|
30
|
+
// }
|
|
31
|
+
const { messageHandler } = instance;
|
|
32
|
+
if (!instance.isDBConnected()) {
|
|
33
|
+
return instance.messageHandler.get(guild, 'NO_DATABASE_FOUND', {}, user);
|
|
34
|
+
}
|
|
35
|
+
const lang = text.toLowerCase();
|
|
36
|
+
if (!lang) {
|
|
37
|
+
return instance.messageHandler.get(guild, 'CURRENT_LANGUAGE', {
|
|
38
|
+
LANGUAGE: instance.messageHandler.getLanguage(guild, user),
|
|
39
|
+
}, user);
|
|
40
|
+
}
|
|
41
|
+
if (!messageHandler.languages().includes(lang)) {
|
|
42
|
+
instance.emit(Events_1.default.LANGUAGE_NOT_SUPPORTED, guild, lang);
|
|
43
|
+
return messageHandler.get(guild, 'LANGUAGE_NOT_SUPPORTED', {
|
|
44
|
+
LANGUAGE: lang,
|
|
45
|
+
}, user);
|
|
46
|
+
}
|
|
47
|
+
instance.messageHandler.setUserLanguage(user, lang);
|
|
48
|
+
await user_languages_1.default.findOneAndUpdate({
|
|
49
|
+
_id: user.id,
|
|
50
|
+
}, {
|
|
51
|
+
_id: user.id,
|
|
52
|
+
language: lang,
|
|
53
|
+
}, {
|
|
54
|
+
upsert: true,
|
|
55
|
+
});
|
|
56
|
+
return instance.messageHandler.get(guild, 'NEW_LANGUAGE', {
|
|
57
|
+
LANGUAGE: lang,
|
|
58
|
+
}, user);
|
|
59
|
+
},
|
|
60
|
+
};
|
|
@@ -69,7 +69,7 @@ class ContextMenuHandler {
|
|
|
69
69
|
!this._instance.botOwner.includes(interaction.user.id)) {
|
|
70
70
|
await interaction.reply({
|
|
71
71
|
content: 'This command is only available to bot owners.',
|
|
72
|
-
|
|
72
|
+
flags: discord_js_1.MessageFlags.Ephemeral,
|
|
73
73
|
});
|
|
74
74
|
return;
|
|
75
75
|
}
|
|
@@ -77,7 +77,7 @@ class ContextMenuHandler {
|
|
|
77
77
|
if (command.guildOnly && !interaction.guild) {
|
|
78
78
|
await interaction.reply({
|
|
79
79
|
content: 'This command can only be used in servers.',
|
|
80
|
-
|
|
80
|
+
flags: discord_js_1.MessageFlags.Ephemeral,
|
|
81
81
|
});
|
|
82
82
|
return;
|
|
83
83
|
}
|
|
@@ -88,7 +88,7 @@ class ContextMenuHandler {
|
|
|
88
88
|
if (!hasPermission) {
|
|
89
89
|
await interaction.reply({
|
|
90
90
|
content: 'You do not have permission to use this command.',
|
|
91
|
-
|
|
91
|
+
flags: discord_js_1.MessageFlags.Ephemeral,
|
|
92
92
|
});
|
|
93
93
|
return;
|
|
94
94
|
}
|
|
@@ -101,7 +101,7 @@ class ContextMenuHandler {
|
|
|
101
101
|
if (!interaction.replied && !interaction.deferred) {
|
|
102
102
|
await interaction.reply({
|
|
103
103
|
content: 'An error occurred while executing this command.',
|
|
104
|
-
|
|
104
|
+
flags: discord_js_1.MessageFlags.Ephemeral,
|
|
105
105
|
});
|
|
106
106
|
}
|
|
107
107
|
}
|
|
@@ -79,6 +79,17 @@ class EntitlementHandler {
|
|
|
79
79
|
entitlement,
|
|
80
80
|
};
|
|
81
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* Check if a guild has any of the specified entitlements
|
|
84
|
+
*/
|
|
85
|
+
async hasAnyGuildEntitlement(guildId, skuIds) {
|
|
86
|
+
const entitlements = await this.getGuildEntitlements(guildId);
|
|
87
|
+
const entitlement = entitlements.find((e) => skuIds.includes(e.skuId));
|
|
88
|
+
return {
|
|
89
|
+
hasEntitlement: !!entitlement,
|
|
90
|
+
entitlement,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
82
93
|
/**
|
|
83
94
|
* Check if a user has all of the specified entitlements
|
|
84
95
|
*/
|
package/dist/index.js
CHANGED
|
@@ -36,6 +36,7 @@ class SpaceCommands extends events_1.EventEmitter {
|
|
|
36
36
|
_ignoreBots = true;
|
|
37
37
|
_botOwner = [];
|
|
38
38
|
_testServers = [];
|
|
39
|
+
_premiumServers = [];
|
|
39
40
|
_defaultLanguage = 'english';
|
|
40
41
|
_ephemeral = true;
|
|
41
42
|
_debug = false;
|
|
@@ -98,6 +99,12 @@ class SpaceCommands extends events_1.EventEmitter {
|
|
|
98
99
|
}
|
|
99
100
|
this._botOwner = botOwners;
|
|
100
101
|
}
|
|
102
|
+
if (options.premiumServers) {
|
|
103
|
+
if (typeof options.premiumServers === 'string') {
|
|
104
|
+
options.premiumServers = [options.premiumServers];
|
|
105
|
+
}
|
|
106
|
+
this._premiumServers = options.premiumServers;
|
|
107
|
+
}
|
|
101
108
|
this._showWarns = showWarns;
|
|
102
109
|
this._delErrMsgCooldown = delErrMsgCooldown;
|
|
103
110
|
this._defaultLanguage = defaultLanguage.toLowerCase();
|
|
@@ -269,6 +276,9 @@ class SpaceCommands extends events_1.EventEmitter {
|
|
|
269
276
|
get testServers() {
|
|
270
277
|
return this._testServers;
|
|
271
278
|
}
|
|
279
|
+
get premiumServers() {
|
|
280
|
+
return this._premiumServers;
|
|
281
|
+
}
|
|
272
282
|
get defaultLanguage() {
|
|
273
283
|
return this._defaultLanguage;
|
|
274
284
|
}
|
package/dist/message-handler.js
CHANGED
|
@@ -37,10 +37,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
const languages_1 = __importDefault(require("./models/languages"));
|
|
40
|
+
const user_languages_1 = __importDefault(require("./models/user-languages"));
|
|
40
41
|
const defualtMessages = require('../messages.json');
|
|
41
42
|
class MessageHandler {
|
|
42
43
|
_instance;
|
|
43
44
|
_guildLanguages = new Map(); // <Guild ID, Language>
|
|
45
|
+
_userLanguages = new Map(); // <User ID, Language>
|
|
44
46
|
_languages = [];
|
|
45
47
|
_messages = {};
|
|
46
48
|
constructor(instance, messagePath) {
|
|
@@ -61,6 +63,11 @@ class MessageHandler {
|
|
|
61
63
|
for (const { _id: guildId, language } of results) {
|
|
62
64
|
this._guildLanguages.set(guildId, language);
|
|
63
65
|
}
|
|
66
|
+
const userResults = await user_languages_1.default.find();
|
|
67
|
+
// @ts-ignore
|
|
68
|
+
for (const { _id: userId, language } of userResults) {
|
|
69
|
+
this._userLanguages.set(userId, language);
|
|
70
|
+
}
|
|
64
71
|
}
|
|
65
72
|
})();
|
|
66
73
|
}
|
|
@@ -72,7 +79,16 @@ class MessageHandler {
|
|
|
72
79
|
this._guildLanguages.set(guild.id, language);
|
|
73
80
|
}
|
|
74
81
|
}
|
|
75
|
-
|
|
82
|
+
async setUserLanguage(user, language) {
|
|
83
|
+
this._userLanguages.set(user.id, language);
|
|
84
|
+
}
|
|
85
|
+
getLanguage(guild, user) {
|
|
86
|
+
if (user) {
|
|
87
|
+
const userLang = this._userLanguages.get(user.id);
|
|
88
|
+
if (userLang) {
|
|
89
|
+
return userLang;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
76
92
|
if (guild) {
|
|
77
93
|
const result = this._guildLanguages.get(guild.id);
|
|
78
94
|
if (result) {
|
|
@@ -81,8 +97,8 @@ class MessageHandler {
|
|
|
81
97
|
}
|
|
82
98
|
return this._instance.defaultLanguage;
|
|
83
99
|
}
|
|
84
|
-
get(guild, messageId, args = {}) {
|
|
85
|
-
const language = this.getLanguage(guild);
|
|
100
|
+
get(guild, messageId, args = {}, user) {
|
|
101
|
+
const language = this.getLanguage(guild, user);
|
|
86
102
|
const translations = this._messages[messageId];
|
|
87
103
|
if (!translations) {
|
|
88
104
|
console.error(`SpaceCommands > Could not find the correct message to send for "${messageId}"`);
|
|
@@ -91,12 +107,12 @@ class MessageHandler {
|
|
|
91
107
|
let result = translations[language];
|
|
92
108
|
for (const key of Object.keys(args)) {
|
|
93
109
|
const expression = new RegExp(`{${key}}`, 'g');
|
|
94
|
-
result = result
|
|
110
|
+
result = result?.replace(expression, args[key]);
|
|
95
111
|
}
|
|
96
112
|
return result;
|
|
97
113
|
}
|
|
98
|
-
getEmbed(guild, embedId, itemId, args = {}) {
|
|
99
|
-
const language = this.getLanguage(guild);
|
|
114
|
+
getEmbed(guild, embedId, itemId, args = {}, user) {
|
|
115
|
+
const language = this.getLanguage(guild, user);
|
|
100
116
|
const items = this._messages[embedId];
|
|
101
117
|
if (!items) {
|
|
102
118
|
console.error(`SpaceCommands > Could not find the correct item to send for "${embedId}" -> "${itemId}"`);
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
// @ts-nocheck
|
|
4
|
+
const supabase_1 = require("../supabase");
|
|
5
|
+
const TABLE_NAME = 'spacecommands_user_languages';
|
|
6
|
+
exports.default = {
|
|
7
|
+
async find(filter = {}) {
|
|
8
|
+
const client = (0, supabase_1.getSupabaseClient)();
|
|
9
|
+
if (!client)
|
|
10
|
+
return [];
|
|
11
|
+
let query = client.from(TABLE_NAME).select('*');
|
|
12
|
+
if (filter._id) {
|
|
13
|
+
query = query.eq('user_id', filter._id);
|
|
14
|
+
}
|
|
15
|
+
const { data, error } = await query;
|
|
16
|
+
if (error) {
|
|
17
|
+
console.error('SpaceCommands > Error fetching user languages:', error);
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
20
|
+
return (data || []).map((row) => ({
|
|
21
|
+
_id: row.user_id,
|
|
22
|
+
language: row.language,
|
|
23
|
+
}));
|
|
24
|
+
},
|
|
25
|
+
async findOne(filter) {
|
|
26
|
+
const client = (0, supabase_1.getSupabaseClient)();
|
|
27
|
+
if (!client)
|
|
28
|
+
return null;
|
|
29
|
+
const { data, error } = await client
|
|
30
|
+
.from(TABLE_NAME)
|
|
31
|
+
.select('*')
|
|
32
|
+
.eq('user_id', filter._id)
|
|
33
|
+
.single();
|
|
34
|
+
if (error) {
|
|
35
|
+
if (error.code === 'PGRST116')
|
|
36
|
+
return null;
|
|
37
|
+
console.error('SpaceCommands > Error finding user language:', error);
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
_id: data.user_id,
|
|
42
|
+
language: data.language,
|
|
43
|
+
};
|
|
44
|
+
},
|
|
45
|
+
async findOneAndUpdate(filter, update, options = {}) {
|
|
46
|
+
const client = (0, supabase_1.getSupabaseClient)();
|
|
47
|
+
if (!client)
|
|
48
|
+
return null;
|
|
49
|
+
const userId = filter._id;
|
|
50
|
+
const language = update.language || update.$set?.language;
|
|
51
|
+
const { data, error } = await client
|
|
52
|
+
.from(TABLE_NAME)
|
|
53
|
+
.upsert({ user_id: userId, language }, { onConflict: 'user_id' })
|
|
54
|
+
.select()
|
|
55
|
+
.single();
|
|
56
|
+
if (error) {
|
|
57
|
+
console.error('SpaceCommands > Error upserting user language:', error);
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
_id: data.user_id,
|
|
62
|
+
language: data.language,
|
|
63
|
+
};
|
|
64
|
+
},
|
|
65
|
+
};
|