comprobot 2.2.4__tar.gz → 2.2.6__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.
- {comprobot-2.2.4 → comprobot-2.2.6}/PKG-INFO +6 -6
- {comprobot-2.2.4 → comprobot-2.2.6}/README.md +4 -3
- {comprobot-2.2.4 → comprobot-2.2.6}/comprobot.egg-info/PKG-INFO +6 -6
- {comprobot-2.2.4 → comprobot-2.2.6}/comprobot.egg-info/requires.txt +1 -2
- {comprobot-2.2.4 → comprobot-2.2.6}/pyproject.toml +2 -3
- {comprobot-2.2.4 → comprobot-2.2.6}/src/__main__.py +0 -2
- {comprobot-2.2.4 → comprobot-2.2.6}/src/config.py +28 -3
- {comprobot-2.2.4 → comprobot-2.2.6}/src/functions.py +46 -26
- {comprobot-2.2.4 → comprobot-2.2.6}/LICENSE +0 -0
- {comprobot-2.2.4 → comprobot-2.2.6}/comprobot.egg-info/SOURCES.txt +0 -0
- {comprobot-2.2.4 → comprobot-2.2.6}/comprobot.egg-info/dependency_links.txt +0 -0
- {comprobot-2.2.4 → comprobot-2.2.6}/comprobot.egg-info/entry_points.txt +0 -0
- {comprobot-2.2.4 → comprobot-2.2.6}/comprobot.egg-info/top_level.txt +0 -0
- {comprobot-2.2.4 → comprobot-2.2.6}/setup.cfg +0 -0
- {comprobot-2.2.4 → comprobot-2.2.6}/src/__init__.py +0 -0
- {comprobot-2.2.4 → comprobot-2.2.6}/src/api.py +0 -0
- {comprobot-2.2.4 → comprobot-2.2.6}/src/bot.py +0 -0
- {comprobot-2.2.4 → comprobot-2.2.6}/src/commands.py +0 -0
- {comprobot-2.2.4 → comprobot-2.2.6}/src/data.py +0 -0
- {comprobot-2.2.4 → comprobot-2.2.6}/src/moderation.py +0 -0
- {comprobot-2.2.4 → comprobot-2.2.6}/src/money_system.py +0 -0
- {comprobot-2.2.4 → comprobot-2.2.6}/src/onboarding.py +0 -0
- {comprobot-2.2.4 → comprobot-2.2.6}/src/process.py +0 -0
- {comprobot-2.2.4 → comprobot-2.2.6}/src/start.py +0 -0
- {comprobot-2.2.4 → comprobot-2.2.6}/src/templates.py +0 -0
- {comprobot-2.2.4 → comprobot-2.2.6}/src/testing.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: comprobot
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.6
|
|
4
4
|
Summary: A self-hostable Discord bot built for maximum customization.
|
|
5
5
|
Author: badluma
|
|
6
6
|
License: MIT
|
|
@@ -18,8 +18,7 @@ Requires-Dist: requests
|
|
|
18
18
|
Requires-Dist: tomlkit
|
|
19
19
|
Requires-Dist: appdirs
|
|
20
20
|
Requires-Dist: ollama
|
|
21
|
-
Requires-Dist:
|
|
22
|
-
Requires-Dist: groq
|
|
21
|
+
Requires-Dist: httpx
|
|
23
22
|
Requires-Dist: InquirerPy
|
|
24
23
|
Provides-Extra: dev
|
|
25
24
|
Requires-Dist: ruff; extra == "dev"
|
|
@@ -29,7 +28,8 @@ Dynamic: license-file
|
|
|
29
28
|
|
|
30
29
|
Comprobot is a highly-customizable, open-source Discord bot that you can run on your own server.
|
|
31
30
|
|
|
32
|
-
It’s built with Python, has a wide range of fun and useful commands, and is designed to be easy to extend.
|
|
31
|
+
It’s built with Python, has a wide range of fun and useful commands, and is designed to be easy to extend.
|
|
32
|
+
You can add new commands, customize outputs, or change the behaviour of existing ones. You can also easily edit the keywords of existing commands and customize their outputs.
|
|
33
33
|
|
|
34
34
|
The bot also comes with built-in AI capabilities when pinging the bot, with Ollama, Groq and Gemini as available providers.
|
|
35
35
|
|
|
@@ -40,12 +40,12 @@ The bot also comes with built-in AI capabilities when pinging the bot, with Olla
|
|
|
40
40
|
pipx install comprobot
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
**APT** (Ubuntu/Debian)
|
|
43
|
+
**APT** (Ubuntu/Debian/Kali)
|
|
44
44
|
```sh
|
|
45
45
|
# If add-apt-repository isn't found, run this first:
|
|
46
46
|
# sudo apt install software-properties-common
|
|
47
47
|
sudo add-apt-repository ppa:badluma/ppa
|
|
48
|
-
sudo apt update
|
|
48
|
+
sudo apt update
|
|
49
49
|
sudo apt install comprobot
|
|
50
50
|
```
|
|
51
51
|
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Comprobot is a highly-customizable, open-source Discord bot that you can run on your own server.
|
|
4
4
|
|
|
5
|
-
It’s built with Python, has a wide range of fun and useful commands, and is designed to be easy to extend.
|
|
5
|
+
It’s built with Python, has a wide range of fun and useful commands, and is designed to be easy to extend.
|
|
6
|
+
You can add new commands, customize outputs, or change the behaviour of existing ones. You can also easily edit the keywords of existing commands and customize their outputs.
|
|
6
7
|
|
|
7
8
|
The bot also comes with built-in AI capabilities when pinging the bot, with Ollama, Groq and Gemini as available providers.
|
|
8
9
|
|
|
@@ -13,12 +14,12 @@ The bot also comes with built-in AI capabilities when pinging the bot, with Olla
|
|
|
13
14
|
pipx install comprobot
|
|
14
15
|
```
|
|
15
16
|
|
|
16
|
-
**APT** (Ubuntu/Debian)
|
|
17
|
+
**APT** (Ubuntu/Debian/Kali)
|
|
17
18
|
```sh
|
|
18
19
|
# If add-apt-repository isn't found, run this first:
|
|
19
20
|
# sudo apt install software-properties-common
|
|
20
21
|
sudo add-apt-repository ppa:badluma/ppa
|
|
21
|
-
sudo apt update
|
|
22
|
+
sudo apt update
|
|
22
23
|
sudo apt install comprobot
|
|
23
24
|
```
|
|
24
25
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: comprobot
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.6
|
|
4
4
|
Summary: A self-hostable Discord bot built for maximum customization.
|
|
5
5
|
Author: badluma
|
|
6
6
|
License: MIT
|
|
@@ -18,8 +18,7 @@ Requires-Dist: requests
|
|
|
18
18
|
Requires-Dist: tomlkit
|
|
19
19
|
Requires-Dist: appdirs
|
|
20
20
|
Requires-Dist: ollama
|
|
21
|
-
Requires-Dist:
|
|
22
|
-
Requires-Dist: groq
|
|
21
|
+
Requires-Dist: httpx
|
|
23
22
|
Requires-Dist: InquirerPy
|
|
24
23
|
Provides-Extra: dev
|
|
25
24
|
Requires-Dist: ruff; extra == "dev"
|
|
@@ -29,7 +28,8 @@ Dynamic: license-file
|
|
|
29
28
|
|
|
30
29
|
Comprobot is a highly-customizable, open-source Discord bot that you can run on your own server.
|
|
31
30
|
|
|
32
|
-
It’s built with Python, has a wide range of fun and useful commands, and is designed to be easy to extend.
|
|
31
|
+
It’s built with Python, has a wide range of fun and useful commands, and is designed to be easy to extend.
|
|
32
|
+
You can add new commands, customize outputs, or change the behaviour of existing ones. You can also easily edit the keywords of existing commands and customize their outputs.
|
|
33
33
|
|
|
34
34
|
The bot also comes with built-in AI capabilities when pinging the bot, with Ollama, Groq and Gemini as available providers.
|
|
35
35
|
|
|
@@ -40,12 +40,12 @@ The bot also comes with built-in AI capabilities when pinging the bot, with Olla
|
|
|
40
40
|
pipx install comprobot
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
**APT** (Ubuntu/Debian)
|
|
43
|
+
**APT** (Ubuntu/Debian/Kali)
|
|
44
44
|
```sh
|
|
45
45
|
# If add-apt-repository isn't found, run this first:
|
|
46
46
|
# sudo apt install software-properties-common
|
|
47
47
|
sudo add-apt-repository ppa:badluma/ppa
|
|
48
|
-
sudo apt update
|
|
48
|
+
sudo apt update
|
|
49
49
|
sudo apt install comprobot
|
|
50
50
|
```
|
|
51
51
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "comprobot"
|
|
7
|
-
version = "2.2.
|
|
7
|
+
version = "2.2.6"
|
|
8
8
|
authors = [{name = "badluma"}]
|
|
9
9
|
description = "A self-hostable Discord bot built for maximum customization."
|
|
10
10
|
readme = "README.md"
|
|
@@ -22,8 +22,7 @@ dependencies = [
|
|
|
22
22
|
"tomlkit",
|
|
23
23
|
"appdirs",
|
|
24
24
|
"ollama",
|
|
25
|
-
"
|
|
26
|
-
"groq",
|
|
25
|
+
"httpx",
|
|
27
26
|
"InquirerPy",
|
|
28
27
|
]
|
|
29
28
|
|
|
@@ -24,7 +24,8 @@ def make_pretty(string):
|
|
|
24
24
|
.replace("_", " ") \
|
|
25
25
|
.replace("-", " ") \
|
|
26
26
|
.title() \
|
|
27
|
-
.replace("Ai", "AI")
|
|
27
|
+
.replace("Ai", "AI") \
|
|
28
|
+
.replace("Api", "API")
|
|
28
29
|
|
|
29
30
|
def pick_file():
|
|
30
31
|
data_dir = appdirs.user_data_dir("Comprobot", appauthor=False)
|
|
@@ -101,7 +102,7 @@ def pick_key(content, is_secret=False):
|
|
|
101
102
|
).execute()
|
|
102
103
|
content[key] = value
|
|
103
104
|
|
|
104
|
-
case str()
|
|
105
|
+
case str():
|
|
105
106
|
print()
|
|
106
107
|
if is_secret:
|
|
107
108
|
value = secret.SecretPrompt(
|
|
@@ -120,6 +121,30 @@ def pick_key(content, is_secret=False):
|
|
|
120
121
|
).execute()
|
|
121
122
|
content[key] = value
|
|
122
123
|
|
|
124
|
+
case int():
|
|
125
|
+
print()
|
|
126
|
+
if is_secret:
|
|
127
|
+
value = secret.SecretPrompt(
|
|
128
|
+
message=f"New value for '{make_pretty(key)}'?",
|
|
129
|
+
style=style,
|
|
130
|
+
amark="!",
|
|
131
|
+
vi_mode=True,
|
|
132
|
+
).execute()
|
|
133
|
+
else:
|
|
134
|
+
value = input.InputPrompt(
|
|
135
|
+
message=f"What number do you want to assign to '{make_pretty(key)}'?",
|
|
136
|
+
instruction=f"(Current: {content[key]})",
|
|
137
|
+
style=style,
|
|
138
|
+
amark="!",
|
|
139
|
+
vi_mode=True,
|
|
140
|
+
).execute()
|
|
141
|
+
|
|
142
|
+
if int(value) == None:
|
|
143
|
+
content[key] = 0
|
|
144
|
+
return
|
|
145
|
+
|
|
146
|
+
content[key] = int(value)
|
|
147
|
+
|
|
123
148
|
case list():
|
|
124
149
|
print()
|
|
125
150
|
value = input.InputPrompt(
|
|
@@ -129,7 +154,7 @@ def pick_key(content, is_secret=False):
|
|
|
129
154
|
amark="!",
|
|
130
155
|
vi_mode=True,
|
|
131
156
|
).execute().split(",")
|
|
132
|
-
content[key] = [item.strip() for item in value]
|
|
157
|
+
content[key] = [item.strip() for item in value if item.strip()]
|
|
133
158
|
|
|
134
159
|
|
|
135
160
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import asyncio
|
|
1
2
|
import os
|
|
2
3
|
import re
|
|
3
4
|
import subprocess
|
|
@@ -5,10 +6,8 @@ from typing import Any, Dict, List, cast
|
|
|
5
6
|
|
|
6
7
|
import appdirs
|
|
7
8
|
import discord
|
|
8
|
-
import
|
|
9
|
+
import httpx
|
|
9
10
|
import ollama
|
|
10
|
-
from google import genai
|
|
11
|
-
from google.genai.errors import ClientError
|
|
12
11
|
|
|
13
12
|
from .bot import client
|
|
14
13
|
from .data import ai, system_prompt_text
|
|
@@ -144,7 +143,6 @@ async def chat(message):
|
|
|
144
143
|
)
|
|
145
144
|
content = response.message.content or ""
|
|
146
145
|
elif provider == "gemini":
|
|
147
|
-
gemini_client = genai.Client(api_key=os.getenv("GEMINI"))
|
|
148
146
|
formatted_messages = []
|
|
149
147
|
for m in messages:
|
|
150
148
|
formatted_messages.append(
|
|
@@ -153,33 +151,55 @@ async def chat(message):
|
|
|
153
151
|
"parts": [{"text": m["content"]}],
|
|
154
152
|
}
|
|
155
153
|
)
|
|
156
|
-
|
|
157
|
-
config = None
|
|
154
|
+
body: Dict[str, Any] = {"contents": formatted_messages}
|
|
158
155
|
if system_prompt_text:
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
156
|
+
body["systemInstruction"] = {"parts": [{"text": system_prompt_text}]}
|
|
157
|
+
|
|
158
|
+
async with httpx.AsyncClient() as http:
|
|
159
|
+
resp = None
|
|
160
|
+
for attempt in range(4):
|
|
161
|
+
resp = await http.post(
|
|
162
|
+
f"https://generativelanguage.googleapis.com/v1beta/models/{ai['model']}:generateContent",
|
|
163
|
+
params={"key": os.getenv("GEMINI")},
|
|
164
|
+
json=body,
|
|
165
|
+
timeout=60,
|
|
166
|
+
)
|
|
167
|
+
if resp.status_code != 429:
|
|
168
|
+
break
|
|
169
|
+
data = resp.json()
|
|
170
|
+
retry_delay = None
|
|
171
|
+
is_daily_quota = False
|
|
172
|
+
for detail in data.get("error", {}).get("details", []):
|
|
173
|
+
if "retryDelay" in detail:
|
|
174
|
+
retry_delay = detail["retryDelay"]
|
|
175
|
+
if "violations" in detail:
|
|
176
|
+
for v in detail["violations"]:
|
|
177
|
+
if "PerDay" in v.get("quotaId", ""):
|
|
178
|
+
is_daily_quota = True
|
|
179
|
+
if is_daily_quota or attempt == 3:
|
|
180
|
+
resp.raise_for_status()
|
|
181
|
+
match = re.search(r"(\d+(?:\.\d+)?)", retry_delay or "")
|
|
182
|
+
wait = float(match.group(1)) if match else min(30 * (2 ** attempt), 120)
|
|
183
|
+
await asyncio.sleep(wait)
|
|
184
|
+
if resp is None:
|
|
185
|
+
raise RuntimeError("Gemini request never sent")
|
|
186
|
+
if resp.status_code == 404:
|
|
187
|
+
print(f"Model '{ai['model']}' not found. Check ai.toml for valid model name.")
|
|
188
|
+
resp.raise_for_status()
|
|
189
|
+
content = resp.json()["candidates"][0]["content"]["parts"][0]["text"]
|
|
173
190
|
elif provider == "groq":
|
|
174
|
-
groq_client = groq.Groq(api_key=os.getenv("GROQ"))
|
|
175
191
|
formatted_messages = [
|
|
176
192
|
{"role": "system", "content": system_prompt_text}
|
|
177
193
|
] + messages
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
194
|
+
async with httpx.AsyncClient() as http:
|
|
195
|
+
resp = await http.post(
|
|
196
|
+
"https://api.groq.com/openai/v1/chat/completions",
|
|
197
|
+
headers={"Authorization": f"Bearer {os.getenv('GROQ')}"},
|
|
198
|
+
json={"model": ai["model"], "messages": formatted_messages},
|
|
199
|
+
timeout=60,
|
|
200
|
+
)
|
|
201
|
+
resp.raise_for_status()
|
|
202
|
+
content = resp.json()["choices"][0]["message"]["content"] or ""
|
|
183
203
|
else:
|
|
184
204
|
raise ValueError(f"Unknown provider: {ai['provider']}")
|
|
185
205
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|