comprobot 2.2.5__tar.gz → 2.3.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.
- {comprobot-2.2.5 → comprobot-2.3.0}/PKG-INFO +2 -3
- {comprobot-2.2.5 → comprobot-2.3.0}/comprobot.egg-info/PKG-INFO +2 -3
- {comprobot-2.2.5 → comprobot-2.3.0}/comprobot.egg-info/requires.txt +1 -2
- {comprobot-2.2.5 → comprobot-2.3.0}/pyproject.toml +2 -3
- {comprobot-2.2.5 → comprobot-2.3.0}/src/api.py +13 -13
- {comprobot-2.2.5 → comprobot-2.3.0}/src/bot.py +1 -0
- comprobot-2.3.0/src/commands.py +54 -0
- {comprobot-2.2.5 → comprobot-2.3.0}/src/config.py +28 -3
- {comprobot-2.2.5 → comprobot-2.3.0}/src/data.py +11 -0
- {comprobot-2.2.5 → comprobot-2.3.0}/src/functions.py +46 -26
- {comprobot-2.2.5 → comprobot-2.3.0}/src/process.py +55 -47
- {comprobot-2.2.5 → comprobot-2.3.0}/src/templates.py +47 -3
- comprobot-2.2.5/src/commands.py +0 -27
- {comprobot-2.2.5 → comprobot-2.3.0}/LICENSE +0 -0
- {comprobot-2.2.5 → comprobot-2.3.0}/README.md +0 -0
- {comprobot-2.2.5 → comprobot-2.3.0}/comprobot.egg-info/SOURCES.txt +0 -0
- {comprobot-2.2.5 → comprobot-2.3.0}/comprobot.egg-info/dependency_links.txt +0 -0
- {comprobot-2.2.5 → comprobot-2.3.0}/comprobot.egg-info/entry_points.txt +0 -0
- {comprobot-2.2.5 → comprobot-2.3.0}/comprobot.egg-info/top_level.txt +0 -0
- {comprobot-2.2.5 → comprobot-2.3.0}/setup.cfg +0 -0
- {comprobot-2.2.5 → comprobot-2.3.0}/src/__init__.py +0 -0
- {comprobot-2.2.5 → comprobot-2.3.0}/src/__main__.py +0 -0
- {comprobot-2.2.5 → comprobot-2.3.0}/src/moderation.py +0 -0
- {comprobot-2.2.5 → comprobot-2.3.0}/src/money_system.py +0 -0
- {comprobot-2.2.5 → comprobot-2.3.0}/src/onboarding.py +0 -0
- {comprobot-2.2.5 → comprobot-2.3.0}/src/start.py +0 -0
- {comprobot-2.2.5 → comprobot-2.3.0}/src/testing.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: comprobot
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.0
|
|
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"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: comprobot
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.0
|
|
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"
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "comprobot"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.3.0"
|
|
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
|
|
|
@@ -39,7 +39,7 @@ def quote():
|
|
|
39
39
|
fetched_quote = data[0]["q"]
|
|
40
40
|
author = data[0]["a"]
|
|
41
41
|
response = (
|
|
42
|
-
choice(output["
|
|
42
|
+
choice(output["general"]["quote"])
|
|
43
43
|
.replace(r"{{QUOTE}}", fetched_quote)
|
|
44
44
|
.replace(r"{{AUTHOR}}", author)
|
|
45
45
|
)
|
|
@@ -54,7 +54,7 @@ def meme():
|
|
|
54
54
|
)
|
|
55
55
|
if not success:
|
|
56
56
|
return url
|
|
57
|
-
return choice(output["
|
|
57
|
+
return choice(output["general"]["meme"]).replace(r"{{URL}}", url)
|
|
58
58
|
|
|
59
59
|
|
|
60
60
|
def waifu():
|
|
@@ -69,7 +69,7 @@ def waifu():
|
|
|
69
69
|
if not success2:
|
|
70
70
|
return waifu2
|
|
71
71
|
return (
|
|
72
|
-
choice(output["
|
|
72
|
+
choice(output["general"]["waifu"])
|
|
73
73
|
.replace(r"{{URL1}}", waifu1)
|
|
74
74
|
.replace(r"{{URL2}}", waifu2)
|
|
75
75
|
)
|
|
@@ -81,7 +81,7 @@ def duck(): # TODO: Fix function (command doesnt respond)
|
|
|
81
81
|
)
|
|
82
82
|
if not success:
|
|
83
83
|
return url
|
|
84
|
-
return choice(output["
|
|
84
|
+
return choice(output["general"]["duck"]).replace(r"{{URL}}", url)
|
|
85
85
|
|
|
86
86
|
|
|
87
87
|
def dog():
|
|
@@ -90,7 +90,7 @@ def dog():
|
|
|
90
90
|
)
|
|
91
91
|
if not success:
|
|
92
92
|
return url
|
|
93
|
-
return choice(output["
|
|
93
|
+
return choice(output["general"]["dog"]).replace(r"{{URL}}", url)
|
|
94
94
|
|
|
95
95
|
|
|
96
96
|
def cat():
|
|
@@ -99,7 +99,7 @@ def cat():
|
|
|
99
99
|
return f"{error_messages['cat']} (HTTP {raw.status_code})"
|
|
100
100
|
try:
|
|
101
101
|
data = raw.json()
|
|
102
|
-
response = choice(output["
|
|
102
|
+
response = choice(output["general"]["cat"]).replace(r"{{URL}}", data[0]["url"])
|
|
103
103
|
except (requests.exceptions.JSONDecodeError, KeyError, IndexError):
|
|
104
104
|
response = error_messages["cat"]
|
|
105
105
|
return response
|
|
@@ -111,7 +111,7 @@ def chuck():
|
|
|
111
111
|
)
|
|
112
112
|
if not success:
|
|
113
113
|
return joke
|
|
114
|
-
return choice(output["
|
|
114
|
+
return choice(output["general"]["chuck_norris"]).replace(r"{{JOKE}}", joke)
|
|
115
115
|
|
|
116
116
|
|
|
117
117
|
def fact():
|
|
@@ -122,7 +122,7 @@ def fact():
|
|
|
122
122
|
)
|
|
123
123
|
if not success:
|
|
124
124
|
return fact_text
|
|
125
|
-
return choice(output["
|
|
125
|
+
return choice(output["general"]["fact"]).replace(r"{{FACT}}", fact_text)
|
|
126
126
|
|
|
127
127
|
|
|
128
128
|
def bible(
|
|
@@ -140,7 +140,7 @@ def bible(
|
|
|
140
140
|
if "random_verse" in data:
|
|
141
141
|
verse = data["random_verse"]
|
|
142
142
|
response = (
|
|
143
|
-
choice(output["
|
|
143
|
+
choice(output["general"]["bible"])
|
|
144
144
|
.replace(r"{{PASSAGE}}", verse["text"].strip())
|
|
145
145
|
.replace(r"{{BOOK}}", verse["book"].strip())
|
|
146
146
|
.replace(r"{{CHAPTER}}", str(verse["chapter"].strip()))
|
|
@@ -158,7 +158,7 @@ def bible(
|
|
|
158
158
|
)
|
|
159
159
|
verse_num = chapter_verse.split(":")[1] if ":" in chapter_verse else "1"
|
|
160
160
|
response = (
|
|
161
|
-
choice(output["
|
|
161
|
+
choice(output["general"]["bible"])
|
|
162
162
|
.replace(r"{{PASSAGE}}", data["text"].strip())
|
|
163
163
|
.replace(r"{{BOOK}}", book.strip())
|
|
164
164
|
.replace(r"{{CHAPTER}}", chapter.strip())
|
|
@@ -188,7 +188,7 @@ def bitcoin(currency_parameter):
|
|
|
188
188
|
data = bitcoin_price.json()
|
|
189
189
|
if "bitcoin" in data and currency in data["bitcoin"]:
|
|
190
190
|
response = (
|
|
191
|
-
choice(output["
|
|
191
|
+
choice(output["general"]["bitcoin"])
|
|
192
192
|
.replace(r"{{AMOUNT}}", str(data["bitcoin"][currency]))
|
|
193
193
|
.replace(r"{{CURRENCY}}", currency.upper())
|
|
194
194
|
)
|
|
@@ -217,7 +217,7 @@ def joke():
|
|
|
217
217
|
try:
|
|
218
218
|
data = raw.json()
|
|
219
219
|
response = (
|
|
220
|
-
choice(output["
|
|
220
|
+
choice(output["general"]["joke"])
|
|
221
221
|
.replace(r"{{SETUP}}", data["setup"])
|
|
222
222
|
.replace(r"{{PUNCHLINE}}", data["punchline"])
|
|
223
223
|
)
|
|
@@ -264,7 +264,7 @@ def currency(currency1, currency2, amount):
|
|
|
264
264
|
rate = raw_response[currency1][currency2]
|
|
265
265
|
converted_amount = rate * amount
|
|
266
266
|
response = (
|
|
267
|
-
choice(output["
|
|
267
|
+
choice(output["general"]["currency"])
|
|
268
268
|
.replace(r"{{FROM_AMOUNT}}", str(amount))
|
|
269
269
|
.replace(r"{{FROM_CURRENCY}}", currency1.upper())
|
|
270
270
|
.replace(r"{{TO_AMOUNT}}", f"{converted_amount:.2f}")
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
from random import choice
|
|
2
|
+
|
|
3
|
+
from .data import active, config, error_messages, keywords, output, descriptions
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def qr(link):
|
|
7
|
+
url = f"https://api.qrserver.com/v1/create-qr-code/?size=150x150&data={link}"
|
|
8
|
+
return choice(output["general"]["qr_code"]).replace(r"{{URL}}", url)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def calculate(calculation):
|
|
12
|
+
try:
|
|
13
|
+
result = eval(calculation)
|
|
14
|
+
response = choice(output["general"]["calculate"]).replace(
|
|
15
|
+
r"{{RESULT}}", str(result)
|
|
16
|
+
)
|
|
17
|
+
except ZeroDivisionError:
|
|
18
|
+
response = error_messages["calculate"]
|
|
19
|
+
except Exception:
|
|
20
|
+
response = error_messages["calculate"]
|
|
21
|
+
return response
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def help(category=None):
|
|
25
|
+
if not category:
|
|
26
|
+
message = "# Commands"
|
|
27
|
+
for category in list(keywords.keys()):
|
|
28
|
+
message += f"\n## {category.title()}\n"
|
|
29
|
+
for command in list(keywords[category].keys()):
|
|
30
|
+
if active.get(command, True):
|
|
31
|
+
message += f"\n**{config["prefix"]}{keywords[category][command][0]}** - {descriptions[category][command]}"
|
|
32
|
+
if len(keywords[category][command]) > 1:
|
|
33
|
+
message += f"\n-# Aliases: {config["prefix"]}{', '.join(keywords[category][command][1:])}"
|
|
34
|
+
message += "\n-# \u200b"
|
|
35
|
+
return message
|
|
36
|
+
else:
|
|
37
|
+
if not category.lower() in list(keywords.keys()):
|
|
38
|
+
return error_messages["unknown_category"]
|
|
39
|
+
message = f"## {category.title()}\n"
|
|
40
|
+
for command in list(keywords[category.lower()].keys()):
|
|
41
|
+
if active.get(command, True):
|
|
42
|
+
message += f"\n**{config["prefix"]}{keywords[category.lower()][command][0]}** - {descriptions[category.lower()][command]}"
|
|
43
|
+
if len(keywords[category.lower()][command]) > 1:
|
|
44
|
+
message += f"\n-# Aliases: {config["prefix"]}{', '.join(keywords[category][command][1:])}"
|
|
45
|
+
message += "\n-# "
|
|
46
|
+
return message
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def ascii():
|
|
50
|
+
if not config["ascii_art"]:
|
|
51
|
+
return error_messages["no_ascii_art"]
|
|
52
|
+
return choice(output["general"]["ascii_art"]).replace(
|
|
53
|
+
r"{{ASCII_ART}}", choice(config["ascii_art"])
|
|
54
|
+
)
|
|
@@ -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
|
|
|
@@ -29,6 +29,12 @@ def merge_defaults(data, defaults):
|
|
|
29
29
|
merge_defaults(data[key], value)
|
|
30
30
|
|
|
31
31
|
|
|
32
|
+
def migrate_section(data, old_key, new_key):
|
|
33
|
+
if old_key in data and new_key not in data:
|
|
34
|
+
data[new_key] = data[old_key]
|
|
35
|
+
del data[old_key]
|
|
36
|
+
|
|
37
|
+
|
|
32
38
|
def load_or_create(path, template_content):
|
|
33
39
|
try:
|
|
34
40
|
with open(path, "r", encoding="utf-8") as f:
|
|
@@ -38,6 +44,8 @@ def load_or_create(path, template_content):
|
|
|
38
44
|
with open(path, "r", encoding="utf-8") as f:
|
|
39
45
|
data = tomlkit.loads(f.read())
|
|
40
46
|
|
|
47
|
+
migrate_section(data, "commands", "general")
|
|
48
|
+
|
|
41
49
|
defaults = tomlkit.loads(template_content)
|
|
42
50
|
merge_defaults(data, defaults)
|
|
43
51
|
|
|
@@ -67,6 +75,9 @@ output: Dict[str, Dict[str, List[str]]] = load_or_create(
|
|
|
67
75
|
moderation: Dict[Any, Any] = load_or_create(
|
|
68
76
|
get_data_path("moderation.toml"), templates.moderation
|
|
69
77
|
)
|
|
78
|
+
descriptions: Dict[str, Dict[str, str]] = load_or_create(
|
|
79
|
+
get_data_path("descriptions.toml"), templates.descriptions
|
|
80
|
+
)
|
|
70
81
|
|
|
71
82
|
ensure_file(get_data_path(".env"), templates.env)
|
|
72
83
|
|
|
@@ -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
|
|
|
@@ -31,40 +31,40 @@ class Comprobot(ext_commands.Cog):
|
|
|
31
31
|
# ── Commands ─────────────────────────────────────────────────────────────
|
|
32
32
|
|
|
33
33
|
@ext_commands.command(
|
|
34
|
-
name=keywords["
|
|
35
|
-
aliases=keywords["
|
|
34
|
+
name=keywords["general"]["quote"][0],
|
|
35
|
+
aliases=keywords["general"]["quote"][1:],
|
|
36
36
|
)
|
|
37
37
|
@ext_commands.check(lambda ctx: active["quote"])
|
|
38
38
|
async def quote_cmd(self, ctx):
|
|
39
39
|
await ctx.send(api.quote())
|
|
40
40
|
|
|
41
41
|
@ext_commands.command(
|
|
42
|
-
name=keywords["
|
|
43
|
-
aliases=keywords["
|
|
42
|
+
name=keywords["general"]["joke"][0],
|
|
43
|
+
aliases=keywords["general"]["joke"][1:],
|
|
44
44
|
)
|
|
45
45
|
@ext_commands.check(lambda ctx: active["joke"])
|
|
46
46
|
async def joke_cmd(self, ctx):
|
|
47
47
|
await ctx.send(api.joke())
|
|
48
48
|
|
|
49
49
|
@ext_commands.command(
|
|
50
|
-
name=keywords["
|
|
51
|
-
aliases=keywords["
|
|
50
|
+
name=keywords["general"]["meme"][0],
|
|
51
|
+
aliases=keywords["general"]["meme"][1:],
|
|
52
52
|
)
|
|
53
53
|
@ext_commands.check(lambda ctx: active["meme"])
|
|
54
54
|
async def meme_cmd(self, ctx):
|
|
55
55
|
await ctx.send(api.meme())
|
|
56
56
|
|
|
57
57
|
@ext_commands.command(
|
|
58
|
-
name=keywords["
|
|
59
|
-
aliases=keywords["
|
|
58
|
+
name=keywords["general"]["waifu"][0],
|
|
59
|
+
aliases=keywords["general"]["waifu"][1:],
|
|
60
60
|
)
|
|
61
61
|
@ext_commands.check(lambda ctx: active["waifu"])
|
|
62
62
|
async def waifu_cmd(self, ctx):
|
|
63
63
|
await ctx.send(api.waifu())
|
|
64
64
|
|
|
65
65
|
@ext_commands.group(
|
|
66
|
-
name=keywords["
|
|
67
|
-
aliases=keywords["
|
|
66
|
+
name=keywords["general"]["image"][0],
|
|
67
|
+
aliases=keywords["general"]["image"][1:],
|
|
68
68
|
invoke_without_command=True,
|
|
69
69
|
)
|
|
70
70
|
@ext_commands.check(lambda ctx: active["image"])
|
|
@@ -72,48 +72,48 @@ class Comprobot(ext_commands.Cog):
|
|
|
72
72
|
await ctx.send(error_messages["missing_argument"])
|
|
73
73
|
|
|
74
74
|
@image_cmd.command(
|
|
75
|
-
name=keywords["
|
|
76
|
-
aliases=keywords["
|
|
75
|
+
name=keywords["general"]["duck"][0],
|
|
76
|
+
aliases=keywords["general"]["duck"][1:],
|
|
77
77
|
)
|
|
78
78
|
@ext_commands.check(lambda ctx: active["duck"])
|
|
79
79
|
async def duck_cmd(self, ctx):
|
|
80
80
|
await ctx.send(api.duck())
|
|
81
81
|
|
|
82
82
|
@image_cmd.command(
|
|
83
|
-
name=keywords["
|
|
84
|
-
aliases=keywords["
|
|
83
|
+
name=keywords["general"]["dog"][0],
|
|
84
|
+
aliases=keywords["general"]["dog"][1:],
|
|
85
85
|
)
|
|
86
86
|
@ext_commands.check(lambda ctx: active["dog"])
|
|
87
87
|
async def dog_cmd(self, ctx):
|
|
88
88
|
await ctx.send(api.dog())
|
|
89
89
|
|
|
90
90
|
@image_cmd.command(
|
|
91
|
-
name=keywords["
|
|
92
|
-
aliases=keywords["
|
|
91
|
+
name=keywords["general"]["cat"][0],
|
|
92
|
+
aliases=keywords["general"]["cat"][1:],
|
|
93
93
|
)
|
|
94
94
|
@ext_commands.check(lambda ctx: active["cat"])
|
|
95
95
|
async def cat_cmd(self, ctx):
|
|
96
96
|
await ctx.send(api.cat())
|
|
97
97
|
|
|
98
98
|
@ext_commands.command(
|
|
99
|
-
name=keywords["
|
|
100
|
-
aliases=keywords["
|
|
99
|
+
name=keywords["general"]["chuck_norris"][0],
|
|
100
|
+
aliases=keywords["general"]["chuck_norris"][1:],
|
|
101
101
|
)
|
|
102
102
|
@ext_commands.check(lambda ctx: active["chuck_norris"])
|
|
103
103
|
async def chuck_cmd(self, ctx):
|
|
104
104
|
await ctx.send(api.chuck())
|
|
105
105
|
|
|
106
106
|
@ext_commands.command(
|
|
107
|
-
name=keywords["
|
|
108
|
-
aliases=keywords["
|
|
107
|
+
name=keywords["general"]["fact"][0],
|
|
108
|
+
aliases=keywords["general"]["fact"][1:],
|
|
109
109
|
)
|
|
110
110
|
@ext_commands.check(lambda ctx: active["fact"])
|
|
111
111
|
async def fact_cmd(self, ctx):
|
|
112
112
|
await ctx.send(api.fact())
|
|
113
113
|
|
|
114
114
|
@ext_commands.command(
|
|
115
|
-
name=keywords["
|
|
116
|
-
aliases=keywords["
|
|
115
|
+
name=keywords["general"]["bible"][0],
|
|
116
|
+
aliases=keywords["general"]["bible"][1:],
|
|
117
117
|
)
|
|
118
118
|
@ext_commands.check(lambda ctx: active["bible"])
|
|
119
119
|
async def bible_cmd(self, ctx, book: str | None = None, chapter: int | None = None, verse: int | None = None):
|
|
@@ -125,68 +125,68 @@ class Comprobot(ext_commands.Cog):
|
|
|
125
125
|
await ctx.send(error_messages["missing_argument"])
|
|
126
126
|
|
|
127
127
|
@ext_commands.command(
|
|
128
|
-
name=keywords["
|
|
129
|
-
aliases=keywords["
|
|
128
|
+
name=keywords["general"]["truth"][0],
|
|
129
|
+
aliases=keywords["general"]["truth"][1:],
|
|
130
130
|
)
|
|
131
131
|
@ext_commands.check(lambda ctx: active["truth"])
|
|
132
132
|
async def truth_cmd(self, ctx, rating: str | None = None):
|
|
133
133
|
result = api.tord("https://api.truthordarebot.xyz/v1/truth", rating)
|
|
134
134
|
if result:
|
|
135
|
-
await ctx.send(choice(output["
|
|
135
|
+
await ctx.send(choice(output["general"]["truth"]).replace("{{QUESTION}}", result))
|
|
136
136
|
else:
|
|
137
137
|
await ctx.send(error_messages["truth"])
|
|
138
138
|
|
|
139
139
|
@ext_commands.command(
|
|
140
|
-
name=keywords["
|
|
141
|
-
aliases=keywords["
|
|
140
|
+
name=keywords["general"]["dare"][0],
|
|
141
|
+
aliases=keywords["general"]["dare"][1:],
|
|
142
142
|
)
|
|
143
143
|
@ext_commands.check(lambda ctx: active["dare"])
|
|
144
144
|
async def dare_cmd(self, ctx, rating: str | None = None):
|
|
145
145
|
result = api.tord("https://api.truthordarebot.xyz/api/dare", rating)
|
|
146
146
|
if result:
|
|
147
|
-
await ctx.send(choice(output["
|
|
147
|
+
await ctx.send(choice(output["general"]["dare"]).replace("{{QUESTION}}", result))
|
|
148
148
|
else:
|
|
149
149
|
await ctx.send(error_messages["dare"])
|
|
150
150
|
|
|
151
151
|
@ext_commands.command(
|
|
152
|
-
name=keywords["
|
|
153
|
-
aliases=keywords["
|
|
152
|
+
name=keywords["general"]["wyr"][0],
|
|
153
|
+
aliases=keywords["general"]["wyr"][1:],
|
|
154
154
|
)
|
|
155
155
|
@ext_commands.check(lambda ctx: active["wyr"])
|
|
156
156
|
async def wyr_cmd(self, ctx, rating: str | None = None):
|
|
157
157
|
result = api.tord("https://api.truthordarebot.xyz/api/wyr", rating)
|
|
158
158
|
if result:
|
|
159
|
-
await ctx.send(choice(output["
|
|
159
|
+
await ctx.send(choice(output["general"]["wyr"]).replace("{{QUESTION}}", result))
|
|
160
160
|
else:
|
|
161
161
|
await ctx.send(error_messages["wyr"])
|
|
162
162
|
|
|
163
163
|
@ext_commands.command(
|
|
164
|
-
name=keywords["
|
|
165
|
-
aliases=keywords["
|
|
164
|
+
name=keywords["general"]["never_have_i_ever"][0],
|
|
165
|
+
aliases=keywords["general"]["never_have_i_ever"][1:],
|
|
166
166
|
)
|
|
167
167
|
@ext_commands.check(lambda ctx: active["never_have_i_ever"])
|
|
168
168
|
async def nhie_cmd(self, ctx, rating: str | None = None):
|
|
169
169
|
result = api.tord("https://api.truthordarebot.xyz/api/nhie", rating)
|
|
170
170
|
if result:
|
|
171
|
-
await ctx.send(choice(output["
|
|
171
|
+
await ctx.send(choice(output["general"]["never_have_i_ever"]).replace("{{QUESTION}}", result))
|
|
172
172
|
else:
|
|
173
173
|
await ctx.send(error_messages["never-hie"])
|
|
174
174
|
|
|
175
175
|
@ext_commands.command(
|
|
176
|
-
name=keywords["
|
|
177
|
-
aliases=keywords["
|
|
176
|
+
name=keywords["general"]["paranoia"][0],
|
|
177
|
+
aliases=keywords["general"]["paranoia"][1:],
|
|
178
178
|
)
|
|
179
179
|
@ext_commands.check(lambda ctx: active["paranoia"])
|
|
180
180
|
async def paranoia_cmd(self, ctx, rating: str | None = None):
|
|
181
181
|
result = api.tord("https://api.truthordarebot.xyz/api/paranoia", rating)
|
|
182
182
|
if result:
|
|
183
|
-
await ctx.send(choice(output["
|
|
183
|
+
await ctx.send(choice(output["general"]["paranoia"]).replace("{{QUESTION}}", result))
|
|
184
184
|
else:
|
|
185
185
|
await ctx.send(error_messages["paranoia"])
|
|
186
186
|
|
|
187
187
|
@ext_commands.command(
|
|
188
|
-
name=keywords["
|
|
189
|
-
aliases=keywords["
|
|
188
|
+
name=keywords["general"]["qr_code"][0],
|
|
189
|
+
aliases=keywords["general"]["qr_code"][1:],
|
|
190
190
|
)
|
|
191
191
|
@ext_commands.check(lambda ctx: active["qr_code"])
|
|
192
192
|
async def qr_cmd(self, ctx, link: str | None = None):
|
|
@@ -196,8 +196,8 @@ class Comprobot(ext_commands.Cog):
|
|
|
196
196
|
await ctx.send(error_messages["missing_argument"])
|
|
197
197
|
|
|
198
198
|
@ext_commands.command(
|
|
199
|
-
name=keywords["
|
|
200
|
-
aliases=keywords["
|
|
199
|
+
name=keywords["general"]["calculate"][0],
|
|
200
|
+
aliases=keywords["general"]["calculate"][1:],
|
|
201
201
|
)
|
|
202
202
|
@ext_commands.check(lambda ctx: active["calculate"])
|
|
203
203
|
async def calculate_cmd(self, ctx, *, expression: str | None = None):
|
|
@@ -207,23 +207,31 @@ class Comprobot(ext_commands.Cog):
|
|
|
207
207
|
await ctx.send(error_messages["missing_argument"])
|
|
208
208
|
|
|
209
209
|
@ext_commands.command(
|
|
210
|
-
name=keywords["
|
|
211
|
-
aliases=keywords["
|
|
210
|
+
name=keywords["general"]["bitcoin"][0],
|
|
211
|
+
aliases=keywords["general"]["bitcoin"][1:],
|
|
212
212
|
)
|
|
213
213
|
@ext_commands.check(lambda ctx: active["bitcoin"])
|
|
214
214
|
async def bitcoin_cmd(self, ctx, currency: str = "usd"):
|
|
215
215
|
await ctx.send(api.bitcoin(currency))
|
|
216
216
|
|
|
217
217
|
@ext_commands.command(
|
|
218
|
-
name=keywords["
|
|
219
|
-
aliases=keywords["
|
|
218
|
+
name=keywords["general"]["help"][0],
|
|
219
|
+
aliases=keywords["general"]["help"][1:],
|
|
220
|
+
)
|
|
221
|
+
@ext_commands.check(lambda ctx: active["help"])
|
|
222
|
+
async def help_cmd(self, ctx, category: str | None = None):
|
|
223
|
+
await ctx.send(cmd_module.help(category))
|
|
224
|
+
|
|
225
|
+
@ext_commands.command(
|
|
226
|
+
name=keywords["general"]["ascii_art"][0],
|
|
227
|
+
aliases=keywords["general"]["ascii_art"][1:],
|
|
220
228
|
)
|
|
221
229
|
async def ascii_cmd(self, ctx):
|
|
222
230
|
await ctx.send(cmd_module.ascii())
|
|
223
231
|
|
|
224
232
|
@ext_commands.command(
|
|
225
|
-
name=keywords["
|
|
226
|
-
aliases=keywords["
|
|
233
|
+
name=keywords["general"]["currency"][0],
|
|
234
|
+
aliases=keywords["general"]["currency"][1:],
|
|
227
235
|
)
|
|
228
236
|
@ext_commands.check(lambda ctx: active["currency"])
|
|
229
237
|
async def currency_cmd(self, ctx, amount: str | None = None, from_currency: str | None = None, to_currency: str | None = None):
|
|
@@ -71,9 +71,11 @@ unknown_command = "Unknown command."
|
|
|
71
71
|
unknown_argument = "Unknown argument."
|
|
72
72
|
missing_argument = "Missing argument."
|
|
73
73
|
no_attachment = "No attachment given."
|
|
74
|
-
bot_unavailable = "Bot not available."
|
|
74
|
+
bot_unavailable = "Bot not available."
|
|
75
|
+
unknown_category = "Unknown category."
|
|
76
|
+
no_ascii_art = "No ASCII art available."'''
|
|
75
77
|
|
|
76
|
-
keywords = r"""[
|
|
78
|
+
keywords = r"""[general]
|
|
77
79
|
quote = ["quote"]
|
|
78
80
|
joke = ["joke"]
|
|
79
81
|
meme = ["meme"]
|
|
@@ -90,6 +92,7 @@ bitcoin = ["bitcoin", "btc"]
|
|
|
90
92
|
currency = ["currency", "convert", "conv"]
|
|
91
93
|
qr_code = ["qr_code", "qr"]
|
|
92
94
|
ascii_art = ["ascii", "art"]
|
|
95
|
+
help = ["help"]
|
|
93
96
|
|
|
94
97
|
truth = ["truth"]
|
|
95
98
|
dare = ["dare"]
|
|
@@ -136,6 +139,7 @@ calculate = true
|
|
|
136
139
|
bitcoin = true
|
|
137
140
|
currency = true
|
|
138
141
|
qr_code = true
|
|
142
|
+
help = true
|
|
139
143
|
|
|
140
144
|
truth = true
|
|
141
145
|
dare = true
|
|
@@ -148,7 +152,47 @@ nsfw = false
|
|
|
148
152
|
purge = true
|
|
149
153
|
"""
|
|
150
154
|
|
|
151
|
-
|
|
155
|
+
descriptions = r"""[general]
|
|
156
|
+
quote = "Get a random inspirational quote."
|
|
157
|
+
joke = "Get a random two-part joke"
|
|
158
|
+
meme = "Get a random meme image"
|
|
159
|
+
waifu = "Compare two random waifu images"
|
|
160
|
+
image = "Get a random animal image (duck/dog/cat)"
|
|
161
|
+
duck = "Get a random duck image"
|
|
162
|
+
dog = "Get a random dog image"
|
|
163
|
+
cat = "Get a random cat image"
|
|
164
|
+
chuck_norris = "Get a random Chuck Norris fact"
|
|
165
|
+
fact = "Get a random fun fact"
|
|
166
|
+
bible = "Get a random or specific Bible verse"
|
|
167
|
+
calculate = "Evaluate a math expression"
|
|
168
|
+
bitcoin = "Get the current Bitcoin price in a given currency"
|
|
169
|
+
currency = "Convert an amount between two currencies"
|
|
170
|
+
qr_code = "Generate a QR code from a URL"
|
|
171
|
+
ascii_art = "Display the bot's ASCII art"
|
|
172
|
+
help = "Show available commands"
|
|
173
|
+
|
|
174
|
+
truth = "Get a truth question for truth or dare"
|
|
175
|
+
dare = "Get a dare challenge for truth or dare"
|
|
176
|
+
wyr = "Get a would you rather question"
|
|
177
|
+
never_have_i_ever = "Get a never have I ever prompt"
|
|
178
|
+
paranoia = "Get a paranoia question"
|
|
179
|
+
|
|
180
|
+
purge = "Delete all messages in the channel (admin only)"
|
|
181
|
+
|
|
182
|
+
[settings]
|
|
183
|
+
settings = "Configure the bot"
|
|
184
|
+
profile_picture = "Change the bot's profile picture"
|
|
185
|
+
banner = "Change the bot's banner"
|
|
186
|
+
change_name = "Change the bot's username"
|
|
187
|
+
change_keywords = "Change a command's trigger keywords"
|
|
188
|
+
|
|
189
|
+
[money]
|
|
190
|
+
check_balance = "Check a user's money balance"
|
|
191
|
+
add_money = "Add money to a user's balance (admin only)"
|
|
192
|
+
remove_money = "Remove money from a user's balance (admin only)"
|
|
193
|
+
"""
|
|
194
|
+
|
|
195
|
+
output = r"""[general]
|
|
152
196
|
quote = ["{{QUOTE}}\n~ {{AUTHOR}}"]
|
|
153
197
|
joke = ["{{SETUP}} ||{{PUNCHLINE}}||"]
|
|
154
198
|
meme = ["{{URL}}"]
|
comprobot-2.2.5/src/commands.py
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
from random import choice
|
|
2
|
-
|
|
3
|
-
from .data import config, error_messages, output
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def qr(link):
|
|
7
|
-
url = f"https://api.qrserver.com/v1/create-qr-code/?size=150x150&data={link}"
|
|
8
|
-
return choice(output["commands"]["qr_code"]).replace(r"{{URL}}", url)
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def calculate(calculation):
|
|
12
|
-
try:
|
|
13
|
-
result = eval(calculation)
|
|
14
|
-
response = choice(output["commands"]["calculate"]).replace(
|
|
15
|
-
r"{{RESULT}}", str(result)
|
|
16
|
-
)
|
|
17
|
-
except ZeroDivisionError:
|
|
18
|
-
response = error_messages["calculate"]
|
|
19
|
-
except Exception:
|
|
20
|
-
response = error_messages["calculate"]
|
|
21
|
-
return response
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def ascii():
|
|
25
|
-
return choice(output["commands"]["ascii_art"]).replace(
|
|
26
|
-
r"{{ASCII_ART}}", choice(config["ascii_art"])
|
|
27
|
-
)
|
|
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
|