discord-cli-agent 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. discord_cli_agent-0.1.0/LICENSE +21 -0
  2. discord_cli_agent-0.1.0/PKG-INFO +230 -0
  3. discord_cli_agent-0.1.0/README.md +213 -0
  4. discord_cli_agent-0.1.0/pyproject.toml +31 -0
  5. discord_cli_agent-0.1.0/setup.cfg +4 -0
  6. discord_cli_agent-0.1.0/src/discli/__init__.py +1 -0
  7. discord_cli_agent-0.1.0/src/discli/cli.py +41 -0
  8. discord_cli_agent-0.1.0/src/discli/client.py +51 -0
  9. discord_cli_agent-0.1.0/src/discli/commands/__init__.py +0 -0
  10. discord_cli_agent-0.1.0/src/discli/commands/channel.py +104 -0
  11. discord_cli_agent-0.1.0/src/discli/commands/config_cmd.py +36 -0
  12. discord_cli_agent-0.1.0/src/discli/commands/dm.py +79 -0
  13. discord_cli_agent-0.1.0/src/discli/commands/listen.py +191 -0
  14. discord_cli_agent-0.1.0/src/discli/commands/member.py +148 -0
  15. discord_cli_agent-0.1.0/src/discli/commands/message.py +154 -0
  16. discord_cli_agent-0.1.0/src/discli/commands/reaction.py +68 -0
  17. discord_cli_agent-0.1.0/src/discli/commands/role.py +139 -0
  18. discord_cli_agent-0.1.0/src/discli/commands/server.py +55 -0
  19. discord_cli_agent-0.1.0/src/discli/commands/thread.py +104 -0
  20. discord_cli_agent-0.1.0/src/discli/commands/typing_cmd.py +24 -0
  21. discord_cli_agent-0.1.0/src/discli/config.py +17 -0
  22. discord_cli_agent-0.1.0/src/discli/utils.py +53 -0
  23. discord_cli_agent-0.1.0/src/discord_cli_agent.egg-info/PKG-INFO +230 -0
  24. discord_cli_agent-0.1.0/src/discord_cli_agent.egg-info/SOURCES.txt +29 -0
  25. discord_cli_agent-0.1.0/src/discord_cli_agent.egg-info/dependency_links.txt +1 -0
  26. discord_cli_agent-0.1.0/src/discord_cli_agent.egg-info/entry_points.txt +2 -0
  27. discord_cli_agent-0.1.0/src/discord_cli_agent.egg-info/requires.txt +6 -0
  28. discord_cli_agent-0.1.0/src/discord_cli_agent.egg-info/top_level.txt +1 -0
  29. discord_cli_agent-0.1.0/tests/test_client.py +17 -0
  30. discord_cli_agent-0.1.0/tests/test_config.py +17 -0
  31. discord_cli_agent-0.1.0/tests/test_utils.py +20 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 DevRohit06
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,230 @@
1
+ Metadata-Version: 2.4
2
+ Name: discord-cli-agent
3
+ Version: 0.1.0
4
+ Summary: Discord CLI for AI agents
5
+ License-Expression: MIT
6
+ Classifier: Programming Language :: Python :: 3
7
+ Classifier: Operating System :: OS Independent
8
+ Requires-Python: >=3.10
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE
11
+ Requires-Dist: discord.py>=2.3
12
+ Requires-Dist: click>=8.1
13
+ Provides-Extra: dev
14
+ Requires-Dist: pytest>=7.0; extra == "dev"
15
+ Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
16
+ Dynamic: license-file
17
+
18
+ # discli
19
+
20
+ A command-line interface for Discord, built for AI agents and humans. Manage servers, send messages, react, handle DMs, threads, and monitor events — all from the terminal.
21
+
22
+ ## Install
23
+
24
+ ```bash
25
+ pip install discord-cli-agent
26
+ ```
27
+
28
+ For development:
29
+
30
+ ```bash
31
+ pip install -e .
32
+ ```
33
+
34
+ Requires Python 3.10+.
35
+
36
+ ## Setup
37
+
38
+ 1. Create a bot at [Discord Developer Portal](https://discord.com/developers/applications)
39
+ 2. Enable **all privileged intents** (Presence, Server Members, Message Content)
40
+ 3. Add the bot to your server with appropriate permissions
41
+ 4. Configure your token:
42
+
43
+ ```bash
44
+ # Option A: Save to config
45
+ discli config set token YOUR_BOT_TOKEN
46
+
47
+ # Option B: Environment variable
48
+ export DISCORD_BOT_TOKEN=YOUR_BOT_TOKEN
49
+
50
+ # Option C: Pass directly
51
+ discli --token YOUR_BOT_TOKEN server list
52
+ ```
53
+
54
+ ## Usage
55
+
56
+ Every command supports `--json` for machine-readable output.
57
+
58
+ ### Messages
59
+
60
+ ```bash
61
+ discli message send #general "Hello world!"
62
+ discli message send #general "Check this out" --embed-title "News" --embed-desc "Big update"
63
+ discli message list #general --limit 20
64
+ discli message get #general 123456789
65
+ discli message reply #general 123456789 "Thanks for your question!"
66
+ discli message edit #general 123456789 "Updated text"
67
+ discli message delete #general 123456789
68
+ ```
69
+
70
+ ### Direct Messages
71
+
72
+ ```bash
73
+ discli dm send alice "Hey, need help?"
74
+ discli dm send 123456789 "Sent by user ID"
75
+ discli dm list alice --limit 10
76
+ ```
77
+
78
+ ### Reactions
79
+
80
+ ```bash
81
+ discli reaction add #general 123456789 👍
82
+ discli reaction remove #general 123456789 👍
83
+ discli reaction list #general 123456789
84
+ ```
85
+
86
+ ### Channels
87
+
88
+ ```bash
89
+ discli channel list --server "My Server"
90
+ discli channel create "My Server" new-channel --type text
91
+ discli channel create "My Server" voice-room --type voice
92
+ discli channel info #general
93
+ discli channel delete #old-channel
94
+ ```
95
+
96
+ ### Threads
97
+
98
+ ```bash
99
+ discli thread create #general 123456789 "Support Ticket"
100
+ discli thread list #general
101
+ discli thread send 987654321 "Following up on your issue"
102
+ ```
103
+
104
+ ### Servers
105
+
106
+ ```bash
107
+ discli server list
108
+ discli server info "My Server"
109
+ ```
110
+
111
+ ### Roles
112
+
113
+ ```bash
114
+ discli role list "My Server"
115
+ discli role create "My Server" Moderator --color ff0000
116
+ discli role assign "My Server" alice Moderator
117
+ discli role remove "My Server" alice Moderator
118
+ discli role delete "My Server" Moderator
119
+ ```
120
+
121
+ ### Members
122
+
123
+ ```bash
124
+ discli member list "My Server" --limit 100
125
+ discli member info "My Server" alice
126
+ discli member kick "My Server" alice --reason "Spam"
127
+ discli member ban "My Server" alice --reason "Repeated violations"
128
+ discli member unban "My Server" alice
129
+ ```
130
+
131
+ ### Typing Indicator
132
+
133
+ ```bash
134
+ discli typing #general # 5 seconds (default)
135
+ discli typing #general --duration 10 # 10 seconds
136
+ ```
137
+
138
+ ### Live Event Monitoring
139
+
140
+ ```bash
141
+ # Listen to everything
142
+ discli listen
143
+
144
+ # Filter by server/channel
145
+ discli listen --server "My Server" --channel #general
146
+
147
+ # Filter by event type
148
+ discli listen --events messages,reactions
149
+
150
+ # Include bot messages (ignored by default)
151
+ discli listen --include-bots
152
+
153
+ # JSON output for piping to an agent
154
+ discli listen --json --events messages
155
+ ```
156
+
157
+ Supported event types: `messages`, `reactions`, `members`, `edits`, `deletes`
158
+
159
+ ## Resolving Identifiers
160
+
161
+ All commands accept both **IDs** and **names**:
162
+
163
+ | Type | By ID | By Name |
164
+ |------|-------|---------|
165
+ | Channel | `123456789` | `#general` |
166
+ | Server | `123456789` | `My Server` |
167
+ | Member | `123456789` | `alice` |
168
+ | Role | `123456789` | `Moderator` |
169
+ | Thread | `123456789` | `Support Ticket` |
170
+ | User (DM) | `123456789` | `alice` |
171
+
172
+ ## JSON Output
173
+
174
+ Add `--json` to any command for machine-readable output:
175
+
176
+ ```bash
177
+ $ discli message list #general --limit 1 --json
178
+ [
179
+ {
180
+ "id": "123456789",
181
+ "author": "alice",
182
+ "content": "Hello!",
183
+ "timestamp": "2026-03-14T10:32:00+00:00"
184
+ }
185
+ ]
186
+
187
+ $ discli listen --json
188
+ {"event": "message", "server": "My Server", "channel": "general", "channel_id": "111", "author": "alice", "author_id": "222", "content": "hello", "message_id": "333", "mentions_bot": false, "attachments": [], ...}
189
+ ```
190
+
191
+ ## Building an AI Agent
192
+
193
+ A basic agent loop using `discli`:
194
+
195
+ ```bash
196
+ # 1. Listen for messages mentioning the bot
197
+ discli listen --json --events messages | while read -r event; do
198
+ mentions_bot=$(echo "$event" | jq -r '.mentions_bot')
199
+ if [ "$mentions_bot" = "true" ]; then
200
+ channel_id=$(echo "$event" | jq -r '.channel_id')
201
+ message_id=$(echo "$event" | jq -r '.message_id')
202
+ content=$(echo "$event" | jq -r '.content')
203
+
204
+ # 2. Show typing while thinking
205
+ discli typing "$channel_id" --duration 3 &
206
+
207
+ # 3. Generate response (your AI here)
208
+ response="Got your message: $content"
209
+
210
+ # 4. Reply to the message
211
+ discli message reply "$channel_id" "$message_id" "$response"
212
+ fi
213
+ done
214
+ ```
215
+
216
+ ## Configuration
217
+
218
+ Config is stored at `~/.discli/config.json`.
219
+
220
+ ```bash
221
+ discli config set token YOUR_TOKEN
222
+ discli config show
223
+ discli config show --json
224
+ ```
225
+
226
+ Token resolution order: `--token` flag > `DISCORD_BOT_TOKEN` env var > config file.
227
+
228
+ ## License
229
+
230
+ MIT
@@ -0,0 +1,213 @@
1
+ # discli
2
+
3
+ A command-line interface for Discord, built for AI agents and humans. Manage servers, send messages, react, handle DMs, threads, and monitor events — all from the terminal.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pip install discord-cli-agent
9
+ ```
10
+
11
+ For development:
12
+
13
+ ```bash
14
+ pip install -e .
15
+ ```
16
+
17
+ Requires Python 3.10+.
18
+
19
+ ## Setup
20
+
21
+ 1. Create a bot at [Discord Developer Portal](https://discord.com/developers/applications)
22
+ 2. Enable **all privileged intents** (Presence, Server Members, Message Content)
23
+ 3. Add the bot to your server with appropriate permissions
24
+ 4. Configure your token:
25
+
26
+ ```bash
27
+ # Option A: Save to config
28
+ discli config set token YOUR_BOT_TOKEN
29
+
30
+ # Option B: Environment variable
31
+ export DISCORD_BOT_TOKEN=YOUR_BOT_TOKEN
32
+
33
+ # Option C: Pass directly
34
+ discli --token YOUR_BOT_TOKEN server list
35
+ ```
36
+
37
+ ## Usage
38
+
39
+ Every command supports `--json` for machine-readable output.
40
+
41
+ ### Messages
42
+
43
+ ```bash
44
+ discli message send #general "Hello world!"
45
+ discli message send #general "Check this out" --embed-title "News" --embed-desc "Big update"
46
+ discli message list #general --limit 20
47
+ discli message get #general 123456789
48
+ discli message reply #general 123456789 "Thanks for your question!"
49
+ discli message edit #general 123456789 "Updated text"
50
+ discli message delete #general 123456789
51
+ ```
52
+
53
+ ### Direct Messages
54
+
55
+ ```bash
56
+ discli dm send alice "Hey, need help?"
57
+ discli dm send 123456789 "Sent by user ID"
58
+ discli dm list alice --limit 10
59
+ ```
60
+
61
+ ### Reactions
62
+
63
+ ```bash
64
+ discli reaction add #general 123456789 👍
65
+ discli reaction remove #general 123456789 👍
66
+ discli reaction list #general 123456789
67
+ ```
68
+
69
+ ### Channels
70
+
71
+ ```bash
72
+ discli channel list --server "My Server"
73
+ discli channel create "My Server" new-channel --type text
74
+ discli channel create "My Server" voice-room --type voice
75
+ discli channel info #general
76
+ discli channel delete #old-channel
77
+ ```
78
+
79
+ ### Threads
80
+
81
+ ```bash
82
+ discli thread create #general 123456789 "Support Ticket"
83
+ discli thread list #general
84
+ discli thread send 987654321 "Following up on your issue"
85
+ ```
86
+
87
+ ### Servers
88
+
89
+ ```bash
90
+ discli server list
91
+ discli server info "My Server"
92
+ ```
93
+
94
+ ### Roles
95
+
96
+ ```bash
97
+ discli role list "My Server"
98
+ discli role create "My Server" Moderator --color ff0000
99
+ discli role assign "My Server" alice Moderator
100
+ discli role remove "My Server" alice Moderator
101
+ discli role delete "My Server" Moderator
102
+ ```
103
+
104
+ ### Members
105
+
106
+ ```bash
107
+ discli member list "My Server" --limit 100
108
+ discli member info "My Server" alice
109
+ discli member kick "My Server" alice --reason "Spam"
110
+ discli member ban "My Server" alice --reason "Repeated violations"
111
+ discli member unban "My Server" alice
112
+ ```
113
+
114
+ ### Typing Indicator
115
+
116
+ ```bash
117
+ discli typing #general # 5 seconds (default)
118
+ discli typing #general --duration 10 # 10 seconds
119
+ ```
120
+
121
+ ### Live Event Monitoring
122
+
123
+ ```bash
124
+ # Listen to everything
125
+ discli listen
126
+
127
+ # Filter by server/channel
128
+ discli listen --server "My Server" --channel #general
129
+
130
+ # Filter by event type
131
+ discli listen --events messages,reactions
132
+
133
+ # Include bot messages (ignored by default)
134
+ discli listen --include-bots
135
+
136
+ # JSON output for piping to an agent
137
+ discli listen --json --events messages
138
+ ```
139
+
140
+ Supported event types: `messages`, `reactions`, `members`, `edits`, `deletes`
141
+
142
+ ## Resolving Identifiers
143
+
144
+ All commands accept both **IDs** and **names**:
145
+
146
+ | Type | By ID | By Name |
147
+ |------|-------|---------|
148
+ | Channel | `123456789` | `#general` |
149
+ | Server | `123456789` | `My Server` |
150
+ | Member | `123456789` | `alice` |
151
+ | Role | `123456789` | `Moderator` |
152
+ | Thread | `123456789` | `Support Ticket` |
153
+ | User (DM) | `123456789` | `alice` |
154
+
155
+ ## JSON Output
156
+
157
+ Add `--json` to any command for machine-readable output:
158
+
159
+ ```bash
160
+ $ discli message list #general --limit 1 --json
161
+ [
162
+ {
163
+ "id": "123456789",
164
+ "author": "alice",
165
+ "content": "Hello!",
166
+ "timestamp": "2026-03-14T10:32:00+00:00"
167
+ }
168
+ ]
169
+
170
+ $ discli listen --json
171
+ {"event": "message", "server": "My Server", "channel": "general", "channel_id": "111", "author": "alice", "author_id": "222", "content": "hello", "message_id": "333", "mentions_bot": false, "attachments": [], ...}
172
+ ```
173
+
174
+ ## Building an AI Agent
175
+
176
+ A basic agent loop using `discli`:
177
+
178
+ ```bash
179
+ # 1. Listen for messages mentioning the bot
180
+ discli listen --json --events messages | while read -r event; do
181
+ mentions_bot=$(echo "$event" | jq -r '.mentions_bot')
182
+ if [ "$mentions_bot" = "true" ]; then
183
+ channel_id=$(echo "$event" | jq -r '.channel_id')
184
+ message_id=$(echo "$event" | jq -r '.message_id')
185
+ content=$(echo "$event" | jq -r '.content')
186
+
187
+ # 2. Show typing while thinking
188
+ discli typing "$channel_id" --duration 3 &
189
+
190
+ # 3. Generate response (your AI here)
191
+ response="Got your message: $content"
192
+
193
+ # 4. Reply to the message
194
+ discli message reply "$channel_id" "$message_id" "$response"
195
+ fi
196
+ done
197
+ ```
198
+
199
+ ## Configuration
200
+
201
+ Config is stored at `~/.discli/config.json`.
202
+
203
+ ```bash
204
+ discli config set token YOUR_TOKEN
205
+ discli config show
206
+ discli config show --json
207
+ ```
208
+
209
+ Token resolution order: `--token` flag > `DISCORD_BOT_TOKEN` env var > config file.
210
+
211
+ ## License
212
+
213
+ MIT
@@ -0,0 +1,31 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "discord-cli-agent"
7
+ version = "0.1.0"
8
+ description = "Discord CLI for AI agents"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.10"
12
+ classifiers = [
13
+ "Programming Language :: Python :: 3",
14
+ "Operating System :: OS Independent",
15
+ ]
16
+ dependencies = [
17
+ "discord.py>=2.3",
18
+ "click>=8.1",
19
+ ]
20
+
21
+ [project.scripts]
22
+ discli = "discli.cli:main"
23
+
24
+ [tool.setuptools.packages.find]
25
+ where = ["src"]
26
+
27
+ [project.optional-dependencies]
28
+ dev = [
29
+ "pytest>=7.0",
30
+ "pytest-asyncio>=0.21",
31
+ ]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1 @@
1
+ """discli — Discord CLI for AI agents."""
@@ -0,0 +1,41 @@
1
+ import click
2
+
3
+ from discli.config import load_config
4
+ from discli.commands.channel import channel_group
5
+ from discli.commands.config_cmd import config_group
6
+ from discli.commands.dm import dm_group
7
+ from discli.commands.listen import listen_cmd
8
+ from discli.commands.member import member_group
9
+ from discli.commands.message import message_group
10
+ from discli.commands.reaction import reaction_group
11
+ from discli.commands.role import role_group
12
+ from discli.commands.server import server_group
13
+ from discli.commands.thread import thread_group
14
+ from discli.commands.typing_cmd import typing_cmd
15
+
16
+
17
+ @click.group()
18
+ @click.option("--token", envvar="DISCORD_BOT_TOKEN", default=None, help="Discord bot token.")
19
+ @click.option("--json", "use_json", is_flag=True, default=False, help="Output as JSON.")
20
+ @click.pass_context
21
+ def main(ctx, token, use_json):
22
+ """discli — Discord CLI for AI agents."""
23
+ ctx.ensure_object(dict)
24
+ if token is None:
25
+ config = load_config()
26
+ token = config.get("token")
27
+ ctx.obj["token"] = token
28
+ ctx.obj["use_json"] = use_json
29
+
30
+
31
+ main.add_command(channel_group)
32
+ main.add_command(config_group)
33
+ main.add_command(dm_group)
34
+ main.add_command(listen_cmd)
35
+ main.add_command(member_group)
36
+ main.add_command(message_group)
37
+ main.add_command(reaction_group)
38
+ main.add_command(role_group)
39
+ main.add_command(server_group)
40
+ main.add_command(thread_group)
41
+ main.add_command(typing_cmd)
@@ -0,0 +1,51 @@
1
+ import asyncio
2
+ from typing import Any, Callable, Coroutine
3
+
4
+ import click
5
+ import discord
6
+
7
+
8
+ def resolve_token(token: str | None, config: dict) -> str:
9
+ if token:
10
+ return token
11
+ config_token = config.get("token")
12
+ if config_token:
13
+ return config_token
14
+ raise click.ClickException(
15
+ "No token provided. Use --token, set DISCORD_BOT_TOKEN, or run: discli config set token YOUR_TOKEN"
16
+ )
17
+
18
+
19
+ async def run_action(token: str, action: Callable[[discord.Client], Coroutine[Any, Any, Any]]) -> Any:
20
+ """Connect a bot client, run an action on_ready, return the result, disconnect."""
21
+ intents = discord.Intents.all()
22
+ client = discord.Client(intents=intents)
23
+ result = None
24
+ error = None
25
+
26
+ @client.event
27
+ async def on_ready():
28
+ nonlocal result, error
29
+ try:
30
+ result = await action(client)
31
+ except Exception as e:
32
+ error = e
33
+ finally:
34
+ await client.close()
35
+
36
+ await client.start(token)
37
+
38
+ if error:
39
+ raise error
40
+ return result
41
+
42
+
43
+ def run_discord(ctx, action: Callable[[discord.Client], Coroutine[Any, Any, Any]]) -> Any:
44
+ """Synchronous entry point: resolve token, run action, return result."""
45
+ token = resolve_token(ctx.obj.get("token"), {})
46
+ try:
47
+ return asyncio.run(run_action(token, action))
48
+ except discord.LoginFailure:
49
+ raise click.ClickException("Invalid bot token.")
50
+ except discord.HTTPException as e:
51
+ raise click.ClickException(f"Discord API error: {e}")
@@ -0,0 +1,104 @@
1
+ import click
2
+ import discord
3
+
4
+ from discli.client import run_discord
5
+ from discli.utils import output, resolve_channel, resolve_guild
6
+
7
+
8
+ @click.group("channel")
9
+ def channel_group():
10
+ """List, create, delete, and inspect channels."""
11
+
12
+
13
+ @channel_group.command("list")
14
+ @click.option("--server", default=None, help="Server name or ID.")
15
+ @click.pass_context
16
+ def channel_list(ctx, server):
17
+ """List channels in a server."""
18
+
19
+ def action(client):
20
+ async def _action(client):
21
+ if server:
22
+ guilds = [resolve_guild(client, server)]
23
+ else:
24
+ guilds = client.guilds
25
+ channels = []
26
+ for g in guilds:
27
+ for ch in g.channels:
28
+ if isinstance(ch, (discord.TextChannel, discord.VoiceChannel)):
29
+ channels.append({
30
+ "id": str(ch.id),
31
+ "name": ch.name,
32
+ "type": str(ch.type),
33
+ "server": g.name,
34
+ })
35
+ plain_lines = [f"#{c['name']} ({c['type']}) — {c['server']} (ID: {c['id']})" for c in channels]
36
+ output(ctx, channels, plain_text="\n".join(plain_lines) if plain_lines else "No channels found.")
37
+ return _action(client)
38
+
39
+ run_discord(ctx, action)
40
+
41
+
42
+ @channel_group.command("create")
43
+ @click.argument("server")
44
+ @click.argument("name")
45
+ @click.option("--type", "channel_type", type=click.Choice(["text", "voice", "category"]), default="text")
46
+ @click.pass_context
47
+ def channel_create(ctx, server, name, channel_type):
48
+ """Create a channel in a server."""
49
+
50
+ def action(client):
51
+ async def _action(client):
52
+ guild = resolve_guild(client, server)
53
+ if channel_type == "text":
54
+ ch = await guild.create_text_channel(name)
55
+ elif channel_type == "voice":
56
+ ch = await guild.create_voice_channel(name)
57
+ else:
58
+ ch = await guild.create_category(name)
59
+ data = {"id": str(ch.id), "name": ch.name, "type": str(ch.type)}
60
+ output(ctx, data, plain_text=f"Created #{ch.name} (ID: {ch.id})")
61
+ return _action(client)
62
+
63
+ run_discord(ctx, action)
64
+
65
+
66
+ @channel_group.command("delete")
67
+ @click.argument("channel")
68
+ @click.pass_context
69
+ def channel_delete(ctx, channel):
70
+ """Delete a channel."""
71
+
72
+ def action(client):
73
+ async def _action(client):
74
+ ch = resolve_channel(client, channel)
75
+ name = ch.name
76
+ await ch.delete()
77
+ output(ctx, {"id": str(ch.id), "deleted": True}, plain_text=f"Deleted #{name}")
78
+ return _action(client)
79
+
80
+ run_discord(ctx, action)
81
+
82
+
83
+ @channel_group.command("info")
84
+ @click.argument("channel")
85
+ @click.pass_context
86
+ def channel_info(ctx, channel):
87
+ """Show channel details."""
88
+
89
+ def action(client):
90
+ async def _action(client):
91
+ ch = resolve_channel(client, channel)
92
+ data = {
93
+ "id": str(ch.id),
94
+ "name": ch.name,
95
+ "type": str(ch.type),
96
+ "server": ch.guild.name,
97
+ "topic": getattr(ch, "topic", None),
98
+ "created_at": ch.created_at.isoformat(),
99
+ }
100
+ plain_lines = [f"{k}: {v}" for k, v in data.items() if v is not None]
101
+ output(ctx, data, plain_text="\n".join(plain_lines))
102
+ return _action(client)
103
+
104
+ run_discord(ctx, action)