comprobot 2.1.8__tar.gz → 2.2.1__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 (27) hide show
  1. comprobot-2.2.1/LICENSE +21 -0
  2. {comprobot-2.1.8 → comprobot-2.2.1}/PKG-INFO +22 -2
  3. {comprobot-2.1.8 → comprobot-2.2.1}/README.md +19 -1
  4. {comprobot-2.1.8 → comprobot-2.2.1}/comprobot.egg-info/PKG-INFO +22 -2
  5. {comprobot-2.1.8 → comprobot-2.2.1}/comprobot.egg-info/SOURCES.txt +3 -1
  6. comprobot-2.2.1/comprobot.egg-info/entry_points.txt +2 -0
  7. {comprobot-2.1.8 → comprobot-2.2.1}/pyproject.toml +2 -2
  8. {comprobot-2.1.8 → comprobot-2.2.1}/src/__main__.py +27 -17
  9. comprobot-2.2.1/src/config.py +221 -0
  10. {comprobot-2.1.8 → comprobot-2.2.1}/src/moderation.py +2 -0
  11. {comprobot-2.1.8 → comprobot-2.2.1}/src/onboarding.py +6 -1
  12. comprobot-2.1.8/src/main.py → comprobot-2.2.1/src/start.py +1 -1
  13. comprobot-2.1.8/comprobot.egg-info/entry_points.txt +0 -2
  14. {comprobot-2.1.8 → comprobot-2.2.1}/comprobot.egg-info/dependency_links.txt +0 -0
  15. {comprobot-2.1.8 → comprobot-2.2.1}/comprobot.egg-info/requires.txt +0 -0
  16. {comprobot-2.1.8 → comprobot-2.2.1}/comprobot.egg-info/top_level.txt +0 -0
  17. {comprobot-2.1.8 → comprobot-2.2.1}/setup.cfg +0 -0
  18. {comprobot-2.1.8 → comprobot-2.2.1}/src/__init__.py +0 -0
  19. {comprobot-2.1.8 → comprobot-2.2.1}/src/api.py +0 -0
  20. {comprobot-2.1.8 → comprobot-2.2.1}/src/bot.py +0 -0
  21. {comprobot-2.1.8 → comprobot-2.2.1}/src/commands.py +0 -0
  22. {comprobot-2.1.8 → comprobot-2.2.1}/src/data.py +0 -0
  23. {comprobot-2.1.8 → comprobot-2.2.1}/src/functions.py +0 -0
  24. {comprobot-2.1.8 → comprobot-2.2.1}/src/money_system.py +0 -0
  25. {comprobot-2.1.8 → comprobot-2.2.1}/src/process.py +0 -0
  26. {comprobot-2.1.8 → comprobot-2.2.1}/src/templates.py +0 -0
  27. {comprobot-2.1.8 → comprobot-2.2.1}/src/testing.py +0 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 badluma
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: comprobot
3
- Version: 2.1.8
3
+ Version: 2.2.1
4
4
  Summary: A self-hostable Discord bot built for maximum customization.
5
5
  Author: badluma
6
6
  License: MIT
@@ -11,6 +11,7 @@ Classifier: License :: OSI Approved :: MIT License
11
11
  Classifier: Operating System :: OS Independent
12
12
  Requires-Python: >=3.10
13
13
  Description-Content-Type: text/markdown
14
+ License-File: LICENSE
14
15
  Requires-Dist: discord.py[voice]
15
16
  Requires-Dist: python-dotenv
16
17
  Requires-Dist: requests
@@ -22,6 +23,7 @@ Requires-Dist: groq
22
23
  Requires-Dist: InquirerPy
23
24
  Provides-Extra: dev
24
25
  Requires-Dist: ruff; extra == "dev"
26
+ Dynamic: license-file
25
27
 
26
28
  # Comprobot
27
29
 
@@ -47,6 +49,11 @@ sudo apt update && sudo apt upgrade
47
49
  sudo apt install comprobot
48
50
  ```
49
51
 
52
+ **AUR** (Arch)
53
+ ```sh
54
+ yay -S --noconfirm --nodiffmenu comprobot
55
+ ```
56
+
50
57
  **Homebrew** (macOS)
51
58
  ```sh
