manikineko 0.2.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.
@@ -0,0 +1,263 @@
1
+ Metadata-Version: 2.4
2
+ Name: manikineko
3
+ Version: 0.2.0
4
+ Summary: Official SDK for Manikineko — Discord-compatible REST, realtime gateway, OAuth2 and app-controlled gateway servers.
5
+ Author: Manikineko
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://manikineko.nl
8
+ Keywords: manikineko,chat,bot,discord-compatible,oauth2
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Topic :: Communications :: Chat
13
+ Requires-Python: >=3.9
14
+ Description-Content-Type: text/markdown
15
+ Provides-Extra: gateway
16
+ Requires-Dist: websockets>=12; extra == "gateway"
17
+ Provides-Extra: all
18
+ Requires-Dist: websockets>=12; extra == "all"
19
+
20
+ # manikineko (Python SDK)
21
+
22
+ Official SDK for the [Manikineko](https://manikineko.nl) platform.
23
+ Python >= 3.9. REST + OAuth2 helpers are stdlib-only; the realtime gateway
24
+ needs the `websockets` package.
25
+
26
+ ```bash
27
+ pip install manikineko # REST + OAuth only
28
+ pip install "manikineko[gateway]" # + realtime gateway (websockets)
29
+ ```
30
+
31
+ ## Bot quickstart
32
+
33
+ ```python
34
+ from manikineko import Client
35
+
36
+ client = Client(
37
+ base_url="https://api.manikineko.nl", # your instance's API host
38
+ token="BOT_TOKEN", # from the developer portal
39
+ token_type="bot",
40
+ )
41
+
42
+ @client.event
43
+ async def on_ready(ready):
44
+ print(f"Logged in as {ready['user']['username']}")
45
+
46
+ @client.event
47
+ async def on_message_create(msg):
48
+ if msg.get("author", {}).get("bot"):
49
+ return
50
+ if msg.get("content") == "!ping":
51
+ client.say(msg["channel_id"], "pong")
52
+
53
+ client.run() # connects the gateway, blocks forever
54
+ ```
55
+
56
+ The SDK speaks the Discord-compatible API (`/api/v10`): snowflake IDs,
57
+ integer channel types, Discord-shaped events — so discord.py-style code
58
+ ports over easily. REST methods are synchronous; event handlers may be
59
+ sync or async.
60
+
61
+ ## What's covered
62
+
63
+ - **REST** — users, guilds, channels, messages, reactions, pins, typing,
64
+ members, bans, roles, invites, audit logs, DMs, reports, HTML channels.
65
+ - **Gateway** — `client.run()`, heartbeats, reconnects, `@client.event`,
66
+ `gateway.request_members()`, `client.set_presence()`.
67
+ - **Voice / VC** — join/leave calls in *any* channel type (incl. DMs),
68
+ voice states, mute/deafen/move moderation, LiveKit credentials or mesh
69
+ WebRTC signalling, `VOICE_STATE_UPDATE` events.
70
+ - **PSTN dialer** — `client.dialer()` places real phone calls into voice
71
+ channels when the instance has SIP/VoIP configured.
72
+ - **Custom emotes** — platform + guild emote listing/CRUD, usable-set
73
+ endpoint, `Client.emoji_tag()` helper for `<:name:id>` content.
74
+ - **Entitlements** — marketplace app integrations: who owns your app.
75
+ - **Urgent popups** — fetch/acknowledge forced system-bot notices.
76
+ - **Uploads** — `send_message(channel, files=[...])` or `upload_file()`.
77
+ - **OAuth2** — `OAuth2Client`: authorize URLs, PKCE, code exchange, refresh,
78
+ client_credentials, revocation, `@me`.
79
+ - **App push API** — `app_servers()`, `app_create_channel()`,
80
+ `app_send_message()`, `app_dispatch_event()` for app-controlled gateway
81
+ servers; guild link config via `set_guild_gateway()`.
82
+ - **Lexicons** — `list_lexicons()`, `put_lexicon()`, `delete_lexicon()`.
83
+ - **Webhooks** — `verify_gateway_signature()` verifies
84
+ `X-Manikineko-Signature` headers on app-gateway deliveries.
85
+ - **Admin** — `client.admin` namespace (staff JWT): system bots, VoIP
86
+ trunks/numbers/credits, maintenance purges, urgent popups.
87
+
88
+ ## Voice / calls
89
+
90
+ Every channel type can host a call — including DM and group DM channels
91
+ (recipient-only). Voice state changes arrive as `VOICE_STATE_UPDATE`.
92
+
93
+ ```python
94
+ cfg = client.get_voice_config() # {"provider": ..., "voip": bool}
95
+
96
+ # Join a call (any channel). When LiveKit is the media backend the
97
+ # response carries a "livekit" dict {"url", "token"} for a LiveKit SDK.
98
+ state = client.join_voice_channel(channel_id, self_mute=True)
99
+
100
+ client.update_voice_state(self_mute=False)
101
+ participants = client.get_voice_states(channel_id)
102
+ client.leave_voice_channel()
103
+
104
+ # Moderation (server channels only):
105
+ client.voice_mute_member(channel_id, user_id, True)
106
+ client.voice_disconnect_member(channel_id, user_id)
107
+ client.voice_move_member(other_channel_id, user_id)
108
+ ```
109
+
110
+ ### PSTN dialer (SIP)
111
+
112
+ When the instance has telephony configured (`VOIP_ENABLED` + SIP trunks),
113
+ bots and users can dial real phone numbers into a voice channel. Outbound
114
+ calls are metered in call credits (HTTP 402 = top up via the shop).
115
+
116
+ ```python
117
+ dialer = client.dialer()
118
+ if dialer.available():
119
+ print("credits:", dialer.credits())
120
+
121
+ # auto-joins the voice channel, then dials:
122
+ call = dialer.dial(channel_id, "+15551234567")
123
+ print(call.id, call.status) # ringing
124
+
125
+ call.wait_for_connect() # status == "active"
126
+ # ... the phone party is now in the voice room ...
127
+ call.hangup() # or call.wait_for_end()
128
+ ```
129
+
130
+ Lower-level primitives are on the client too: `dial_phone()`,
131
+ `get_call()`, `get_channel_calls()`, `hangup_call()`, `get_call_credits()`,
132
+ `get_call_credit_history()`. Inbound calls to an instance DID ring into
133
+ the linked voice channel.
134
+
135
+ ## Custom emotes
136
+
137
+ ```python
138
+ emojis = client.get_guild_emojis(guild_id)
139
+ client.create_guild_emoji(guild_id, "nyaa", "https://cdn…/nyaa.png")
140
+
141
+ # in message content: ":nyaa:" resolves by name, or use a tag by ID:
142
+ client.say(channel_id, f"hello {Client.emoji_tag(emojis[0])}")
143
+
144
+ usable = client.get_usable_emojis() # picker payload
145
+ ```
146
+
147
+ Server emotes outside their home guild need premium; violations return 403.
148
+
149
+ ## Entitlements (marketplace app integrations)
150
+
151
+ ```python
152
+ # As a user:
153
+ owned = client.get_my_entitlements()
154
+
155
+ # As an app (bot token or client_credentials + applications.gateway):
156
+ all_owners = app_client.app_entitlements()
157
+ check = app_client.app_check_entitlement(user_id) # {"entitled": True}
158
+ ```
159
+
160
+ ## Urgent popups
161
+
162
+ System bots can push forced popups (`type="urgent"`, or admin urgent
163
+ messages). Users see them on `URGENT_MESSAGE` gateway events and via
164
+ `GET /urgent/pending`:
165
+
166
+ ```python
167
+ @client.on("URGENT_MESSAGE")
168
+ def on_urgent(u):
169
+ print("URGENT:", u["title"], u["body"])
170
+
171
+ pending = client.get_pending_urgent_messages()
172
+ client.acknowledge_urgent(pending[0]["id"]) # dismiss
173
+ ```
174
+
175
+ ## Admin API
176
+
177
+ `client.admin` targets `/api/v1/admin/*` and needs a staff JWT
178
+ (`token_type="bearer"`). IDs on this surface are native UUIDs.
179
+
180
+ ```python
181
+ admin = client.admin
182
+
183
+ admin.system_bots.send_message(
184
+ bot_id, user_ids=[uid1, uid2],
185
+ content="scheduled maintenance tonight",
186
+ type="urgent", severity="warning", title="Heads up",
187
+ )
188
+
189
+ admin.voip.create_trunk(name="twilio", carrier="twilio-byoc",
190
+ host="…sip.twilio.com", prefixes=["+1"],
191
+ rate_credits=2)
192
+ admin.voip.adjust_credits(user_id=uid, amount=100, note="promo")
193
+
194
+ admin.maintenance.purge_stale_reports()
195
+ admin.urgent.create(title="v2 launched", body="…", scope="global")
196
+ ```
197
+
198
+ ## Auth
199
+
200
+ | Token kind | `token_type` | Notes |
201
+ | --- | --- | --- |
202
+ | Bot token | `"bot"` (default) | `Authorization: Bot <token>` |
203
+ | OAuth2 access token | `"bearer"` | Scoped — see `Scope` constants |
204
+ | User JWT | `"bearer"` | First-party session token |
205
+
206
+ ## OAuth2 ("Login with Manikineko")
207
+
208
+ ```python
209
+ from manikineko import OAuth2Client, generate_pkce
210
+
211
+ oauth = OAuth2Client(
212
+ base_url="https://api.manikineko.nl",
213
+ client_id="YOUR_CLIENT_ID",
214
+ client_secret="YOUR_CLIENT_SECRET",
215
+ redirect_uri="https://myapp.example/callback",
216
+ )
217
+
218
+ verifier, challenge = generate_pkce()
219
+ url = oauth.authorize_url(["identify", "email"], state=state, code_challenge=challenge)
220
+
221
+ # In your callback handler:
222
+ tokens = oauth.exchange_code(code, code_verifier=verifier)
223
+ me = oauth.user(tokens["access_token"]) # GET /users/@me
224
+ later = oauth.refresh_token(tokens["refresh_token"])
225
+ oauth.revoke(tokens["access_token"])
226
+ ```
227
+
228
+ `client_credentials` tokens (e.g. `scope="applications.gateway"`) call the
229
+ app push API:
230
+
231
+ ```python
232
+ tok = oauth.client_credentials("applications.gateway")
233
+ app = Client(base_url, token=tok["access_token"], token_type="bearer")
234
+ for server in app.app_servers():
235
+ app.app_send_message(server["id"], channel_id, "hello from my app")
236
+ app.app_dispatch_event(server["id"], "score_update", data={"score": 42})
237
+ ```
238
+
239
+ ## Gateway events
240
+
241
+ Dispatch names mirror Discord: `READY`, `MESSAGE_CREATE`, `MESSAGE_UPDATE`,
242
+ `MESSAGE_DELETE`, `CHANNEL_*`, `GUILD_*`, `GUILD_MEMBER_*`, `GUILD_ROLE_*`,
243
+ `GUILD_BAN_*`, `MESSAGE_REACTION_*`, `PRESENCE_UPDATE`, `TYPING_START`,
244
+ `INVITE_*`, `VOICE_STATE_UPDATE`. Manikineko extras: `APP_EVENT`,
245
+ `URGENT_MESSAGE`, `WARNING_RECEIVED`, `USER_SUSPENDED`, `USER_BANNED`.
246
+
247
+ ```python
248
+ @client.on("*")
249
+ def log_all(payload):
250
+ print(payload["event"], payload["data"])
251
+ ```
252
+
253
+ ## Escape hatches
254
+
255
+ ```python
256
+ client.request("GET", "/channels/123/messages") # compat API
257
+ client.api("GET", "/themes") # native /api/v1
258
+ ```
259
+
260
+ ## Errors
261
+
262
+ `APIError` (`.status`, `.code`, `.body`), `OAuthError` (`.error`,
263
+ `.error_description`), `InvalidSessionError` on bad gateway tokens.
@@ -0,0 +1,244 @@
1
+ # manikineko (Python SDK)
2
+
3
+ Official SDK for the [Manikineko](https://manikineko.nl) platform.
4
+ Python >= 3.9. REST + OAuth2 helpers are stdlib-only; the realtime gateway
5
+ needs the `websockets` package.
6
+
7
+ ```bash
8
+ pip install manikineko # REST + OAuth only
9
+ pip install "manikineko[gateway]" # + realtime gateway (websockets)
10
+ ```
11
+
12
+ ## Bot quickstart
13
+
14
+ ```python
15
+ from manikineko import Client
16
+
17
+ client = Client(
18
+ base_url="https://api.manikineko.nl", # your instance's API host
19
+ token="BOT_TOKEN", # from the developer portal
20
+ token_type="bot",
21
+ )
22
+
23
+ @client.event
24
+ async def on_ready(ready):
25
+ print(f"Logged in as {ready['user']['username']}")
26
+
27
+ @client.event
28
+ async def on_message_create(msg):
29
+ if msg.get("author", {}).get("bot"):
30
+ return
31
+ if msg.get("content") == "!ping":
32
+ client.say(msg["channel_id"], "pong")
33
+
34
+ client.run() # connects the gateway, blocks forever
35
+ ```
36
+
37
+ The SDK speaks the Discord-compatible API (`/api/v10`): snowflake IDs,
38
+ integer channel types, Discord-shaped events — so discord.py-style code
39
+ ports over easily. REST methods are synchronous; event handlers may be
40
+ sync or async.
41
+
42
+ ## What's covered
43
+
44
+ - **REST** — users, guilds, channels, messages, reactions, pins, typing,
45
+ members, bans, roles, invites, audit logs, DMs, reports, HTML channels.
46
+ - **Gateway** — `client.run()`, heartbeats, reconnects, `@client.event`,
47
+ `gateway.request_members()`, `client.set_presence()`.
48
+ - **Voice / VC** — join/leave calls in *any* channel type (incl. DMs),
49
+ voice states, mute/deafen/move moderation, LiveKit credentials or mesh
50
+ WebRTC signalling, `VOICE_STATE_UPDATE` events.
51
+ - **PSTN dialer** — `client.dialer()` places real phone calls into voice
52
+ channels when the instance has SIP/VoIP configured.
53
+ - **Custom emotes** — platform + guild emote listing/CRUD, usable-set
54
+ endpoint, `Client.emoji_tag()` helper for `<:name:id>` content.
55
+ - **Entitlements** — marketplace app integrations: who owns your app.
56
+ - **Urgent popups** — fetch/acknowledge forced system-bot notices.
57
+ - **Uploads** — `send_message(channel, files=[...])` or `upload_file()`.
58
+ - **OAuth2** — `OAuth2Client`: authorize URLs, PKCE, code exchange, refresh,
59
+ client_credentials, revocation, `@me`.
60
+ - **App push API** — `app_servers()`, `app_create_channel()`,
61
+ `app_send_message()`, `app_dispatch_event()` for app-controlled gateway
62
+ servers; guild link config via `set_guild_gateway()`.
63
+ - **Lexicons** — `list_lexicons()`, `put_lexicon()`, `delete_lexicon()`.
64
+ - **Webhooks** — `verify_gateway_signature()` verifies
65
+ `X-Manikineko-Signature` headers on app-gateway deliveries.
66
+ - **Admin** — `client.admin` namespace (staff JWT): system bots, VoIP
67
+ trunks/numbers/credits, maintenance purges, urgent popups.
68
+
69
+ ## Voice / calls
70
+
71
+ Every channel type can host a call — including DM and group DM channels
72
+ (recipient-only). Voice state changes arrive as `VOICE_STATE_UPDATE`.
73
+
74
+ ```python
75
+ cfg = client.get_voice_config() # {"provider": ..., "voip": bool}
76
+
77
+ # Join a call (any channel). When LiveKit is the media backend the
78
+ # response carries a "livekit" dict {"url", "token"} for a LiveKit SDK.
79
+ state = client.join_voice_channel(channel_id, self_mute=True)
80
+
81
+ client.update_voice_state(self_mute=False)
82
+ participants = client.get_voice_states(channel_id)
83
+ client.leave_voice_channel()
84
+
85
+ # Moderation (server channels only):
86
+ client.voice_mute_member(channel_id, user_id, True)
87
+ client.voice_disconnect_member(channel_id, user_id)
88
+ client.voice_move_member(other_channel_id, user_id)
89
+ ```
90
+
91
+ ### PSTN dialer (SIP)
92
+
93
+ When the instance has telephony configured (`VOIP_ENABLED` + SIP trunks),
94
+ bots and users can dial real phone numbers into a voice channel. Outbound
95
+ calls are metered in call credits (HTTP 402 = top up via the shop).
96
+
97
+ ```python
98
+ dialer = client.dialer()
99
+ if dialer.available():
100
+ print("credits:", dialer.credits())
101
+
102
+ # auto-joins the voice channel, then dials:
103
+ call = dialer.dial(channel_id, "+15551234567")
104
+ print(call.id, call.status) # ringing
105
+
106
+ call.wait_for_connect() # status == "active"
107
+ # ... the phone party is now in the voice room ...
108
+ call.hangup() # or call.wait_for_end()
109
+ ```
110
+
111
+ Lower-level primitives are on the client too: `dial_phone()`,
112
+ `get_call()`, `get_channel_calls()`, `hangup_call()`, `get_call_credits()`,
113
+ `get_call_credit_history()`. Inbound calls to an instance DID ring into
114
+ the linked voice channel.
115
+
116
+ ## Custom emotes
117
+
118
+ ```python
119
+ emojis = client.get_guild_emojis(guild_id)
120
+ client.create_guild_emoji(guild_id, "nyaa", "https://cdn…/nyaa.png")
121
+
122
+ # in message content: ":nyaa:" resolves by name, or use a tag by ID:
123
+ client.say(channel_id, f"hello {Client.emoji_tag(emojis[0])}")
124
+
125
+ usable = client.get_usable_emojis() # picker payload
126
+ ```
127
+
128
+ Server emotes outside their home guild need premium; violations return 403.
129
+
130
+ ## Entitlements (marketplace app integrations)
131
+
132
+ ```python
133
+ # As a user:
134
+ owned = client.get_my_entitlements()
135
+
136
+ # As an app (bot token or client_credentials + applications.gateway):
137
+ all_owners = app_client.app_entitlements()
138
+ check = app_client.app_check_entitlement(user_id) # {"entitled": True}
139
+ ```
140
+
141
+ ## Urgent popups
142
+
143
+ System bots can push forced popups (`type="urgent"`, or admin urgent
144
+ messages). Users see them on `URGENT_MESSAGE` gateway events and via
145
+ `GET /urgent/pending`:
146
+
147
+ ```python
148
+ @client.on("URGENT_MESSAGE")
149
+ def on_urgent(u):
150
+ print("URGENT:", u["title"], u["body"])
151
+
152
+ pending = client.get_pending_urgent_messages()
153
+ client.acknowledge_urgent(pending[0]["id"]) # dismiss
154
+ ```
155
+
156
+ ## Admin API
157
+
158
+ `client.admin` targets `/api/v1/admin/*` and needs a staff JWT
159
+ (`token_type="bearer"`). IDs on this surface are native UUIDs.
160
+
161
+ ```python
162
+ admin = client.admin
163
+
164
+ admin.system_bots.send_message(
165
+ bot_id, user_ids=[uid1, uid2],
166
+ content="scheduled maintenance tonight",
167
+ type="urgent", severity="warning", title="Heads up",
168
+ )
169
+
170
+ admin.voip.create_trunk(name="twilio", carrier="twilio-byoc",
171
+ host="…sip.twilio.com", prefixes=["+1"],
172
+ rate_credits=2)
173
+ admin.voip.adjust_credits(user_id=uid, amount=100, note="promo")
174
+
175
+ admin.maintenance.purge_stale_reports()
176
+ admin.urgent.create(title="v2 launched", body="…", scope="global")
177
+ ```
178
+
179
+ ## Auth
180
+
181
+ | Token kind | `token_type` | Notes |
182
+ | --- | --- | --- |
183
+ | Bot token | `"bot"` (default) | `Authorization: Bot <token>` |
184
+ | OAuth2 access token | `"bearer"` | Scoped — see `Scope` constants |
185
+ | User JWT | `"bearer"` | First-party session token |
186
+
187
+ ## OAuth2 ("Login with Manikineko")
188
+
189
+ ```python
190
+ from manikineko import OAuth2Client, generate_pkce
191
+
192
+ oauth = OAuth2Client(
193
+ base_url="https://api.manikineko.nl",
194
+ client_id="YOUR_CLIENT_ID",
195
+ client_secret="YOUR_CLIENT_SECRET",
196
+ redirect_uri="https://myapp.example/callback",
197
+ )
198
+
199
+ verifier, challenge = generate_pkce()
200
+ url = oauth.authorize_url(["identify", "email"], state=state, code_challenge=challenge)
201
+
202
+ # In your callback handler:
203
+ tokens = oauth.exchange_code(code, code_verifier=verifier)
204
+ me = oauth.user(tokens["access_token"]) # GET /users/@me
205
+ later = oauth.refresh_token(tokens["refresh_token"])
206
+ oauth.revoke(tokens["access_token"])
207
+ ```
208
+
209
+ `client_credentials` tokens (e.g. `scope="applications.gateway"`) call the
210
+ app push API:
211
+
212
+ ```python
213
+ tok = oauth.client_credentials("applications.gateway")
214
+ app = Client(base_url, token=tok["access_token"], token_type="bearer")
215
+ for server in app.app_servers():
216
+ app.app_send_message(server["id"], channel_id, "hello from my app")
217
+ app.app_dispatch_event(server["id"], "score_update", data={"score": 42})
218
+ ```
219
+
220
+ ## Gateway events
221
+
222
+ Dispatch names mirror Discord: `READY`, `MESSAGE_CREATE`, `MESSAGE_UPDATE`,
223
+ `MESSAGE_DELETE`, `CHANNEL_*`, `GUILD_*`, `GUILD_MEMBER_*`, `GUILD_ROLE_*`,
224
+ `GUILD_BAN_*`, `MESSAGE_REACTION_*`, `PRESENCE_UPDATE`, `TYPING_START`,
225
+ `INVITE_*`, `VOICE_STATE_UPDATE`. Manikineko extras: `APP_EVENT`,
226
+ `URGENT_MESSAGE`, `WARNING_RECEIVED`, `USER_SUSPENDED`, `USER_BANNED`.
227
+
228
+ ```python
229
+ @client.on("*")
230
+ def log_all(payload):
231
+ print(payload["event"], payload["data"])
232
+ ```
233
+
234
+ ## Escape hatches
235
+
236
+ ```python
237
+ client.request("GET", "/channels/123/messages") # compat API
238
+ client.api("GET", "/themes") # native /api/v1
239
+ ```
240
+
241
+ ## Errors
242
+
243
+ `APIError` (`.status`, `.code`, `.body`), `OAuthError` (`.error`,
244
+ `.error_description`), `InvalidSessionError` on bad gateway tokens.
@@ -0,0 +1,89 @@
1
+ """Official Python SDK for the Manikineko platform.
2
+
3
+ Quickstart::
4
+
5
+ from manikineko import Client
6
+
7
+ client = Client(
8
+ base_url="https://api.manikineko.nl",
9
+ token="BOT_TOKEN",
10
+ token_type="bot",
11
+ )
12
+
13
+ @client.event
14
+ async def on_message_create(msg):
15
+ if msg.get("author", {}).get("bot"):
16
+ return
17
+ if msg.get("content") == "!ping":
18
+ client.say(msg["channel_id"], "pong")
19
+
20
+ client.run()
21
+ """
22
+
23
+ from .admin import AdminAPI
24
+ from .client import Client
25
+ from .dialer import Dialer, PhoneCall
26
+ from .errors import (
27
+ APIError,
28
+ InvalidSessionError,
29
+ ManikinekoError,
30
+ OAuthError,
31
+ )
32
+ from .gateway import Gateway
33
+ from .oauth import OAuth2Client, generate_pkce, verify_gateway_signature
34
+ from .types import (
35
+ ApplicationCommandOptionType,
36
+ ApplicationCommandType,
37
+ AutoModAction,
38
+ AutoModTrigger,
39
+ Capability,
40
+ ChannelType,
41
+ GatewayEvent,
42
+ GatewayOp,
43
+ InteractionCallbackType,
44
+ InteractionContextType,
45
+ InteractionType,
46
+ MessageFlags,
47
+ MessageType,
48
+ PrivilegeStatus,
49
+ RPCCommand,
50
+ RPCStatus,
51
+ Scope,
52
+ UserFlags,
53
+ )
54
+
55
+ __version__ = "0.2.0"
56
+
57
+ __all__ = [
58
+ "Client",
59
+ "Gateway",
60
+ "OAuth2Client",
61
+ "Dialer",
62
+ "PhoneCall",
63
+ "AdminAPI",
64
+ "generate_pkce",
65
+ "verify_gateway_signature",
66
+ "ManikinekoError",
67
+ "APIError",
68
+ "OAuthError",
69
+ "InvalidSessionError",
70
+ "ChannelType",
71
+ "ApplicationCommandType",
72
+ "ApplicationCommandOptionType",
73
+ "InteractionType",
74
+ "InteractionCallbackType",
75
+ "InteractionContextType",
76
+ "MessageType",
77
+ "MessageFlags",
78
+ "GatewayOp",
79
+ "GatewayEvent",
80
+ "Capability",
81
+ "PrivilegeStatus",
82
+ "RPCCommand",
83
+ "RPCStatus",
84
+ "AutoModTrigger",
85
+ "AutoModAction",
86
+ "Scope",
87
+ "UserFlags",
88
+ "__version__",
89
+ ]