@ibbybuilds/discli 0.1.0 → 0.3.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 CHANGED
@@ -37,7 +37,7 @@ One command = one API call. No bot server. No token overhead.
37
37
 
38
38
  ```bash
39
39
  # Install
40
- npm install -g discli
40
+ npm install -g @ibbybuilds/discli
41
41
 
42
42
  # Setup (paste your bot token)
43
43
  discli init --token YOUR_BOT_TOKEN
@@ -118,6 +118,35 @@ discli perm set <channel> <role> --deny send_messages # Fine-grained control
118
118
  discli perm list # List permission names
119
119
  ```
120
120
 
121
+ ### Messages
122
+
123
+ ```bash
124
+ discli msg send <channel> "Hello world" # Send message
125
+ discli msg send <channel> "reply" --reply <msg-id> # Reply to message
126
+ discli msg embed <channel> --title "X" --description "Y" --color "#5865F2" # Rich embed
127
+ discli msg embed <channel> --title "X" --field "Name|Value|inline" # Embed with fields
128
+ discli msg read <channel> -n 10 # Read last N messages
129
+ discli msg edit <channel> <msg-id> "new text" # Edit bot message
130
+ discli msg delete <channel> <msg-id> --confirm # Delete message
131
+ discli msg react <channel> <msg-id> 👍 # Add reaction
132
+ discli msg unreact <channel> <msg-id> 👍 # Remove reaction
133
+ discli msg pin <channel> <msg-id> # Pin message
134
+ discli msg unpin <channel> <msg-id> # Unpin message
135
+ discli msg pins <channel> # List pinned messages
136
+ discli msg thread <channel> "Thread Name" # Create thread
137
+ discli msg thread <channel> "Name" --message <msg-id> # Thread from message
138
+ ```
139
+
140
+ ### Audit Log
141
+
142
+ ```bash
143
+ discli audit log # View recent audit log
144
+ discli audit log -n 50 # Last 50 entries
145
+ discli audit log --type member_kick # Filter by action type
146
+ discli audit log --user <id> # Filter by who did it
147
+ discli audit types # List all action type names
148
+ ```
149
+
121
150
  <br>
122
151
 
123
152
  ## For AI Agents
@@ -146,7 +175,7 @@ discli is designed for AI coding agents like Claude Code, Cursor, Codex, and oth
146
175
 
147
176
  ```bash
148
177
  # Install discli globally
149
- npm install -g discli
178
+ npm install -g @ibbybuilds/discli
150
179
 
151
180
  # Copy the skill file
152
181
  cp node_modules/discli/skills/SKILL.md ~/.claude/skills/discli/SKILL.md
@@ -223,7 +252,8 @@ discli uses your bot token. You create the bot, you control the permissions, you
223
252
  | **Create channels** | ✅ | ✅ | ❌ | ✅ |
224
253
  | **Manage roles** | ✅ | ✅ | ❌ | ✅ |
225
254
  | **Set permissions** | ✅ | ✅ | ❌ | ✅ |
226
- | **Read messages** | Coming soon | ✅ | ✅ | ✅ |
255
+ | **Read messages** | | ✅ | ✅ | ✅ |
256
+ | **Send embeds** | ✅ | ✅ | ❌ | ✅ |
227
257
  | **Self-hosted** | ✅ | ✅ | ✅ | N/A |
228
258
 
229
259
  <br>
package/dist/cli.js CHANGED
@@ -144,6 +144,16 @@ var DiscordAPI = class {
144
144
  async getGuild(guildId) {
145
145
  return await this.request("GET", `/guilds/${guildId}?with_counts=true`);
146
146
  }
147
+ // ── Audit Log ──
148
+ async getAuditLog(guildId, opts) {
149
+ const params = new URLSearchParams();
150
+ if (opts?.user_id) params.set("user_id", opts.user_id);
151
+ if (opts?.action_type !== void 0) params.set("action_type", String(opts.action_type));
152
+ if (opts?.limit) params.set("limit", String(Math.min(opts.limit, 100)));
153
+ if (opts?.before) params.set("before", opts.before);
154
+ const qs = params.toString();
155
+ return await this.request("GET", `/guilds/${guildId}/audit-logs${qs ? "?" + qs : ""}`);
156
+ }
147
157
  // ── Channels ──
148
158
  async listChannels(guildId) {
149
159
  return await this.request("GET", `/guilds/${guildId}/channels`);
@@ -151,6 +161,56 @@ var DiscordAPI = class {
151
161
  async createChannel(guildId, opts) {
152
162
  return await this.request("POST", `/guilds/${guildId}/channels`, opts);
153
163
  }
164
+ // ── Messages ──
165
+ async sendMessage(channelId, data) {
166
+ return await this.request("POST", `/channels/${channelId}/messages`, data);
167
+ }
168
+ async getMessages(channelId, limit = 50, before) {
169
+ let path = `/channels/${channelId}/messages?limit=${Math.min(limit, 100)}`;
170
+ if (before) path += `&before=${before}`;
171
+ return await this.request("GET", path);
172
+ }
173
+ async getMessage(channelId, messageId) {
174
+ return await this.request("GET", `/channels/${channelId}/messages/${messageId}`);
175
+ }
176
+ async editMessage(channelId, messageId, data) {
177
+ return await this.request("PATCH", `/channels/${channelId}/messages/${messageId}`, data);
178
+ }
179
+ // ── Reactions ──
180
+ async addReaction(channelId, messageId, emoji) {
181
+ const encoded = encodeURIComponent(emoji);
182
+ await this.request("PUT", `/channels/${channelId}/messages/${messageId}/reactions/${encoded}/@me`);
183
+ }
184
+ async removeReaction(channelId, messageId, emoji) {
185
+ const encoded = encodeURIComponent(emoji);
186
+ await this.request("DELETE", `/channels/${channelId}/messages/${messageId}/reactions/${encoded}/@me`);
187
+ }
188
+ // ── Threads ──
189
+ async createThread(channelId, name, messageId) {
190
+ if (messageId) {
191
+ return await this.request("POST", `/channels/${channelId}/messages/${messageId}/threads`, {
192
+ name,
193
+ auto_archive_duration: 1440
194
+ });
195
+ }
196
+ return await this.request("POST", `/channels/${channelId}/threads`, {
197
+ name,
198
+ type: 11,
199
+ auto_archive_duration: 1440
200
+ });
201
+ }
202
+ async deleteMessage(channelId, messageId) {
203
+ await this.request("DELETE", `/channels/${channelId}/messages/${messageId}`);
204
+ }
205
+ async pinMessage(channelId, messageId) {
206
+ await this.request("PUT", `/channels/${channelId}/pins/${messageId}`);
207
+ }
208
+ async unpinMessage(channelId, messageId) {
209
+ await this.request("DELETE", `/channels/${channelId}/pins/${messageId}`);
210
+ }
211
+ async getPinnedMessages(channelId) {
212
+ return await this.request("GET", `/channels/${channelId}/pins`);
213
+ }
154
214
  async deleteChannel(channelId) {
155
215
  await this.request("DELETE", `/channels/${channelId}`);
156
216
  }
@@ -173,6 +233,12 @@ var DiscordAPI = class {
173
233
  async createRole(guildId, data) {
174
234
  return await this.request("POST", `/guilds/${guildId}/roles`, data);
175
235
  }
236
+ async modifyRole(guildId, roleId, data) {
237
+ return await this.request("PATCH", `/guilds/${guildId}/roles/${roleId}`, data);
238
+ }
239
+ async reorderRoles(guildId, positions) {
240
+ return await this.request("PATCH", `/guilds/${guildId}/roles`, positions);
241
+ }
176
242
  async deleteRole(guildId, roleId) {
177
243
  await this.request("DELETE", `/guilds/${guildId}/roles/${roleId}`);
178
244
  }
@@ -199,6 +265,46 @@ var DiscordAPI = class {
199
265
  return await this.request("PATCH", `/guilds/${guildId}/members/${userId}`, data);
200
266
  }
201
267
  };
268
+ var AUDIT_ACTION = {
269
+ guild_update: 1,
270
+ channel_create: 10,
271
+ channel_update: 11,
272
+ channel_delete: 12,
273
+ member_kick: 20,
274
+ member_prune: 21,
275
+ member_ban_add: 22,
276
+ member_ban_remove: 23,
277
+ member_update: 24,
278
+ member_role_update: 25,
279
+ bot_add: 28,
280
+ role_create: 30,
281
+ role_update: 31,
282
+ role_delete: 32,
283
+ invite_create: 40,
284
+ invite_delete: 42,
285
+ webhook_create: 50,
286
+ webhook_update: 51,
287
+ webhook_delete: 52,
288
+ emoji_create: 60,
289
+ emoji_delete: 62,
290
+ message_delete: 72,
291
+ message_bulk_delete: 73,
292
+ message_pin: 74,
293
+ message_unpin: 75,
294
+ thread_create: 110,
295
+ thread_update: 111,
296
+ thread_delete: 112,
297
+ automod_rule_create: 140,
298
+ automod_rule_update: 141,
299
+ automod_rule_delete: 142,
300
+ automod_block_message: 143,
301
+ integration_create: 80,
302
+ integration_update: 81,
303
+ integration_delete: 82
304
+ };
305
+ var AUDIT_ACTION_NAME = Object.fromEntries(
306
+ Object.entries(AUDIT_ACTION).map(([k, v]) => [v, k])
307
+ );
202
308
 
203
309
  // src/commands/init.ts
204
310
  import { readFileSync as readFileSync2 } from "fs";
@@ -854,14 +960,265 @@ function registerPermission(program2) {
854
960
  });
855
961
  }
856
962
 
963
+ // src/commands/message.ts
964
+ function parseColor(color) {
965
+ return parseInt(color.replace("#", ""), 16);
966
+ }
967
+ function registerMessage(program2) {
968
+ const message = program2.command("message").alias("msg").description("Send, read, and manage messages");
969
+ message.command("send").description("Send a message to a channel").argument("<channel>", "Channel name or ID").argument("<text>", "Message content (supports Discord markdown)").option("--reply <id>", "Reply to a message ID").action(async (channelName, text, opts) => {
970
+ const fmt = resolveFormat(program2.opts().format);
971
+ const api = new DiscordAPI(requireToken());
972
+ const guildId = requireServer(program2.opts().server);
973
+ const ch = await resolveChannel(api, guildId, channelName);
974
+ const payload = { content: text };
975
+ if (opts.reply) {
976
+ payload.message_reference = { message_id: opts.reply };
977
+ }
978
+ const msg = await api.sendMessage(ch.id, payload);
979
+ if (fmt !== "table") {
980
+ printResult(msg, fmt);
981
+ } else {
982
+ console.log(`Sent message to #${ch.name} (${msg.id})`);
983
+ }
984
+ });
985
+ message.command("embed").description("Send an embed (rich card) to a channel").argument("<channel>", "Channel name or ID").option("--title <text>", "Embed title").option("--description <text>", "Embed description (supports markdown)").option("--color <hex>", "Embed color (e.g. #5865F2)").option("--url <url>", "Title link URL").option("--image <url>", "Large image URL").option("--thumbnail <url>", "Small thumbnail URL").option("--footer <text>", "Footer text").option("--author <name>", "Author name").option("--field <value...>", 'Add field: "Name|Value" or "Name|Value|inline"').option("--content <text>", "Text content above the embed").option("--reply <id>", "Reply to a message ID").action(async (channelName, opts) => {
986
+ const fmt = resolveFormat(program2.opts().format);
987
+ const api = new DiscordAPI(requireToken());
988
+ const guildId = requireServer(program2.opts().server);
989
+ const ch = await resolveChannel(api, guildId, channelName);
990
+ const embed = {};
991
+ if (opts.title) embed.title = opts.title;
992
+ if (opts.description) embed.description = opts.description;
993
+ if (opts.color) embed.color = parseColor(opts.color);
994
+ if (opts.url) embed.url = opts.url;
995
+ if (opts.image) embed.image = { url: opts.image };
996
+ if (opts.thumbnail) embed.thumbnail = { url: opts.thumbnail };
997
+ if (opts.footer) embed.footer = { text: opts.footer };
998
+ if (opts.author) embed.author = { name: opts.author };
999
+ if (opts.field) {
1000
+ embed.fields = opts.field.map((f) => {
1001
+ const parts = f.split("|");
1002
+ return {
1003
+ name: parts[0],
1004
+ value: parts[1] || "",
1005
+ inline: parts[2] === "inline"
1006
+ };
1007
+ });
1008
+ }
1009
+ if (!embed.title && !embed.description) {
1010
+ console.error("Provide at least --title or --description for the embed.");
1011
+ process.exit(2);
1012
+ }
1013
+ const payload = { embeds: [embed] };
1014
+ if (opts.content) payload.content = opts.content;
1015
+ if (opts.reply) payload.message_reference = { message_id: opts.reply };
1016
+ const msg = await api.sendMessage(ch.id, payload);
1017
+ if (fmt !== "table") {
1018
+ printResult(msg, fmt);
1019
+ } else {
1020
+ console.log(`Sent embed to #${ch.name} (${msg.id})`);
1021
+ }
1022
+ });
1023
+ message.command("read").description("Read recent messages from a channel").argument("<channel>", "Channel name or ID").option("-n <count>", "Number of messages to fetch", "10").option("--before <id>", "Fetch messages before this message ID").action(async (channelName, opts) => {
1024
+ const fmt = resolveFormat(program2.opts().format);
1025
+ const api = new DiscordAPI(requireToken());
1026
+ const guildId = requireServer(program2.opts().server);
1027
+ const ch = await resolveChannel(api, guildId, channelName);
1028
+ const messages = await api.getMessages(ch.id, parseInt(opts.n), opts.before);
1029
+ if (fmt !== "table") {
1030
+ printResult(messages, fmt);
1031
+ return;
1032
+ }
1033
+ console.log(`
1034
+ #${ch.name} \u2014 last ${messages.length} messages`);
1035
+ console.log("\u2500".repeat(40));
1036
+ for (const msg of messages.reverse()) {
1037
+ const time = new Date(msg.timestamp).toLocaleString();
1038
+ const bot = msg.author.bot ? " [BOT]" : "";
1039
+ const edited = msg.edited_timestamp ? " (edited)" : "";
1040
+ const pinned = msg.pinned ? " \u{1F4CC}" : "";
1041
+ console.log(` ${msg.author.username}${bot} \u2014 ${time}${edited}${pinned}`);
1042
+ if (msg.content) console.log(` ${msg.content}`);
1043
+ if (msg.embeds && msg.embeds.length > 0) {
1044
+ for (const e of msg.embeds) {
1045
+ if (e.title) console.log(` [Embed] ${e.title}`);
1046
+ if (e.description) console.log(` ${e.description.slice(0, 100)}`);
1047
+ }
1048
+ }
1049
+ console.log();
1050
+ }
1051
+ });
1052
+ message.command("edit").description("Edit a message sent by the bot").argument("<channel>", "Channel name or ID").argument("<message-id>", "Message ID to edit").argument("<text>", "New message content").action(async (channelName, messageId, text) => {
1053
+ const fmt = resolveFormat(program2.opts().format);
1054
+ const api = new DiscordAPI(requireToken());
1055
+ const guildId = requireServer(program2.opts().server);
1056
+ const ch = await resolveChannel(api, guildId, channelName);
1057
+ const msg = await api.editMessage(ch.id, messageId, { content: text });
1058
+ if (fmt !== "table") {
1059
+ printResult(msg, fmt);
1060
+ } else {
1061
+ console.log(`Edited message ${messageId} in #${ch.name}`);
1062
+ }
1063
+ });
1064
+ message.command("delete").description("Delete a message").argument("<channel>", "Channel name or ID").argument("<message-id>", "Message ID to delete").option("--confirm", "Required to actually delete").action(async (channelName, messageId, opts) => {
1065
+ const api = new DiscordAPI(requireToken());
1066
+ const guildId = requireServer(program2.opts().server);
1067
+ const ch = await resolveChannel(api, guildId, channelName);
1068
+ if (!opts.confirm) {
1069
+ console.error(`This will delete message ${messageId} in #${ch.name}. Add --confirm to proceed.`);
1070
+ process.exit(2);
1071
+ }
1072
+ await api.deleteMessage(ch.id, messageId);
1073
+ console.log(`Deleted message ${messageId} from #${ch.name}`);
1074
+ });
1075
+ message.command("react").description("Add a reaction to a message").argument("<channel>", "Channel name or ID").argument("<message-id>", "Message ID").argument("<emoji>", "Emoji to react with (e.g. \u{1F44D} or :thumbsup:)").action(async (channelName, messageId, emoji) => {
1076
+ const api = new DiscordAPI(requireToken());
1077
+ const guildId = requireServer(program2.opts().server);
1078
+ const ch = await resolveChannel(api, guildId, channelName);
1079
+ await api.addReaction(ch.id, messageId, emoji);
1080
+ console.log(`Reacted ${emoji} on message ${messageId} in #${ch.name}`);
1081
+ });
1082
+ message.command("unreact").description("Remove bot reaction from a message").argument("<channel>", "Channel name or ID").argument("<message-id>", "Message ID").argument("<emoji>", "Emoji to remove").action(async (channelName, messageId, emoji) => {
1083
+ const api = new DiscordAPI(requireToken());
1084
+ const guildId = requireServer(program2.opts().server);
1085
+ const ch = await resolveChannel(api, guildId, channelName);
1086
+ await api.removeReaction(ch.id, messageId, emoji);
1087
+ console.log(`Removed ${emoji} reaction from message ${messageId}`);
1088
+ });
1089
+ message.command("pin").description("Pin a message").argument("<channel>", "Channel name or ID").argument("<message-id>", "Message ID to pin").action(async (channelName, messageId) => {
1090
+ const api = new DiscordAPI(requireToken());
1091
+ const guildId = requireServer(program2.opts().server);
1092
+ const ch = await resolveChannel(api, guildId, channelName);
1093
+ await api.pinMessage(ch.id, messageId);
1094
+ console.log(`Pinned message ${messageId} in #${ch.name}`);
1095
+ });
1096
+ message.command("unpin").description("Unpin a message").argument("<channel>", "Channel name or ID").argument("<message-id>", "Message ID to unpin").action(async (channelName, messageId) => {
1097
+ const api = new DiscordAPI(requireToken());
1098
+ const guildId = requireServer(program2.opts().server);
1099
+ const ch = await resolveChannel(api, guildId, channelName);
1100
+ await api.unpinMessage(ch.id, messageId);
1101
+ console.log(`Unpinned message ${messageId} in #${ch.name}`);
1102
+ });
1103
+ message.command("pins").description("List pinned messages in a channel").argument("<channel>", "Channel name or ID").action(async (channelName) => {
1104
+ const fmt = resolveFormat(program2.opts().format);
1105
+ const api = new DiscordAPI(requireToken());
1106
+ const guildId = requireServer(program2.opts().server);
1107
+ const ch = await resolveChannel(api, guildId, channelName);
1108
+ const pins = await api.getPinnedMessages(ch.id);
1109
+ if (fmt !== "table") {
1110
+ printResult(pins, fmt);
1111
+ return;
1112
+ }
1113
+ if (pins.length === 0) {
1114
+ console.log(`
1115
+ #${ch.name}: no pinned messages`);
1116
+ return;
1117
+ }
1118
+ console.log(`
1119
+ #${ch.name} \u2014 ${pins.length} pinned`);
1120
+ console.log("\u2500".repeat(30));
1121
+ for (const msg of pins) {
1122
+ const time = new Date(msg.timestamp).toLocaleString();
1123
+ console.log(` ${msg.author.username} \u2014 ${time}`);
1124
+ if (msg.content) console.log(` ${msg.content}`);
1125
+ console.log(` ID: ${msg.id}`);
1126
+ console.log();
1127
+ }
1128
+ });
1129
+ message.command("thread").description("Create a thread from a message or in a channel").argument("<channel>", "Channel name or ID").argument("<name>", "Thread name").option("--message <id>", "Create thread from this message ID").action(async (channelName, name, opts) => {
1130
+ const fmt = resolveFormat(program2.opts().format);
1131
+ const api = new DiscordAPI(requireToken());
1132
+ const guildId = requireServer(program2.opts().server);
1133
+ const ch = await resolveChannel(api, guildId, channelName);
1134
+ const thread = await api.createThread(ch.id, name, opts.message);
1135
+ if (fmt !== "table") {
1136
+ printResult(thread, fmt);
1137
+ } else {
1138
+ console.log(`Created thread "${name}" in #${ch.name} (${thread.id})`);
1139
+ }
1140
+ });
1141
+ }
1142
+
1143
+ // src/commands/audit.ts
1144
+ function registerAudit(program2) {
1145
+ const audit = program2.command("audit").description("View server audit log");
1146
+ audit.command("log").description("View recent audit log entries").option("-n <count>", "Number of entries to fetch", "20").option("--type <action>", "Filter by action type (e.g. member_kick, channel_create)").option("--user <id>", "Filter by user who performed the action").action(async (opts) => {
1147
+ const fmt = resolveFormat(program2.opts().format);
1148
+ const api = new DiscordAPI(requireToken());
1149
+ const guildId = requireServer(program2.opts().server);
1150
+ const queryOpts = {
1151
+ limit: parseInt(opts.n)
1152
+ };
1153
+ if (opts.type) {
1154
+ const actionType = AUDIT_ACTION[opts.type];
1155
+ if (actionType === void 0) {
1156
+ console.error(`Unknown action type: ${opts.type}`);
1157
+ console.error(`Available: ${Object.keys(AUDIT_ACTION).join(", ")}`);
1158
+ process.exit(2);
1159
+ }
1160
+ queryOpts.action_type = actionType;
1161
+ }
1162
+ if (opts.user) {
1163
+ queryOpts.user_id = opts.user;
1164
+ }
1165
+ const log = await api.getAuditLog(guildId, queryOpts);
1166
+ if (fmt !== "table") {
1167
+ printResult(log.audit_log_entries, fmt);
1168
+ return;
1169
+ }
1170
+ const userMap = new Map(log.users.map((u) => [u.id, u.username]));
1171
+ console.log("\nAudit Log");
1172
+ console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
1173
+ if (log.audit_log_entries.length === 0) {
1174
+ console.log(" (no entries)");
1175
+ return;
1176
+ }
1177
+ for (const entry of log.audit_log_entries) {
1178
+ const who = entry.user_id ? userMap.get(entry.user_id) ?? entry.user_id : "(system)";
1179
+ const action = AUDIT_ACTION_NAME[entry.action_type] ?? `unknown(${entry.action_type})`;
1180
+ const target = entry.target_id ?? "";
1181
+ const reason = entry.reason ? ` \u2014 "${entry.reason}"` : "";
1182
+ console.log(` ${who} \u2192 ${action} ${target}${reason}`);
1183
+ if (entry.changes && entry.changes.length > 0) {
1184
+ for (const change of entry.changes.slice(0, 3)) {
1185
+ const old = change.old_value !== void 0 ? String(change.old_value).slice(0, 30) : "";
1186
+ const nw = change.new_value !== void 0 ? String(change.new_value).slice(0, 30) : "";
1187
+ if (old && nw) {
1188
+ console.log(` ${change.key}: ${old} \u2192 ${nw}`);
1189
+ } else if (nw) {
1190
+ console.log(` ${change.key}: ${nw}`);
1191
+ }
1192
+ }
1193
+ }
1194
+ }
1195
+ console.log();
1196
+ });
1197
+ audit.command("types").description("List available audit log action types").action(() => {
1198
+ const fmt = resolveFormat(program2.opts().format);
1199
+ if (fmt !== "table") {
1200
+ const types = Object.entries(AUDIT_ACTION).map(([name, value]) => ({ name, value }));
1201
+ printResult(types, fmt);
1202
+ } else {
1203
+ console.log("\nAudit Log Action Types");
1204
+ console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
1205
+ for (const [name, value] of Object.entries(AUDIT_ACTION)) {
1206
+ console.log(` ${name.padEnd(25)} ${value}`);
1207
+ }
1208
+ }
1209
+ });
1210
+ }
1211
+
857
1212
  // src/cli.ts
