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.
Files changed (26) hide show
  1. {comprobot-2.2.4 → comprobot-2.2.6}/PKG-INFO +6 -6
  2. {comprobot-2.2.4 → comprobot-2.2.6}/README.md +4 -3
  3. {comprobot-2.2.4 → comprobot-2.2.6}/comprobot.egg-info/PKG-INFO +6 -6
  4. {comprobot-2.2.4 → comprobot-2.2.6}/comprobot.egg-info/requires.txt +1 -2
  5. {comprobot-2.2.4 → comprobot-2.2.6}/pyproject.toml +2 -3
  6. {comprobot-2.2.4 → comprobot-2.2.6}/src/__main__.py +0 -2
  7. {comprobot-2.2.4 → comprobot-2.2.6}/src/config.py +28 -3
  8. {comprobot-2.2.4 → comprobot-2.2.6}/src/functions.py +46 -26
  9. {comprobot-2.2.4 → comprobot-2.2.6}/LICENSE +0 -0
  10. {comprobot-2.2.4 → comprobot-2.2.6}/comprobot.egg-info/SOURCES.txt +0 -0
  11. {comprobot-2.2.4 → comprobot-2.2.6}/comprobot.egg-info/dependency_links.txt +0 -0
  12. {comprobot-2.2.4 → comprobot-2.2.6}/comprobot.egg-info/entry_points.txt +0 -0
  13. {comprobot-2.2.4 → comprobot-2.2.6}/comprobot.egg-info/top_level.txt +0 -0
  14. {comprobot-2.2.4 → comprobot-2.2.6}/setup.cfg +0 -0
  15. {comprobot-2.2.4 → comprobot-2.2.6}/src/__init__.py +0 -0
  16. {comprobot-2.2.4 → comprobot-2.2.6}/src/api.py +0 -0
  17. {comprobot-2.2.4 → comprobot-2.2.6}/src/bot.py +0 -0
  18. {comprobot-2.2.4 → comprobot-2.2.6}/src/commands.py +0 -0
  19. {comprobot-2.2.4 → comprobot-2.2.6}/src/data.py +0 -0
  20. {comprobot-2.2.4 → comprobot-2.2.6}/src/moderation.py +0 -0
  21. {comprobot-2.2.4 → comprobot-2.2.6}/src/money_system.py +0 -0
  22. {comprobot-2.2.4 → comprobot-2.2.6}/src/onboarding.py +0 -0
  23. {comprobot-2.2.4 → comprobot-2.2.6}/src/process.py +0 -0
  24. {comprobot-2.2.4 → comprobot-2.2.6}/src/start.py +0 -0
  25. {comprobot-2.2.4 → comprobot-2.2.6}/src/templates.py +0 -0
  26. {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.4
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: google-genai
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. 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.
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 && sudo apt upgrade
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. 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.
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 && sudo apt upgrade
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.4
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: google-genai
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. 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.
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 && sudo apt upgrade
48
+ sudo apt update
49
49
  sudo apt install comprobot
50
50
  ```
51
51
 
@@ -4,8 +4,7 @@ requests
4
4
  tomlkit
5
5
  appdirs
6
6
  ollama
7
- google-genai
8
- groq
7
+ httpx
9
8
  InquirerPy
10
9
 
11
10
  [dev]
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "comprobot"
7
- version = "2.2.4"
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
- "google-genai",
26
- "groq",
25
+ "httpx",
27
26
  "InquirerPy",
28
27
  ]
29
28
 
@@ -23,8 +23,6 @@ def main():
23
23
 
24
24
  args = parser.parse_args()
25
25
 
26
- print(args)
27
-
28
26
  match args.command:
29
27
  case "start":
30
28
  start()
@@ -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() | int():
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 groq
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
- config = genai.types.GenerateContentConfig(
160
- system_instruction=system_prompt_text
161
- )
162
-
163
- try:
164
- response = gemini_client.models.generate_content(
165
- model=ai["model"], contents=formatted_messages, config=config
166
- )
167
- content = response.text or ""
168
- except ClientError as e:
169
- if "NOT_FOUND" in str(e) or "404" in str(e):
170
- available = gemini_client.models.list()
171
- print(f"Available models: {[m.name for m in available]}")
172
- raise
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
- response = groq_client.chat.completions.create(
179
- model=cast(str, ai["model"]),
180
- messages=cast(Any, formatted_messages),
181
- )
182
- content = response.choices[0].message.content or ""
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