pygpt-net 2.6.1__py3-none-any.whl → 2.6.2__py3-none-any.whl
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.
- pygpt_net/CHANGELOG.txt +4 -0
- pygpt_net/__init__.py +3 -3
- pygpt_net/app.py +15 -1
- pygpt_net/controller/chat/response.py +5 -3
- pygpt_net/controller/chat/stream.py +40 -2
- pygpt_net/controller/plugins/plugins.py +25 -0
- pygpt_net/controller/presets/editor.py +33 -88
- pygpt_net/controller/presets/experts.py +20 -1
- pygpt_net/controller/presets/presets.py +2 -2
- pygpt_net/controller/ui/mode.py +17 -66
- pygpt_net/core/agents/runner.py +15 -7
- pygpt_net/core/experts/experts.py +3 -3
- pygpt_net/data/config/config.json +3 -3
- pygpt_net/data/config/models.json +3 -3
- pygpt_net/data/locale/locale.de.ini +2 -0
- pygpt_net/data/locale/locale.en.ini +2 -0
- pygpt_net/data/locale/locale.es.ini +2 -0
- pygpt_net/data/locale/locale.fr.ini +2 -0
- pygpt_net/data/locale/locale.it.ini +2 -0
- pygpt_net/data/locale/locale.pl.ini +3 -1
- pygpt_net/data/locale/locale.uk.ini +2 -0
- pygpt_net/data/locale/locale.zh.ini +2 -0
- pygpt_net/plugin/base/plugin.py +35 -3
- pygpt_net/plugin/bitbucket/__init__.py +12 -0
- pygpt_net/plugin/bitbucket/config.py +267 -0
- pygpt_net/plugin/bitbucket/plugin.py +125 -0
- pygpt_net/plugin/bitbucket/worker.py +569 -0
- pygpt_net/plugin/facebook/__init__.py +12 -0
- pygpt_net/plugin/facebook/config.py +359 -0
- pygpt_net/plugin/facebook/plugin.py +114 -0
- pygpt_net/plugin/facebook/worker.py +698 -0
- pygpt_net/plugin/github/__init__.py +12 -0
- pygpt_net/plugin/github/config.py +441 -0
- pygpt_net/plugin/github/plugin.py +124 -0
- pygpt_net/plugin/github/worker.py +674 -0
- pygpt_net/plugin/google/__init__.py +12 -0
- pygpt_net/plugin/google/config.py +367 -0
- pygpt_net/plugin/google/plugin.py +126 -0
- pygpt_net/plugin/google/worker.py +826 -0
- pygpt_net/plugin/slack/__init__.py +12 -0
- pygpt_net/plugin/slack/config.py +349 -0
- pygpt_net/plugin/slack/plugin.py +116 -0
- pygpt_net/plugin/slack/worker.py +639 -0
- pygpt_net/plugin/telegram/__init__.py +12 -0
- pygpt_net/plugin/telegram/config.py +308 -0
- pygpt_net/plugin/telegram/plugin.py +118 -0
- pygpt_net/plugin/telegram/worker.py +563 -0
- pygpt_net/plugin/twitter/__init__.py +12 -0
- pygpt_net/plugin/twitter/config.py +491 -0
- pygpt_net/plugin/twitter/plugin.py +126 -0
- pygpt_net/plugin/twitter/worker.py +837 -0
- pygpt_net/provider/agents/llama_index/legacy/openai_assistant.py +35 -3
- pygpt_net/ui/base/config_dialog.py +4 -0
- pygpt_net/ui/dialog/preset.py +34 -77
- pygpt_net/ui/layout/toolbox/presets.py +2 -2
- pygpt_net/ui/main.py +3 -1
- {pygpt_net-2.6.1.dist-info → pygpt_net-2.6.2.dist-info}/METADATA +145 -2
- {pygpt_net-2.6.1.dist-info → pygpt_net-2.6.2.dist-info}/RECORD +61 -33
- {pygpt_net-2.6.1.dist-info → pygpt_net-2.6.2.dist-info}/LICENSE +0 -0
- {pygpt_net-2.6.1.dist-info → pygpt_net-2.6.2.dist-info}/WHEEL +0 -0
- {pygpt_net-2.6.1.dist-info → pygpt_net-2.6.2.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# ================================================== #
|
|
4
|
+
# This file is a part of PYGPT package #
|
|
5
|
+
# Website: https://pygpt.net #
|
|
6
|
+
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
|
7
|
+
# MIT License #
|
|
8
|
+
# Created By : Marcin Szczygliński #
|
|
9
|
+
# Updated Date: 2025.08.14 00:00:00 #
|
|
10
|
+
# ================================================== #
|
|
11
|
+
|
|
12
|
+
from pygpt_net.plugin.base.config import BaseConfig, BasePlugin
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Config(BaseConfig):
|
|
16
|
+
def __init__(self, plugin: BasePlugin = None, *args, **kwargs):
|
|
17
|
+
super(Config, self).__init__(plugin)
|
|
18
|
+
self.plugin = plugin
|
|
19
|
+
|
|
20
|
+
def from_defaults(self, plugin: BasePlugin = None):
|
|
21
|
+
# Endpoints / HTTP
|
|
22
|
+
plugin.add_option(
|
|
23
|
+
"api_base",
|
|
24
|
+
type="text",
|
|
25
|
+
value="https://api.x.com",
|
|
26
|
+
label="API base",
|
|
27
|
+
description="Base API URL (default https://api.x.com).",
|
|
28
|
+
)
|
|
29
|
+
plugin.add_option(
|
|
30
|
+
"authorize_base",
|
|
31
|
+
type="text",
|
|
32
|
+
value="https://x.com",
|
|
33
|
+
label="Authorize base",
|
|
34
|
+
description="Base for OAuth authorize (default https://x.com).",
|
|
35
|
+
)
|
|
36
|
+
plugin.add_option(
|
|
37
|
+
"http_timeout",
|
|
38
|
+
type="int",
|
|
39
|
+
value=30,
|
|
40
|
+
label="HTTP timeout (s)",
|
|
41
|
+
description="Requests timeout in seconds.",
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
# OAuth2 PKCE
|
|
45
|
+
plugin.add_option(
|
|
46
|
+
"oauth2_client_id",
|
|
47
|
+
type="text",
|
|
48
|
+
value="",
|
|
49
|
+
label="OAuth2 Client ID",
|
|
50
|
+
description="Client ID from X Developer Portal.",
|
|
51
|
+
secret=True,
|
|
52
|
+
)
|
|
53
|
+
plugin.add_option(
|
|
54
|
+
"oauth2_client_secret",
|
|
55
|
+
type="text",
|
|
56
|
+
value="",
|
|
57
|
+
label="OAuth2 Client Secret (optional)",
|
|
58
|
+
description="Only for confidential clients (Basic auth on token endpoints).",
|
|
59
|
+
secret=True,
|
|
60
|
+
)
|
|
61
|
+
plugin.add_option(
|
|
62
|
+
"oauth2_confidential",
|
|
63
|
+
type="bool",
|
|
64
|
+
value=False,
|
|
65
|
+
label="Confidential client (use Basic auth)",
|
|
66
|
+
description="Enable if your App is confidential and you want to use Basic auth with token endpoints.",
|
|
67
|
+
)
|
|
68
|
+
plugin.add_option(
|
|
69
|
+
"oauth2_redirect_uri",
|
|
70
|
+
type="text",
|
|
71
|
+
value="http://127.0.0.1:8731/callback",
|
|
72
|
+
label="Redirect URI",
|
|
73
|
+
description="Must exactly match one of the callback URLs in your X App (including port).",
|
|
74
|
+
)
|
|
75
|
+
plugin.add_option(
|
|
76
|
+
"oauth2_scopes",
|
|
77
|
+
type="text",
|
|
78
|
+
value="tweet.read users.read like.read like.write tweet.write bookmark.read bookmark.write tweet.moderate.write offline.access",
|
|
79
|
+
label="Scopes",
|
|
80
|
+
description="Space-separated OAuth2 scopes for Authorization Code with PKCE.",
|
|
81
|
+
)
|
|
82
|
+
plugin.add_option(
|
|
83
|
+
"oauth2_code_verifier",
|
|
84
|
+
type="text",
|
|
85
|
+
value="",
|
|
86
|
+
label="(auto) code_verifier",
|
|
87
|
+
description="Generated by x_oauth_begin.",
|
|
88
|
+
secret=True,
|
|
89
|
+
)
|
|
90
|
+
plugin.add_option(
|
|
91
|
+
"oauth2_state",
|
|
92
|
+
type="text",
|
|
93
|
+
value="",
|
|
94
|
+
label="(auto) state",
|
|
95
|
+
description="Generated by x_oauth_begin.",
|
|
96
|
+
secret=True,
|
|
97
|
+
)
|
|
98
|
+
plugin.add_option(
|
|
99
|
+
"oauth2_access_token",
|
|
100
|
+
type="textarea",
|
|
101
|
+
value="",
|
|
102
|
+
label="(auto) Access token",
|
|
103
|
+
description="Stored user access token.",
|
|
104
|
+
secret=True,
|
|
105
|
+
)
|
|
106
|
+
plugin.add_option(
|
|
107
|
+
"oauth2_refresh_token",
|
|
108
|
+
type="textarea",
|
|
109
|
+
value="",
|
|
110
|
+
label="(auto) Refresh token",
|
|
111
|
+
description="Stored user refresh token.",
|
|
112
|
+
secret=True,
|
|
113
|
+
)
|
|
114
|
+
plugin.add_option(
|
|
115
|
+
"oauth2_expires_at",
|
|
116
|
+
type="text",
|
|
117
|
+
value="0",
|
|
118
|
+
label="(auto) Expires at (unix)",
|
|
119
|
+
description="Auto-calculated expiry time.",
|
|
120
|
+
secret=False,
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
# App-only bearer (optional for read-only)
|
|
124
|
+
plugin.add_option(
|
|
125
|
+
"bearer_token",
|
|
126
|
+
type="textarea",
|
|
127
|
+
value="",
|
|
128
|
+
label="App-only Bearer token (optional)",
|
|
129
|
+
description="Optional app-only bearer for read endpoints.",
|
|
130
|
+
secret=True,
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
# Convenience cache
|
|
134
|
+
plugin.add_option(
|
|
135
|
+
"user_id",
|
|
136
|
+
type="text",
|
|
137
|
+
value="",
|
|
138
|
+
label="(auto) User ID",
|
|
139
|
+
description="Cached after x_me or oauth exchange.",
|
|
140
|
+
)
|
|
141
|
+
plugin.add_option(
|
|
142
|
+
"username",
|
|
143
|
+
type="text",
|
|
144
|
+
value="",
|
|
145
|
+
label="(auto) Username",
|
|
146
|
+
description="Cached after x_me or oauth exchange.",
|
|
147
|
+
)
|
|
148
|
+
plugin.add_option(
|
|
149
|
+
"oauth_auto_begin",
|
|
150
|
+
type="bool",
|
|
151
|
+
value=True,
|
|
152
|
+
label="Auto-start OAuth when required",
|
|
153
|
+
description="If a command needs user token, begin PKCE flow automatically.",
|
|
154
|
+
)
|
|
155
|
+
plugin.add_option(
|
|
156
|
+
"oauth_open_browser",
|
|
157
|
+
type="bool",
|
|
158
|
+
value=True,
|
|
159
|
+
label="Open browser automatically",
|
|
160
|
+
description="Open authorize URL in default browser.",
|
|
161
|
+
)
|
|
162
|
+
plugin.add_option(
|
|
163
|
+
"oauth_local_server",
|
|
164
|
+
type="bool",
|
|
165
|
+
value=True,
|
|
166
|
+
label="Use local server for OAuth",
|
|
167
|
+
description="Start local HTTP server to capture redirect (requires redirect_uri = http://localhost[:port]/path).",
|
|
168
|
+
)
|
|
169
|
+
plugin.add_option(
|
|
170
|
+
"oauth_local_timeout",
|
|
171
|
+
type="int",
|
|
172
|
+
value=180,
|
|
173
|
+
label="OAuth local timeout (s)",
|
|
174
|
+
description="How long to wait for redirect with code.",
|
|
175
|
+
)
|
|
176
|
+
plugin.add_option(
|
|
177
|
+
"oauth_success_html",
|
|
178
|
+
type="textarea",
|
|
179
|
+
value="<html><body><h3>Authorization complete. You can close this window.</h3></body></html>",
|
|
180
|
+
label="Success HTML",
|
|
181
|
+
description="HTML shown on local callback success.",
|
|
182
|
+
)
|
|
183
|
+
plugin.add_option(
|
|
184
|
+
"oauth_fail_html",
|
|
185
|
+
type="textarea",
|
|
186
|
+
value="<html><body><h3>Authorization failed.</h3></body></html>",
|
|
187
|
+
label="Fail HTML",
|
|
188
|
+
description="HTML shown on local callback error.",
|
|
189
|
+
)
|
|
190
|
+
plugin.add_option(
|
|
191
|
+
"oauth_local_port",
|
|
192
|
+
type="int",
|
|
193
|
+
value=8731,
|
|
194
|
+
label="OAuth local port (0=auto)",
|
|
195
|
+
description="Local HTTP port for callback; use >1024. Must be registered in X App.",
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
plugin.add_option(
|
|
199
|
+
"oauth_allow_port_fallback",
|
|
200
|
+
type="bool",
|
|
201
|
+
value=True,
|
|
202
|
+
label="Allow fallback port if busy",
|
|
203
|
+
description="If preferred port is busy/forbidden, pick a free local port and rebuild the redirect URL.",
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
# ---------------- Commands ----------------
|
|
207
|
+
|
|
208
|
+
# Auth
|
|
209
|
+
plugin.add_cmd(
|
|
210
|
+
"x_oauth_begin",
|
|
211
|
+
instruction="Begin OAuth2 PKCE flow (returns authorize URL).",
|
|
212
|
+
params=[
|
|
213
|
+
{"name": "scopes", "type": "str", "required": False, "description": "Override scopes (space-separated)"},
|
|
214
|
+
{"name": "state", "type": "str", "required": False, "description": "Optional CSRF state"},
|
|
215
|
+
],
|
|
216
|
+
enabled=True,
|
|
217
|
+
description="Auth: begin OAuth2",
|
|
218
|
+
tab="auth",
|
|
219
|
+
)
|
|
220
|
+
plugin.add_cmd(
|
|
221
|
+
"x_oauth_exchange",
|
|
222
|
+
instruction="Exchange authorization code for access/refresh tokens.",
|
|
223
|
+
params=[
|
|
224
|
+
{"name": "code", "type": "str", "required": True, "description": "Authorization code"},
|
|
225
|
+
{"name": "state", "type": "str", "required": False, "description": "State (if used)"},
|
|
226
|
+
],
|
|
227
|
+
enabled=True,
|
|
228
|
+
description="Auth: exchange code",
|
|
229
|
+
tab="auth",
|
|
230
|
+
)
|
|
231
|
+
plugin.add_cmd(
|
|
232
|
+
"x_oauth_refresh",
|
|
233
|
+
instruction="Refresh access token using refresh_token.",
|
|
234
|
+
params=[],
|
|
235
|
+
enabled=True,
|
|
236
|
+
description="Auth: refresh token",
|
|
237
|
+
tab="auth",
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
# Users
|
|
241
|
+
plugin.add_cmd(
|
|
242
|
+
"x_me",
|
|
243
|
+
instruction="Get authorized user (requires user token).",
|
|
244
|
+
params=[
|
|
245
|
+
{"name": "user.fields", "type": "str", "required": False, "description": "e.g. created_at,verified,public_metrics"},
|
|
246
|
+
{"name": "expansions", "type": "str", "required": False, "description": "e.g. pinned_tweet_id"},
|
|
247
|
+
{"name": "tweet.fields", "type": "str", "required": False, "description": "fields of pinned tweet"},
|
|
248
|
+
],
|
|
249
|
+
enabled=True,
|
|
250
|
+
description="Users: me",
|
|
251
|
+
tab="users",
|
|
252
|
+
)
|
|
253
|
+
plugin.add_cmd(
|
|
254
|
+
"x_user_by_username",
|
|
255
|
+
instruction="Lookup user by username.",
|
|
256
|
+
params=[
|
|
257
|
+
{"name": "username", "type": "str", "required": True, "description": "Handle without @"},
|
|
258
|
+
{"name": "user_fields", "type": "str", "required": False, "description": "Comma list"},
|
|
259
|
+
{"name": "expansions", "type": "str", "required": False, "description": "Comma list"},
|
|
260
|
+
{"name": "tweet_fields", "type": "str", "required": False, "description": "Comma list"},
|
|
261
|
+
],
|
|
262
|
+
enabled=True,
|
|
263
|
+
description="Users: by username",
|
|
264
|
+
tab="users",
|
|
265
|
+
)
|
|
266
|
+
plugin.add_cmd(
|
|
267
|
+
"x_user_by_id",
|
|
268
|
+
instruction="Lookup user by ID.",
|
|
269
|
+
params=[
|
|
270
|
+
{"name": "id", "type": "str", "required": True, "description": "User ID"},
|
|
271
|
+
{"name": "user_fields", "type": "str", "required": False, "description": "Comma list"},
|
|
272
|
+
],
|
|
273
|
+
enabled=True,
|
|
274
|
+
description="Users: by id",
|
|
275
|
+
tab="users",
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
# Timelines / Search
|
|
279
|
+
plugin.add_cmd(
|
|
280
|
+
"x_user_tweets",
|
|
281
|
+
instruction="User Tweet timeline.",
|
|
282
|
+
params=[
|
|
283
|
+
{"name": "id", "type": "str", "required": True, "description": "User ID"},
|
|
284
|
+
{"name": "max_results", "type": "int", "required": False, "description": "5..100 (default 20)"},
|
|
285
|
+
{"name": "since_id", "type": "str", "required": False, "description": "Since id"},
|
|
286
|
+
{"name": "until_id", "type": "str", "required": False, "description": "Until id"},
|
|
287
|
+
{"name": "exclude", "type": "list", "required": False, "description": "['replies','retweets']"},
|
|
288
|
+
{"name": "tweet_fields", "type": "str", "required": False, "description": "Comma list"},
|
|
289
|
+
{"name": "expansions", "type": "str", "required": False, "description": "Comma list"},
|
|
290
|
+
{"name": "media_fields", "type": "str", "required": False, "description": "Comma list"},
|
|
291
|
+
{"name": "pagination_token", "type": "str", "required": False, "description": "For next page"},
|
|
292
|
+
],
|
|
293
|
+
enabled=True,
|
|
294
|
+
description="Timeline: user tweets",
|
|
295
|
+
tab="tweets",
|
|
296
|
+
)
|
|
297
|
+
plugin.add_cmd(
|
|
298
|
+
"x_search_recent",
|
|
299
|
+
instruction="Recent search (last 7 days).",
|
|
300
|
+
params=[
|
|
301
|
+
{"name": "query", "type": "str", "required": True, "description": "Query string with operators"},
|
|
302
|
+
{"name": "max_results", "type": "int", "required": False, "description": "10..100 (default 25)"},
|
|
303
|
+
{"name": "since_id", "type": "str", "required": False, "description": "Since id"},
|
|
304
|
+
{"name": "until_id", "type": "str", "required": False, "description": "Until id"},
|
|
305
|
+
{"name": "start_time", "type": "str", "required": False, "description": "RFC3339"},
|
|
306
|
+
{"name": "end_time", "type": "str", "required": False, "description": "RFC3339"},
|
|
307
|
+
{"name": "tweet_fields", "type": "str", "required": False, "description": "Comma list"},
|
|
308
|
+
{"name": "expansions", "type": "str", "required": False, "description": "Comma list"},
|
|
309
|
+
{"name": "media_fields", "type": "str", "required": False, "description": "Comma list"},
|
|
310
|
+
{"name": "next_token", "type": "str", "required": False, "description": "For next page"},
|
|
311
|
+
],
|
|
312
|
+
enabled=True,
|
|
313
|
+
description="Search: recent",
|
|
314
|
+
tab="search",
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
# Tweet CRUD
|
|
318
|
+
plugin.add_cmd(
|
|
319
|
+
"x_tweet_create",
|
|
320
|
+
instruction="Create a Tweet/Post.",
|
|
321
|
+
params=[
|
|
322
|
+
{"name": "text", "type": "str", "required": False, "description": "Tweet text"},
|
|
323
|
+
{"name": "media_ids", "type": "list", "required": False, "description": "Uploaded media ids"},
|
|
324
|
+
{"name": "tagged_user_ids", "type": "list", "required": False, "description": "User IDs to tag"},
|
|
325
|
+
{"name": "quote_tweet_id", "type": "str", "required": False, "description": "Quote tweet id"},
|
|
326
|
+
{"name": "in_reply_to_tweet_id", "type": "str", "required": False, "description": "Reply to id"},
|
|
327
|
+
{"name": "exclude_reply_user_ids", "type": "list", "required": False, "description": "Exclude ids"},
|
|
328
|
+
{"name": "reply_settings", "type": "str", "required": False, "description": "everyone|following|mentionedUsers"},
|
|
329
|
+
{"name": "place_id", "type": "str", "required": False, "description": "Geo place id"},
|
|
330
|
+
{"name": "poll", "type": "dict", "required": False, "description": "duration_minutes, options"},
|
|
331
|
+
{"name": "card_uri", "type": "str", "required": False, "description": "Card URI"},
|
|
332
|
+
],
|
|
333
|
+
enabled=True,
|
|
334
|
+
description="Tweets: create",
|
|
335
|
+
tab="tweets",
|
|
336
|
+
)
|
|
337
|
+
plugin.add_cmd(
|
|
338
|
+
"x_tweet_delete",
|
|
339
|
+
instruction="Delete Tweet by ID.",
|
|
340
|
+
params=[{"name": "id", "type": "str", "required": True, "description": "Tweet ID"}],
|
|
341
|
+
enabled=True,
|
|
342
|
+
description="Tweets: delete",
|
|
343
|
+
tab="tweets",
|
|
344
|
+
)
|
|
345
|
+
plugin.add_cmd(
|
|
346
|
+
"x_tweet_reply",
|
|
347
|
+
instruction="Reply to a Tweet.",
|
|
348
|
+
params=[
|
|
349
|
+
{"name": "in_reply_to_tweet_id", "type": "str", "required": True, "description": "Parent tweet id"},
|
|
350
|
+
{"name": "text", "type": "str", "required": False, "description": "Reply text"},
|
|
351
|
+
{"name": "media_ids", "type": "list", "required": False, "description": "Media ids"},
|
|
352
|
+
],
|
|
353
|
+
enabled=True,
|
|
354
|
+
description="Tweets: reply",
|
|
355
|
+
tab="tweets",
|
|
356
|
+
)
|
|
357
|
+
plugin.add_cmd(
|
|
358
|
+
"x_tweet_quote",
|
|
359
|
+
instruction="Quote a Tweet.",
|
|
360
|
+
params=[
|
|
361
|
+
{"name": "quote_tweet_id", "type": "str", "required": True, "description": "Quoted tweet id"},
|
|
362
|
+
{"name": "text", "type": "str", "required": False, "description": "Quote text"},
|
|
363
|
+
{"name": "media_ids", "type": "list", "required": False, "description": "Media ids"},
|
|
364
|
+
],
|
|
365
|
+
enabled=True,
|
|
366
|
+
description="Tweets: quote",
|
|
367
|
+
tab="tweets",
|
|
368
|
+
)
|
|
369
|
+
|
|
370
|
+
# Actions
|
|
371
|
+
plugin.add_cmd(
|
|
372
|
+
"x_like",
|
|
373
|
+
instruction="Like a Tweet.",
|
|
374
|
+
params=[
|
|
375
|
+
{"name": "tweet_id", "type": "str", "required": True, "description": "Tweet id"},
|
|
376
|
+
{"name": "user_id", "type": "str", "required": False, "description": "Defaults to me"},
|
|
377
|
+
],
|
|
378
|
+
enabled=True,
|
|
379
|
+
description="Actions: like",
|
|
380
|
+
tab="actions",
|
|
381
|
+
)
|
|
382
|
+
plugin.add_cmd(
|
|
383
|
+
"x_unlike",
|
|
384
|
+
instruction="Unlike a Tweet.",
|
|
385
|
+
params=[
|
|
386
|
+
{"name": "tweet_id", "type": "str", "required": True, "description": "Tweet id"},
|
|
387
|
+
{"name": "user_id", "type": "str", "required": False, "description": "Defaults to me"},
|
|
388
|
+
],
|
|
389
|
+
enabled=True,
|
|
390
|
+
description="Actions: unlike",
|
|
391
|
+
tab="actions",
|
|
392
|
+
)
|
|
393
|
+
plugin.add_cmd(
|
|
394
|
+
"x_retweet",
|
|
395
|
+
instruction="Retweet.",
|
|
396
|
+
params=[
|
|
397
|
+
{"name": "tweet_id", "type": "str", "required": True, "description": "Tweet id"},
|
|
398
|
+
{"name": "user_id", "type": "str", "required": False, "description": "Defaults to me"},
|
|
399
|
+
],
|
|
400
|
+
enabled=True,
|
|
401
|
+
description="Actions: retweet",
|
|
402
|
+
tab="actions",
|
|
403
|
+
)
|
|
404
|
+
plugin.add_cmd(
|
|
405
|
+
"x_unretweet",
|
|
406
|
+
instruction="Undo retweet.",
|
|
407
|
+
params=[
|
|
408
|
+
{"name": "tweet_id", "type": "str", "required": True, "description": "Original tweet id"},
|
|
409
|
+
{"name": "user_id", "type": "str", "required": False, "description": "Defaults to me"},
|
|
410
|
+
],
|
|
411
|
+
enabled=True,
|
|
412
|
+
description="Actions: unretweet",
|
|
413
|
+
tab="actions",
|
|
414
|
+
)
|
|
415
|
+
plugin.add_cmd(
|
|
416
|
+
"x_hide_reply",
|
|
417
|
+
instruction="Hide or unhide a reply to your Tweet.",
|
|
418
|
+
params=[
|
|
419
|
+
{"name": "tweet_id", "type": "str", "required": True, "description": "Reply tweet id"},
|
|
420
|
+
{"name": "hidden", "type": "bool", "required": False, "description": "Default true"},
|
|
421
|
+
],
|
|
422
|
+
enabled=True,
|
|
423
|
+
description="Actions: hide/unhide reply",
|
|
424
|
+
tab="actions",
|
|
425
|
+
)
|
|
426
|
+
|
|
427
|
+
# Bookmarks
|
|
428
|
+
plugin.add_cmd(
|
|
429
|
+
"x_bookmarks_list",
|
|
430
|
+
instruction="List my bookmarks.",
|
|
431
|
+
params=[
|
|
432
|
+
{"name": "user_id", "type": "str", "required": False, "description": "Defaults to me"},
|
|
433
|
+
{"name": "max_results", "type": "int", "required": False, "description": "Default 50"},
|
|
434
|
+
{"name": "pagination_token", "type": "str", "required": False, "description": "Next page token"},
|
|
435
|
+
{"name": "tweet_fields", "type": "str", "required": False, "description": "Comma list"},
|
|
436
|
+
{"name": "expansions", "type": "str", "required": False, "description": "Comma list"},
|
|
437
|
+
{"name": "media_fields", "type": "str", "required": False, "description": "Comma list"},
|
|
438
|
+
],
|
|
439
|
+
enabled=True,
|
|
440
|
+
description="Bookmarks: list",
|
|
441
|
+
tab="bookmarks",
|
|
442
|
+
)
|
|
443
|
+
plugin.add_cmd(
|
|
444
|
+
"x_bookmark_add",
|
|
445
|
+
instruction="Add bookmark.",
|
|
446
|
+
params=[
|
|
447
|
+
{"name": "tweet_id", "type": "str", "required": True, "description": "Tweet id"},
|
|
448
|
+
{"name": "user_id", "type": "str", "required": False, "description": "Defaults to me"},
|
|
449
|
+
],
|
|
450
|
+
enabled=True,
|
|
451
|
+
description="Bookmarks: add",
|
|
452
|
+
tab="bookmarks",
|
|
453
|
+
)
|
|
454
|
+
plugin.add_cmd(
|
|
455
|
+
"x_bookmark_remove",
|
|
456
|
+
instruction="Remove bookmark.",
|
|
457
|
+
params=[
|
|
458
|
+
{"name": "tweet_id", "type": "str", "required": True, "description": "Tweet id"},
|
|
459
|
+
{"name": "user_id", "type": "str", "required": False, "description": "Defaults to me"},
|
|
460
|
+
],
|
|
461
|
+
enabled=True,
|
|
462
|
+
description="Bookmarks: remove",
|
|
463
|
+
tab="bookmarks",
|
|
464
|
+
)
|
|
465
|
+
|
|
466
|
+
# Media
|
|
467
|
+
plugin.add_cmd(
|
|
468
|
+
"x_upload_media",
|
|
469
|
+
instruction="Upload media (INIT/APPEND/FINALIZE). Returns media_id.",
|
|
470
|
+
params=[
|
|
471
|
+
{"name": "path", "type": "str", "required": True, "description": "Local file path"},
|
|
472
|
+
{"name": "media_type", "type": "str", "required": False, "description": "Mime, auto-guessed"},
|
|
473
|
+
{"name": "media_category", "type": "str", "required": False, "description": "tweet_image|tweet_video|tweet_gif"},
|
|
474
|
+
{"name": "chunk_size", "type": "int", "required": False, "description": "Bytes, default 1MB"},
|
|
475
|
+
{"name": "wait_for_processing", "type": "bool", "required": False, "description": "Poll STATUS if needed"},
|
|
476
|
+
],
|
|
477
|
+
enabled=True,
|
|
478
|
+
description="Media: upload",
|
|
479
|
+
tab="media",
|
|
480
|
+
)
|
|
481
|
+
plugin.add_cmd(
|
|
482
|
+
"x_media_set_alt_text",
|
|
483
|
+
instruction="Attach alt text (accessibility) to uploaded media.",
|
|
484
|
+
params=[
|
|
485
|
+
{"name": "media_id", "type": "str", "required": True, "description": "Media id from upload"},
|
|
486
|
+
{"name": "alt_text", "type": "str", "required": True, "description": "Up to 1000 chars"},
|
|
487
|
+
],
|
|
488
|
+
enabled=True,
|
|
489
|
+
description="Media: set alt text",
|
|
490
|
+
tab="media",
|
|
491
|
+
)
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# ================================================== #
|
|
4
|
+
# This file is a part of PYGPT package #
|
|
5
|
+
# Website: https://pygpt.net #
|
|
6
|
+
# GitHub: https://github.com/szczyglis-dev/py-gpt #
|
|
7
|
+
# MIT License #
|
|
8
|
+
# Created By : Marcin Szczygliński #
|
|
9
|
+
# Updated Date: 2025.07.14 00:00:00 #
|
|
10
|
+
# ================================================== #
|
|
11
|
+
|
|
12
|
+
import os
|
|
13
|
+
|
|
14
|
+
from pygpt_net.plugin.base.plugin import BasePlugin
|
|
15
|
+
from pygpt_net.core.events import Event
|
|
16
|
+
from pygpt_net.item.ctx import CtxItem
|
|
17
|
+
|
|
18
|
+
from .config import Config
|
|
19
|
+
from .worker import Worker
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class Plugin(BasePlugin):
|
|
23
|
+
def __init__(self, *args, **kwargs):
|
|
24
|
+
super(Plugin, self).__init__(*args, **kwargs)
|
|
25
|
+
self.id = "twitter"
|
|
26
|
+
self.name = "Twitter/X"
|
|
27
|
+
self.description = "Interact with tweets and users, manage bookmarks and media, perform likes, retweets, and more."
|
|
28
|
+
self.prefix = "API"
|
|
29
|
+
self.order = 100
|
|
30
|
+
self.allowed_cmds = [
|
|
31
|
+
'x_oauth_begin',
|
|
32
|
+
'x_oauth_exchange',
|
|
33
|
+
'x_oauth_refresh',
|
|
34
|
+
'x_me',
|
|
35
|
+
'x_user_by_username',
|
|
36
|
+
'x_user_by_id',
|
|
37
|
+
'x_user_tweets',
|
|
38
|
+
'x_search_recent',
|
|
39
|
+
'x_tweet_create',
|
|
40
|
+
'x_tweet_delete',
|
|
41
|
+
'x_tweet_reply',
|
|
42
|
+
'x_tweet_quote',
|
|
43
|
+
'x_like',
|
|
44
|
+
'x_unlike',
|
|
45
|
+
'x_retweet',
|
|
46
|
+
'x_unretweet',
|
|
47
|
+
'x_hide_reply',
|
|
48
|
+
'x_bookmarks_list',
|
|
49
|
+
'x_bookmark_add',
|
|
50
|
+
'x_bookmark_remove',
|
|
51
|
+
'x_upload_media',
|
|
52
|
+
'x_media_set_alt_text'
|
|
53
|
+
]
|
|
54
|
+
self.use_locale = False
|
|
55
|
+
self.worker = None
|
|
56
|
+
self.config = Config(self)
|
|
57
|
+
self.init_options()
|
|
58
|
+
|
|
59
|
+
def init_options(self):
|
|
60
|
+
"""Initialize options"""
|
|
61
|
+
self.config.from_defaults(self)
|
|
62
|
+
|
|
63
|
+
def handle(self, event: Event, *args, **kwargs):
|
|
64
|
+
"""
|
|
65
|
+
Handle dispatched event
|
|
66
|
+
|
|
67
|
+
:param event: event object
|
|
68
|
+
:param args: event args
|
|
69
|
+
:param kwargs: event kwargs
|
|
70
|
+
"""
|
|
71
|
+
name = event.name
|
|
72
|
+
data = event.data
|
|
73
|
+
ctx = event.ctx
|
|
74
|
+
|
|
75
|
+
if name == Event.CMD_SYNTAX:
|
|
76
|
+
self.cmd_syntax(data)
|
|
77
|
+
|
|
78
|
+
elif name == Event.CMD_EXECUTE:
|
|
79
|
+
self.cmd(
|
|
80
|
+
ctx,
|
|
81
|
+
data['commands'],
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
def cmd_syntax(self, data: dict):
|
|
85
|
+
"""
|
|
86
|
+
Event: CMD_SYNTAX
|
|
87
|
+
|
|
88
|
+
:param data: event data dict
|
|
89
|
+
"""
|
|
90
|
+
for option in self.allowed_cmds:
|
|
91
|
+
if self.has_cmd(option):
|
|
92
|
+
data['cmd'].append(self.get_cmd(option)) # append command
|
|
93
|
+
|
|
94
|
+
def cmd(self, ctx: CtxItem, cmds: list):
|
|
95
|
+
"""
|
|
96
|
+
Event: CMD_EXECUTE
|
|
97
|
+
|
|
98
|
+
:param ctx: CtxItem
|
|
99
|
+
:param cmds: commands dict
|
|
100
|
+
"""
|
|
101
|
+
is_cmd = False
|
|
102
|
+
my_commands = []
|
|
103
|
+
for item in cmds:
|
|
104
|
+
if item["cmd"] in self.allowed_cmds:
|
|
105
|
+
my_commands.append(item)
|
|
106
|
+
is_cmd = True
|
|
107
|
+
|
|
108
|
+
if not is_cmd:
|
|
109
|
+
return
|
|
110
|
+
|
|
111
|
+
# set state: busy
|
|
112
|
+
self.cmd_prepare(ctx, my_commands)
|
|
113
|
+
|
|
114
|
+
try:
|
|
115
|
+
worker = Worker()
|
|
116
|
+
worker.from_defaults(self)
|
|
117
|
+
worker.cmds = my_commands
|
|
118
|
+
worker.ctx = ctx
|
|
119
|
+
|
|
120
|
+
if not self.is_async(ctx):
|
|
121
|
+
worker.run()
|
|
122
|
+
return
|
|
123
|
+
worker.run_async()
|
|
124
|
+
|
|
125
|
+
except Exception as e:
|
|
126
|
+
self.error(e)
|