anipy-cli 2.7.31__py3-none-any.whl → 3.0.0.dev0__py3-none-any.whl

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.

Potentially problematic release.


This version of anipy-cli might be problematic. Click here for more details.

Files changed (62) hide show
  1. anipy_cli/__init__.py +2 -20
  2. anipy_cli/arg_parser.py +30 -20
  3. anipy_cli/cli.py +66 -0
  4. anipy_cli/clis/__init__.py +15 -0
  5. anipy_cli/clis/base_cli.py +32 -0
  6. anipy_cli/clis/binge_cli.py +83 -0
  7. anipy_cli/clis/default_cli.py +104 -0
  8. anipy_cli/clis/download_cli.py +111 -0
  9. anipy_cli/clis/history_cli.py +93 -0
  10. anipy_cli/clis/mal_cli.py +71 -0
  11. anipy_cli/{cli/clis → clis}/seasonal_cli.py +9 -6
  12. anipy_cli/colors.py +4 -4
  13. anipy_cli/config.py +308 -87
  14. anipy_cli/discord.py +34 -0
  15. anipy_cli/mal_proxy.py +216 -0
  16. anipy_cli/menus/__init__.py +5 -0
  17. anipy_cli/{cli/menus → menus}/base_menu.py +8 -12
  18. anipy_cli/menus/mal_menu.py +660 -0
  19. anipy_cli/menus/menu.py +194 -0
  20. anipy_cli/menus/seasonal_menu.py +263 -0
  21. anipy_cli/prompts.py +231 -0
  22. anipy_cli/util.py +262 -0
  23. anipy_cli-3.0.0.dev0.dist-info/METADATA +67 -0
  24. anipy_cli-3.0.0.dev0.dist-info/RECORD +26 -0
  25. {anipy_cli-2.7.31.dist-info → anipy_cli-3.0.0.dev0.dist-info}/WHEEL +1 -2
  26. anipy_cli-3.0.0.dev0.dist-info/entry_points.txt +3 -0
  27. anipy_cli/cli/__init__.py +0 -1
  28. anipy_cli/cli/cli.py +0 -37
  29. anipy_cli/cli/clis/__init__.py +0 -6
  30. anipy_cli/cli/clis/base_cli.py +0 -43
  31. anipy_cli/cli/clis/binge_cli.py +0 -54
  32. anipy_cli/cli/clis/default_cli.py +0 -46
  33. anipy_cli/cli/clis/download_cli.py +0 -92
  34. anipy_cli/cli/clis/history_cli.py +0 -64
  35. anipy_cli/cli/clis/mal_cli.py +0 -27
  36. anipy_cli/cli/menus/__init__.py +0 -3
  37. anipy_cli/cli/menus/mal_menu.py +0 -411
  38. anipy_cli/cli/menus/menu.py +0 -108
  39. anipy_cli/cli/menus/seasonal_menu.py +0 -177
  40. anipy_cli/cli/util.py +0 -125
  41. anipy_cli/download.py +0 -467
  42. anipy_cli/history.py +0 -83
  43. anipy_cli/mal.py +0 -651
  44. anipy_cli/misc.py +0 -227
  45. anipy_cli/player/__init__.py +0 -1
  46. anipy_cli/player/player.py +0 -35
  47. anipy_cli/player/players/__init__.py +0 -3
  48. anipy_cli/player/players/base.py +0 -107
  49. anipy_cli/player/players/mpv.py +0 -19
  50. anipy_cli/player/players/mpv_control.py +0 -37
  51. anipy_cli/player/players/syncplay.py +0 -19
  52. anipy_cli/player/players/vlc.py +0 -18
  53. anipy_cli/query.py +0 -100
  54. anipy_cli/run_anipy_cli.py +0 -14
  55. anipy_cli/seasonal.py +0 -112
  56. anipy_cli/url_handler.py +0 -470
  57. anipy_cli/version.py +0 -1
  58. anipy_cli-2.7.31.dist-info/LICENSE +0 -674
  59. anipy_cli-2.7.31.dist-info/METADATA +0 -162
  60. anipy_cli-2.7.31.dist-info/RECORD +0 -43
  61. anipy_cli-2.7.31.dist-info/entry_points.txt +0 -2
  62. anipy_cli-2.7.31.dist-info/top_level.txt +0 -1
