comprobot 2.0.4__tar.gz → 2.1.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.1.0/Comprobot/__main__.py +77 -0
- {comprobot-2.0.4 → comprobot-2.1.0}/Comprobot/bot.py +3 -2
- comprobot-2.1.0/Comprobot/data.py +76 -0
- {comprobot-2.0.4 → comprobot-2.1.0}/Comprobot/functions.py +3 -2
- {comprobot-2.0.4 → comprobot-2.1.0}/Comprobot/money_system.py +4 -4
- comprobot-2.1.0/Comprobot/onboarding.py +180 -0
- {comprobot-2.0.4 → comprobot-2.1.0}/Comprobot/templates.py +1 -10
- {comprobot-2.0.4/comprobot.egg-info → comprobot-2.1.0}/PKG-INFO +3 -2
- {comprobot-2.0.4 → comprobot-2.1.0}/README.md +1 -1
- {comprobot-2.0.4 → comprobot-2.1.0/comprobot.egg-info}/PKG-INFO +3 -2
- {comprobot-2.0.4 → comprobot-2.1.0}/comprobot.egg-info/SOURCES.txt +1 -0
- {comprobot-2.0.4 → comprobot-2.1.0}/comprobot.egg-info/requires.txt +1 -0
- {comprobot-2.0.4 → comprobot-2.1.0}/pyproject.toml +2 -1
- comprobot-2.0.4/Comprobot/__main__.py +0 -4
- comprobot-2.0.4/Comprobot/data.py +0 -84
- {comprobot-2.0.4 → comprobot-2.1.0}/Comprobot/__init__.py +0 -0
- {comprobot-2.0.4 → comprobot-2.1.0}/Comprobot/api.py +0 -0
- {comprobot-2.0.4 → comprobot-2.1.0}/Comprobot/commands.py +0 -0
- {comprobot-2.0.4 → comprobot-2.1.0}/Comprobot/main.py +0 -0
- {comprobot-2.0.4 → comprobot-2.1.0}/Comprobot/moderation.py +0 -0
- {comprobot-2.0.4 → comprobot-2.1.0}/Comprobot/process.py +0 -0
- {comprobot-2.0.4 → comprobot-2.1.0}/comprobot.egg-info/dependency_links.txt +0 -0
- {comprobot-2.0.4 → comprobot-2.1.0}/comprobot.egg-info/entry_points.txt +0 -0
- {comprobot-2.0.4 → comprobot-2.1.0}/comprobot.egg-info/top_level.txt +0 -0
- {comprobot-2.0.4 → comprobot-2.1.0}/setup.cfg +0 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
|
|
3
|
+
import dotenv
|
|
4
|
+
|
|
5
|
+
from .data import active, ai, get_data_path, save_toml
|
|
6
|
+
from .main import main
|
|
7
|
+
from .onboarding import onboarding
|
|
8
|
+
|
|
9
|
+
parser = argparse.ArgumentParser(
|
|
10
|
+
prog="comprobot",
|
|
11
|
+
description="A self-hostable open-source Discord bot built for maximum customization.",
|
|
12
|
+
)
|
|
13
|
+
subparsers = parser.add_subparsers(dest="command", metavar="")
|
|
14
|
+
subparsers.add_parser("onboard", help="Set up Comprobot for the first time.")
|
|
15
|
+
subparsers.add_parser("start", help="Start the bot.")
|
|
16
|
+
# subparsers.add_parser("config", help="View or edit the bot's configuration.") TODO: implement config command
|
|
17
|
+
# subparsers.add_parser("reset", help="Reset the bot's data and configuration.") TODO: implement reset command
|
|
18
|
+
|
|
19
|
+
args = parser.parse_args()
|
|
20
|
+
|
|
21
|
+
settings: dict = {}
|
|
22
|
+
|
|
23
|
+
if __name__ == "__main__":
|
|
24
|
+
match args.command:
|
|
25
|
+
case "start":
|
|
26
|
+
main()
|
|
27
|
+
case "onboard":
|
|
28
|
+
settings = onboarding()
|
|
29
|
+
|
|
30
|
+
dotenv.set_key(
|
|
31
|
+
dotenv_path=".env",
|
|
32
|
+
key_to_set="BOT_TOKEN",
|
|
33
|
+
value_to_set=str(settings["token"]),
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
for key in active:
|
|
37
|
+
if key in settings["commands_activated"]:
|
|
38
|
+
active[key] = True
|
|
39
|
+
else:
|
|
40
|
+
active[key] = False
|
|
41
|
+
|
|
42
|
+
ai["activated"] = settings["ai_activated"]
|
|
43
|
+
|
|
44
|
+
ai["provider"] = settings["provider"]
|
|
45
|
+
|
|
46
|
+
if settings["provider"] == "groq":
|
|
47
|
+
dotenv.set_key(
|
|
48
|
+
dotenv_path=".env",
|
|
49
|
+
key_to_set="GROQ",
|
|
50
|
+
value_to_set=settings["api_key"],
|
|
51
|
+
)
|
|
52
|
+
dotenv.set_key(dotenv_path=".env", key_to_set="GEMINI", value_to_set="")
|
|
53
|
+
|
|
54
|
+
elif settings["provider"] == "gemini":
|
|
55
|
+
dotenv.set_key(
|
|
56
|
+
dotenv_path=".env",
|
|
57
|
+
key_to_set="GEMINI",
|
|
58
|
+
value_to_set=settings["api_key"],
|
|
59
|
+
)
|
|
60
|
+
dotenv.set_key(dotenv_path=".env", key_to_set="GROQ", value_to_set="")
|
|
61
|
+
|
|
62
|
+
else:
|
|
63
|
+
dotenv.set_key(dotenv_path=".env", key_to_set="GROQ", value_to_set="")
|
|
64
|
+
dotenv.set_key(dotenv_path=".env", key_to_set="GEMINI", value_to_set="")
|
|
65
|
+
|
|
66
|
+
if settings["model"]:
|
|
67
|
+
ai["model"] = settings["model"]
|
|
68
|
+
else:
|
|
69
|
+
ai["model"] = ""
|
|
70
|
+
|
|
71
|
+
save_toml(ai, get_data_path("ai.toml"))
|
|
72
|
+
save_toml(active, get_data_path("active.toml"))
|
|
73
|
+
|
|
74
|
+
main()
|
|
75
|
+
|
|
76
|
+
case _:
|
|
77
|
+
print(parser.format_help())
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from typing import Any, Dict, List
|
|
3
|
+
|
|
4
|
+
import appdirs
|
|
5
|
+
import tomlkit
|
|
6
|
+
|
|
7
|
+
from . import templates
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def get_data_path(filename):
|
|
11
|
+
|
|
12
|
+
base_dir = appdirs.user_data_dir(appname="Comprobot", appauthor=False)
|
|
13
|
+
return os.path.join(base_dir, filename)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def ensure_file(path, content):
|
|
17
|
+
|
|
18
|
+
os.makedirs(os.path.dirname(path), exist_ok=True)
|
|
19
|
+
if not os.path.isfile(path):
|
|
20
|
+
with open(path, "w") as f:
|
|
21
|
+
f.write(content)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def merge_defaults(data, defaults):
|
|
25
|
+
for key, value in defaults.items():
|
|
26
|
+
if key not in data:
|
|
27
|
+
data[key] = value
|
|
28
|
+
elif isinstance(value, dict) and isinstance(data.get(key), dict):
|
|
29
|
+
merge_defaults(data[key], value)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def load_or_create(path, template_content):
|
|
33
|
+
try:
|
|
34
|
+
with open(path, "rb") as f:
|
|
35
|
+
data = tomlkit.load(f)
|
|
36
|
+
except FileNotFoundError:
|
|
37
|
+
ensure_file(path, template_content)
|
|
38
|
+
with open(path, "rb") as f:
|
|
39
|
+
data = tomlkit.load(f)
|
|
40
|
+
|
|
41
|
+
defaults = tomlkit.loads(template_content)
|
|
42
|
+
merge_defaults(data, defaults)
|
|
43
|
+
|
|
44
|
+
if data != defaults:
|
|
45
|
+
with open(path, "w") as f:
|
|
46
|
+
tomlkit.dump(data, f)
|
|
47
|
+
|
|
48
|
+
return data
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
error_messages: Dict[str, str] = load_or_create(
|
|
52
|
+
get_data_path("error-messages.toml"), templates.error_messages
|
|
53
|
+
)
|
|
54
|
+
config: Dict[str, Any] = load_or_create(get_data_path("config.toml"), templates.config)
|
|
55
|
+
keywords: Dict[str, Dict[str, List[str]]] = load_or_create(
|
|
56
|
+
get_data_path("keywords.toml"), templates.keywords
|
|
57
|
+
)
|
|
58
|
+
ai: Dict[str, Any] = load_or_create(get_data_path("ai.toml"), templates.ai)
|
|
59
|
+
system_prompt_text = ai["system_prompt"]
|
|
60
|
+
money: Dict[str, Dict[str, int]] = load_or_create(
|
|
61
|
+
get_data_path("money.toml"), r"""members = {}"""
|
|
62
|
+
)
|
|
63
|
+
active: Dict[str, bool] = load_or_create(get_data_path("active.toml"), templates.active)
|
|
64
|
+
output: Dict[str, Dict[str, List[str]]] = load_or_create(
|
|
65
|
+
get_data_path("output.toml"), templates.output
|
|
66
|
+
)
|
|
67
|
+
moderation: Dict[Any, Any] = load_or_create(
|
|
68
|
+
get_data_path("moderation.toml"), templates.moderation
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
ensure_file(get_data_path(".env"), templates.env)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def save_toml(data, path):
|
|
75
|
+
with open(path, "w") as f:
|
|
76
|
+
tomlkit.dump(data, f)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import re
|
|
3
|
+
import subprocess
|
|
3
4
|
from typing import Any, Dict, List, cast
|
|
4
5
|
|
|
5
6
|
import appdirs
|
|
@@ -22,9 +23,9 @@ def para(count=1):
|
|
|
22
23
|
|
|
23
24
|
def clear():
|
|
24
25
|
if os.name == "nt":
|
|
25
|
-
|
|
26
|
+
subprocess.call("cls")
|
|
26
27
|
else:
|
|
27
|
-
|
|
28
|
+
subprocess.call("clear")
|
|
28
29
|
|
|
29
30
|
|
|
30
31
|
async def direct_msg(message, author_message):
|
|
@@ -6,7 +6,7 @@ import tomlkit.exceptions
|
|
|
6
6
|
|
|
7
7
|
def add_money(username, amount):
|
|
8
8
|
data.money["members"][username] = data.money["members"].get(username, 0) + amount
|
|
9
|
-
data.
|
|
9
|
+
data.save_toml(data.money, data.get_data_path("money.toml"))
|
|
10
10
|
balance = data.money["members"][username]
|
|
11
11
|
return (
|
|
12
12
|
choice(data.output["money"]["add_money"])
|
|
@@ -21,7 +21,7 @@ def remove_money(username, amount):
|
|
|
21
21
|
current = data.money["members"].get(username, 0)
|
|
22
22
|
if current < amount:
|
|
23
23
|
data.money["members"][username] = 0
|
|
24
|
-
data.
|
|
24
|
+
data.save_toml(data.money, data.get_data_path("money.toml"))
|
|
25
25
|
return (
|
|
26
26
|
choice(data.output["money"]["insufficient_funds"])
|
|
27
27
|
.replace("{{USERNAME}}", username)
|
|
@@ -30,7 +30,7 @@ def remove_money(username, amount):
|
|
|
30
30
|
)
|
|
31
31
|
else:
|
|
32
32
|
data.money["members"][username] -= amount
|
|
33
|
-
data.
|
|
33
|
+
data.save_toml(data.money, data.get_data_path("money.toml"))
|
|
34
34
|
balance = data.money["members"][username]
|
|
35
35
|
return (
|
|
36
36
|
choice(data.output["money"]["remove_money"])
|
|
@@ -46,7 +46,7 @@ def check_balance(username):
|
|
|
46
46
|
balance = data.money["members"][username]
|
|
47
47
|
except (KeyError, tomlkit.exceptions.NonExistentKey):
|
|
48
48
|
data.money["members"][username] = 0
|
|
49
|
-
data.
|
|
49
|
+
data.save_toml(data.money, data.get_data_path("money.toml"))
|
|
50
50
|
balance = 0
|
|
51
51
|
return (
|
|
52
52
|
choice(data.output["money"]["check_balance"])
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
import appdirs
|
|
5
|
+
import InquirerPy.utils
|
|
6
|
+
import tomlkit
|
|
7
|
+
from InquirerPy.base.control import Choice
|
|
8
|
+
from InquirerPy.prompts import checkbox, confirm, input, secret
|
|
9
|
+
from InquirerPy.prompts import list as inquirer_list
|
|
10
|
+
|
|
11
|
+
from .data import config
|
|
12
|
+
|
|
13
|
+
ACCENT = "\033[0;36m"
|
|
14
|
+
GRAY = "\u001b[0;37m"
|
|
15
|
+
RESET = "\033[0m"
|
|
16
|
+
|
|
17
|
+
style = InquirerPy.utils.InquirerPyStyle({"questionmark": "white"})
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def onboarding():
|
|
21
|
+
from . import templates
|
|
22
|
+
|
|
23
|
+
active_data = tomlkit.loads(templates.active)
|
|
24
|
+
all_commands = list(active_data.keys())
|
|
25
|
+
active_choices = [Choice(value, enabled=True) for value in all_commands]
|
|
26
|
+
|
|
27
|
+
print(f"\n{ACCENT}Welcome to Comprobot{RESET}")
|
|
28
|
+
print("Thank you so much for downloading this bot!")
|
|
29
|
+
print("I am going to guide you through the process of setting it up.")
|
|
30
|
+
print(f"- First, go to {ACCENT}discord.com/developers/applications{RESET}.")
|
|
31
|
+
print("- Create a new application.")
|
|
32
|
+
print(
|
|
33
|
+
f"- Under the {ACCENT}Bot{RESET} section, you can customize the bot's name, avatar and banner."
|
|
34
|
+
)
|
|
35
|
+
print(f"- Next, head to the {ACCENT}OAuth2{RESET} section.")
|
|
36
|
+
print(
|
|
37
|
+
f"- Under {ACCENT}OAuth2 URL Generator{RESET}, select only the {ACCENT}bot{RESET} option."
|
|
38
|
+
)
|
|
39
|
+
print(
|
|
40
|
+
f"- Then, scroll down to {ACCENT}Bot Permissions{RESET} and select {ACCENT}Administrator{RESET}."
|
|
41
|
+
)
|
|
42
|
+
print(
|
|
43
|
+
f"- Copy the link and open it in a new tab. Select your server, then click {ACCENT}Continue{RESET} and {ACCENT}Authorize{RESET}"
|
|
44
|
+
)
|
|
45
|
+
print(
|
|
46
|
+
f"- Back on the {ACCENT}Application dashboard{RESET}, head back to the {ACCENT}Bot{RESET} section."
|
|
47
|
+
)
|
|
48
|
+
print(
|
|
49
|
+
f"- Click on {ACCENT}Reset Token{RESET} and then on {ACCENT}Yes, do it!{RESET}."
|
|
50
|
+
)
|
|
51
|
+
print("- Copy the new token and paste it here.")
|
|
52
|
+
print()
|
|
53
|
+
|
|
54
|
+
try:
|
|
55
|
+
# 1. Bot Token
|
|
56
|
+
token = secret.SecretPrompt(
|
|
57
|
+
message="Your bot token:",
|
|
58
|
+
style=style,
|
|
59
|
+
vi_mode=True,
|
|
60
|
+
).execute()
|
|
61
|
+
|
|
62
|
+
print()
|
|
63
|
+
|
|
64
|
+
# 2. Commands to activate
|
|
65
|
+
commands_activated = checkbox.CheckboxPrompt(
|
|
66
|
+
message="Select commands to activate:",
|
|
67
|
+
instruction="Press Space to deselect and press Enter to continue.",
|
|
68
|
+
choices=active_choices,
|
|
69
|
+
style=style,
|
|
70
|
+
transformer=lambda result: (
|
|
71
|
+
f"{len(result)} commands selected" if result else "No commands selected"
|
|
72
|
+
),
|
|
73
|
+
show_cursor=False,
|
|
74
|
+
).execute()
|
|
75
|
+
|
|
76
|
+
print()
|
|
77
|
+
|
|
78
|
+
# 3. Activate AI features
|
|
79
|
+
ai_activated = confirm.ConfirmPrompt(
|
|
80
|
+
message="Do you want to activate AI features?", style=style, default=True
|
|
81
|
+
).execute()
|
|
82
|
+
if ai_activated:
|
|
83
|
+
print()
|
|
84
|
+
|
|
85
|
+
# 3.1. Select provider
|
|
86
|
+
provider = inquirer_list.ListPrompt(
|
|
87
|
+
message="Select a provider:",
|
|
88
|
+
choices=[
|
|
89
|
+
Choice(value="groq", name="Groq (recommended)"),
|
|
90
|
+
Choice(value="gemini", name="Gemini"),
|
|
91
|
+
Choice(value="ollama", name="Ollama (local)"),
|
|
92
|
+
],
|
|
93
|
+
default="groq",
|
|
94
|
+
style=style,
|
|
95
|
+
show_cursor=False,
|
|
96
|
+
).execute()
|
|
97
|
+
|
|
98
|
+
match provider:
|
|
99
|
+
case "groq":
|
|
100
|
+
print()
|
|
101
|
+
print(
|
|
102
|
+
f"To get your forever-free Groq API key, head to {ACCENT}console.groq.com/keys{RESET}."
|
|
103
|
+
)
|
|
104
|
+
print(
|
|
105
|
+
"Create an account and then create a new API key without an expiration date."
|
|
106
|
+
)
|
|
107
|
+
print("Then copy the API key and paste it here.")
|
|
108
|
+
case "gemini":
|
|
109
|
+
print()
|
|
110
|
+
pass
|
|
111
|
+
case "ollama":
|
|
112
|
+
pass
|
|
113
|
+
case _:
|
|
114
|
+
ai_activated = False
|
|
115
|
+
provider = None
|
|
116
|
+
api_key = None
|
|
117
|
+
|
|
118
|
+
if provider in ["groq", "gemini"]:
|
|
119
|
+
print()
|
|
120
|
+
|
|
121
|
+
# 3.2. Get API key
|
|
122
|
+
api_key = secret.SecretPrompt(
|
|
123
|
+
message="Your API key:",
|
|
124
|
+
style=style,
|
|
125
|
+
vi_mode=True,
|
|
126
|
+
).execute()
|
|
127
|
+
else:
|
|
128
|
+
api_key = None
|
|
129
|
+
print()
|
|
130
|
+
|
|
131
|
+
# 3.3. Select model
|
|
132
|
+
model = input.InputPrompt(
|
|
133
|
+
message="Enter the model you want to use:",
|
|
134
|
+
style=style,
|
|
135
|
+
vi_mode=True,
|
|
136
|
+
).execute()
|
|
137
|
+
|
|
138
|
+
else:
|
|
139
|
+
model = None
|
|
140
|
+
provider = None
|
|
141
|
+
api_key = None
|
|
142
|
+
|
|
143
|
+
print()
|
|
144
|
+
|
|
145
|
+
except KeyboardInterrupt:
|
|
146
|
+
quit()
|
|
147
|
+
|
|
148
|
+
env_path = os.path.join(
|
|
149
|
+
appdirs.user_data_dir(appname="Comprobot", appauthor=False), ".env"
|
|
150
|
+
)
|
|
151
|
+
with open(env_path, "w") as f:
|
|
152
|
+
f.write(f"BOT_TOKEN={token}\n")
|
|
153
|
+
if api_key:
|
|
154
|
+
if provider == "groq":
|
|
155
|
+
f.write(f"GROQ={api_key}\n")
|
|
156
|
+
f.write("GEMINI=\n")
|
|
157
|
+
elif provider == "gemini":
|
|
158
|
+
f.write(f"GEMINI={api_key}\n")
|
|
159
|
+
f.write("GROQ=\n")
|
|
160
|
+
else:
|
|
161
|
+
f.write("GROQ=\n")
|
|
162
|
+
f.write("GEMINI=\n")
|
|
163
|
+
|
|
164
|
+
result = {
|
|
165
|
+
"token": token,
|
|
166
|
+
"commands_activated": commands_activated,
|
|
167
|
+
"ai_activated": ai_activated,
|
|
168
|
+
"provider": provider,
|
|
169
|
+
"api_key": api_key,
|
|
170
|
+
"model": model,
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if config["debug_mode"]:
|
|
174
|
+
print()
|
|
175
|
+
print(json.dumps(result, indent=4))
|
|
176
|
+
print()
|
|
177
|
+
|
|
178
|
+
print(f"{ACCENT}You're all set!{RESET} Have fun using Comprobot!")
|
|
179
|
+
|
|
180
|
+
return result
|
|
@@ -118,20 +118,11 @@ mute = []
|
|
|
118
118
|
time_to_mute = 5 # In minutes
|
|
119
119
|
"""
|
|
120
120
|
|
|
121
|
-
|
|
121
|
+
env = r"""BOT_TOKEN=
|
|
122
122
|
GEMINI=
|
|
123
123
|
GROQ=
|
|
124
124
|
"""
|
|
125
125
|
|
|
126
|
-
create_commands = r"""create("config.toml", config)
|
|
127
|
-
create("error-messages.toml", error_messages)
|
|
128
|
-
create("keywords.toml", keywords)
|
|
129
|
-
create("ai.toml", ai)
|
|
130
|
-
create("moderation.toml", moderation)
|
|
131
|
-
create("data/.do_not_touch/money.toml", money)
|
|
132
|
-
create("data/.do_not_touch/conversation_history.toml", conversation_history)
|
|
133
|
-
create(".env", env_template)"""
|
|
134
|
-
|
|
135
126
|
active = r"""quote = true
|
|
136
127
|
joke = true
|
|
137
128
|
meme = true
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: comprobot
|
|
3
|
-
Version: 2.0
|
|
3
|
+
Version: 2.1.0
|
|
4
4
|
Summary: A self-hostable Discord bot built for maximum customization.
|
|
5
5
|
Author: badluma
|
|
6
6
|
License: MIT
|
|
@@ -19,10 +19,11 @@ Requires-Dist: appdirs
|
|
|
19
19
|
Requires-Dist: ollama
|
|
20
20
|
Requires-Dist: google-genai
|
|
21
21
|
Requires-Dist: groq
|
|
22
|
+
Requires-Dist: InqurererPy
|
|
22
23
|
Provides-Extra: dev
|
|
23
24
|
Requires-Dist: ruff; extra == "dev"
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
# Comprobot
|
|
26
27
|
|
|
27
28
|
Comprobot is a highly-customizable, open-source Discord bot that you can run on your own server.
|
|
28
29
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: comprobot
|
|
3
|
-
Version: 2.0
|
|
3
|
+
Version: 2.1.0
|
|
4
4
|
Summary: A self-hostable Discord bot built for maximum customization.
|
|
5
5
|
Author: badluma
|
|
6
6
|
License: MIT
|
|
@@ -19,10 +19,11 @@ Requires-Dist: appdirs
|
|
|
19
19
|
Requires-Dist: ollama
|
|
20
20
|
Requires-Dist: google-genai
|
|
21
21
|
Requires-Dist: groq
|
|
22
|
+
Requires-Dist: InqurererPy
|
|
22
23
|
Provides-Extra: dev
|
|
23
24
|
Requires-Dist: ruff; extra == "dev"
|
|
24
25
|
|
|
25
|
-
|
|
26
|
+
# Comprobot
|
|
26
27
|
|
|
27
28
|
Comprobot is a highly-customizable, open-source Discord bot that you can run on your own server.
|
|
28
29
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "comprobot"
|
|
7
|
-
version = "2.0
|
|
7
|
+
version = "2.1.0"
|
|
8
8
|
authors = [{name = "badluma"}]
|
|
9
9
|
description = "A self-hostable Discord bot built for maximum customization."
|
|
10
10
|
readme = "README.md"
|
|
@@ -24,6 +24,7 @@ dependencies = [
|
|
|
24
24
|
"ollama",
|
|
25
25
|
"google-genai",
|
|
26
26
|
"groq",
|
|
27
|
+
"InqurererPy",
|
|
27
28
|
]
|
|
28
29
|
|
|
29
30
|
[project.optional-dependencies]
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
from typing import Any, Dict, List
|
|
3
|
-
|
|
4
|
-
import appdirs
|
|
5
|
-
import tomlkit
|
|
6
|
-
|
|
7
|
-
from . import templates
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def _get_data_path(filename):
|
|
11
|
-
|
|
12
|
-
base_dir = appdirs.user_data_dir(appname="Comprobot", appauthor=False)
|
|
13
|
-
return os.path.join(base_dir, filename)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def _ensure_file(path, content):
|
|
17
|
-
|
|
18
|
-
os.makedirs(os.path.dirname(path), exist_ok=True)
|
|
19
|
-
if not os.path.isfile(path):
|
|
20
|
-
with open(path, "w") as f:
|
|
21
|
-
f.write(content)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def _merge_defaults(data, defaults):
|
|
25
|
-
for key, value in defaults.items():
|
|
26
|
-
if key not in data:
|
|
27
|
-
data[key] = value
|
|
28
|
-
elif isinstance(value, dict) and isinstance(data.get(key), dict):
|
|
29
|
-
_merge_defaults(data[key], value)
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
def _load_or_create(path, template_content):
|
|
33
|
-
try:
|
|
34
|
-
with open(path, "rb") as f:
|
|
35
|
-
data = tomlkit.load(f)
|
|
36
|
-
except FileNotFoundError:
|
|
37
|
-
_ensure_file(path, template_content)
|
|
38
|
-
with open(path, "rb") as f:
|
|
39
|
-
data = tomlkit.load(f)
|
|
40
|
-
|
|
41
|
-
defaults = tomlkit.loads(template_content)
|
|
42
|
-
_merge_defaults(data, defaults)
|
|
43
|
-
|
|
44
|
-
if data != defaults:
|
|
45
|
-
with open(path, "w") as f:
|
|
46
|
-
tomlkit.dump(data, f)
|
|
47
|
-
|
|
48
|
-
return data
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
error_messages: Dict[str, str] = _load_or_create(
|
|
52
|
-
_get_data_path("error-messages.toml"), templates.error_messages
|
|
53
|
-
)
|
|
54
|
-
config: Dict[str, Any] = _load_or_create(
|
|
55
|
-
_get_data_path("config.toml"), templates.config
|
|
56
|
-
)
|
|
57
|
-
keywords: Dict[str, Dict[str, List[str]]] = _load_or_create(
|
|
58
|
-
_get_data_path("keywords.toml"), templates.keywords
|
|
59
|
-
)
|
|
60
|
-
ai: Dict[str, Any] = _load_or_create(_get_data_path("ai.toml"), templates.ai)
|
|
61
|
-
system_prompt_text = ai["system_prompt"]
|
|
62
|
-
money: Dict[str, Dict[str, int]] = _load_or_create(
|
|
63
|
-
_get_data_path("money.toml"), r"""members = {}"""
|
|
64
|
-
)
|
|
65
|
-
active: Dict[str, bool] = _load_or_create(
|
|
66
|
-
_get_data_path("active.toml"), templates.active
|
|
67
|
-
)
|
|
68
|
-
output: Dict[str, Dict[str, List[str]]] = _load_or_create(
|
|
69
|
-
_get_data_path("output.toml"), templates.output
|
|
70
|
-
)
|
|
71
|
-
moderation: Dict[Any, Any] = _load_or_create(
|
|
72
|
-
_get_data_path("moderation.toml"), templates.moderation
|
|
73
|
-
)
|
|
74
|
-
|
|
75
|
-
_ensure_file(_get_data_path(".env"), templates.env_template)
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
def save_toml(data, path):
|
|
79
|
-
with open(path, "w") as f:
|
|
80
|
-
tomlkit.dump(data, f)
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
def save_money():
|
|
84
|
-
save_toml(money, _get_data_path("money.toml"))
|
|
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
|