52
59
  brew tap badluma/homebrew
@@ -59,7 +66,20 @@ scoop bucket add badluma https://github.com/badluma/scoop-bucket
59
66
  scoop install comprobot
60
67
  ```
61
68
 
62
- Support for Docker Hub and AUR (Arch Linux) is planned.
69
+ **Docker**
70
+ ```sh
71
+ docker run -d \
72
+ -v comprobot-data:/root/.local/share/Comprobot \
73
+ --name comprobot \
74
+ badluma/comprobot:latest
75
+ ```
76
+
77
+ First run, set up credentials:
78
+ ```sh
79
+ docker run -it --rm \
80
+ -v comprobot-data:/root/.local/share/Comprobot \
81
+ badluma/comprobot:latest onboard
82
+ ```
63
83
 
64
84
  ## Documentation
65
85
 
@@ -22,6 +22,11 @@ sudo apt update && sudo apt upgrade
22
22
  sudo apt install comprobot
23
23
  ```
24
24
 
25
+ **AUR** (Arch)
26
+ ```sh
27
+ yay -S --noconfirm --nodiffmenu comprobot
28
+ ```
29
+
25
30
  **Homebrew** (macOS)
26
31
  ```sh
27
32
  brew tap badluma/homebrew
@@ -34,7 +39,20 @@ scoop bucket add badluma https://github.com/badluma/scoop-bucket
34
39
  scoop install comprobot
35
40
  ```
36
41
 
37
- Support for Docker Hub and AUR (Arch Linux) is planned.
42
+ **Docker**
43
+ ```sh
44
+ docker run -d \
45
+ -v comprobot-data:/root/.local/share/Comprobot \
46
+ --name comprobot \
47
+ badluma/comprobot:latest
48
+ ```
49
+
50
+ First run, set up credentials:
51
+ ```sh
52
+ docker run -it --rm \
53
+ -v comprobot-data:/root/.local/share/Comprobot \
54
+ badluma/comprobot:latest onboard
55
+ ```
38
56
 
39
57
  ## Documentation
40
58
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: comprobot
3
- Version: 2.1.8
3
+ Version: 2.2.1
4
4
  Summary: A self-hostable Discord bot built for maximum customization.
5
5
  Author: badluma
6
6
  License: MIT
@@ -11,6 +11,7 @@ Classifier: License :: OSI Approved :: MIT License
11
11
  Classifier: Operating System :: OS Independent
12
12
  Requires-Python: >=3.10
13
13
  Description-Content-Type: text/markdown
14
+ License-File: LICENSE
14
15
  Requires-Dist: discord.py[voice]
15
16
  Requires-Dist: python-dotenv
16
17
  Requires-Dist: requests
@@ -22,6 +23,7 @@ Requires-Dist: groq
22
23
  Requires-Dist: InquirerPy
23
24
  Provides-Extra: dev
24
25
  Requires-Dist: ruff; extra == "dev"
26
+ Dynamic: license-file
25
27
 
26
28
  # Comprobot
27
29
 
@@ -47,6 +49,11 @@ sudo apt update && sudo apt upgrade
47
49
  sudo apt install comprobot
48
50
  ```
49
51
 
52
+ **AUR** (Arch)
53
+ ```sh
54
+ yay -S --noconfirm --nodiffmenu comprobot
55
+ ```
56
+
50
57
  **Homebrew** (macOS)
51
58
  ```sh
52
59
  brew tap badluma/homebrew
@@ -59,7 +66,20 @@ scoop bucket add badluma https://github.com/badluma/scoop-bucket
59
66
  scoop install comprobot