@@ -1,64 +0,0 @@
1
- from anipy_cli.arg_parser import CliArgs
2
- from anipy_cli.misc import Entry, error, print_names
3
- from anipy_cli.colors import cinput, colors
4
- from anipy_cli.history import history
5
- from anipy_cli.url_handler import epHandler, videourl
6
- from anipy_cli.player import get_player
7
- from anipy_cli.cli.menus import Menu
8
- from anipy_cli.cli.clis.base_cli import CliBase
9
-
10
-
11
- class HistoryCli(CliBase):
12
- def __init__(self, options: CliArgs, rpc_client=None):
13
- super().__init__(options, rpc_client)
14
-
15
- self.entry = Entry()
16
- self.player = get_player(
17
- rpc_client=self.rpc_client, player_override=self.options.optional_player
18
- )
19
- self.hist = history(self.entry).read_save_data()
20
-
21
- def print_header(self):
22
- pass
23
-
24
- def take_input(self):
25
- if not self.hist:
26
- self.exit("No History")
27
-
28
- shows = [x for x in self.hist]
29
- print_names(shows)
30
-
31
- while True:
32
- inp = cinput(colors.CYAN, "Enter Number: ")
33
- try:
34
- if int(inp) <= 0:
35
- raise ValueError
36
-
37
- picked = shows[int(inp) - 1]
38
- break
39
- except ValueError:
40
- error("invalid input")
41
- except IndexError:
42
- error("invalid Input")
43
-
44
- self.entry.show_name = picked
45
- self.entry.ep = self.hist[picked]["ep"]
46
- self.entry.ep_url = self.hist[picked]["ep-link"]
47
- self.entry.category_url = self.hist[picked]["category-link"]
48
- self.entry.latest_ep = epHandler(self.entry).get_latest()
49
-
50
- def process(self):
51
- url_parser = videourl(self.entry, self.options.quality)
52
- url_parser.stream_url()
53
- self.entry = url_parser.get_entry()
54
-
55
- def show(self):
56
- self.player.play_title(self.entry)
57
-
58
- def post(self):
59
- Menu(
60
- options=self.options,
61
- entry=self.entry,
62
- player=self.player,
63
- rpc_client=self.rpc_client,
64
- ).run()
@@ -1,27 +0,0 @@
1
- from anipy_cli.arg_parser import CliArgs
2
- from anipy_cli.cli.menus import MALMenu
3
- from anipy_cli.cli.clis.base_cli import CliBase
4
-
5
-
6
- class MalCli(CliBase):
7
- def __init__(self, options: CliArgs, rpc_client=None):
8
- super().__init__(options, rpc_client)
9
-
10
- def print_header(self):
11
- pass
12
-
13
- def take_input(self):
14
- pass
15
-
16
- def process(self):
17
- pass
18
-
19
- def show(self):
20
- pass
21
-
22
- def post(self):
23
- menu = MALMenu(options=self.options, rpc_client=self.rpc_client)
24
- if self.options.auto_update:
25
- menu.download(mode="all")
26
- else:
27
- menu.run()
@@ -1,3 +0,0 @@
1
- from anipy_cli.cli.menus.menu import Menu
2
- from anipy_cli.cli.menus.mal_menu import MALMenu
3
- from anipy_cli.cli.menus.seasonal_menu import SeasonalMenu
@@ -1,411 +0,0 @@
1
- from typing import List
2
-
3
- from anipy_cli.arg_parser import CliArgs
4
- from anipy_cli.colors import colors, cprint, cinput
5
- from anipy_cli.misc import Entry, print_names, error
6
- from anipy_cli.player import get_player
7
- from anipy_cli.url_handler import videourl
8
- from anipy_cli.query import query
9
- from anipy_cli.download import download
10
- from anipy_cli.config import Config
11
- from anipy_cli.mal import MAL
12
- from anipy_cli.cli.util import binge, get_season_searches
13
- from anipy_cli.cli.menus.base_menu import MenuBase, MenuOption
14
-
15
-
16
- class MALMenu(MenuBase):
17
- def __init__(self, options: CliArgs, rpc_client=None):
18
- self.entry = Entry()
19
- self.options = options
20
- self.rpc_client = rpc_client
21
-
22
- self.dl_path = Config().seasonals_dl_path
23
- if options.location:
24
- self.dl_path = options.location
25
-
26
- user = None
27
- if Config().mal_user and Config().mal_user != "":
28
- user = Config().mal_user
29
-
30
- if options.mal_password is not None and options.mal_password != "":
31
- password = options.mal_password
32
- else:
33
- password = Config().mal_password
34
- if not password or password == "":
35
- password = None
36
-
37
- if user is None or password is None:
38
- cprint(colors.ERROR, "Missing credentials!\n")
39
- cprint(
40
- colors.CYAN,
41
- "In order to use the MAL-Mode, you need to specify your username and password.\n",
42
- )
43
- cprint(
44
- colors.CYAN, "Those can be specified in the anipy-cli config file.\n"
45
- )
46
-
47
- if user is None:
48
- while not user:
49
- user_input = cinput(
50
- colors.CYAN,
51
- "Please enter your MyAnimeList ",
52
- colors.YELLOW,
53
- "Username ",
54
- colors.CYAN,
55
- ":\n",
56
- )
57
- if user_input and user_input != "":
58
- user = user_input
59
-
60
- if password is None:
61
- cprint(
62
- colors.MAGENTA,
63
- "The password can also be passed with the '--mal-password' parameter.",
64
- )
65
- while not password:
66
- pw_input = cinput(
67
- colors.CYAN,
68
- "Please enter your MyAnimeList ",
69
- colors.YELLOW,
70
- "Password ",
71
- colors.CYAN,
72
- ":\n",
73
- )
74
- if pw_input and pw_input != "":
75
- password = pw_input
76
-
77
- self.m_class = MAL(user, password)
78
-
79
- def print_header(self):
80
- pass
81
-
82
- @property
83
- def menu_options(self) -> List[MenuOption]:
84
- return [
85
- MenuOption("Add Anime", self.add_anime, "a"),
86
- MenuOption("Delete one anime from mal list", self.del_anime, "e"),
87
- MenuOption("List anime in mal list", self.list_animes, "l"),
88
- MenuOption("Map MAL anime to gogo Links", self.create_gogo_maps, "m"),
89
- MenuOption("Sync MAL list into seasonals", self.sync_mal_to_seasonals, "s"),
90
- MenuOption(
91
- "Sync seasonals into MAL list",
92
- self.m_class.sync_seasonals_with_mal,
93
- "b",
94
- ),
95
- MenuOption(
96
- "Download newest episodes", lambda: self.download(mode="latest"), "d"
97
- ),
98
- MenuOption("Download all episodes", lambda: self.download(mode="all"), "x"),
99
- MenuOption("Binge watch newest episodes", self.binge_latest, "w"),
100
- MenuOption("Quit", self.quit, "q"),
101
- ]
102
-
103
- def add_anime(self):
104
- searches = []
105
- if (
106
- not self.options.no_season_search
107
- and input("Search for anime in Season? (y|n): \n>> ") == "y"
108
- ):
109
- searches = get_season_searches(gogo=False)
110
-
111
- else:
112
- searches.append(input("Search: "))
113
-
114
- for search in searches:
115
- if isinstance(search, dict):
116
- mal_entry = search
117
-
118
- else:
119
- print("\nCurrent: ", search)
120
- temp_search = self.m_class.get_anime(search)
121
- names = [item["node"]["title"] for item in temp_search]
122
- print_names(names)
123
- selected = False
124
- skip = False
125
- while selected is False:
126
- try:
127
- sel_index = input("Select show (Number or c for cancel):\n")
128
- if sel_index == "c":
129
- skip = True
130
- break
131
- selected = int(sel_index) - 1
132
- except ValueError:
133
- print("Please enter a valid number.")
134
- if skip:
135
- continue
136
- mal_entry = temp_search[selected]
137
-
138
- self.m_class.update_anime_list(
139
- mal_entry["node"]["id"], {"status": "watching"}
140
- )
141
- self.create_gogo_maps()
142
-
143
- self.print_options()
144
-
145
- def del_anime(self):
146
- mal_list = self.m_class.get_anime_list()
147
- mal_list = [x for x in mal_list]
148
- mal_names = [n["node"]["title"] for n in mal_list]
149
- print_names(mal_names)
150
- while True:
151
- inp = cinput(colors.CYAN, "Enter Number: ")
152
- try:
153
- picked = mal_list[int(inp) - 1]["node"]["id"]
154
- break
155
- except:
156
- error("Invalid Input")
157
-
158
- self.m_class.del_show(picked)
159
- self.print_options()
160
-
161
- def list_animes(self):
162
- mal_list = self.m_class.get_anime_list()
163
- for i in mal_list:
164
- status = i["node"]["my_list_status"]["status"]
165
-
166
- if status == "completed":
167
- color = colors.MAGENTA
168
- elif status == "on_hold":
169
- color = colors.YELLOW
170
- elif status == "plan_to_watch":
171
- color = colors.BLUE
172
- elif status == "dropped":
173
- color = colors.ERROR
174
- else:
175
- color = colors.GREEN
176
-
177
- cprint(
178
- colors.CYAN,
179
- "==> Last watched EP: {}".format(
180
- i["node"]["my_list_status"]["num_episodes_watched"]
181
- ),
182
- color,
183
- " | ({}) | ".format(status),
184
- colors.CYAN,
185
- i["node"]["title"],
186
- )
187
- # List is empty
188
- if not mal_list:
189
- cprint(colors.YELLOW, "No anime found.\nAdd an anime to your list first.")
190
-
191
- input("Enter to continue")
192
- self.print_options()
193
-
194
- def list_possible(self, latest_urls):
195
- for i in latest_urls:
196
- cprint(colors.RED, f"{i}:")
197
- for j in latest_urls[i]["ep_list"]:
198
- cprint(colors.CYAN, f"==> EP: {j[0]}")
199
-
200
- def download(self, mode="all"):
201
- print("Preparing list of episodes...")
202
- if mode == "latest":
203
- urls = self.m_class.latest_eps()
204
-
205
- else:
206
- urls = self.m_class.latest_eps(all_eps=True)
207
-
208
- if not urls:
209
- error("Nothing to download")
210
- return
211
-
212
- cprint(colors.CYAN, "Stuff to be downloaded:")
213
- self.list_possible(urls)
214
- if not self.options.auto_update:
215
- cinput(colors.RED, "Enter to continue or CTRL+C to abort.")
216
-
217
- for i in urls:
218
- cprint(f"Downloading newest urls for {i}", colors.CYAN)
219
- show_entry = Entry()
220
- show_entry.show_name = i
221
- for j in urls[i]["ep_list"]:
222
- show_entry.embed_url = ""
223
- show_entry.ep = j[0]
224
- show_entry.ep_url = j[1]
225
- url_class = videourl(show_entry, self.options.quality)
226
- url_class.stream_url()
227
- show_entry = url_class.get_entry()
228
- download(
229
- show_entry, self.options.quality, self.options.ffmpeg, self.dl_path
230
- ).download()
231
-
232
- if not self.options.auto_update:
233
- self.print_options()
234
-
235
- def binge_latest(self):
236
- latest_eps = self.m_class.latest_eps()
237
- cprint(colors.CYAN, "Stuff to be watched:")
238
- self.list_possible(latest_eps)
239
- cinput(colors.RED, "Enter to continue or CTRL+C to abort.")
240
- ep_list = []
241
- ep_urls = []
242
- ep_dic = {}
243
- for i in latest_eps:
244
- for j in latest_eps[i]["ep_list"]:
245
- ep_list.append(j[0])
246
- ep_urls.append(j[1])
247
-
248
- ep_dic.update(
249
- {
250
- i: {
251
- "ep_urls": [x for x in ep_urls],
252
- "eps": [x for x in ep_list],
253
- "category_url": latest_eps[i]["category_url"],
254
- }
255
- }
256
- )
257
- ep_list.clear()
258
- ep_urls.clear()
259
-
260
- player = get_player(self.rpc_client, self.options.optional_player)
261
- binge(
262
- ep_dic,
263
- self.options.quality,
264
- player=player,
265
- mode="mal",
266
- mal_class=self.m_class,
267
- )
268
- player.kill_player()
269
- self.print_options()
270
-
271
- def sync_mal_to_seasonals(self):
272
- self.create_gogo_maps()
273
-
274
- self.m_class.sync_mal_with_seasonal()
275
-
276
- def manual_gogomap(self):
277
- self.create_gogo_maps()
278
-
279
- def create_gogo_maps(self):
280
- if not self.options.auto_update and input(
281
- "Try auto mapping MAL to gogo format? (y/n):\n"
282
- ).lower() in ["y", "yes"]:
283
- self.m_class.auto_map_all_without_map()
284
- failed_to_map = list(self.m_class.get_all_without_gogo_map())
285
- failed_to_map.sort(key=len, reverse=True)
286
- if not self.options.auto_update and len(failed_to_map) > 0:
287
- cprint(colors.YELLOW, "Some Anime failed auto-mapping...")
288
- cprint(colors.GREEN, "Select Anime for manual mapping:\n")
289
- selected = []
290
- searches = []
291
-
292
- print_names(failed_to_map)
293
- print("Selection: (e.g. 1, 1 3, 1-3 or * [for all]) \n")
294
- cprint(colors.YELLOW, "Enter or n to skip...")
295
- selection = cinput(colors.GREEN, ">>")
296
- if selection.__contains__("-"):
297
- selection_range = selection.strip(" ").split("-")
298
- for i in range(
299
- int(selection_range[0]) - 1, int(selection_range[1]) - 1, 1
300
- ):
301
- selected.append(i)
302
-
303
- elif selection in ["all", "*"]:
304
- selected = range(0, len(failed_to_map) - 1)
305
- elif selection in ["", "n", "N"]:
306
- selected = []
307
-
308
- else:
309
- for i in selection.strip(" ").split(" "):
310
- selected.append(int(i) - 1)
311
-
312
- for value in selected:
313
- show_entries = []
314
- done = False
315
- search_name = failed_to_map[value]
316
- while not done:
317
- cprint(
318
- colors.GREEN,
319
- "Current: ",
320
- colors.CYAN,
321
- f"{failed_to_map[value]}\n",
322
- )
323
- show_entry = Entry()
324
- query_class = query(search_name, show_entry)
325
- links_query = query_class.get_links()
326
-
327
- if not links_query:
328
- skip = False
329
- while not links_query and not skip:
330
- cprint(
331
- colors.ERROR,
332
- "No search results for ",
333
- colors.YELLOW,
334
- failed_to_map[value],
335
- )
336
- cprint(
337
- colors.GREEN,
338
- "Sometimes the names on GoGo are too different from the ones on MAL.\n",
339
- )
340
- cprint(colors.CYAN, "Try custom name for mapping? (Y/N):\n")
341
- if input().lower() == "y":
342
- query_class = query(
343
- cinput(
344
- colors.GREEN,
345
- "Enter Search String to search on GoGo:\n",
346
- ),
347
- show_entry,
348
- )
349
- links_query = query_class.get_links()
350
- if links_query:
351
- show = query_class.pick_show(cancelable=True)
352
- if show:
353
- show_entries.append(show_entry)
354
- mapped = self.m_class.manual_map_gogo_mal(
355
- failed_to_map[value],
356
- {
357
- "link": show_entry.category_url,
358
- "name": show_entry.show_name,
359
- },
360
- )
361
- if mapped:
362
- del failed_to_map[value]
363
- del selected[value]
364
- else:
365
- print("Skipping show")
366
- skip = True
367
- done = True
368
- elif links_query[0] != 0:
369
- links, names = links_query
370
- search_another = True
371
- while search_another and len(links) > 0:
372
- show = query_class.pick_show(cancelable=True)
373
- if show:
374
- show_entries.append(show_entry)
375
- self.m_class.manual_map_gogo_mal(
376
- failed_to_map[value],
377
- {
378
- "link": show_entry.category_url,
379
- "name": show_entry.show_name,
380
- },
381
- )
382
-
383
- links.remove(
384
- "/category/"
385
- + show_entry.category_url.split("/category/")[1]
386
- )
387
- names.remove(show_entry.show_name)
388
- print(
389
- f"{colors.GREEN} Added {show_entry.show_name} ...{colors.END}"
390
- )
391
- if input(
392
- f"Add another show map to {failed_to_map[value]}? (y/n):\n"
393
- ).lower() not in ["y", "yes"]:
394
- search_another = False
395
- done = True
396
- else:
397
- search_name_parts = search_name.split(" ")
398
- if len(search_name_parts) <= 1:
399
- print(
400
- f"{colors.YELLOW}Could not find {failed_to_map[value]} on gogo.{colors.END}"
401
- )
402
- done = True
403
- else:
404
- print(
405
- f"{colors.YELLOW} Nothing found. Trying to shorten name...{colors.END}"
406
- )
407
-
408
- search_name_parts.pop()
409
- search_name = " ".join(search_name_parts)
410
- self.m_class.write_save_data()
411
- self.m_class.write_mal_list()
@@ -1,108 +0,0 @@
1
- import sys
2
- import os
3
- from typing import List
4
-
5
- from anipy_cli.arg_parser import CliArgs
6
- from anipy_cli.colors import colors, cprint
7
- from anipy_cli.misc import Entry, error, clear_console
8
- from anipy_cli.player import PlayerBaseType
9
- from anipy_cli.url_handler import videourl, epHandler
10
- from anipy_cli.query import query
11
- from anipy_cli.download import download
12
- from anipy_cli.config import Config
13
- from anipy_cli.cli.menus.base_menu import MenuBase, MenuOption
14
-
15
-
16
- class Menu(MenuBase):
17
- def __init__(
18
- self, options: CliArgs, entry: Entry, player: PlayerBaseType, rpc_client=None
19
- ):
20
- self.rpc_client = rpc_client
21
- self.options = options
22
- self.entry = entry
23
- self.player = player
24
-
25
- @property
26
- def menu_options(self) -> List[MenuOption]:
27
- return [
28
- MenuOption("Next Episode", self.next_ep, "n"),
29
- MenuOption("Previous Episode", self.prev_ep, "p"),
30
- MenuOption("Replay Episode", self.repl_ep, "r"),
31
- MenuOption("Select episode", self.selec_ep, "s"),
32
- MenuOption("Search for Anime", self.search, "a"),
33
- MenuOption("Print Video Info", self.video_info, "i"),
34
- MenuOption("Download Episode", self.download_video, "d"),
35
- MenuOption("Quit", self.quit, "q"),
36
- ]
37
-
38
- def print_header(self):
39
- cprint(
40
- colors.GREEN,
41
- "Playing: ",
42
- colors.BLUE,
43
- self.entry.show_name,
44
- colors.GREEN,
45
- f" | {self.entry.quality} | ",
46
- colors.RED,
47
- f"{self.entry.ep}/{self.entry.latest_ep}",
48
- )
49
-
50
- def start_ep(self):
51
- self.entry.embed_url = ""
52
- url_class = videourl(self.entry, self.options.quality)
53
- url_class.stream_url()
54
- self.entry = url_class.get_entry()
55
- self.player.play_title(self.entry)
56
-
57
- def next_ep(self):
58
- ep_class = epHandler(self.entry)
59
- self.entry = ep_class.next_ep()
60
- self.start_ep()
61
- self.print_options()
62
-
63
- def prev_ep(self):
64
- ep_class = epHandler(self.entry)
65
- self.entry = ep_class.prev_ep()
66
- self.start_ep()
67
- self.print_options()
68
-
69
- def repl_ep(self):
70
- self.start_ep()
71
-
72
- def selec_ep(self):
73
- ep_class = epHandler(self.entry)
74
- self.entry = ep_class.pick_ep()
75
- self.start_ep()
76
- self.print_options()
77
-
78
- def search(self):
79
- clear_console()
80
- query_class = query(input("Search: "), self.entry)
81
- if query_class.get_links() == 0:
82
- error("no search results")
83
- return
84
- else:
85
- self.entry = query_class.pick_show()
86
- ep_class = epHandler(self.entry)
87
- self.entry = ep_class.pick_ep()
88
- self.start_ep()
89
- self.print_options()
90
-
91
- def video_info(self):
92
- print(f"Show Name: {self.entry.show_name}")
93
- print(f"Category Url: {self.entry.category_url}")
94
- print(f"Episode Url: {self.entry.ep_url}")
95
- print(f"Episode: {self.entry.ep}")
96
- print(f"Embed Url: {self.entry.embed_url}")
97
- print(f"Stream Url: {self.entry.stream_url}")
98
- print(f"Quality: {self.entry.quality}")
99
-
100
- def download_video(self):
101
- path = download(self.entry, self.options.quality).download()
102
- if Config().auto_open_dl_defaultcli:
103
- self.player.play_file(str(path))
104
- self.print_options()
105
-
106
- def quit(self):
107
- self.player.kill_player()
108
- sys.exit(0)