858
1213
  var program = new Command();
859
- program.name("discli").description("discli \u2014 Discord server management CLI").version("0.1.0").option("--format <fmt>", "Output format: json, yaml, table, auto (auto = yaml when piped, table in terminal)", "auto").option("--server <id>", "Server ID override");
1214
+ program.name("discli").description("discli \u2014 Discord server management CLI").version("0.3.0").option("--format <fmt>", "Output format: json, yaml, table, auto (auto = yaml when piped, table in terminal)", "auto").option("--server <id>", "Server ID override");
860
1215
  registerInit(program);
861
1216
  registerServer(program);
862
1217
  registerChannel(program);
863
1218
  registerRole(program);
864
1219
  registerMember(program);
865
1220
  registerPermission(program);
1221
+ registerMessage(program);
1222
+ registerAudit(program);
866
1223
  program.parse();
867
1224
  //# sourceMappingURL=cli.js.map
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/utils/config.ts","../src/utils/api.ts","../src/commands/init.ts","../src/utils/output.ts","../src/commands/server.ts","../src/utils/resolve.ts","../src/commands/channel.ts","../src/commands/role.ts","../src/commands/member.ts","../src/commands/permission.ts"],"sourcesContent":["import { Command } from 'commander';\r\nimport { registerInit } from './commands/init.js';\r\nimport { registerServer } from './commands/server.js';\r\nimport { registerChannel } from './commands/channel.js';\r\nimport { registerRole } from './commands/role.js';\r\nimport { registerMember } from './commands/member.js';\r\nimport { registerPermission } from './commands/permission.js';\r\n\r\nconst program = new Command();\r\n\r\nprogram\r\n .name('discli')\r\n .description('discli — Discord server management CLI')\r\n .version('0.1.0')\r\n .option('--format <fmt>', 'Output format: json, yaml, table, auto (auto = yaml when piped, table in terminal)', 'auto')\r\n .option('--server <id>', 'Server ID override');\r\n\r\nregisterInit(program);\r\nregisterServer(program);\r\nregisterChannel(program);\r\nregisterRole(program);\r\nregisterMember(program);\r\nregisterPermission(program);\r\n\r\nprogram.parse();\r\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\r\nimport { homedir } from 'os';\r\nimport { join } from 'path';\r\n\r\nconst CONFIG_DIR = join(homedir(), '.discli');\r\nconst CONFIG_FILE = join(CONFIG_DIR, 'config.json');\r\nconst ENV_FILE = join(CONFIG_DIR, '.env');\r\n\r\ninterface DctlConfig {\r\n default_server_id?: string;\r\n default_server_name?: string;\r\n}\r\n\r\nfunction ensureConfigDir(): void {\r\n if (!existsSync(CONFIG_DIR)) {\r\n mkdirSync(CONFIG_DIR, { recursive: true });\r\n }\r\n}\r\n\r\nexport function loadConfig(): DctlConfig {\r\n if (!existsSync(CONFIG_FILE)) return {};\r\n try {\r\n return JSON.parse(readFileSync(CONFIG_FILE, 'utf-8'));\r\n } catch {\r\n return {};\r\n }\r\n}\r\n\r\nexport function saveConfig(data: DctlConfig): void {\r\n ensureConfigDir();\r\n writeFileSync(CONFIG_FILE, JSON.stringify(data, null, 2) + '\\n');\r\n}\r\n\r\nexport function loadToken(): string | null {\r\n if (!existsSync(ENV_FILE)) return null;\r\n const content = readFileSync(ENV_FILE, 'utf-8');\r\n const match = content.match(/^BOT_TOKEN=(.+)$/m);\r\n return match ? match[1].trim() : null;\r\n}\r\n\r\nexport function saveToken(token: string): void {\r\n ensureConfigDir();\r\n writeFileSync(ENV_FILE, `BOT_TOKEN=${token}\\n`);\r\n}\r\n\r\nexport function getDefaultServer(): string | null {\r\n return loadConfig().default_server_id ?? null;\r\n}\r\n\r\nexport function getDefaultServerName(): string | null {\r\n return loadConfig().default_server_name ?? null;\r\n}\r\n\r\nexport function setDefaultServer(id: string, name: string): void {\r\n const cfg = loadConfig();\r\n cfg.default_server_id = id;\r\n cfg.default_server_name = name;\r\n saveConfig(cfg);\r\n}\r\n\r\nexport function requireToken(): string {\r\n const token = loadToken();\r\n if (!token) {\r\n console.error('Error: Not configured. Run \"discli init\" first.');\r\n process.exit(1);\r\n }\r\n return token;\r\n}\r\n\r\nexport function requireServer(override?: string): string {\r\n const server = override || getDefaultServer();\r\n if (!server) {\r\n console.error('Error: No server selected. Run \"discli server select\" or use --server <id>.');\r\n process.exit(1);\r\n }\r\n return server;\r\n}\r\n","const BASE = 'https://discord.com/api/v10';\r\n\r\nexport const PERMISSION: Record<string, bigint> = {\r\n view_channel: 1n << 10n,\r\n send_messages: 1n << 11n,\r\n send_messages_in_threads: 1n << 38n,\r\n create_public_threads: 1n << 35n,\r\n create_private_threads: 1n << 36n,\r\n embed_links: 1n << 14n,\r\n attach_files: 1n << 15n,\r\n add_reactions: 1n << 6n,\r\n use_external_emojis: 1n << 18n,\r\n read_message_history: 1n << 16n,\r\n mention_everyone: 1n << 17n,\r\n manage_messages: 1n << 13n,\r\n manage_channels: 1n << 4n,\r\n manage_roles: 1n << 28n,\r\n connect: 1n << 20n,\r\n speak: 1n << 21n,\r\n mute_members: 1n << 22n,\r\n deafen_members: 1n << 23n,\r\n move_members: 1n << 24n,\r\n use_voice_activity: 1n << 25n,\r\n};\r\n\r\nexport const CHANNEL_TYPE: Record<string, number> = {\r\n text: 0,\r\n voice: 2,\r\n category: 4,\r\n announcement: 5,\r\n stage: 13,\r\n forum: 15,\r\n};\r\n\r\nexport const CHANNEL_TYPE_NAME: Record<number, string> = Object.fromEntries(\r\n Object.entries(CHANNEL_TYPE).map(([k, v]) => [v, k])\r\n);\r\n\r\nexport class DiscordAPI {\r\n private token: string;\r\n\r\n constructor(token: string) {\r\n this.token = token;\r\n }\r\n\r\n private async request(method: string, path: string, body?: unknown): Promise<unknown> {\r\n const headers: Record<string, string> = {\r\n Authorization: `Bot ${this.token}`,\r\n };\r\n if (body) {\r\n headers['Content-Type'] = 'application/json';\r\n }\r\n\r\n const res = await fetch(`${BASE}${path}`, {\r\n method,\r\n headers,\r\n body: body ? JSON.stringify(body) : undefined,\r\n });\r\n\r\n if (res.status === 429) {\r\n const data = (await res.json()) as { retry_after?: number };\r\n console.error(`Rate limited. Retry after ${data.retry_after ?? '?'}s.`);\r\n process.exit(1);\r\n }\r\n if (res.status === 403) {\r\n console.error('403 Forbidden — missing permissions.');\r\n process.exit(4);\r\n }\r\n if (res.status === 404) {\r\n console.error('404 Not found.');\r\n process.exit(3);\r\n }\r\n if (res.status >= 400) {\r\n const text = await res.text();\r\n console.error(`Discord API error ${res.status}: ${text.slice(0, 200)}`);\r\n process.exit(1);\r\n }\r\n\r\n if (res.status === 204) return null;\r\n return res.json();\r\n }\r\n\r\n // ── Guilds ──\r\n\r\n async listGuilds(): Promise<Guild[]> {\r\n return (await this.request('GET', '/users/@me/guilds')) as Guild[];\r\n }\r\n\r\n async getGuild(guildId: string): Promise<GuildFull> {\r\n return (await this.request('GET', `/guilds/${guildId}?with_counts=true`)) as GuildFull;\r\n }\r\n\r\n // ── Channels ──\r\n\r\n async listChannels(guildId: string): Promise<Channel[]> {\r\n return (await this.request('GET', `/guilds/${guildId}/channels`)) as Channel[];\r\n }\r\n\r\n async createChannel(\r\n guildId: string,\r\n opts: { name: string; type?: number; parent_id?: string; topic?: string }\r\n ): Promise<Channel> {\r\n return (await this.request('POST', `/guilds/${guildId}/channels`, opts)) as Channel;\r\n }\r\n\r\n async deleteChannel(channelId: string): Promise<void> {\r\n await this.request('DELETE', `/channels/${channelId}`);\r\n }\r\n\r\n async modifyChannel(channelId: string, data: Record<string, unknown>): Promise<Channel> {\r\n return (await this.request('PATCH', `/channels/${channelId}`, data)) as Channel;\r\n }\r\n\r\n async getChannel(channelId: string): Promise<Channel> {\r\n return (await this.request('GET', `/channels/${channelId}`)) as Channel;\r\n }\r\n\r\n async editChannelPermission(\r\n channelId: string,\r\n overwriteId: string,\r\n data: { allow: string; deny: string; type: number }\r\n ): Promise<void> {\r\n await this.request('PUT', `/channels/${channelId}/permissions/${overwriteId}`, data);\r\n }\r\n\r\n async deleteChannelPermission(channelId: string, overwriteId: string): Promise<void> {\r\n await this.request('DELETE', `/channels/${channelId}/permissions/${overwriteId}`);\r\n }\r\n\r\n // ── Roles ──\r\n\r\n async listRoles(guildId: string): Promise<Role[]> {\r\n return (await this.request('GET', `/guilds/${guildId}/roles`)) as Role[];\r\n }\r\n\r\n async createRole(guildId: string, data: Record<string, unknown>): Promise<Role> {\r\n return (await this.request('POST', `/guilds/${guildId}/roles`, data)) as Role;\r\n }\r\n\r\n async deleteRole(guildId: string, roleId: string): Promise<void> {\r\n await this.request('DELETE', `/guilds/${guildId}/roles/${roleId}`);\r\n }\r\n\r\n async addRoleToMember(guildId: string, userId: string, roleId: string): Promise<void> {\r\n await this.request('PUT', `/guilds/${guildId}/members/${userId}/roles/${roleId}`);\r\n }\r\n\r\n async removeRoleFromMember(guildId: string, userId: string, roleId: string): Promise<void> {\r\n await this.request('DELETE', `/guilds/${guildId}/members/${userId}/roles/${roleId}`);\r\n }\r\n\r\n // ── Members ──\r\n\r\n async listMembers(guildId: string, limit = 100): Promise<Member[]> {\r\n return (await this.request('GET', `/guilds/${guildId}/members?limit=${Math.min(limit, 1000)}`)) as Member[];\r\n }\r\n\r\n async getMember(guildId: string, userId: string): Promise<Member> {\r\n return (await this.request('GET', `/guilds/${guildId}/members/${userId}`)) as Member;\r\n }\r\n\r\n async kickMember(guildId: string, userId: string): Promise<void> {\r\n await this.request('DELETE', `/guilds/${guildId}/members/${userId}`);\r\n }\r\n\r\n async banMember(guildId: string, userId: string): Promise<void> {\r\n await this.request('PUT', `/guilds/${guildId}/bans/${userId}`);\r\n }\r\n\r\n async modifyMember(guildId: string, userId: string, data: Record<string, unknown>): Promise<Member> {\r\n return (await this.request('PATCH', `/guilds/${guildId}/members/${userId}`, data)) as Member;\r\n }\r\n}\r\n\r\n// ── Types ──\r\n\r\nexport interface Guild {\r\n id: string;\r\n name: string;\r\n icon: string | null;\r\n owner: boolean;\r\n permissions: string;\r\n}\r\n\r\nexport interface GuildFull extends Guild {\r\n approximate_member_count?: number;\r\n approximate_presence_count?: number;\r\n description: string | null;\r\n premium_tier: number;\r\n premium_subscription_count: number;\r\n}\r\n\r\nexport interface PermissionOverwrite {\r\n id: string;\r\n type: number; // 0 = role, 1 = member\r\n allow: string;\r\n deny: string;\r\n}\r\n\r\nexport interface Channel {\r\n id: string;\r\n name: string;\r\n type: number;\r\n position: number;\r\n parent_id: string | null;\r\n topic?: string | null;\r\n permission_overwrites?: PermissionOverwrite[];\r\n}\r\n\r\nexport interface Role {\r\n id: string;\r\n name: string;\r\n color: number;\r\n position: number;\r\n permissions: string;\r\n managed: boolean;\r\n mentionable: boolean;\r\n}\r\n\r\nexport interface Member {\r\n user?: {\r\n id: string;\r\n username: string;\r\n global_name: string | null;\r\n };\r\n nick: string | null;\r\n roles: string[];\r\n joined_at: string;\r\n}\r\n","import { Command } from 'commander';\r\nimport { saveToken, setDefaultServer, loadToken } from '../utils/config.js';\r\nimport { DiscordAPI } from '../utils/api.js';\r\nimport { readFileSync } from 'fs';\r\n\r\nexport function registerInit(program: Command): void {\r\n program\r\n .command('init')\r\n .description('Set up discli with your bot token and default server')\r\n .option('--token <token>', 'Bot token (or reads from stdin)')\r\n .action(async (opts) => {\r\n let token = opts.token;\r\n\r\n if (!token) {\r\n // Try reading from stdin if piped\r\n if (!process.stdin.isTTY) {\r\n token = readFileSync(0, 'utf-8').trim();\r\n }\r\n }\r\n\r\n if (!token) {\r\n // Check if already configured\r\n const existing = loadToken();\r\n if (existing) {\r\n console.log('Already configured. Use --token to update.');\r\n token = existing;\r\n } else {\r\n console.error('Usage: discli init --token <your-bot-token>');\r\n console.error(' Get your token from https://discord.com/developers/applications');\r\n process.exit(2);\r\n }\r\n }\r\n\r\n // Validate token\r\n const api = new DiscordAPI(token);\r\n let guilds;\r\n try {\r\n guilds = await api.listGuilds();\r\n } catch {\r\n console.error('Invalid token or cannot connect to Discord.');\r\n process.exit(1);\r\n }\r\n\r\n saveToken(token);\r\n console.log(`Token saved to ~/.discli/.env`);\r\n\r\n if (guilds.length === 0) {\r\n console.log('Bot is not in any servers yet. Add it to a server first.');\r\n return;\r\n }\r\n\r\n console.log('\\nServers:');\r\n guilds.forEach((g, i) => {\r\n console.log(` ${i + 1}. ${g.name} (${g.id})`);\r\n });\r\n\r\n // Auto-select if only one server\r\n if (guilds.length === 1) {\r\n setDefaultServer(guilds[0].id, guilds[0].name);\r\n console.log(`\\nDefault server: ${guilds[0].name}`);\r\n } else {\r\n console.log(`\\nSet default with: discli server select <id>`);\r\n }\r\n\r\n console.log('\\nReady! Try: discli server info');\r\n });\r\n}\r\n","import { stringify as yamlStringify } from 'yaml';\r\n\r\nexport function resolveFormat(explicit: string): string {\r\n if (explicit !== 'auto') return explicit;\r\n return process.stdout.isTTY ? 'table' : 'yaml';\r\n}\r\n\r\nexport function printResult(data: unknown, format: string): void {\r\n const fmt = resolveFormat(format);\r\n\r\n if (fmt === 'json') {\r\n console.log(JSON.stringify(data, null, 2));\r\n return;\r\n }\r\n\r\n if (fmt === 'yaml') {\r\n console.log(yamlStringify(data, { indent: 2 }).trimEnd());\r\n return;\r\n }\r\n\r\n if (Array.isArray(data)) {\r\n if (data.length === 0) {\r\n console.log(' (none)');\r\n return;\r\n }\r\n if (typeof data[0] === 'object') {\r\n printTable(data as Record<string, unknown>[]);\r\n } else {\r\n data.forEach((item) => console.log(` ${item}`));\r\n }\r\n return;\r\n }\r\n\r\n if (typeof data === 'object' && data !== null) {\r\n const obj = data as Record<string, unknown>;\r\n const maxKey = Math.max(...Object.keys(obj).map((k) => k.length));\r\n for (const [k, v] of Object.entries(obj)) {\r\n console.log(` ${k.padEnd(maxKey)} ${v}`);\r\n }\r\n return;\r\n }\r\n\r\n console.log(String(data));\r\n}\r\n\r\nexport function printTable(rows: Record<string, unknown>[], columns?: string[]): void {\r\n if (rows.length === 0) {\r\n console.log(' (none)');\r\n return;\r\n }\r\n\r\n const cols = columns ?? Object.keys(rows[0]);\r\n const widths: Record<string, number> = {};\r\n for (const col of cols) {\r\n widths[col] = col.length;\r\n }\r\n for (const row of rows) {\r\n for (const col of cols) {\r\n widths[col] = Math.max(widths[col], String(row[col] ?? '').length);\r\n }\r\n }\r\n\r\n const header = cols.map((c) => c.toUpperCase().padEnd(widths[c])).join(' ');\r\n const sep = cols.map((c) => '─'.repeat(widths[c])).join(' ');\r\n console.log(` ${header}`);\r\n console.log(` ${sep}`);\r\n\r\n for (const row of rows) {\r\n const line = cols.map((c) => String(row[c] ?? '').padEnd(widths[c])).join(' ');\r\n console.log(` ${line}`);\r\n }\r\n}\r\n","import { Command } from 'commander';\r\nimport { DiscordAPI } from '../utils/api.js';\r\nimport { requireToken, requireServer, setDefaultServer } from '../utils/config.js';\r\nimport { printResult, resolveFormat } from '../utils/output.js';\r\n\r\nexport function registerServer(program: Command): void {\r\n const server = program\r\n .command('server')\r\n .description('Manage and inspect servers');\r\n\r\n server\r\n .command('list')\r\n .description('List all servers the bot is in')\r\n .action(async () => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guilds = await api.listGuilds();\r\n\r\n if (fmt !== 'table') {\r\n printResult(guilds, fmt);\r\n return;\r\n }\r\n\r\n const rows = guilds.map((g) => ({\r\n id: g.id,\r\n name: g.name,\r\n owner: g.owner ? 'yes' : 'no',\r\n }));\r\n console.log('\\nServers');\r\n console.log('───────');\r\n printResult(rows, fmt);\r\n });\r\n\r\n server\r\n .command('select')\r\n .description('Set the default server')\r\n .argument('<id>', 'Server ID')\r\n .action(async (id: string) => {\r\n const api = new DiscordAPI(requireToken());\r\n const guild = await api.getGuild(id);\r\n setDefaultServer(guild.id, guild.name);\r\n console.log(`Default server set to: ${guild.name} (${guild.id})`);\r\n });\r\n\r\n server\r\n .command('info')\r\n .description('Show server details')\r\n .action(async () => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const guild = await api.getGuild(guildId);\r\n\r\n if (fmt !== 'table') {\r\n printResult(guild, fmt);\r\n return;\r\n }\r\n\r\n const info = {\r\n name: guild.name,\r\n id: guild.id,\r\n description: guild.description || '(none)',\r\n members: guild.approximate_member_count ?? '?',\r\n online: guild.approximate_presence_count ?? '?',\r\n boosts: guild.premium_subscription_count,\r\n boost_tier: guild.premium_tier,\r\n };\r\n\r\n console.log(`\\n${guild.name}`);\r\n console.log('─'.repeat(guild.name.length));\r\n printResult(info, fmt);\r\n });\r\n}\r\n","import { DiscordAPI, CHANNEL_TYPE_NAME } from './api.js';\r\nimport type { Channel, Role, Member } from './api.js';\r\n\r\nexport async function resolveChannel(\r\n api: DiscordAPI,\r\n guildId: string,\r\n name: string\r\n): Promise<Channel> {\r\n const channels = await api.listChannels(guildId);\r\n\r\n // Try ID match\r\n const byId = channels.find((c) => c.id === name);\r\n if (byId) return byId;\r\n\r\n // Strip # prefix\r\n const clean = name.replace(/^#/, '');\r\n\r\n const matches = channels.filter((c) => c.name.toLowerCase() === clean.toLowerCase());\r\n if (matches.length === 1) return matches[0];\r\n if (matches.length > 1) {\r\n const names = matches.map((m) => `#${m.name} (${CHANNEL_TYPE_NAME[m.type] ?? '?'})`).join(', ');\r\n console.error(`Ambiguous channel \"${clean}\". Matches: ${names}`);\r\n process.exit(1);\r\n }\r\n\r\n console.error(`Channel \"${name}\" not found.`);\r\n process.exit(3);\r\n}\r\n\r\nexport async function resolveCategory(\r\n api: DiscordAPI,\r\n guildId: string,\r\n name: string\r\n): Promise<Channel> {\r\n const channels = await api.listChannels(guildId);\r\n\r\n const byId = channels.find((c) => c.id === name && c.type === 4);\r\n if (byId) return byId;\r\n\r\n const matches = channels.filter(\r\n (c) => c.type === 4 && c.name.toLowerCase() === name.toLowerCase()\r\n );\r\n if (matches.length === 1) return matches[0];\r\n if (matches.length > 1) {\r\n console.error(`Ambiguous category \"${name}\".`);\r\n process.exit(1);\r\n }\r\n\r\n console.error(`Category \"${name}\" not found.`);\r\n process.exit(3);\r\n}\r\n\r\nexport async function resolveRole(\r\n api: DiscordAPI,\r\n guildId: string,\r\n name: string\r\n): Promise<Role> {\r\n const roles = await api.listRoles(guildId);\r\n\r\n const byId = roles.find((r) => r.id === name);\r\n if (byId) return byId;\r\n\r\n const clean = name.replace(/^@/, '');\r\n const matches = roles.filter((r) => r.name.toLowerCase() === clean.toLowerCase());\r\n if (matches.length === 1) return matches[0];\r\n if (matches.length > 1) {\r\n const names = matches.map((m) => `@${m.name}`).join(', ');\r\n console.error(`Ambiguous role \"${clean}\". Matches: ${names}`);\r\n process.exit(1);\r\n }\r\n\r\n console.error(`Role \"${name}\" not found.`);\r\n process.exit(3);\r\n}\r\n\r\nexport async function resolveMember(\r\n api: DiscordAPI,\r\n guildId: string,\r\n name: string\r\n): Promise<Member> {\r\n // Try as ID\r\n if (/^\\d+$/.test(name)) {\r\n try {\r\n return await api.getMember(guildId, name);\r\n } catch {\r\n // fall through to search\r\n }\r\n }\r\n\r\n const members = await api.listMembers(guildId, 1000);\r\n const clean = name.replace(/^@/, '').toLowerCase();\r\n\r\n const matches = members.filter((m) => {\r\n const username = m.user?.username?.toLowerCase() ?? '';\r\n const globalName = m.user?.global_name?.toLowerCase() ?? '';\r\n const nick = m.nick?.toLowerCase() ?? '';\r\n return username === clean || globalName === clean || nick === clean;\r\n });\r\n\r\n if (matches.length === 1) return matches[0];\r\n if (matches.length > 1) {\r\n const names = matches.map((m) => m.user?.username).join(', ');\r\n console.error(`Ambiguous user \"${name}\". Matches: ${names}`);\r\n process.exit(1);\r\n }\r\n\r\n console.error(`Member \"${name}\" not found.`);\r\n process.exit(3);\r\n}\r\n","import { Command } from 'commander';\r\nimport { DiscordAPI, CHANNEL_TYPE, CHANNEL_TYPE_NAME } from '../utils/api.js';\r\nimport { requireToken, requireServer } from '../utils/config.js';\r\nimport { printResult, resolveFormat } from '../utils/output.js';\r\nimport { resolveChannel, resolveCategory } from '../utils/resolve.js';\r\n\r\nexport function registerChannel(program: Command): void {\r\n const channel = program\r\n .command('channel')\r\n .description('Manage server channels');\r\n\r\n channel\r\n .command('list')\r\n .description('List all channels grouped by category')\r\n .option('-n <count>', 'Limit number of channels shown', parseInt)\r\n .action(async (opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n let channels = await api.listChannels(guildId);\r\n if (opts.n) channels = channels.slice(0, opts.n);\r\n\r\n if (fmt !== 'table') {\r\n printResult(channels, fmt);\r\n return;\r\n }\r\n\r\n // Group by category\r\n const categories = channels\r\n .filter((c) => c.type === 4)\r\n .sort((a, b) => a.position - b.position);\r\n const uncategorized = channels.filter(\r\n (c) => c.type !== 4 && !c.parent_id\r\n );\r\n\r\n if (uncategorized.length > 0) {\r\n console.log('\\n (no category)');\r\n for (const ch of uncategorized.sort((a, b) => a.position - b.position)) {\r\n const type = CHANNEL_TYPE_NAME[ch.type] ?? '?';\r\n console.log(` ${type === 'text' ? '#' : '🔊'} ${ch.name}`);\r\n }\r\n }\r\n\r\n for (const cat of categories) {\r\n console.log(`\\n ${cat.name.toUpperCase()}`);\r\n const children = channels\r\n .filter((c) => c.parent_id === cat.id && c.type !== 4)\r\n .sort((a, b) => a.position - b.position);\r\n for (const ch of children) {\r\n const type = CHANNEL_TYPE_NAME[ch.type] ?? '?';\r\n const prefix = type === 'voice' || type === 'stage' ? '🔊' : '#';\r\n const topic = ch.topic ? ` — ${ch.topic}` : '';\r\n console.log(` ${prefix} ${ch.name}${topic}`);\r\n }\r\n }\r\n console.log();\r\n });\r\n\r\n channel\r\n .command('create')\r\n .description('Create a new channel')\r\n .argument('<name>', 'Channel name')\r\n .option('--type <type>', 'Channel type: text, voice, category, announcement, stage, forum', 'text')\r\n .option('--category <name>', 'Parent category name or ID')\r\n .option('--topic <topic>', 'Channel topic')\r\n .option('--dry-run', 'Show what would be created without creating it')\r\n .action(async (name: string, opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n\r\n const channelType = CHANNEL_TYPE[opts.type];\r\n if (channelType === undefined) {\r\n console.error(`Unknown channel type: ${opts.type}. Use: ${Object.keys(CHANNEL_TYPE).join(', ')}`);\r\n process.exit(2);\r\n }\r\n\r\n let parentId: string | undefined;\r\n if (opts.category) {\r\n const cat = await resolveCategory(api, guildId, opts.category);\r\n parentId = cat.id;\r\n }\r\n\r\n if (opts.dryRun) {\r\n const result = { action: 'create_channel', name, type: opts.type, category: opts.category ?? null, topic: opts.topic ?? null };\r\n printResult(result, fmt);\r\n return;\r\n }\r\n\r\n const ch = await api.createChannel(guildId, {\r\n name,\r\n type: channelType,\r\n parent_id: parentId,\r\n topic: opts.topic,\r\n });\r\n\r\n if (fmt !== 'table') {\r\n printResult(ch, fmt);\r\n } else {\r\n console.log(`Created #${ch.name} (${CHANNEL_TYPE_NAME[ch.type] ?? '?'}) — ${ch.id}`);\r\n }\r\n });\r\n\r\n channel\r\n .command('delete')\r\n .description('Delete a channel')\r\n .argument('<name>', 'Channel name or ID')\r\n .option('--confirm', 'Required to actually delete')\r\n .action(async (name: string, opts) => {\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, name);\r\n\r\n if (!opts.confirm) {\r\n console.error(`This will delete #${ch.name} (${ch.id}). Add --confirm to proceed.`);\r\n process.exit(2);\r\n }\r\n\r\n await api.deleteChannel(ch.id);\r\n console.log(`Deleted #${ch.name}`);\r\n });\r\n\r\n channel\r\n .command('rename')\r\n .description('Rename a channel')\r\n .argument('<channel>', 'Channel name or ID')\r\n .argument('<new-name>', 'New channel name')\r\n .option('--dry-run', 'Show what would change')\r\n .action(async (channelName: string, newName: string, opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n\r\n if (opts.dryRun) {\r\n printResult({ action: 'rename_channel', from: ch.name, to: newName, id: ch.id }, fmt);\r\n return;\r\n }\r\n\r\n await api.modifyChannel(ch.id, { name: newName });\r\n console.log(`Renamed #${ch.name} → #${newName}`);\r\n });\r\n\r\n channel\r\n .command('topic')\r\n .description('Set a channel topic')\r\n .argument('<channel>', 'Channel name or ID')\r\n .argument('<topic>', 'New topic text')\r\n .action(async (channelName: string, topic: string) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n\r\n const updated = await api.modifyChannel(ch.id, { topic });\r\n if (fmt !== 'table') {\r\n printResult(updated, fmt);\r\n } else {\r\n console.log(`Set topic for #${ch.name}: ${topic}`);\r\n }\r\n });\r\n\r\n channel\r\n .command('move')\r\n .description('Move a channel to a category')\r\n .argument('<channel>', 'Channel name or ID')\r\n .option('--category <name>', 'Target category name or ID')\r\n .option('--position <n>', 'Position within category', parseInt)\r\n .action(async (channelName: string, opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n\r\n const update: Record<string, unknown> = {};\r\n if (opts.category) {\r\n const cat = await resolveCategory(api, guildId, opts.category);\r\n update.parent_id = cat.id;\r\n }\r\n if (opts.position !== undefined) {\r\n update.position = opts.position;\r\n }\r\n\r\n if (Object.keys(update).length === 0) {\r\n console.error('Specify --category and/or --position.');\r\n process.exit(2);\r\n }\r\n\r\n const updated = await api.modifyChannel(ch.id, update);\r\n if (fmt !== 'table') {\r\n printResult(updated, fmt);\r\n } else {\r\n console.log(`Moved #${ch.name}${opts.category ? ` → ${opts.category}` : ''}${opts.position !== undefined ? ` (position ${opts.position})` : ''}`);\r\n }\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { DiscordAPI } from '../utils/api.js';\r\nimport { requireToken, requireServer } from '../utils/config.js';\r\nimport { printResult, resolveFormat } from '../utils/output.js';\r\nimport { resolveRole, resolveMember } from '../utils/resolve.js';\r\n\r\nexport function registerRole(program: Command): void {\r\n const role = program\r\n .command('role')\r\n .description('Manage server roles');\r\n\r\n role\r\n .command('list')\r\n .description('List all roles')\r\n .option('-n <count>', 'Limit number of roles shown', parseInt)\r\n .action(async (opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const roles = await api.listRoles(guildId);\r\n\r\n const sorted = roles.sort((a, b) => b.position - a.position).slice(0, opts.n ?? roles.length);\r\n\r\n if (fmt !== 'table') {\r\n printResult(sorted, fmt);\r\n return;\r\n }\r\n\r\n const rows = sorted.map((r) => ({\r\n name: r.name,\r\n id: r.id,\r\n color: r.color ? `#${r.color.toString(16).padStart(6, '0')}` : '(none)',\r\n managed: r.managed ? 'bot' : '',\r\n position: r.position,\r\n }));\r\n\r\n console.log('\\nRoles');\r\n console.log('─────');\r\n printResult(rows, fmt);\r\n });\r\n\r\n role\r\n .command('create')\r\n .description('Create a new role')\r\n .argument('<name>', 'Role name')\r\n .option('--color <hex>', 'Color hex (e.g. #ff5733)')\r\n .option('--mentionable', 'Allow anyone to mention this role')\r\n .option('--dry-run', 'Show what would be created')\r\n .action(async (name: string, opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n\r\n const data: Record<string, unknown> = { name };\r\n if (opts.color) {\r\n data.color = parseInt(opts.color.replace('#', ''), 16);\r\n }\r\n if (opts.mentionable) {\r\n data.mentionable = true;\r\n }\r\n\r\n if (opts.dryRun) {\r\n printResult({ action: 'create_role', ...data }, fmt);\r\n return;\r\n }\r\n\r\n const r = await api.createRole(guildId, data);\r\n if (fmt !== 'table') {\r\n printResult(r, fmt);\r\n } else {\r\n console.log(`Created role @${r.name} — ${r.id}`);\r\n }\r\n });\r\n\r\n role\r\n .command('delete')\r\n .description('Delete a role')\r\n .argument('<name>', 'Role name or ID')\r\n .option('--confirm', 'Required to actually delete')\r\n .action(async (name: string, opts) => {\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const r = await resolveRole(api, guildId, name);\r\n\r\n if (!opts.confirm) {\r\n console.error(`This will delete @${r.name} (${r.id}). Add --confirm to proceed.`);\r\n process.exit(2);\r\n }\r\n\r\n await api.deleteRole(guildId, r.id);\r\n console.log(`Deleted role @${r.name}`);\r\n });\r\n\r\n role\r\n .command('assign')\r\n .description('Assign a role to a member')\r\n .argument('<role>', 'Role name or ID')\r\n .argument('<user>', 'Username or ID')\r\n .action(async (roleName: string, userName: string) => {\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const r = await resolveRole(api, guildId, roleName);\r\n const m = await resolveMember(api, guildId, userName);\r\n\r\n await api.addRoleToMember(guildId, m.user!.id, r.id);\r\n console.log(`Assigned @${r.name} to ${m.user!.username}`);\r\n });\r\n\r\n role\r\n .command('remove')\r\n .description('Remove a role from a member')\r\n .argument('<role>', 'Role name or ID')\r\n .argument('<user>', 'Username or ID')\r\n .action(async (roleName: string, userName: string) => {\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const r = await resolveRole(api, guildId, roleName);\r\n const m = await resolveMember(api, guildId, userName);\r\n\r\n await api.removeRoleFromMember(guildId, m.user!.id, r.id);\r\n console.log(`Removed @${r.name} from ${m.user!.username}`);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { DiscordAPI } from '../utils/api.js';\r\nimport { requireToken, requireServer } from '../utils/config.js';\r\nimport { printResult, resolveFormat } from '../utils/output.js';\r\nimport { resolveMember } from '../utils/resolve.js';\r\n\r\nexport function registerMember(program: Command): void {\r\n const member = program\r\n .command('member')\r\n .description('Manage server members');\r\n\r\n member\r\n .command('list')\r\n .description('List server members')\r\n .option('-n, --limit <n>', 'Max members to show', '100')\r\n .action(async (opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const members = await api.listMembers(guildId, parseInt(opts.limit));\r\n\r\n if (fmt !== 'table') {\r\n printResult(members, fmt);\r\n return;\r\n }\r\n\r\n const rows = members.map((m) => ({\r\n username: m.user?.username ?? '?',\r\n display: m.user?.global_name ?? m.nick ?? '',\r\n nick: m.nick ?? '',\r\n roles: m.roles.length,\r\n joined: m.joined_at?.slice(0, 10) ?? '?',\r\n }));\r\n\r\n console.log(`\\nMembers (${members.length})`);\r\n console.log('──────────');\r\n printResult(rows, fmt);\r\n });\r\n\r\n member\r\n .command('info')\r\n .description('Show member details')\r\n .argument('<user>', 'Username or ID')\r\n .action(async (userName: string) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const m = await resolveMember(api, guildId, userName);\r\n\r\n if (fmt !== 'table') {\r\n printResult(m, fmt);\r\n return;\r\n }\r\n\r\n const roles = await api.listRoles(guildId);\r\n const memberRoles = m.roles\r\n .map((rid) => roles.find((r) => r.id === rid)?.name ?? rid)\r\n .join(', ');\r\n\r\n const info = {\r\n username: m.user?.username ?? '?',\r\n display_name: m.user?.global_name ?? '(none)',\r\n nickname: m.nick ?? '(none)',\r\n id: m.user?.id ?? '?',\r\n roles: memberRoles || '(none)',\r\n joined: m.joined_at?.slice(0, 10) ?? '?',\r\n };\r\n\r\n console.log(`\\n${m.user?.username ?? 'Member'}`);\r\n console.log('─'.repeat((m.user?.username ?? 'Member').length));\r\n printResult(info, fmt);\r\n });\r\n\r\n member\r\n .command('kick')\r\n .description('Kick a member from the server')\r\n .argument('<user>', 'Username or ID')\r\n .option('--reason <text>', 'Reason for kick')\r\n .option('--confirm', 'Required to actually kick')\r\n .action(async (userName: string, opts) => {\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const m = await resolveMember(api, guildId, userName);\r\n\r\n if (!opts.confirm) {\r\n console.error(`This will kick ${m.user!.username} (${m.user!.id}). Add --confirm to proceed.`);\r\n process.exit(2);\r\n }\r\n\r\n await api.kickMember(guildId, m.user!.id);\r\n console.log(`Kicked ${m.user!.username}${opts.reason ? ` — ${opts.reason}` : ''}`);\r\n });\r\n\r\n member\r\n .command('ban')\r\n .description('Ban a member from the server')\r\n .argument('<user>', 'Username or ID')\r\n .option('--reason <text>', 'Reason for ban')\r\n .option('--confirm', 'Required to actually ban')\r\n .action(async (userName: string, opts) => {\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const m = await resolveMember(api, guildId, userName);\r\n\r\n if (!opts.confirm) {\r\n console.error(`This will BAN ${m.user!.username} (${m.user!.id}). Add --confirm to proceed.`);\r\n process.exit(2);\r\n }\r\n\r\n await api.banMember(guildId, m.user!.id);\r\n console.log(`Banned ${m.user!.username}${opts.reason ? ` — ${opts.reason}` : ''}`);\r\n });\r\n\r\n member\r\n .command('nick')\r\n .description('Change a member\\'s nickname')\r\n .argument('<user>', 'Username or ID')\r\n .argument('<nickname>', 'New nickname')\r\n .action(async (userName: string, nickname: string) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const m = await resolveMember(api, guildId, userName);\r\n\r\n await api.modifyMember(guildId, m.user!.id, { nick: nickname });\r\n if (fmt !== 'table') {\r\n printResult({ action: 'nick', user: m.user!.username, nick: nickname }, fmt);\r\n } else {\r\n console.log(`Set nickname for ${m.user!.username} → ${nickname}`);\r\n }\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { DiscordAPI, PERMISSION } from '../utils/api.js';\r\nimport { requireToken, requireServer } from '../utils/config.js';\r\nimport { printResult, resolveFormat } from '../utils/output.js';\r\nimport { resolveChannel, resolveRole } from '../utils/resolve.js';\r\n\r\nfunction parsePermissions(perms: string): bigint {\r\n let bits = 0n;\r\n for (const p of perms.split(',')) {\r\n const name = p.trim().toLowerCase();\r\n const val = PERMISSION[name];\r\n if (val === undefined) {\r\n console.error(`Unknown permission: ${name}`);\r\n console.error(`Available: ${Object.keys(PERMISSION).join(', ')}`);\r\n process.exit(2);\r\n }\r\n bits |= val;\r\n }\r\n return bits;\r\n}\r\n\r\nfunction describePermissions(bitfield: string): string[] {\r\n const bits = BigInt(bitfield);\r\n if (bits === 0n) return [];\r\n return Object.entries(PERMISSION)\r\n .filter(([, val]) => (bits & val) === val)\r\n .map(([name]) => name);\r\n}\r\n\r\nexport function registerPermission(program: Command): void {\r\n const perm = program\r\n .command('permission')\r\n .alias('perm')\r\n .description('Manage channel permissions');\r\n\r\n perm\r\n .command('view')\r\n .description('View permission overwrites for a channel')\r\n .argument('<channel>', 'Channel name or ID')\r\n .action(async (channelName: string) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n\r\n const full = await api.getChannel(ch.id);\r\n const overwrites = full.permission_overwrites ?? [];\r\n const roles = await api.listRoles(guildId);\r\n\r\n if (fmt !== 'table') {\r\n printResult(overwrites, fmt);\r\n return;\r\n }\r\n\r\n if (overwrites.length === 0) {\r\n console.log(`\\n#${ch.name}: no permission overwrites (inherits from category/server)`);\r\n return;\r\n }\r\n\r\n console.log(`\\n#${ch.name} — Permission Overwrites`);\r\n console.log('─'.repeat(40));\r\n\r\n for (const ow of overwrites) {\r\n const target = ow.type === 0\r\n ? roles.find((r) => r.id === ow.id)?.name ?? ow.id\r\n : `member:${ow.id}`;\r\n const allowed = describePermissions(ow.allow);\r\n const denied = describePermissions(ow.deny);\r\n\r\n console.log(`\\n @${target} (${ow.type === 0 ? 'role' : 'member'})`);\r\n if (allowed.length > 0) console.log(` ✅ allow: ${allowed.join(', ')}`);\r\n if (denied.length > 0) console.log(` ❌ deny: ${denied.join(', ')}`);\r\n if (allowed.length === 0 && denied.length === 0) console.log(` (neutral)`);\r\n }\r\n console.log();\r\n });\r\n\r\n perm\r\n .command('set')\r\n .description('Set permission overwrite for a role on a channel')\r\n .argument('<channel>', 'Channel name or ID')\r\n .argument('<role>', 'Role name or ID')\r\n .option('--allow <perms>', 'Comma-separated permissions to allow')\r\n .option('--deny <perms>', 'Comma-separated permissions to deny')\r\n .option('--dry-run', 'Show what would change')\r\n .action(async (channelName: string, roleName: string, opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n const role = await resolveRole(api, guildId, roleName);\r\n\r\n if (!opts.allow && !opts.deny) {\r\n console.error('Specify --allow and/or --deny with comma-separated permissions.');\r\n console.error(`Available: ${Object.keys(PERMISSION).join(', ')}`);\r\n process.exit(2);\r\n }\r\n\r\n const allow = opts.allow ? parsePermissions(opts.allow) : 0n;\r\n const deny = opts.deny ? parsePermissions(opts.deny) : 0n;\r\n\r\n if (opts.dryRun) {\r\n printResult({\r\n action: 'set_permission',\r\n channel: ch.name,\r\n role: role.name,\r\n allow: opts.allow ?? '(none)',\r\n deny: opts.deny ?? '(none)',\r\n }, fmt);\r\n return;\r\n }\r\n\r\n await api.editChannelPermission(ch.id, role.id, {\r\n allow: allow.toString(),\r\n deny: deny.toString(),\r\n type: 0, // role\r\n });\r\n\r\n if (fmt !== 'table') {\r\n printResult({ channel: ch.name, role: role.name, allow: allow.toString(), deny: deny.toString() }, fmt);\r\n } else {\r\n console.log(`Set permissions on #${ch.name} for @${role.name}`);\r\n if (opts.allow) console.log(` ✅ allow: ${opts.allow}`);\r\n if (opts.deny) console.log(` ❌ deny: ${opts.deny}`);\r\n }\r\n });\r\n\r\n perm\r\n .command('lock')\r\n .description('Make a channel read-only for @everyone')\r\n .argument('<channel>', 'Channel name or ID')\r\n .option('--dry-run', 'Show what would change')\r\n .action(async (channelName: string, opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n\r\n // @everyone role ID = guild ID\r\n const deny = PERMISSION.send_messages\r\n | PERMISSION.send_messages_in_threads\r\n | PERMISSION.create_public_threads;\r\n\r\n if (opts.dryRun) {\r\n printResult({ action: 'lock', channel: ch.name, deny_for: '@everyone' }, fmt);\r\n return;\r\n }\r\n\r\n await api.editChannelPermission(ch.id, guildId, {\r\n allow: '0',\r\n deny: deny.toString(),\r\n type: 0,\r\n });\r\n\r\n console.log(`Locked #${ch.name} — read-only for @everyone`);\r\n });\r\n\r\n perm\r\n .command('unlock')\r\n .description('Remove read-only restriction for @everyone')\r\n .argument('<channel>', 'Channel name or ID')\r\n .action(async (channelName: string) => {\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n\r\n await api.deleteChannelPermission(ch.id, guildId);\r\n console.log(`Unlocked #${ch.name} — @everyone can send messages`);\r\n });\r\n\r\n perm\r\n .command('list')\r\n .description('List all available permission names')\r\n .action(() => {\r\n const fmt = resolveFormat(program.opts().format);\r\n if (fmt !== 'table') {\r\n const perms = Object.entries(PERMISSION).map(([name, val]) => ({ name, bit: val.toString() }));\r\n printResult(perms, fmt);\r\n } else {\r\n console.log('\\nAvailable Permissions');\r\n console.log('────────────────────');\r\n for (const name of Object.keys(PERMISSION)) {\r\n console.log(` ${name}`);\r\n }\r\n }\r\n });\r\n}\r\n"],"mappings":"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","names":["readFileSync","program","program","program","program","program","program"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/utils/config.ts","../src/utils/api.ts","../src/commands/init.ts","../src/utils/output.ts","../src/commands/server.ts","../src/utils/resolve.ts","../src/commands/channel.ts","../src/commands/role.ts","../src/commands/member.ts","../src/commands/permission.ts","../src/commands/message.ts","../src/commands/audit.ts"],"sourcesContent":["import { Command } from 'commander';\r\nimport { registerInit } from './commands/init.js';\r\nimport { registerServer } from './commands/server.js';\r\nimport { registerChannel } from './commands/channel.js';\r\nimport { registerRole } from './commands/role.js';\r\nimport { registerMember } from './commands/member.js';\r\nimport { registerPermission } from './commands/permission.js';\r\nimport { registerMessage } from './commands/message.js';\r\nimport { registerAudit } from './commands/audit.js';\r\n\r\nconst program = new Command();\r\n\r\nprogram\r\n .name('discli')\r\n .description('discli — Discord server management CLI')\r\n .version('0.3.0')\r\n .option('--format <fmt>', 'Output format: json, yaml, table, auto (auto = yaml when piped, table in terminal)', 'auto')\r\n .option('--server <id>', 'Server ID override');\r\n\r\nregisterInit(program);\r\nregisterServer(program);\r\nregisterChannel(program);\r\nregisterRole(program);\r\nregisterMember(program);\r\nregisterPermission(program);\r\nregisterMessage(program);\r\nregisterAudit(program);\r\n\r\nprogram.parse();\r\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';\r\nimport { homedir } from 'os';\r\nimport { join } from 'path';\r\n\r\nconst CONFIG_DIR = join(homedir(), '.discli');\r\nconst CONFIG_FILE = join(CONFIG_DIR, 'config.json');\r\nconst ENV_FILE = join(CONFIG_DIR, '.env');\r\n\r\ninterface DctlConfig {\r\n default_server_id?: string;\r\n default_server_name?: string;\r\n}\r\n\r\nfunction ensureConfigDir(): void {\r\n if (!existsSync(CONFIG_DIR)) {\r\n mkdirSync(CONFIG_DIR, { recursive: true });\r\n }\r\n}\r\n\r\nexport function loadConfig(): DctlConfig {\r\n if (!existsSync(CONFIG_FILE)) return {};\r\n try {\r\n return JSON.parse(readFileSync(CONFIG_FILE, 'utf-8'));\r\n } catch {\r\n return {};\r\n }\r\n}\r\n\r\nexport function saveConfig(data: DctlConfig): void {\r\n ensureConfigDir();\r\n writeFileSync(CONFIG_FILE, JSON.stringify(data, null, 2) + '\\n');\r\n}\r\n\r\nexport function loadToken(): string | null {\r\n if (!existsSync(ENV_FILE)) return null;\r\n const content = readFileSync(ENV_FILE, 'utf-8');\r\n const match = content.match(/^BOT_TOKEN=(.+)$/m);\r\n return match ? match[1].trim() : null;\r\n}\r\n\r\nexport function saveToken(token: string): void {\r\n ensureConfigDir();\r\n writeFileSync(ENV_FILE, `BOT_TOKEN=${token}\\n`);\r\n}\r\n\r\nexport function getDefaultServer(): string | null {\r\n return loadConfig().default_server_id ?? null;\r\n}\r\n\r\nexport function getDefaultServerName(): string | null {\r\n return loadConfig().default_server_name ?? null;\r\n}\r\n\r\nexport function setDefaultServer(id: string, name: string): void {\r\n const cfg = loadConfig();\r\n cfg.default_server_id = id;\r\n cfg.default_server_name = name;\r\n saveConfig(cfg);\r\n}\r\n\r\nexport function requireToken(): string {\r\n const token = loadToken();\r\n if (!token) {\r\n console.error('Error: Not configured. Run \"discli init\" first.');\r\n process.exit(1);\r\n }\r\n return token;\r\n}\r\n\r\nexport function requireServer(override?: string): string {\r\n const server = override || getDefaultServer();\r\n if (!server) {\r\n console.error('Error: No server selected. Run \"discli server select\" or use --server <id>.');\r\n process.exit(1);\r\n }\r\n return server;\r\n}\r\n","const BASE = 'https://discord.com/api/v10';\r\n\r\nexport const PERMISSION: Record<string, bigint> = {\r\n view_channel: 1n << 10n,\r\n send_messages: 1n << 11n,\r\n send_messages_in_threads: 1n << 38n,\r\n create_public_threads: 1n << 35n,\r\n create_private_threads: 1n << 36n,\r\n embed_links: 1n << 14n,\r\n attach_files: 1n << 15n,\r\n add_reactions: 1n << 6n,\r\n use_external_emojis: 1n << 18n,\r\n read_message_history: 1n << 16n,\r\n mention_everyone: 1n << 17n,\r\n manage_messages: 1n << 13n,\r\n manage_channels: 1n << 4n,\r\n manage_roles: 1n << 28n,\r\n connect: 1n << 20n,\r\n speak: 1n << 21n,\r\n mute_members: 1n << 22n,\r\n deafen_members: 1n << 23n,\r\n move_members: 1n << 24n,\r\n use_voice_activity: 1n << 25n,\r\n};\r\n\r\nexport const CHANNEL_TYPE: Record<string, number> = {\r\n text: 0,\r\n voice: 2,\r\n category: 4,\r\n announcement: 5,\r\n stage: 13,\r\n forum: 15,\r\n};\r\n\r\nexport const CHANNEL_TYPE_NAME: Record<number, string> = Object.fromEntries(\r\n Object.entries(CHANNEL_TYPE).map(([k, v]) => [v, k])\r\n);\r\n\r\nexport class DiscordAPI {\r\n private token: string;\r\n\r\n constructor(token: string) {\r\n this.token = token;\r\n }\r\n\r\n private async request(method: string, path: string, body?: unknown): Promise<unknown> {\r\n const headers: Record<string, string> = {\r\n Authorization: `Bot ${this.token}`,\r\n };\r\n if (body) {\r\n headers['Content-Type'] = 'application/json';\r\n }\r\n\r\n const res = await fetch(`${BASE}${path}`, {\r\n method,\r\n headers,\r\n body: body ? JSON.stringify(body) : undefined,\r\n });\r\n\r\n if (res.status === 429) {\r\n const data = (await res.json()) as { retry_after?: number };\r\n console.error(`Rate limited. Retry after ${data.retry_after ?? '?'}s.`);\r\n process.exit(1);\r\n }\r\n if (res.status === 403) {\r\n console.error('403 Forbidden — missing permissions.');\r\n process.exit(4);\r\n }\r\n if (res.status === 404) {\r\n console.error('404 Not found.');\r\n process.exit(3);\r\n }\r\n if (res.status >= 400) {\r\n const text = await res.text();\r\n console.error(`Discord API error ${res.status}: ${text.slice(0, 200)}`);\r\n process.exit(1);\r\n }\r\n\r\n if (res.status === 204) return null;\r\n return res.json();\r\n }\r\n\r\n // ── Guilds ──\r\n\r\n async listGuilds(): Promise<Guild[]> {\r\n return (await this.request('GET', '/users/@me/guilds')) as Guild[];\r\n }\r\n\r\n async getGuild(guildId: string): Promise<GuildFull> {\r\n return (await this.request('GET', `/guilds/${guildId}?with_counts=true`)) as GuildFull;\r\n }\r\n\r\n // ── Audit Log ──\r\n\r\n async getAuditLog(\r\n guildId: string,\r\n opts?: { user_id?: string; action_type?: number; limit?: number; before?: string }\r\n ): Promise<AuditLog> {\r\n const params = new URLSearchParams();\r\n if (opts?.user_id) params.set('user_id', opts.user_id);\r\n if (opts?.action_type !== undefined) params.set('action_type', String(opts.action_type));\r\n if (opts?.limit) params.set('limit', String(Math.min(opts.limit, 100)));\r\n if (opts?.before) params.set('before', opts.before);\r\n const qs = params.toString();\r\n return (await this.request('GET', `/guilds/${guildId}/audit-logs${qs ? '?' + qs : ''}`)) as AuditLog;\r\n }\r\n\r\n // ── Channels ──\r\n\r\n async listChannels(guildId: string): Promise<Channel[]> {\r\n return (await this.request('GET', `/guilds/${guildId}/channels`)) as Channel[];\r\n }\r\n\r\n async createChannel(\r\n guildId: string,\r\n opts: { name: string; type?: number; parent_id?: string; topic?: string }\r\n ): Promise<Channel> {\r\n return (await this.request('POST', `/guilds/${guildId}/channels`, opts)) as Channel;\r\n }\r\n\r\n // ── Messages ──\r\n\r\n async sendMessage(channelId: string, data: MessagePayload): Promise<Message> {\r\n return (await this.request('POST', `/channels/${channelId}/messages`, data)) as Message;\r\n }\r\n\r\n async getMessages(channelId: string, limit = 50, before?: string): Promise<Message[]> {\r\n let path = `/channels/${channelId}/messages?limit=${Math.min(limit, 100)}`;\r\n if (before) path += `&before=${before}`;\r\n return (await this.request('GET', path)) as Message[];\r\n }\r\n\r\n async getMessage(channelId: string, messageId: string): Promise<Message> {\r\n return (await this.request('GET', `/channels/${channelId}/messages/${messageId}`)) as Message;\r\n }\r\n\r\n async editMessage(channelId: string, messageId: string, data: MessagePayload): Promise<Message> {\r\n return (await this.request('PATCH', `/channels/${channelId}/messages/${messageId}`, data)) as Message;\r\n }\r\n\r\n // ── Reactions ──\r\n\r\n async addReaction(channelId: string, messageId: string, emoji: string): Promise<void> {\r\n const encoded = encodeURIComponent(emoji);\r\n await this.request('PUT', `/channels/${channelId}/messages/${messageId}/reactions/${encoded}/@me`);\r\n }\r\n\r\n async removeReaction(channelId: string, messageId: string, emoji: string): Promise<void> {\r\n const encoded = encodeURIComponent(emoji);\r\n await this.request('DELETE', `/channels/${channelId}/messages/${messageId}/reactions/${encoded}/@me`);\r\n }\r\n\r\n // ── Threads ──\r\n\r\n async createThread(channelId: string, name: string, messageId?: string): Promise<Channel> {\r\n if (messageId) {\r\n return (await this.request('POST', `/channels/${channelId}/messages/${messageId}/threads`, {\r\n name, auto_archive_duration: 1440\r\n })) as Channel;\r\n }\r\n return (await this.request('POST', `/channels/${channelId}/threads`, {\r\n name, type: 11, auto_archive_duration: 1440\r\n })) as Channel;\r\n }\r\n\r\n async deleteMessage(channelId: string, messageId: string): Promise<void> {\r\n await this.request('DELETE', `/channels/${channelId}/messages/${messageId}`);\r\n }\r\n\r\n async pinMessage(channelId: string, messageId: string): Promise<void> {\r\n await this.request('PUT', `/channels/${channelId}/pins/${messageId}`);\r\n }\r\n\r\n async unpinMessage(channelId: string, messageId: string): Promise<void> {\r\n await this.request('DELETE', `/channels/${channelId}/pins/${messageId}`);\r\n }\r\n\r\n async getPinnedMessages(channelId: string): Promise<Message[]> {\r\n return (await this.request('GET', `/channels/${channelId}/pins`)) as Message[];\r\n }\r\n\r\n async deleteChannel(channelId: string): Promise<void> {\r\n await this.request('DELETE', `/channels/${channelId}`);\r\n }\r\n\r\n async modifyChannel(channelId: string, data: Record<string, unknown>): Promise<Channel> {\r\n return (await this.request('PATCH', `/channels/${channelId}`, data)) as Channel;\r\n }\r\n\r\n async getChannel(channelId: string): Promise<Channel> {\r\n return (await this.request('GET', `/channels/${channelId}`)) as Channel;\r\n }\r\n\r\n async editChannelPermission(\r\n channelId: string,\r\n overwriteId: string,\r\n data: { allow: string; deny: string; type: number }\r\n ): Promise<void> {\r\n await this.request('PUT', `/channels/${channelId}/permissions/${overwriteId}`, data);\r\n }\r\n\r\n async deleteChannelPermission(channelId: string, overwriteId: string): Promise<void> {\r\n await this.request('DELETE', `/channels/${channelId}/permissions/${overwriteId}`);\r\n }\r\n\r\n // ── Roles ──\r\n\r\n async listRoles(guildId: string): Promise<Role[]> {\r\n return (await this.request('GET', `/guilds/${guildId}/roles`)) as Role[];\r\n }\r\n\r\n async createRole(guildId: string, data: Record<string, unknown>): Promise<Role> {\r\n return (await this.request('POST', `/guilds/${guildId}/roles`, data)) as Role;\r\n }\r\n\r\n async modifyRole(guildId: string, roleId: string, data: Record<string, unknown>): Promise<Role> {\r\n return (await this.request('PATCH', `/guilds/${guildId}/roles/${roleId}`, data)) as Role;\r\n }\r\n\r\n async reorderRoles(guildId: string, positions: { id: string; position: number }[]): Promise<Role[]> {\r\n return (await this.request('PATCH', `/guilds/${guildId}/roles`, positions)) as Role[];\r\n }\r\n\r\n async deleteRole(guildId: string, roleId: string): Promise<void> {\r\n await this.request('DELETE', `/guilds/${guildId}/roles/${roleId}`);\r\n }\r\n\r\n async addRoleToMember(guildId: string, userId: string, roleId: string): Promise<void> {\r\n await this.request('PUT', `/guilds/${guildId}/members/${userId}/roles/${roleId}`);\r\n }\r\n\r\n async removeRoleFromMember(guildId: string, userId: string, roleId: string): Promise<void> {\r\n await this.request('DELETE', `/guilds/${guildId}/members/${userId}/roles/${roleId}`);\r\n }\r\n\r\n // ── Members ──\r\n\r\n async listMembers(guildId: string, limit = 100): Promise<Member[]> {\r\n return (await this.request('GET', `/guilds/${guildId}/members?limit=${Math.min(limit, 1000)}`)) as Member[];\r\n }\r\n\r\n async getMember(guildId: string, userId: string): Promise<Member> {\r\n return (await this.request('GET', `/guilds/${guildId}/members/${userId}`)) as Member;\r\n }\r\n\r\n async kickMember(guildId: string, userId: string): Promise<void> {\r\n await this.request('DELETE', `/guilds/${guildId}/members/${userId}`);\r\n }\r\n\r\n async banMember(guildId: string, userId: string): Promise<void> {\r\n await this.request('PUT', `/guilds/${guildId}/bans/${userId}`);\r\n }\r\n\r\n async modifyMember(guildId: string, userId: string, data: Record<string, unknown>): Promise<Member> {\r\n return (await this.request('PATCH', `/guilds/${guildId}/members/${userId}`, data)) as Member;\r\n }\r\n}\r\n\r\n// ── Types ──\r\n\r\nexport interface Guild {\r\n id: string;\r\n name: string;\r\n icon: string | null;\r\n owner: boolean;\r\n permissions: string;\r\n}\r\n\r\nexport interface GuildFull extends Guild {\r\n approximate_member_count?: number;\r\n approximate_presence_count?: number;\r\n description: string | null;\r\n premium_tier: number;\r\n premium_subscription_count: number;\r\n}\r\n\r\nexport interface PermissionOverwrite {\r\n id: string;\r\n type: number; // 0 = role, 1 = member\r\n allow: string;\r\n deny: string;\r\n}\r\n\r\nexport interface Channel {\r\n id: string;\r\n name: string;\r\n type: number;\r\n position: number;\r\n parent_id: string | null;\r\n topic?: string | null;\r\n permission_overwrites?: PermissionOverwrite[];\r\n}\r\n\r\nexport interface Role {\r\n id: string;\r\n name: string;\r\n color: number;\r\n position: number;\r\n permissions: string;\r\n managed: boolean;\r\n mentionable: boolean;\r\n}\r\n\r\nexport interface Member {\r\n user?: {\r\n id: string;\r\n username: string;\r\n global_name: string | null;\r\n };\r\n nick: string | null;\r\n roles: string[];\r\n joined_at: string;\r\n}\r\n\r\nexport interface Embed {\r\n title?: string;\r\n description?: string;\r\n url?: string;\r\n color?: number;\r\n timestamp?: string;\r\n footer?: { text: string; icon_url?: string };\r\n image?: { url: string };\r\n thumbnail?: { url: string };\r\n author?: { name: string; url?: string; icon_url?: string };\r\n fields?: { name: string; value: string; inline?: boolean }[];\r\n}\r\n\r\nexport interface MessagePayload {\r\n content?: string;\r\n embeds?: Embed[];\r\n message_reference?: { message_id: string };\r\n}\r\n\r\nexport interface Message {\r\n id: string;\r\n channel_id: string;\r\n content: string;\r\n timestamp: string;\r\n edited_timestamp: string | null;\r\n pinned: boolean;\r\n author: {\r\n id: string;\r\n username: string;\r\n bot?: boolean;\r\n };\r\n embeds?: Embed[];\r\n}\r\n\r\nexport interface AuditLogEntry {\r\n id: string;\r\n user_id: string | null;\r\n target_id: string | null;\r\n action_type: number;\r\n reason?: string;\r\n changes?: { key: string; old_value?: unknown; new_value?: unknown }[];\r\n}\r\n\r\nexport interface AuditLog {\r\n audit_log_entries: AuditLogEntry[];\r\n users: { id: string; username: string }[];\r\n}\r\n\r\nexport const AUDIT_ACTION: Record<string, number> = {\r\n guild_update: 1,\r\n channel_create: 10,\r\n channel_update: 11,\r\n channel_delete: 12,\r\n member_kick: 20,\r\n member_prune: 21,\r\n member_ban_add: 22,\r\n member_ban_remove: 23,\r\n member_update: 24,\r\n member_role_update: 25,\r\n bot_add: 28,\r\n role_create: 30,\r\n role_update: 31,\r\n role_delete: 32,\r\n invite_create: 40,\r\n invite_delete: 42,\r\n webhook_create: 50,\r\n webhook_update: 51,\r\n webhook_delete: 52,\r\n emoji_create: 60,\r\n emoji_delete: 62,\r\n message_delete: 72,\r\n message_bulk_delete: 73,\r\n message_pin: 74,\r\n message_unpin: 75,\r\n thread_create: 110,\r\n thread_update: 111,\r\n thread_delete: 112,\r\n automod_rule_create: 140,\r\n automod_rule_update: 141,\r\n automod_rule_delete: 142,\r\n automod_block_message: 143,\r\n integration_create: 80,\r\n integration_update: 81,\r\n integration_delete: 82,\r\n};\r\n\r\nexport const AUDIT_ACTION_NAME: Record<number, string> = Object.fromEntries(\r\n Object.entries(AUDIT_ACTION).map(([k, v]) => [v, k])\r\n);\r\n","import { Command } from 'commander';\r\nimport { saveToken, setDefaultServer, loadToken } from '../utils/config.js';\r\nimport { DiscordAPI } from '../utils/api.js';\r\nimport { readFileSync } from 'fs';\r\n\r\nexport function registerInit(program: Command): void {\r\n program\r\n .command('init')\r\n .description('Set up discli with your bot token and default server')\r\n .option('--token <token>', 'Bot token (or reads from stdin)')\r\n .action(async (opts) => {\r\n let token = opts.token;\r\n\r\n if (!token) {\r\n // Try reading from stdin if piped\r\n if (!process.stdin.isTTY) {\r\n token = readFileSync(0, 'utf-8').trim();\r\n }\r\n }\r\n\r\n if (!token) {\r\n // Check if already configured\r\n const existing = loadToken();\r\n if (existing) {\r\n console.log('Already configured. Use --token to update.');\r\n token = existing;\r\n } else {\r\n console.error('Usage: discli init --token <your-bot-token>');\r\n console.error(' Get your token from https://discord.com/developers/applications');\r\n process.exit(2);\r\n }\r\n }\r\n\r\n // Validate token\r\n const api = new DiscordAPI(token);\r\n let guilds;\r\n try {\r\n guilds = await api.listGuilds();\r\n } catch {\r\n console.error('Invalid token or cannot connect to Discord.');\r\n process.exit(1);\r\n }\r\n\r\n saveToken(token);\r\n console.log(`Token saved to ~/.discli/.env`);\r\n\r\n if (guilds.length === 0) {\r\n console.log('Bot is not in any servers yet. Add it to a server first.');\r\n return;\r\n }\r\n\r\n console.log('\\nServers:');\r\n guilds.forEach((g, i) => {\r\n console.log(` ${i + 1}. ${g.name} (${g.id})`);\r\n });\r\n\r\n // Auto-select if only one server\r\n if (guilds.length === 1) {\r\n setDefaultServer(guilds[0].id, guilds[0].name);\r\n console.log(`\\nDefault server: ${guilds[0].name}`);\r\n } else {\r\n console.log(`\\nSet default with: discli server select <id>`);\r\n }\r\n\r\n console.log('\\nReady! Try: discli server info');\r\n });\r\n}\r\n","import { stringify as yamlStringify } from 'yaml';\r\n\r\nexport function resolveFormat(explicit: string): string {\r\n if (explicit !== 'auto') return explicit;\r\n return process.stdout.isTTY ? 'table' : 'yaml';\r\n}\r\n\r\nexport function printResult(data: unknown, format: string): void {\r\n const fmt = resolveFormat(format);\r\n\r\n if (fmt === 'json') {\r\n console.log(JSON.stringify(data, null, 2));\r\n return;\r\n }\r\n\r\n if (fmt === 'yaml') {\r\n console.log(yamlStringify(data, { indent: 2 }).trimEnd());\r\n return;\r\n }\r\n\r\n if (Array.isArray(data)) {\r\n if (data.length === 0) {\r\n console.log(' (none)');\r\n return;\r\n }\r\n if (typeof data[0] === 'object') {\r\n printTable(data as Record<string, unknown>[]);\r\n } else {\r\n data.forEach((item) => console.log(` ${item}`));\r\n }\r\n return;\r\n }\r\n\r\n if (typeof data === 'object' && data !== null) {\r\n const obj = data as Record<string, unknown>;\r\n const maxKey = Math.max(...Object.keys(obj).map((k) => k.length));\r\n for (const [k, v] of Object.entries(obj)) {\r\n console.log(` ${k.padEnd(maxKey)} ${v}`);\r\n }\r\n return;\r\n }\r\n\r\n console.log(String(data));\r\n}\r\n\r\nexport function printTable(rows: Record<string, unknown>[], columns?: string[]): void {\r\n if (rows.length === 0) {\r\n console.log(' (none)');\r\n return;\r\n }\r\n\r\n const cols = columns ?? Object.keys(rows[0]);\r\n const widths: Record<string, number> = {};\r\n for (const col of cols) {\r\n widths[col] = col.length;\r\n }\r\n for (const row of rows) {\r\n for (const col of cols) {\r\n widths[col] = Math.max(widths[col], String(row[col] ?? '').length);\r\n }\r\n }\r\n\r\n const header = cols.map((c) => c.toUpperCase().padEnd(widths[c])).join(' ');\r\n const sep = cols.map((c) => '─'.repeat(widths[c])).join(' ');\r\n console.log(` ${header}`);\r\n console.log(` ${sep}`);\r\n\r\n for (const row of rows) {\r\n const line = cols.map((c) => String(row[c] ?? '').padEnd(widths[c])).join(' ');\r\n console.log(` ${line}`);\r\n }\r\n}\r\n","import { Command } from 'commander';\r\nimport { DiscordAPI } from '../utils/api.js';\r\nimport { requireToken, requireServer, setDefaultServer } from '../utils/config.js';\r\nimport { printResult, resolveFormat } from '../utils/output.js';\r\n\r\nexport function registerServer(program: Command): void {\r\n const server = program\r\n .command('server')\r\n .description('Manage and inspect servers');\r\n\r\n server\r\n .command('list')\r\n .description('List all servers the bot is in')\r\n .action(async () => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guilds = await api.listGuilds();\r\n\r\n if (fmt !== 'table') {\r\n printResult(guilds, fmt);\r\n return;\r\n }\r\n\r\n const rows = guilds.map((g) => ({\r\n id: g.id,\r\n name: g.name,\r\n owner: g.owner ? 'yes' : 'no',\r\n }));\r\n console.log('\\nServers');\r\n console.log('───────');\r\n printResult(rows, fmt);\r\n });\r\n\r\n server\r\n .command('select')\r\n .description('Set the default server')\r\n .argument('<id>', 'Server ID')\r\n .action(async (id: string) => {\r\n const api = new DiscordAPI(requireToken());\r\n const guild = await api.getGuild(id);\r\n setDefaultServer(guild.id, guild.name);\r\n console.log(`Default server set to: ${guild.name} (${guild.id})`);\r\n });\r\n\r\n server\r\n .command('info')\r\n .description('Show server details')\r\n .action(async () => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const guild = await api.getGuild(guildId);\r\n\r\n if (fmt !== 'table') {\r\n printResult(guild, fmt);\r\n return;\r\n }\r\n\r\n const info = {\r\n name: guild.name,\r\n id: guild.id,\r\n description: guild.description || '(none)',\r\n members: guild.approximate_member_count ?? '?',\r\n online: guild.approximate_presence_count ?? '?',\r\n boosts: guild.premium_subscription_count,\r\n boost_tier: guild.premium_tier,\r\n };\r\n\r\n console.log(`\\n${guild.name}`);\r\n console.log('─'.repeat(guild.name.length));\r\n printResult(info, fmt);\r\n });\r\n}\r\n","import { DiscordAPI, CHANNEL_TYPE_NAME } from './api.js';\r\nimport type { Channel, Role, Member } from './api.js';\r\n\r\nexport async function resolveChannel(\r\n api: DiscordAPI,\r\n guildId: string,\r\n name: string\r\n): Promise<Channel> {\r\n const channels = await api.listChannels(guildId);\r\n\r\n // Try ID match\r\n const byId = channels.find((c) => c.id === name);\r\n if (byId) return byId;\r\n\r\n // Strip # prefix\r\n const clean = name.replace(/^#/, '');\r\n\r\n const matches = channels.filter((c) => c.name.toLowerCase() === clean.toLowerCase());\r\n if (matches.length === 1) return matches[0];\r\n if (matches.length > 1) {\r\n const names = matches.map((m) => `#${m.name} (${CHANNEL_TYPE_NAME[m.type] ?? '?'})`).join(', ');\r\n console.error(`Ambiguous channel \"${clean}\". Matches: ${names}`);\r\n process.exit(1);\r\n }\r\n\r\n console.error(`Channel \"${name}\" not found.`);\r\n process.exit(3);\r\n}\r\n\r\nexport async function resolveCategory(\r\n api: DiscordAPI,\r\n guildId: string,\r\n name: string\r\n): Promise<Channel> {\r\n const channels = await api.listChannels(guildId);\r\n\r\n const byId = channels.find((c) => c.id === name && c.type === 4);\r\n if (byId) return byId;\r\n\r\n const matches = channels.filter(\r\n (c) => c.type === 4 && c.name.toLowerCase() === name.toLowerCase()\r\n );\r\n if (matches.length === 1) return matches[0];\r\n if (matches.length > 1) {\r\n console.error(`Ambiguous category \"${name}\".`);\r\n process.exit(1);\r\n }\r\n\r\n console.error(`Category \"${name}\" not found.`);\r\n process.exit(3);\r\n}\r\n\r\nexport async function resolveRole(\r\n api: DiscordAPI,\r\n guildId: string,\r\n name: string\r\n): Promise<Role> {\r\n const roles = await api.listRoles(guildId);\r\n\r\n const byId = roles.find((r) => r.id === name);\r\n if (byId) return byId;\r\n\r\n const clean = name.replace(/^@/, '');\r\n const matches = roles.filter((r) => r.name.toLowerCase() === clean.toLowerCase());\r\n if (matches.length === 1) return matches[0];\r\n if (matches.length > 1) {\r\n const names = matches.map((m) => `@${m.name}`).join(', ');\r\n console.error(`Ambiguous role \"${clean}\". Matches: ${names}`);\r\n process.exit(1);\r\n }\r\n\r\n console.error(`Role \"${name}\" not found.`);\r\n process.exit(3);\r\n}\r\n\r\nexport async function resolveMember(\r\n api: DiscordAPI,\r\n guildId: string,\r\n name: string\r\n): Promise<Member> {\r\n // Try as ID\r\n if (/^\\d+$/.test(name)) {\r\n try {\r\n return await api.getMember(guildId, name);\r\n } catch {\r\n // fall through to search\r\n }\r\n }\r\n\r\n const members = await api.listMembers(guildId, 1000);\r\n const clean = name.replace(/^@/, '').toLowerCase();\r\n\r\n const matches = members.filter((m) => {\r\n const username = m.user?.username?.toLowerCase() ?? '';\r\n const globalName = m.user?.global_name?.toLowerCase() ?? '';\r\n const nick = m.nick?.toLowerCase() ?? '';\r\n return username === clean || globalName === clean || nick === clean;\r\n });\r\n\r\n if (matches.length === 1) return matches[0];\r\n if (matches.length > 1) {\r\n const names = matches.map((m) => m.user?.username).join(', ');\r\n console.error(`Ambiguous user \"${name}\". Matches: ${names}`);\r\n process.exit(1);\r\n }\r\n\r\n console.error(`Member \"${name}\" not found.`);\r\n process.exit(3);\r\n}\r\n","import { Command } from 'commander';\r\nimport { DiscordAPI, CHANNEL_TYPE, CHANNEL_TYPE_NAME } from '../utils/api.js';\r\nimport { requireToken, requireServer } from '../utils/config.js';\r\nimport { printResult, resolveFormat } from '../utils/output.js';\r\nimport { resolveChannel, resolveCategory } from '../utils/resolve.js';\r\n\r\nexport function registerChannel(program: Command): void {\r\n const channel = program\r\n .command('channel')\r\n .description('Manage server channels');\r\n\r\n channel\r\n .command('list')\r\n .description('List all channels grouped by category')\r\n .option('-n <count>', 'Limit number of channels shown', parseInt)\r\n .action(async (opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n let channels = await api.listChannels(guildId);\r\n if (opts.n) channels = channels.slice(0, opts.n);\r\n\r\n if (fmt !== 'table') {\r\n printResult(channels, fmt);\r\n return;\r\n }\r\n\r\n // Group by category\r\n const categories = channels\r\n .filter((c) => c.type === 4)\r\n .sort((a, b) => a.position - b.position);\r\n const uncategorized = channels.filter(\r\n (c) => c.type !== 4 && !c.parent_id\r\n );\r\n\r\n if (uncategorized.length > 0) {\r\n console.log('\\n (no category)');\r\n for (const ch of uncategorized.sort((a, b) => a.position - b.position)) {\r\n const type = CHANNEL_TYPE_NAME[ch.type] ?? '?';\r\n console.log(` ${type === 'text' ? '#' : '🔊'} ${ch.name}`);\r\n }\r\n }\r\n\r\n for (const cat of categories) {\r\n console.log(`\\n ${cat.name.toUpperCase()}`);\r\n const children = channels\r\n .filter((c) => c.parent_id === cat.id && c.type !== 4)\r\n .sort((a, b) => a.position - b.position);\r\n for (const ch of children) {\r\n const type = CHANNEL_TYPE_NAME[ch.type] ?? '?';\r\n const prefix = type === 'voice' || type === 'stage' ? '🔊' : '#';\r\n const topic = ch.topic ? ` — ${ch.topic}` : '';\r\n console.log(` ${prefix} ${ch.name}${topic}`);\r\n }\r\n }\r\n console.log();\r\n });\r\n\r\n channel\r\n .command('create')\r\n .description('Create a new channel')\r\n .argument('<name>', 'Channel name')\r\n .option('--type <type>', 'Channel type: text, voice, category, announcement, stage, forum', 'text')\r\n .option('--category <name>', 'Parent category name or ID')\r\n .option('--topic <topic>', 'Channel topic')\r\n .option('--dry-run', 'Show what would be created without creating it')\r\n .action(async (name: string, opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n\r\n const channelType = CHANNEL_TYPE[opts.type];\r\n if (channelType === undefined) {\r\n console.error(`Unknown channel type: ${opts.type}. Use: ${Object.keys(CHANNEL_TYPE).join(', ')}`);\r\n process.exit(2);\r\n }\r\n\r\n let parentId: string | undefined;\r\n if (opts.category) {\r\n const cat = await resolveCategory(api, guildId, opts.category);\r\n parentId = cat.id;\r\n }\r\n\r\n if (opts.dryRun) {\r\n const result = { action: 'create_channel', name, type: opts.type, category: opts.category ?? null, topic: opts.topic ?? null };\r\n printResult(result, fmt);\r\n return;\r\n }\r\n\r\n const ch = await api.createChannel(guildId, {\r\n name,\r\n type: channelType,\r\n parent_id: parentId,\r\n topic: opts.topic,\r\n });\r\n\r\n if (fmt !== 'table') {\r\n printResult(ch, fmt);\r\n } else {\r\n console.log(`Created #${ch.name} (${CHANNEL_TYPE_NAME[ch.type] ?? '?'}) — ${ch.id}`);\r\n }\r\n });\r\n\r\n channel\r\n .command('delete')\r\n .description('Delete a channel')\r\n .argument('<name>', 'Channel name or ID')\r\n .option('--confirm', 'Required to actually delete')\r\n .action(async (name: string, opts) => {\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, name);\r\n\r\n if (!opts.confirm) {\r\n console.error(`This will delete #${ch.name} (${ch.id}). Add --confirm to proceed.`);\r\n process.exit(2);\r\n }\r\n\r\n await api.deleteChannel(ch.id);\r\n console.log(`Deleted #${ch.name}`);\r\n });\r\n\r\n channel\r\n .command('rename')\r\n .description('Rename a channel')\r\n .argument('<channel>', 'Channel name or ID')\r\n .argument('<new-name>', 'New channel name')\r\n .option('--dry-run', 'Show what would change')\r\n .action(async (channelName: string, newName: string, opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n\r\n if (opts.dryRun) {\r\n printResult({ action: 'rename_channel', from: ch.name, to: newName, id: ch.id }, fmt);\r\n return;\r\n }\r\n\r\n await api.modifyChannel(ch.id, { name: newName });\r\n console.log(`Renamed #${ch.name} → #${newName}`);\r\n });\r\n\r\n channel\r\n .command('topic')\r\n .description('Set a channel topic')\r\n .argument('<channel>', 'Channel name or ID')\r\n .argument('<topic>', 'New topic text')\r\n .action(async (channelName: string, topic: string) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n\r\n const updated = await api.modifyChannel(ch.id, { topic });\r\n if (fmt !== 'table') {\r\n printResult(updated, fmt);\r\n } else {\r\n console.log(`Set topic for #${ch.name}: ${topic}`);\r\n }\r\n });\r\n\r\n channel\r\n .command('move')\r\n .description('Move a channel to a category')\r\n .argument('<channel>', 'Channel name or ID')\r\n .option('--category <name>', 'Target category name or ID')\r\n .option('--position <n>', 'Position within category', parseInt)\r\n .action(async (channelName: string, opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n\r\n const update: Record<string, unknown> = {};\r\n if (opts.category) {\r\n const cat = await resolveCategory(api, guildId, opts.category);\r\n update.parent_id = cat.id;\r\n }\r\n if (opts.position !== undefined) {\r\n update.position = opts.position;\r\n }\r\n\r\n if (Object.keys(update).length === 0) {\r\n console.error('Specify --category and/or --position.');\r\n process.exit(2);\r\n }\r\n\r\n const updated = await api.modifyChannel(ch.id, update);\r\n if (fmt !== 'table') {\r\n printResult(updated, fmt);\r\n } else {\r\n console.log(`Moved #${ch.name}${opts.category ? ` → ${opts.category}` : ''}${opts.position !== undefined ? ` (position ${opts.position})` : ''}`);\r\n }\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { DiscordAPI } from '../utils/api.js';\r\nimport { requireToken, requireServer } from '../utils/config.js';\r\nimport { printResult, resolveFormat } from '../utils/output.js';\r\nimport { resolveRole, resolveMember } from '../utils/resolve.js';\r\n\r\nexport function registerRole(program: Command): void {\r\n const role = program\r\n .command('role')\r\n .description('Manage server roles');\r\n\r\n role\r\n .command('list')\r\n .description('List all roles')\r\n .option('-n <count>', 'Limit number of roles shown', parseInt)\r\n .action(async (opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const roles = await api.listRoles(guildId);\r\n\r\n const sorted = roles.sort((a, b) => b.position - a.position).slice(0, opts.n ?? roles.length);\r\n\r\n if (fmt !== 'table') {\r\n printResult(sorted, fmt);\r\n return;\r\n }\r\n\r\n const rows = sorted.map((r) => ({\r\n name: r.name,\r\n id: r.id,\r\n color: r.color ? `#${r.color.toString(16).padStart(6, '0')}` : '(none)',\r\n managed: r.managed ? 'bot' : '',\r\n position: r.position,\r\n }));\r\n\r\n console.log('\\nRoles');\r\n console.log('─────');\r\n printResult(rows, fmt);\r\n });\r\n\r\n role\r\n .command('create')\r\n .description('Create a new role')\r\n .argument('<name>', 'Role name')\r\n .option('--color <hex>', 'Color hex (e.g. #ff5733)')\r\n .option('--mentionable', 'Allow anyone to mention this role')\r\n .option('--dry-run', 'Show what would be created')\r\n .action(async (name: string, opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n\r\n const data: Record<string, unknown> = { name };\r\n if (opts.color) {\r\n data.color = parseInt(opts.color.replace('#', ''), 16);\r\n }\r\n if (opts.mentionable) {\r\n data.mentionable = true;\r\n }\r\n\r\n if (opts.dryRun) {\r\n printResult({ action: 'create_role', ...data }, fmt);\r\n return;\r\n }\r\n\r\n const r = await api.createRole(guildId, data);\r\n if (fmt !== 'table') {\r\n printResult(r, fmt);\r\n } else {\r\n console.log(`Created role @${r.name} — ${r.id}`);\r\n }\r\n });\r\n\r\n role\r\n .command('delete')\r\n .description('Delete a role')\r\n .argument('<name>', 'Role name or ID')\r\n .option('--confirm', 'Required to actually delete')\r\n .action(async (name: string, opts) => {\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const r = await resolveRole(api, guildId, name);\r\n\r\n if (!opts.confirm) {\r\n console.error(`This will delete @${r.name} (${r.id}). Add --confirm to proceed.`);\r\n process.exit(2);\r\n }\r\n\r\n await api.deleteRole(guildId, r.id);\r\n console.log(`Deleted role @${r.name}`);\r\n });\r\n\r\n role\r\n .command('assign')\r\n .description('Assign a role to a member')\r\n .argument('<role>', 'Role name or ID')\r\n .argument('<user>', 'Username or ID')\r\n .action(async (roleName: string, userName: string) => {\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const r = await resolveRole(api, guildId, roleName);\r\n const m = await resolveMember(api, guildId, userName);\r\n\r\n await api.addRoleToMember(guildId, m.user!.id, r.id);\r\n console.log(`Assigned @${r.name} to ${m.user!.username}`);\r\n });\r\n\r\n role\r\n .command('remove')\r\n .description('Remove a role from a member')\r\n .argument('<role>', 'Role name or ID')\r\n .argument('<user>', 'Username or ID')\r\n .action(async (roleName: string, userName: string) => {\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const r = await resolveRole(api, guildId, roleName);\r\n const m = await resolveMember(api, guildId, userName);\r\n\r\n await api.removeRoleFromMember(guildId, m.user!.id, r.id);\r\n console.log(`Removed @${r.name} from ${m.user!.username}`);\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { DiscordAPI } from '../utils/api.js';\r\nimport { requireToken, requireServer } from '../utils/config.js';\r\nimport { printResult, resolveFormat } from '../utils/output.js';\r\nimport { resolveMember } from '../utils/resolve.js';\r\n\r\nexport function registerMember(program: Command): void {\r\n const member = program\r\n .command('member')\r\n .description('Manage server members');\r\n\r\n member\r\n .command('list')\r\n .description('List server members')\r\n .option('-n, --limit <n>', 'Max members to show', '100')\r\n .action(async (opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const members = await api.listMembers(guildId, parseInt(opts.limit));\r\n\r\n if (fmt !== 'table') {\r\n printResult(members, fmt);\r\n return;\r\n }\r\n\r\n const rows = members.map((m) => ({\r\n username: m.user?.username ?? '?',\r\n display: m.user?.global_name ?? m.nick ?? '',\r\n nick: m.nick ?? '',\r\n roles: m.roles.length,\r\n joined: m.joined_at?.slice(0, 10) ?? '?',\r\n }));\r\n\r\n console.log(`\\nMembers (${members.length})`);\r\n console.log('──────────');\r\n printResult(rows, fmt);\r\n });\r\n\r\n member\r\n .command('info')\r\n .description('Show member details')\r\n .argument('<user>', 'Username or ID')\r\n .action(async (userName: string) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const m = await resolveMember(api, guildId, userName);\r\n\r\n if (fmt !== 'table') {\r\n printResult(m, fmt);\r\n return;\r\n }\r\n\r\n const roles = await api.listRoles(guildId);\r\n const memberRoles = m.roles\r\n .map((rid) => roles.find((r) => r.id === rid)?.name ?? rid)\r\n .join(', ');\r\n\r\n const info = {\r\n username: m.user?.username ?? '?',\r\n display_name: m.user?.global_name ?? '(none)',\r\n nickname: m.nick ?? '(none)',\r\n id: m.user?.id ?? '?',\r\n roles: memberRoles || '(none)',\r\n joined: m.joined_at?.slice(0, 10) ?? '?',\r\n };\r\n\r\n console.log(`\\n${m.user?.username ?? 'Member'}`);\r\n console.log('─'.repeat((m.user?.username ?? 'Member').length));\r\n printResult(info, fmt);\r\n });\r\n\r\n member\r\n .command('kick')\r\n .description('Kick a member from the server')\r\n .argument('<user>', 'Username or ID')\r\n .option('--reason <text>', 'Reason for kick')\r\n .option('--confirm', 'Required to actually kick')\r\n .action(async (userName: string, opts) => {\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const m = await resolveMember(api, guildId, userName);\r\n\r\n if (!opts.confirm) {\r\n console.error(`This will kick ${m.user!.username} (${m.user!.id}). Add --confirm to proceed.`);\r\n process.exit(2);\r\n }\r\n\r\n await api.kickMember(guildId, m.user!.id);\r\n console.log(`Kicked ${m.user!.username}${opts.reason ? ` — ${opts.reason}` : ''}`);\r\n });\r\n\r\n member\r\n .command('ban')\r\n .description('Ban a member from the server')\r\n .argument('<user>', 'Username or ID')\r\n .option('--reason <text>', 'Reason for ban')\r\n .option('--confirm', 'Required to actually ban')\r\n .action(async (userName: string, opts) => {\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const m = await resolveMember(api, guildId, userName);\r\n\r\n if (!opts.confirm) {\r\n console.error(`This will BAN ${m.user!.username} (${m.user!.id}). Add --confirm to proceed.`);\r\n process.exit(2);\r\n }\r\n\r\n await api.banMember(guildId, m.user!.id);\r\n console.log(`Banned ${m.user!.username}${opts.reason ? ` — ${opts.reason}` : ''}`);\r\n });\r\n\r\n member\r\n .command('nick')\r\n .description('Change a member\\'s nickname')\r\n .argument('<user>', 'Username or ID')\r\n .argument('<nickname>', 'New nickname')\r\n .action(async (userName: string, nickname: string) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const m = await resolveMember(api, guildId, userName);\r\n\r\n await api.modifyMember(guildId, m.user!.id, { nick: nickname });\r\n if (fmt !== 'table') {\r\n printResult({ action: 'nick', user: m.user!.username, nick: nickname }, fmt);\r\n } else {\r\n console.log(`Set nickname for ${m.user!.username} → ${nickname}`);\r\n }\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { DiscordAPI, PERMISSION } from '../utils/api.js';\r\nimport { requireToken, requireServer } from '../utils/config.js';\r\nimport { printResult, resolveFormat } from '../utils/output.js';\r\nimport { resolveChannel, resolveRole } from '../utils/resolve.js';\r\n\r\nfunction parsePermissions(perms: string): bigint {\r\n let bits = 0n;\r\n for (const p of perms.split(',')) {\r\n const name = p.trim().toLowerCase();\r\n const val = PERMISSION[name];\r\n if (val === undefined) {\r\n console.error(`Unknown permission: ${name}`);\r\n console.error(`Available: ${Object.keys(PERMISSION).join(', ')}`);\r\n process.exit(2);\r\n }\r\n bits |= val;\r\n }\r\n return bits;\r\n}\r\n\r\nfunction describePermissions(bitfield: string): string[] {\r\n const bits = BigInt(bitfield);\r\n if (bits === 0n) return [];\r\n return Object.entries(PERMISSION)\r\n .filter(([, val]) => (bits & val) === val)\r\n .map(([name]) => name);\r\n}\r\n\r\nexport function registerPermission(program: Command): void {\r\n const perm = program\r\n .command('permission')\r\n .alias('perm')\r\n .description('Manage channel permissions');\r\n\r\n perm\r\n .command('view')\r\n .description('View permission overwrites for a channel')\r\n .argument('<channel>', 'Channel name or ID')\r\n .action(async (channelName: string) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n\r\n const full = await api.getChannel(ch.id);\r\n const overwrites = full.permission_overwrites ?? [];\r\n const roles = await api.listRoles(guildId);\r\n\r\n if (fmt !== 'table') {\r\n printResult(overwrites, fmt);\r\n return;\r\n }\r\n\r\n if (overwrites.length === 0) {\r\n console.log(`\\n#${ch.name}: no permission overwrites (inherits from category/server)`);\r\n return;\r\n }\r\n\r\n console.log(`\\n#${ch.name} — Permission Overwrites`);\r\n console.log('─'.repeat(40));\r\n\r\n for (const ow of overwrites) {\r\n const target = ow.type === 0\r\n ? roles.find((r) => r.id === ow.id)?.name ?? ow.id\r\n : `member:${ow.id}`;\r\n const allowed = describePermissions(ow.allow);\r\n const denied = describePermissions(ow.deny);\r\n\r\n console.log(`\\n @${target} (${ow.type === 0 ? 'role' : 'member'})`);\r\n if (allowed.length > 0) console.log(` ✅ allow: ${allowed.join(', ')}`);\r\n if (denied.length > 0) console.log(` ❌ deny: ${denied.join(', ')}`);\r\n if (allowed.length === 0 && denied.length === 0) console.log(` (neutral)`);\r\n }\r\n console.log();\r\n });\r\n\r\n perm\r\n .command('set')\r\n .description('Set permission overwrite for a role on a channel')\r\n .argument('<channel>', 'Channel name or ID')\r\n .argument('<role>', 'Role name or ID')\r\n .option('--allow <perms>', 'Comma-separated permissions to allow')\r\n .option('--deny <perms>', 'Comma-separated permissions to deny')\r\n .option('--dry-run', 'Show what would change')\r\n .action(async (channelName: string, roleName: string, opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n const role = await resolveRole(api, guildId, roleName);\r\n\r\n if (!opts.allow && !opts.deny) {\r\n console.error('Specify --allow and/or --deny with comma-separated permissions.');\r\n console.error(`Available: ${Object.keys(PERMISSION).join(', ')}`);\r\n process.exit(2);\r\n }\r\n\r\n const allow = opts.allow ? parsePermissions(opts.allow) : 0n;\r\n const deny = opts.deny ? parsePermissions(opts.deny) : 0n;\r\n\r\n if (opts.dryRun) {\r\n printResult({\r\n action: 'set_permission',\r\n channel: ch.name,\r\n role: role.name,\r\n allow: opts.allow ?? '(none)',\r\n deny: opts.deny ?? '(none)',\r\n }, fmt);\r\n return;\r\n }\r\n\r\n await api.editChannelPermission(ch.id, role.id, {\r\n allow: allow.toString(),\r\n deny: deny.toString(),\r\n type: 0, // role\r\n });\r\n\r\n if (fmt !== 'table') {\r\n printResult({ channel: ch.name, role: role.name, allow: allow.toString(), deny: deny.toString() }, fmt);\r\n } else {\r\n console.log(`Set permissions on #${ch.name} for @${role.name}`);\r\n if (opts.allow) console.log(` ✅ allow: ${opts.allow}`);\r\n if (opts.deny) console.log(` ❌ deny: ${opts.deny}`);\r\n }\r\n });\r\n\r\n perm\r\n .command('lock')\r\n .description('Make a channel read-only for @everyone')\r\n .argument('<channel>', 'Channel name or ID')\r\n .option('--dry-run', 'Show what would change')\r\n .action(async (channelName: string, opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n\r\n // @everyone role ID = guild ID\r\n const deny = PERMISSION.send_messages\r\n | PERMISSION.send_messages_in_threads\r\n | PERMISSION.create_public_threads;\r\n\r\n if (opts.dryRun) {\r\n printResult({ action: 'lock', channel: ch.name, deny_for: '@everyone' }, fmt);\r\n return;\r\n }\r\n\r\n await api.editChannelPermission(ch.id, guildId, {\r\n allow: '0',\r\n deny: deny.toString(),\r\n type: 0,\r\n });\r\n\r\n console.log(`Locked #${ch.name} — read-only for @everyone`);\r\n });\r\n\r\n perm\r\n .command('unlock')\r\n .description('Remove read-only restriction for @everyone')\r\n .argument('<channel>', 'Channel name or ID')\r\n .action(async (channelName: string) => {\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n\r\n await api.deleteChannelPermission(ch.id, guildId);\r\n console.log(`Unlocked #${ch.name} — @everyone can send messages`);\r\n });\r\n\r\n perm\r\n .command('list')\r\n .description('List all available permission names')\r\n .action(() => {\r\n const fmt = resolveFormat(program.opts().format);\r\n if (fmt !== 'table') {\r\n const perms = Object.entries(PERMISSION).map(([name, val]) => ({ name, bit: val.toString() }));\r\n printResult(perms, fmt);\r\n } else {\r\n console.log('\\nAvailable Permissions');\r\n console.log('────────────────────');\r\n for (const name of Object.keys(PERMISSION)) {\r\n console.log(` ${name}`);\r\n }\r\n }\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { DiscordAPI } from '../utils/api.js';\r\nimport type { Embed, MessagePayload } from '../utils/api.js';\r\nimport { requireToken, requireServer } from '../utils/config.js';\r\nimport { printResult, resolveFormat } from '../utils/output.js';\r\nimport { resolveChannel } from '../utils/resolve.js';\r\n\r\nfunction parseColor(color: string): number {\r\n return parseInt(color.replace('#', ''), 16);\r\n}\r\n\r\nexport function registerMessage(program: Command): void {\r\n const message = program\r\n .command('message')\r\n .alias('msg')\r\n .description('Send, read, and manage messages');\r\n\r\n message\r\n .command('send')\r\n .description('Send a message to a channel')\r\n .argument('<channel>', 'Channel name or ID')\r\n .argument('<text>', 'Message content (supports Discord markdown)')\r\n .option('--reply <id>', 'Reply to a message ID')\r\n .action(async (channelName: string, text: string, opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n\r\n const payload: MessagePayload = { content: text };\r\n if (opts.reply) {\r\n payload.message_reference = { message_id: opts.reply };\r\n }\r\n\r\n const msg = await api.sendMessage(ch.id, payload);\r\n if (fmt !== 'table') {\r\n printResult(msg, fmt);\r\n } else {\r\n console.log(`Sent message to #${ch.name} (${msg.id})`);\r\n }\r\n });\r\n\r\n message\r\n .command('embed')\r\n .description('Send an embed (rich card) to a channel')\r\n .argument('<channel>', 'Channel name or ID')\r\n .option('--title <text>', 'Embed title')\r\n .option('--description <text>', 'Embed description (supports markdown)')\r\n .option('--color <hex>', 'Embed color (e.g. #5865F2)')\r\n .option('--url <url>', 'Title link URL')\r\n .option('--image <url>', 'Large image URL')\r\n .option('--thumbnail <url>', 'Small thumbnail URL')\r\n .option('--footer <text>', 'Footer text')\r\n .option('--author <name>', 'Author name')\r\n .option('--field <value...>', 'Add field: \"Name|Value\" or \"Name|Value|inline\"')\r\n .option('--content <text>', 'Text content above the embed')\r\n .option('--reply <id>', 'Reply to a message ID')\r\n .action(async (channelName: string, opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n\r\n const embed: Embed = {};\r\n if (opts.title) embed.title = opts.title;\r\n if (opts.description) embed.description = opts.description;\r\n if (opts.color) embed.color = parseColor(opts.color);\r\n if (opts.url) embed.url = opts.url;\r\n if (opts.image) embed.image = { url: opts.image };\r\n if (opts.thumbnail) embed.thumbnail = { url: opts.thumbnail };\r\n if (opts.footer) embed.footer = { text: opts.footer };\r\n if (opts.author) embed.author = { name: opts.author };\r\n if (opts.field) {\r\n embed.fields = (opts.field as string[]).map((f: string) => {\r\n const parts = f.split('|');\r\n return {\r\n name: parts[0],\r\n value: parts[1] || '',\r\n inline: parts[2] === 'inline',\r\n };\r\n });\r\n }\r\n\r\n if (!embed.title && !embed.description) {\r\n console.error('Provide at least --title or --description for the embed.');\r\n process.exit(2);\r\n }\r\n\r\n const payload: MessagePayload = { embeds: [embed] };\r\n if (opts.content) payload.content = opts.content;\r\n if (opts.reply) payload.message_reference = { message_id: opts.reply };\r\n\r\n const msg = await api.sendMessage(ch.id, payload);\r\n if (fmt !== 'table') {\r\n printResult(msg, fmt);\r\n } else {\r\n console.log(`Sent embed to #${ch.name} (${msg.id})`);\r\n }\r\n });\r\n\r\n message\r\n .command('read')\r\n .description('Read recent messages from a channel')\r\n .argument('<channel>', 'Channel name or ID')\r\n .option('-n <count>', 'Number of messages to fetch', '10')\r\n .option('--before <id>', 'Fetch messages before this message ID')\r\n .action(async (channelName: string, opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n\r\n const messages = await api.getMessages(ch.id, parseInt(opts.n), opts.before);\r\n\r\n if (fmt !== 'table') {\r\n printResult(messages, fmt);\r\n return;\r\n }\r\n\r\n console.log(`\\n#${ch.name} — last ${messages.length} messages`);\r\n console.log('─'.repeat(40));\r\n\r\n for (const msg of messages.reverse()) {\r\n const time = new Date(msg.timestamp).toLocaleString();\r\n const bot = msg.author.bot ? ' [BOT]' : '';\r\n const edited = msg.edited_timestamp ? ' (edited)' : '';\r\n const pinned = msg.pinned ? ' 📌' : '';\r\n console.log(` ${msg.author.username}${bot} — ${time}${edited}${pinned}`);\r\n if (msg.content) console.log(` ${msg.content}`);\r\n if (msg.embeds && msg.embeds.length > 0) {\r\n for (const e of msg.embeds) {\r\n if (e.title) console.log(` [Embed] ${e.title}`);\r\n if (e.description) console.log(` ${e.description.slice(0, 100)}`);\r\n }\r\n }\r\n console.log();\r\n }\r\n });\r\n\r\n message\r\n .command('edit')\r\n .description('Edit a message sent by the bot')\r\n .argument('<channel>', 'Channel name or ID')\r\n .argument('<message-id>', 'Message ID to edit')\r\n .argument('<text>', 'New message content')\r\n .action(async (channelName: string, messageId: string, text: string) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n\r\n const msg = await api.editMessage(ch.id, messageId, { content: text });\r\n if (fmt !== 'table') {\r\n printResult(msg, fmt);\r\n } else {\r\n console.log(`Edited message ${messageId} in #${ch.name}`);\r\n }\r\n });\r\n\r\n message\r\n .command('delete')\r\n .description('Delete a message')\r\n .argument('<channel>', 'Channel name or ID')\r\n .argument('<message-id>', 'Message ID to delete')\r\n .option('--confirm', 'Required to actually delete')\r\n .action(async (channelName: string, messageId: string, opts) => {\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n\r\n if (!opts.confirm) {\r\n console.error(`This will delete message ${messageId} in #${ch.name}. Add --confirm to proceed.`);\r\n process.exit(2);\r\n }\r\n\r\n await api.deleteMessage(ch.id, messageId);\r\n console.log(`Deleted message ${messageId} from #${ch.name}`);\r\n });\r\n\r\n message\r\n .command('react')\r\n .description('Add a reaction to a message')\r\n .argument('<channel>', 'Channel name or ID')\r\n .argument('<message-id>', 'Message ID')\r\n .argument('<emoji>', 'Emoji to react with (e.g. 👍 or :thumbsup:)')\r\n .action(async (channelName: string, messageId: string, emoji: string) => {\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n\r\n await api.addReaction(ch.id, messageId, emoji);\r\n console.log(`Reacted ${emoji} on message ${messageId} in #${ch.name}`);\r\n });\r\n\r\n message\r\n .command('unreact')\r\n .description('Remove bot reaction from a message')\r\n .argument('<channel>', 'Channel name or ID')\r\n .argument('<message-id>', 'Message ID')\r\n .argument('<emoji>', 'Emoji to remove')\r\n .action(async (channelName: string, messageId: string, emoji: string) => {\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n\r\n await api.removeReaction(ch.id, messageId, emoji);\r\n console.log(`Removed ${emoji} reaction from message ${messageId}`);\r\n });\r\n\r\n message\r\n .command('pin')\r\n .description('Pin a message')\r\n .argument('<channel>', 'Channel name or ID')\r\n .argument('<message-id>', 'Message ID to pin')\r\n .action(async (channelName: string, messageId: string) => {\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n\r\n await api.pinMessage(ch.id, messageId);\r\n console.log(`Pinned message ${messageId} in #${ch.name}`);\r\n });\r\n\r\n message\r\n .command('unpin')\r\n .description('Unpin a message')\r\n .argument('<channel>', 'Channel name or ID')\r\n .argument('<message-id>', 'Message ID to unpin')\r\n .action(async (channelName: string, messageId: string) => {\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n\r\n await api.unpinMessage(ch.id, messageId);\r\n console.log(`Unpinned message ${messageId} in #${ch.name}`);\r\n });\r\n\r\n message\r\n .command('pins')\r\n .description('List pinned messages in a channel')\r\n .argument('<channel>', 'Channel name or ID')\r\n .action(async (channelName: string) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n\r\n const pins = await api.getPinnedMessages(ch.id);\r\n\r\n if (fmt !== 'table') {\r\n printResult(pins, fmt);\r\n return;\r\n }\r\n\r\n if (pins.length === 0) {\r\n console.log(`\\n#${ch.name}: no pinned messages`);\r\n return;\r\n }\r\n\r\n console.log(`\\n#${ch.name} — ${pins.length} pinned`);\r\n console.log('─'.repeat(30));\r\n for (const msg of pins) {\r\n const time = new Date(msg.timestamp).toLocaleString();\r\n console.log(` ${msg.author.username} — ${time}`);\r\n if (msg.content) console.log(` ${msg.content}`);\r\n console.log(` ID: ${msg.id}`);\r\n console.log();\r\n }\r\n });\r\n\r\n message\r\n .command('thread')\r\n .description('Create a thread from a message or in a channel')\r\n .argument('<channel>', 'Channel name or ID')\r\n .argument('<name>', 'Thread name')\r\n .option('--message <id>', 'Create thread from this message ID')\r\n .action(async (channelName: string, name: string, opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n const ch = await resolveChannel(api, guildId, channelName);\r\n\r\n const thread = await api.createThread(ch.id, name, opts.message);\r\n if (fmt !== 'table') {\r\n printResult(thread, fmt);\r\n } else {\r\n console.log(`Created thread \"${name}\" in #${ch.name} (${thread.id})`);\r\n }\r\n });\r\n}\r\n","import { Command } from 'commander';\r\nimport { DiscordAPI, AUDIT_ACTION, AUDIT_ACTION_NAME } from '../utils/api.js';\r\nimport { requireToken, requireServer } from '../utils/config.js';\r\nimport { printResult, resolveFormat } from '../utils/output.js';\r\n\r\nexport function registerAudit(program: Command): void {\r\n const audit = program\r\n .command('audit')\r\n .description('View server audit log');\r\n\r\n audit\r\n .command('log')\r\n .description('View recent audit log entries')\r\n .option('-n <count>', 'Number of entries to fetch', '20')\r\n .option('--type <action>', 'Filter by action type (e.g. member_kick, channel_create)')\r\n .option('--user <id>', 'Filter by user who performed the action')\r\n .action(async (opts) => {\r\n const fmt = resolveFormat(program.opts().format);\r\n const api = new DiscordAPI(requireToken());\r\n const guildId = requireServer(program.opts().server);\r\n\r\n const queryOpts: { limit?: number; action_type?: number; user_id?: string } = {\r\n limit: parseInt(opts.n),\r\n };\r\n\r\n if (opts.type) {\r\n const actionType = AUDIT_ACTION[opts.type];\r\n if (actionType === undefined) {\r\n console.error(`Unknown action type: ${opts.type}`);\r\n console.error(`Available: ${Object.keys(AUDIT_ACTION).join(', ')}`);\r\n process.exit(2);\r\n }\r\n queryOpts.action_type = actionType;\r\n }\r\n\r\n if (opts.user) {\r\n queryOpts.user_id = opts.user;\r\n }\r\n\r\n const log = await api.getAuditLog(guildId, queryOpts);\r\n\r\n if (fmt !== 'table') {\r\n printResult(log.audit_log_entries, fmt);\r\n return;\r\n }\r\n\r\n const userMap = new Map(log.users.map((u) => [u.id, u.username]));\r\n\r\n console.log('\\nAudit Log');\r\n console.log('─────────');\r\n\r\n if (log.audit_log_entries.length === 0) {\r\n console.log(' (no entries)');\r\n return;\r\n }\r\n\r\n for (const entry of log.audit_log_entries) {\r\n const who = entry.user_id ? userMap.get(entry.user_id) ?? entry.user_id : '(system)';\r\n const action = AUDIT_ACTION_NAME[entry.action_type] ?? `unknown(${entry.action_type})`;\r\n const target = entry.target_id ?? '';\r\n const reason = entry.reason ? ` — \"${entry.reason}\"` : '';\r\n\r\n console.log(` ${who} → ${action} ${target}${reason}`);\r\n\r\n if (entry.changes && entry.changes.length > 0) {\r\n for (const change of entry.changes.slice(0, 3)) {\r\n const old = change.old_value !== undefined ? String(change.old_value).slice(0, 30) : '';\r\n const nw = change.new_value !== undefined ? String(change.new_value).slice(0, 30) : '';\r\n if (old && nw) {\r\n console.log(` ${change.key}: ${old} → ${nw}`);\r\n } else if (nw) {\r\n console.log(` ${change.key}: ${nw}`);\r\n }\r\n }\r\n }\r\n }\r\n console.log();\r\n });\r\n\r\n audit\r\n .command('types')\r\n .description('List available audit log action types')\r\n .action(() => {\r\n const fmt = resolveFormat(program.opts().format);\r\n if (fmt !== 'table') {\r\n const types = Object.entries(AUDIT_ACTION).map(([name, value]) => ({ name, value }));\r\n printResult(types, fmt);\r\n } else {\r\n console.log('\\nAudit Log Action Types');\r\n console.log('─────────────────────');\r\n for (const [name, value] of Object.entries(AUDIT_ACTION)) {\r\n console.log(` ${name.padEnd(25)} ${value}`);\r\n }\r\n }\r\n });\r\n}\r\n"],"mappings":"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","names":["readFileSync","program","program","program","program","program","program","program","program"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ibbybuilds/discli",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "discli — Discord server management CLI. Control your servers from the terminal. Built for humans and AI agents.",
5
5
  "type": "module",
6
6
  "bin": {
package/skills/SKILL.md CHANGED
@@ -52,6 +52,27 @@ discli perm set <ch> <role> # Set permissions (--allow, --deny)
52
52
  discli perm lock <channel> # Make read-only for @everyone
53
53
  discli perm unlock <channel> # Remove read-only
54
54
  discli perm list # List available permission names
55
+
56
+ discli msg send <channel> "text" # Send message
57
+ discli msg send <ch> "text" --reply <id> # Reply to message
58
+ discli msg embed <ch> --title "X" --description "Y" --color "#hex" # Rich embed
59
+ discli msg embed <ch> --title "X" --field "Name|Value|inline" # Embed with fields
60
+ discli msg read <channel> -n 10 # Read last N messages
61
+ discli msg edit <ch> <msg-id> "new" # Edit bot message
62
+ discli msg delete <ch> <id> --confirm # Delete message
63
+ discli msg react <ch> <id> 👍 # Add reaction
64
+ discli msg unreact <ch> <id> 👍 # Remove reaction
65
+ discli msg pin <ch> <id> # Pin message
66
+ discli msg unpin <ch> <id> # Unpin message
67
+ discli msg pins <channel> # List pinned messages
68
+ discli msg thread <ch> "Name" # Create thread
69
+ discli msg thread <ch> "Name" --message <id> # Thread from message
70
+
71
+ discli audit log # View recent audit log
72
+ discli audit log -n 50 # Last 50 entries
73
+ discli audit log --type member_kick # Filter by action type
74
+ discli audit log --user <id> # Filter by who performed action
75
+ discli audit types # List action type names
55
76
  ```
56
77
 
57
78
  ## Global Flags