60
67
  ```
61
68
 
62
- Support for Docker Hub and AUR (Arch Linux) is planned.
69
+ **Docker**
70
+ ```sh
71
+ docker run -d \
72
+ -v comprobot-data:/root/.local/share/Comprobot \
73
+ --name comprobot \
74
+ badluma/comprobot:latest
75
+ ```
76
+
77
+ First run, set up credentials:
78
+ ```sh
79
+ docker run -it --rm \
80
+ -v comprobot-data:/root/.local/share/Comprobot \
81
+ badluma/comprobot:latest onboard
82
+ ```
63
83
 
64
84
  ## Documentation
65
85
 
@@ -1,3 +1,4 @@
1
+ LICENSE
1
2
  README.md
2
3
  pyproject.toml
3
4
  comprobot.egg-info/PKG-INFO
@@ -11,12 +12,13 @@ src/__main__.py
11
12
  src/api.py
12
13
  src/bot.py
13
14
  src/commands.py
15
+ src/config.py
14
16
  src/data.py
15
17
  src/functions.py
16
- src/main.py
17
18
  src/moderation.py
18
19
  src/money_system.py
19
20
  src/onboarding.py
20
21
  src/process.py
22
+ src/start.py
21
23
  src/templates.py
22
24
  src/testing.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ comprobot = src.__main__:main
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "comprobot"
7
- version = "2.1.8"
7
+ version = "2.2.1"
8
8
  authors = [{name = "badluma"}]
9
9
  description = "A self-hostable Discord bot built for maximum customization."
10
10
  readme = "README.md"
@@ -35,7 +35,7 @@ Homepage = "https://badluma.github.io/Comprobot-Docs"
35
35
  Repository = "https://github.com/badluma/comprobot"
36
36
 
37
37
  [project.scripts]
38
- comprobot = "src.__main__:cli_main"
38
+ comprobot = "src.__main__:main"
39
39
 
40
40
  [tool.setuptools.packages.find]
41
41
  where = ["."]
@@ -1,33 +1,40 @@
1
1
  import argparse
2
2
 
3
- import dotenv
3
+ from dotenv import set_key as dotenv_set_key
4
4
 
5
5
  from .data import active, ai, get_data_path, save_toml
6
- from .main import main
6
+ from .start import start
7
7
  from .onboarding import onboarding
8
+ from .config import configure
8
9
 
9
10
 
10
- def cli_main():
11
+ def main():
11
12
  parser = argparse.ArgumentParser(
12
13
  prog="comprobot",
13
14
  description="A self-hostable open-source Discord bot built for maximum customization.",
14
15
  )
15
16
  subparsers = parser.add_subparsers(dest="command", metavar="")
16
- subparsers.add_parser("onboard", help="Set up Comprobot for the first time.")
17
17
  subparsers.add_parser("start", help="Start the bot.")
18
+ subparsers.add_parser("onboard", help="Set up Comprobot for the first time.")
19
+ config_parser = subparsers.add_parser("config", help="Configure the bot's settings.")
20
+ config_parser.add_argument("config_args", nargs=argparse.REMAINDER)
18
21
  test_parser = subparsers.add_parser("test", help="Process a message through the bot's command processor.")
19
22
  test_parser.add_argument("message", help="The message to process (e.g. '!calculate 2+2')")
20
23
 
21
24
  args = parser.parse_args()
22
25
 
26
+ print(args)
27
+
23
28
  match args.command:
24
29
  case "start":
25
- main()
30
+ start()
26
31
  case "onboard":
27
32
  settings = onboarding()
28
33
 
29
- dotenv.set_key(
30
- dotenv_path=".env",
34
+ env_path = get_data_path(".env")
35
+
36
+ dotenv_set_key(
37
+ dotenv_path=env_path,
31
38
  key_to_set="BOT_TOKEN",
32
39
  value_to_set=str(settings["token"]),
33
40
  )
@@ -43,24 +50,24 @@ def cli_main():
43
50
  ai["provider"] = settings["provider"]
44
51
 
45
52
  if settings["provider"] == "groq":
46
- dotenv.set_key(
47
- dotenv_path=".env",
53
+ dotenv_set_key(
54
+ dotenv_path=env_path,
48
55
  key_to_set="GROQ",
49
56
  value_to_set=settings["api_key"],
50
57
  )
51
- dotenv.set_key(dotenv_path=".env", key_to_set="GEMINI", value_to_set="")
58
+ dotenv_set_key(dotenv_path=env_path, key_to_set="GEMINI", value_to_set="")
52
59
 
53
60
  elif settings["provider"] == "gemini":
54
- dotenv.set_key(
55
- dotenv_path=".env",
61
+ dotenv_set_key(
62
+ dotenv_path=env_path,
56
63
  key_to_set="GEMINI",
57
64
  value_to_set=settings["api_key"],
58
65
  )
59
- dotenv.set_key(dotenv_path=".env", key_to_set="GROQ", value_to_set="")
66
+ dotenv_set_key(dotenv_path=env_path, key_to_set="GROQ", value_to_set="")
60
67
 
61
68
  else:
62
- dotenv.set_key(dotenv_path=".env", key_to_set="GROQ", value_to_set="")
63
- dotenv.set_key(dotenv_path=".env", key_to_set="GEMINI", value_to_set="")
69
+ dotenv_set_key(dotenv_path=env_path, key_to_set="GROQ", value_to_set="")
70
+ dotenv_set_key(dotenv_path=env_path, key_to_set="GEMINI", value_to_set="")
64
71
 
65
72
  if settings["model"]:
66
73
  ai["model"] = settings["model"]
@@ -70,7 +77,10 @@ def cli_main():
70
77
  save_toml(ai, get_data_path("ai.toml"))
71
78
  save_toml(active, get_data_path("active.toml"))
72
79
 
73
- main()
80
+ start()
81
+
82
+ case "config":
83
+ configure(args.config_args)
74
84
 
75
85
  case "test":
76
86
  from .testing import run_test
@@ -81,4 +91,4 @@ def cli_main():
81
91
 
82
92
 
83
93
  if __name__ == "__main__":
84
- cli_main()
94
+ main()
@@ -0,0 +1,221 @@
1
+ import sys
2
+ import os
3
+
4
+ import appdirs
5
+ import tomlkit
6
+
7
+ import InquirerPy.utils
8
+ from InquirerPy.base.control import Choice
9
+ from InquirerPy.prompts import checkbox, confirm, input, secret
10
+ from InquirerPy.prompts import list as inquirer_list
11
+ from tomlkit.items import Key
12
+
13
+ style = InquirerPy.utils.InquirerPyStyle({
14
+ "instruction": "#aaaaaa italic",
15
+ "questionmark": "#5865F2 bold",
16
+ "answermark": "#5865F2",
17
+ "answer": "#5865F2",
18
+ "question": "#ffffff",
19
+ })
20
+
21
+ def make_pretty(string):
22
+ return string \
23
+ .replace(".toml", "") \
24
+ .replace("_", " ") \
25
+ .replace("-", " ") \
26
+ .title() \
27
+ .replace("Ai", "AI")
28
+
29
+ def pick_file():
30
+ data_dir = appdirs.user_data_dir("Comprobot", appauthor=False)
31
+
32
+ files = {}
33
+
34
+ for file in os.listdir(data_dir):
35
+ if not file.endswith(".toml"):
36
+ continue
37
+ files[file] = {}
38
+ files[file]["path"] = os.path.join(data_dir, file)
39
+ files[file]["display"] = make_pretty(file)
40
+
41
+ if not files:
42
+ print("No configuration files found.")
43
+ sys.exit(1)
44
+
45
+ env_path = os.path.join(appdirs.user_data_dir("Comprobot", appauthor=False), ".env")
46
+
47
+ file_to_edit = inquirer_list.ListPrompt(
48
+ message="Which file do you want to edit?",
49
+ choices=[Choice(value=files[file]["path"], name=files[file]["display"]) for file in files]
50
+ + ([Choice(value=env_path, name="Secrets")] if os.path.exists(env_path) else [])
51
+ + [Choice(value="exit", name="Exit")],
52
+ style=style,
53
+ amark="!",
54
+ vi_mode=True,
55
+ show_cursor=False,
56
+ ).execute()
57
+
58
+ if file_to_edit == "exit":
59
+ sys.exit(0)
60
+
61
+ if file_to_edit == env_path:
62
+ from dotenv import dotenv_values
63
+ content = {k: v or "" for k, v in dotenv_values(file_to_edit).items()}
64
+ return (file_to_edit, content)
65
+
66
+ with open(file_to_edit, "r") as f:
67
+ content = tomlkit.load(f)
68
+
69
+ return (file_to_edit, content)
70
+
71
+
72
+ def pick_key(content, is_secret=False):
73
+
74
+ print()
75
+
76
+ key = inquirer_list.ListPrompt(
77
+ message="Which key do you want to edit?",
78
+ choices=[Choice(value=key, name=make_pretty(key)) for key in list(content.keys())]
79
+ + [Choice(value="exit", name="Exit")],
80
+ style=style,
81
+ amark="!",
82
+ show_cursor=False,
83
+ vi_mode=True,
84
+ ).execute()
85
+
86
+ if key == "exit":
87
+ sys.exit(0)
88
+
89
+ match content[key]:
90
+ case dict():
91
+ pick_key(content[key], is_secret=is_secret)
92
+
93
+ case bool():
94
+ print()
95
+ value = confirm.ConfirmPrompt(
96
+ message=f"Do you want to set '{make_pretty(key)}' to True or False?",
97
+ instruction=f"(y/n) (Current: {content[key]})",
98
+ style=style,
99
+ amark="!",
100
+ vi_mode=True,
101
+ ).execute()
102
+ content[key] = value
103
+
104
+ case str() | int():
105
+ print()
106
+ if is_secret:
107
+ value = secret.SecretPrompt(
108
+ message=f"New value for '{make_pretty(key)}'?",
109
+ style=style,
110
+ amark="!",
111
+ vi_mode=True,
112
+ ).execute()
113
+ else:
114
+ value = input.InputPrompt(
115
+ message=f"What value do you want to assign to '{make_pretty(key)}'?",
116
+ instruction=f"(Current: {content[key]})",
117
+ style=style,
118
+ amark="!",
119
+ vi_mode=True,
120
+ ).execute()
121
+ content[key] = value
122
+
123
+ case list():
124
+ print()
125
+ value = input.InputPrompt(
126
+ message=f"What values do you want to assign to '{make_pretty(key)}'?",
127
+ instruction=f"(separate by commas) (Current: {', '.join(content[key]) if content[key] else 'None'})",
128
+ style=style,
129
+ amark="!",
130
+ vi_mode=True,
131
+ ).execute().split(",")
132
+ content[key] = [item.strip() for item in value]
133
+
134
+
135
+
136
+ def configure(args):
137
+
138
+ if not args:
139
+ print()
140
+ try:
141
+ file_to_edit, content = pick_file()
142
+ except KeyboardInterrupt:
143
+ sys.exit(0)
144
+ except Exception as e:
145
+ print(f"Error: {e}")
146
+ sys.exit(1)
147
+
148
+ is_secret = file_to_edit.endswith(".env")
149
+
150
+ while True:
151
+ try:
152
+ pick_key(content, is_secret=is_secret)
153
+ except KeyboardInterrupt:
154
+ sys.exit(0)
155
+ except Exception as e:
156
+ print(f"Error: {e}")
157
+ continue
158
+
159
+ if is_secret:
160
+ from dotenv import set_key as dotenv_set_key
161
+ for k, v in content.items():
162
+ dotenv_set_key(dotenv_path=file_to_edit, key_to_set=k, value_to_set=v)
163
+ else:
164
+ with open(file_to_edit, "w") as f:
165
+ tomlkit.dump(content, f)
166
+ else:
167
+ if len(args) < 3:
168
+ print("Usage: config <file> <key> <value(s)>")
169
+ sys.exit(1)
170
+
171
+ file_name, key, *values = args
172
+
173
+ data_dir = appdirs.user_data_dir("Comprobot", appauthor=False)
174
+
175
+ if file_name == "secrets":
176
+ from dotenv import set_key as dotenv_set_key
177
+ env_path = os.path.join(data_dir, ".env")
178
+ if not os.path.exists(env_path):
179
+ print(".env file not found.")
180
+ sys.exit(1)
181
+ if not values:
182
+ print("Usage: config secrets <key> <value>")
183
+ sys.exit(1)
184
+ dotenv_set_key(dotenv_path=env_path, key_to_set=key, value_to_set=values[0])
185
+ return
186
+
187
+ file_path = os.path.join(data_dir, f"{file_name}.toml")
188
+
189
+ if not os.path.exists(file_path):
190
+ print(f"File '{file_name}.toml' not found.")
191
+ sys.exit(1)
192
+
193
+ with open(file_path, "r") as f:
194
+ content = tomlkit.load(f)
195
+
196
+ if key not in content:
197
+ print(f"Key '{key}' not found in {file_name}.toml.")
198
+ sys.exit(1)
199
+
200
+ current = content[key]
201
+
202
+ match current:
203
+ case bool():
204
+ v = values[0].lower()
205
+ if v not in ("true", "false"):
206
+ print(f"Invalid value '{values[0]}' for bool. Use 'true' or 'false'.")
207
+ sys.exit(1)
208
+ content[key] = v == "true"
209
+ case list():
210
+ content[key] = values
211
+ case str():
212
+ content[key] = values[0]
213
+ case int():
214
+ try:
215
+ content[key] = int(values[0])
216
+ except ValueError:
217
+ print(f"Invalid value '{values[0]}' for int key.")
218
+ sys.exit(1)
219
+
220
+ with open(file_path, "w") as f:
221
+ tomlkit.dump(content, f)
@@ -15,6 +15,7 @@ async def ban(message, item):
15
15
  member = await message.guild.fetch_member(message.author.id)
16
16
  except discord.NotFound:
17
17
  print(f"Could not fetch member {message.author.name}.")
18
+ return
18
19
 
19
20
  try:
20
21
  try:
@@ -36,6 +37,7 @@ async def kick(message, item):
36
37
  member = await message.guild.fetch_member(message.author.id)
37
38
  except discord.NotFound:
38
39
  print(f"Could not fetch member {message.author.name}.")
40
+ return
39
41
 
40
42
  try:
41
43
  try:
@@ -56,6 +56,7 @@ def onboarding():
56
56
  token = secret.SecretPrompt(
57
57
  message="Your bot token:",
58
58
  style=style,
59
+ amark="!",
59
60
  vi_mode=True,
60
61
  ).execute()
61
62
 
@@ -67,6 +68,7 @@ def onboarding():
67
68
  instruction="Press Space to deselect and press Enter to continue.",
68
69
  choices=active_choices,
69
70
  style=style,
71
+ amark="!",
70
72
  transformer=lambda result: (
71
73
  f"{len(result)} commands selected" if result else "No commands selected"
72
74
  ),
@@ -77,7 +79,7 @@ def onboarding():
77
79
 
78
80
  # 3. Activate AI features
79
81
  ai_activated = confirm.ConfirmPrompt(
80
- message="Do you want to activate AI features?", style=style, default=True
82
+ message="Do you want to activate AI features?", style=style, amark="!", default=True
81
83
  ).execute()
82
84
  if ai_activated:
83
85
  print()
@@ -92,6 +94,7 @@ def onboarding():
92
94
  ],
93
95
  default="groq",
94
96
  style=style,
97
+ amark="!",
95
98
  show_cursor=False,
96
99
  ).execute()
97
100
 
@@ -122,6 +125,7 @@ def onboarding():
122
125
  api_key = secret.SecretPrompt(
123
126
  message="Your API key:",
124
127
  style=style,
128
+ amark="!",
125
129
  vi_mode=True,
126
130
  ).execute()
127
131
  else:
@@ -132,6 +136,7 @@ def onboarding():
132
136
  model = input.InputPrompt(
133
137
  message="Enter the model you want to use:",
134
138
  style=style,
139
+ amark="!",
135
140
  vi_mode=True,
136
141
  ).execute()
137
142
 
@@ -40,7 +40,7 @@ async def on_ready():
40
40
  para()
41
41
 
42
42
 
43
- def main():
43
+ def start():
44
44
  print(
45
45
  f"Configuration directory: {appdirs.user_data_dir(appname='Comprobot', appauthor=False)}"
46
46
  )
@@ -1,2 +0,0 @@
1
- [console_scripts]
2
- comprobot = src.__main__:cli_main
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