weeb-cli 2.0.0__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.
Files changed (53) hide show
  1. {weeb_cli-2.0.0/weeb_cli.egg-info → weeb_cli-2.1.0}/PKG-INFO +3 -3
  2. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/README.md +2 -2
  3. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/pyproject.toml +1 -1
  4. weeb_cli-2.1.0/weeb_cli/__init__.py +1 -0
  5. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/commands/downloads.py +12 -0
  6. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/commands/search.py +12 -0
  7. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/commands/settings.py +207 -0
  8. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/commands/watchlist.py +30 -8
  9. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/locales/en.json +31 -1
  10. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/locales/tr.json +31 -1
  11. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/main.py +18 -0
  12. weeb_cli-2.1.0/weeb_cli/services/tracker.py +737 -0
  13. {weeb_cli-2.0.0 → weeb_cli-2.1.0/weeb_cli.egg-info}/PKG-INFO +3 -3
  14. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli.egg-info/SOURCES.txt +1 -0
  15. weeb_cli-2.0.0/weeb_cli/__init__.py +0 -1
  16. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/LICENSE +0 -0
  17. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/setup.cfg +0 -0
  18. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/__main__.py +0 -0
  19. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/commands/setup.py +0 -0
  20. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/config.py +0 -0
  21. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/i18n.py +0 -0
  22. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/providers/__init__.py +0 -0
  23. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/providers/allanime.py +0 -0
  24. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/providers/animecix.py +0 -0
  25. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/providers/anizle.py +0 -0
  26. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/providers/base.py +0 -0
  27. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/providers/extractors/__init__.py +0 -0
  28. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/providers/extractors/megacloud.py +0 -0
  29. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/providers/hianime.py +0 -0
  30. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/providers/registry.py +0 -0
  31. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/providers/turkanime.py +0 -0
  32. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/services/__init__.py +0 -0
  33. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/services/database.py +0 -0
  34. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/services/dependency_manager.py +0 -0
  35. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/services/details.py +0 -0
  36. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/services/downloader.py +0 -0
  37. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/services/local_library.py +0 -0
  38. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/services/logger.py +0 -0
  39. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/services/notifier.py +0 -0
  40. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/services/player.py +0 -0
  41. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/services/progress.py +0 -0
  42. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/services/scraper.py +0 -0
  43. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/services/search.py +0 -0
  44. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/services/updater.py +0 -0
  45. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/services/watch.py +0 -0
  46. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/ui/__init__.py +0 -0
  47. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/ui/header.py +0 -0
  48. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/ui/menu.py +0 -0
  49. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli/ui/prompt.py +0 -0
  50. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli.egg-info/dependency_links.txt +0 -0
  51. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli.egg-info/entry_points.txt +0 -0
  52. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli.egg-info/requires.txt +0 -0
  53. {weeb_cli-2.0.0 → weeb_cli-2.1.0}/weeb_cli.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: weeb-cli
3
- Version: 2.0.0
3
+ Version: 2.1.0
4
4
  Summary: Tarayıcı yok, reklam yok, dikkat dağıtıcı unsur yok. Sadece siz ve eşsiz bir anime izleme deneyimi.
5
5
  Author-email: ewgsta <ewgst@proton.me>
6
6
  License-Expression: CC-BY-NC-ND-4.0
@@ -25,7 +25,7 @@ Requires-Dist: appdirs
25
25
  Dynamic: license-file
26
26
 
27
27
  <p align="center">
28
- <img src="weeb_landing/logo/weeb-logo.png" alt="Weeb CLI Logo" width="120">
28
+ <img src="weeb_landing/logo/512x512.webp" alt="Weeb CLI Logo" width="120">
29
29
  </p>
30
30
 
31
31
  <h1 align="center">Weeb CLI</h1>
@@ -124,7 +124,7 @@ pip install -e .
124
124
  ## Kullanım
125
125
 
126
126
  ```bash
127
- weeb
127
+ weeb-cli
128
128
  ```
129
129
 
130
130
  ### Klavye Kontrolleri
@@ -1,5 +1,5 @@
1
1
  <p align="center">
2
- <img src="weeb_landing/logo/weeb-logo.png" alt="Weeb CLI Logo" width="120">
2
+ <img src="weeb_landing/logo/512x512.webp" alt="Weeb CLI Logo" width="120">
3
3
  </p>
4
4
 
5
5
  <h1 align="center">Weeb CLI</h1>
@@ -98,7 +98,7 @@ pip install -e .
98
98
  ## Kullanım
99
99
 
100
100
  ```bash
101
- weeb
101
+ weeb-cli
102
102
  ```
103
103
 
104
104
  ### Klavye Kontrolleri
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "weeb-cli"
7
- version = "2.0.0"
7
+ version = "2.1.0"
8
8
  description = "Tarayıcı yok, reklam yok, dikkat dağıtıcı unsur yok. Sadece siz ve eşsiz bir anime izleme deneyimi."
9
9
  readme = "README.md"
10
10
  authors = [{ name = "ewgsta", email = "ewgst@proton.me" }]
@@ -0,0 +1 @@
1
+ __version__ = "2.1.0"
@@ -348,6 +348,18 @@ def play_local_episode(anime, episode):
348
348
  episode["number"],
349
349
  anime["episode_count"]
350
350
  )
351
+
352
+ from weeb_cli.services.tracker import anilist_tracker, mal_tracker
353
+ anilist_tracker.update_progress(
354
+ anime["title"],
355
+ episode["number"],
356
+ anime["episode_count"]
357
+ )
358
+ mal_tracker.update_progress(
359
+ anime["title"],
360
+ episode["number"],
361
+ anime["episode_count"]
362
+ )
351
363
  except:
352
364
  pass
353
365
 
@@ -327,6 +327,18 @@ def handle_watch_flow(slug, details):
327
327
  total_episodes=total_eps
328
328
  )
329
329
 
330
+ from weeb_cli.services.tracker import anilist_tracker, mal_tracker
331
+ anilist_tracker.update_progress(
332
+ details.get("title"),
333
+ n,
334
+ total_eps
335
+ )
336
+ mal_tracker.update_progress(
337
+ details.get("title"),
338
+ n,
339
+ total_eps
340
+ )
341
+
330
342
  completed_ids.add(n)
331
343
  if n >= next_ep_num:
332
344
  next_ep_num = n + 1
@@ -65,6 +65,9 @@ def open_settings():
65
65
  if config.get("ytdlp_enabled"):
66
66
  choices.append(opt_ytdlp_conf)
67
67
 
68
+ opt_trackers = i18n.get("settings.trackers")
69
+ choices.append(opt_trackers)
70
+
68
71
  try:
69
72
  answer = questionary.select(
70
73
  i18n.get("settings.title"),
@@ -98,6 +101,8 @@ def open_settings():
98
101
  toggle_config("ytdlp_enabled", "yt-dlp")
99
102
  elif answer == opt_ytdlp_conf:
100
103
  ytdlp_settings_menu()
104
+ elif answer == opt_trackers:
105
+ trackers_menu()
101
106
  elif answer is None:
102
107
  return
103
108
 
@@ -378,3 +383,205 @@ def manage_drive(drive):
378
383
 
379
384
  except KeyboardInterrupt:
380
385
  return
386
+
387
+
388
+ def trackers_menu():
389
+ while True:
390
+ console.clear()
391
+ show_header(i18n.get("settings.trackers"))
392
+
393
+ opt_anilist = "AniList"
394
+ opt_mal = "MyAnimeList"
395
+
396
+ try:
397
+ sel = questionary.select(
398
+ i18n.get("downloads.action_prompt"),
399
+ choices=[opt_anilist, opt_mal],
400
+ pointer=">",
401
+ use_shortcuts=False
402
+ ).ask()
403
+
404
+ if sel is None:
405
+ return
406
+
407
+ if sel == opt_anilist:
408
+ anilist_settings_menu()
409
+ elif sel == opt_mal:
410
+ mal_settings_menu()
411
+
412
+ except KeyboardInterrupt:
413
+ return
414
+
415
+
416
+ def anilist_settings_menu():
417
+ from weeb_cli.services.tracker import anilist_tracker
418
+
419
+ while True:
420
+ console.clear()
421
+ show_header("AniList")
422
+
423
+ if anilist_tracker.is_authenticated():
424
+ username = anilist_tracker.get_username()
425
+ console.print(f"[green]{i18n.t('settings.anilist_connected', user=username)}[/green]\n")
426
+
427
+ pending = anilist_tracker.get_pending_count()
428
+ if pending > 0:
429
+ console.print(f"[yellow]{i18n.t('settings.anilist_pending', count=pending)}[/yellow]\n")
430
+
431
+ opt_sync = i18n.get("settings.anilist_sync")
432
+ opt_logout = i18n.get("settings.anilist_logout")
433
+
434
+ choices = []
435
+ if pending > 0:
436
+ choices.append(opt_sync)
437
+ choices.append(opt_logout)
438
+
439
+ try:
440
+ sel = questionary.select(
441
+ i18n.get("downloads.action_prompt"),
442
+ choices=choices,
443
+ pointer=">",
444
+ use_shortcuts=False
445
+ ).ask()
446
+
447
+ if sel is None:
448
+ return
449
+
450
+ if sel == opt_sync:
451
+ with console.status(i18n.get("common.processing"), spinner="dots"):
452
+ synced = anilist_tracker.sync_pending()
453
+ console.print(f"[green]{i18n.t('settings.anilist_synced', count=synced)}[/green]")
454
+ time.sleep(1)
455
+ elif sel == opt_logout:
456
+ confirm = questionary.confirm(
457
+ i18n.get("settings.confirm_logout"),
458
+ default=False
459
+ ).ask()
460
+ if confirm:
461
+ anilist_tracker.logout()
462
+ console.print(f"[green]{i18n.get('settings.anilist_logged_out')}[/green]")
463
+ time.sleep(1)
464
+ return
465
+
466
+ except KeyboardInterrupt:
467
+ return
468
+ else:
469
+ console.print(f"[dim]{i18n.get('settings.anilist_not_connected')}[/dim]\n")
470
+
471
+ opt_login = i18n.get("settings.anilist_login")
472
+
473
+ try:
474
+ sel = questionary.select(
475
+ i18n.get("downloads.action_prompt"),
476
+ choices=[opt_login],
477
+ pointer=">",
478
+ use_shortcuts=False
479
+ ).ask()
480
+
481
+ if sel is None:
482
+ return
483
+
484
+ if sel == opt_login:
485
+ console.print(f"\n[cyan]{i18n.get('settings.anilist_opening_browser')}[/cyan]")
486
+ console.print(f"[dim]{i18n.get('settings.anilist_waiting')}[/dim]\n")
487
+
488
+ with console.status(i18n.get("common.processing"), spinner="dots"):
489
+ token = anilist_tracker.start_auth_server(timeout=120)
490
+
491
+ if token:
492
+ success = anilist_tracker.authenticate(token)
493
+ if success:
494
+ console.print(f"[green]{i18n.get('settings.anilist_login_success')}[/green]")
495
+ else:
496
+ console.print(f"[red]{i18n.get('settings.anilist_login_failed')}[/red]")
497
+ else:
498
+ console.print(f"[yellow]{i18n.get('settings.anilist_timeout')}[/yellow]")
499
+ time.sleep(1)
500
+
501
+ except KeyboardInterrupt:
502
+ return
503
+
504
+
505
+ def mal_settings_menu():
506
+ from weeb_cli.services.tracker import mal_tracker
507
+
508
+ while True:
509
+ console.clear()
510
+ show_header("MyAnimeList")
511
+
512
+ if mal_tracker.is_authenticated():
513
+ username = mal_tracker.get_username()
514
+ console.print(f"[green]{i18n.t('settings.mal_connected', user=username)}[/green]\n")
515
+
516
+ pending = mal_tracker.get_pending_count()
517
+ if pending > 0:
518
+ console.print(f"[yellow]{i18n.t('settings.mal_pending', count=pending)}[/yellow]\n")
519
+
520
+ opt_sync = i18n.get("settings.mal_sync")
521
+ opt_logout = i18n.get("settings.mal_logout")
522
+
523
+ choices = []
524
+ if pending > 0:
525
+ choices.append(opt_sync)
526
+ choices.append(opt_logout)
527
+
528
+ try:
529
+ sel = questionary.select(
530
+ i18n.get("downloads.action_prompt"),
531
+ choices=choices,
532
+ pointer=">",
533
+ use_shortcuts=False
534
+ ).ask()
535
+
536
+ if sel is None:
537
+ return
538
+
539
+ if sel == opt_sync:
540
+ with console.status(i18n.get("common.processing"), spinner="dots"):
541
+ synced = mal_tracker.sync_pending()
542
+ console.print(f"[green]{i18n.t('settings.mal_synced', count=synced)}[/green]")
543
+ time.sleep(1)
544
+ elif sel == opt_logout:
545
+ confirm = questionary.confirm(
546
+ i18n.get("settings.confirm_logout"),
547
+ default=False
548
+ ).ask()
549
+ if confirm:
550
+ mal_tracker.logout()
551
+ console.print(f"[green]{i18n.get('settings.mal_logged_out')}[/green]")
552
+ time.sleep(1)
553
+ return
554
+
555
+ except KeyboardInterrupt:
556
+ return
557
+ else:
558
+ console.print(f"[dim]{i18n.get('settings.mal_not_connected')}[/dim]\n")
559
+
560
+ opt_login = i18n.get("settings.mal_login")
561
+
562
+ try:
563
+ sel = questionary.select(
564
+ i18n.get("downloads.action_prompt"),
565
+ choices=[opt_login],
566
+ pointer=">",
567
+ use_shortcuts=False
568
+ ).ask()
569
+
570
+ if sel is None:
571
+ return
572
+
573
+ if sel == opt_login:
574
+ console.print(f"\n[cyan]{i18n.get('settings.mal_opening_browser')}[/cyan]")
575
+ console.print(f"[dim]{i18n.get('settings.mal_waiting')}[/dim]\n")
576
+
577
+ with console.status(i18n.get("common.processing"), spinner="dots"):
578
+ user = mal_tracker.start_auth_flow(timeout=120)
579
+
580
+ if user:
581
+ console.print(f"[green]{i18n.get('settings.mal_login_success')}[/green]")
582
+ else:
583
+ console.print(f"[red]{i18n.get('settings.mal_login_failed')}[/red]")
584
+ time.sleep(1)
585
+
586
+ except KeyboardInterrupt:
587
+ return
@@ -1,4 +1,5 @@
1
1
  import questionary
2
+ from pathlib import Path
2
3
  from rich.console import Console
3
4
  from rich.table import Table
4
5
  from weeb_cli.i18n import i18n
@@ -83,6 +84,8 @@ def show_completed_list():
83
84
 
84
85
  def show_in_progress_list():
85
86
  from weeb_cli.commands.search import show_anime_details
87
+ from weeb_cli.commands.downloads import show_anime_episodes
88
+ from weeb_cli.services.local_library import local_library
86
89
 
87
90
  console.clear()
88
91
  show_header(i18n.get("watchlist.in_progress"))
@@ -97,6 +100,8 @@ def show_in_progress_list():
97
100
  pass
98
101
  return
99
102
 
103
+ indexed_anime = {a["title"].lower(): a for a in local_library.get_indexed_anime()}
104
+
100
105
  choices = []
101
106
  for anime in in_progress:
102
107
  watched = len(anime.get("completed", []))
@@ -104,9 +109,13 @@ def show_in_progress_list():
104
109
  total_str = str(total) if total > 0 else "?"
105
110
  title = anime.get("title", anime["slug"])
106
111
  next_ep = anime.get("last_watched", 0) + 1
112
+
113
+ is_local = title.lower() in indexed_anime
114
+ prefix = "[dim]●[/dim] " if is_local else ""
115
+
107
116
  choices.append(questionary.Choice(
108
117
  title=f"{title} [{watched}/{total_str}] - {i18n.get('watchlist.next')}: {next_ep}",
109
- value=anime
118
+ value={"anime": anime, "is_local": is_local, "local_data": indexed_anime.get(title.lower())}
110
119
  ))
111
120
 
112
121
  try:
@@ -118,13 +127,26 @@ def show_in_progress_list():
118
127
  ).ask()
119
128
 
120
129
  if selected:
121
- anime_data = {
122
- "id": selected["slug"],
123
- "slug": selected["slug"],
124
- "title": selected.get("title", selected["slug"]),
125
- "name": selected.get("title", selected["slug"])
126
- }
127
- show_anime_details(anime_data)
130
+ if selected["is_local"] and selected["local_data"]:
131
+ local_data = selected["local_data"]
132
+ anime_path = local_data["folder_path"]
133
+ anime_info = {
134
+ "title": local_data["title"],
135
+ "path": anime_path,
136
+ "episodes": local_library._scan_anime_folder(Path(anime_path)),
137
+ "episode_count": local_data["episode_count"],
138
+ "source": local_data["source_name"]
139
+ }
140
+ show_anime_episodes(anime_info)
141
+ else:
142
+ anime = selected["anime"]
143
+ anime_data = {
144
+ "id": anime["slug"],
145
+ "slug": anime["slug"],
146
+ "title": anime.get("title", anime["slug"]),
147
+ "name": anime.get("title", anime["slug"])
148
+ }
149
+ show_anime_details(anime_data)
128
150
 
129
151
  except KeyboardInterrupt:
130
152
  pass
@@ -26,6 +26,7 @@
26
26
  },
27
27
  "settings": {
28
28
  "title": "Settings",
29
+ "trackers": "MyAnimeList & AniList",
29
30
  "language": "Change Language",
30
31
  "source": "Select Scraping Source",
31
32
  "aria2": "Aria2 Downloader",
@@ -59,7 +60,36 @@
59
60
  "remove_drive": "Remove Drive",
60
61
  "confirm_remove": "Are you sure you want to remove this drive?",
61
62
  "drive_renamed": "Drive renamed.",
62
- "drive_removed": "Drive removed."
63
+ "drive_removed": "Drive removed.",
64
+ "anilist": "AniList",
65
+ "anilist_connected": "Connected: {user}",
66
+ "anilist_not_connected": "Connect your AniList account to sync your watch history.",
67
+ "anilist_login": "Connect to AniList",
68
+ "anilist_logout": "Disconnect",
69
+ "anilist_sync": "Sync Pending Updates",
70
+ "anilist_pending": "{count} updates pending",
71
+ "anilist_synced": "{count} updates synced",
72
+ "anilist_opening_browser": "Opening browser...",
73
+ "anilist_waiting": "Log in via browser, it will be detected automatically...",
74
+ "anilist_timeout": "Timeout. Please try again.",
75
+ "anilist_paste_token": "After logging in, paste the token from the URL here:",
76
+ "anilist_login_success": "Successfully connected to AniList!",
77
+ "anilist_login_failed": "Connection failed. Token may be invalid.",
78
+ "anilist_logged_out": "Disconnected from AniList.",
79
+ "confirm_logout": "Are you sure you want to disconnect?",
80
+ "mal": "MyAnimeList",
81
+ "mal_connected": "Connected: {user}",
82
+ "mal_not_connected": "Connect your MAL account to sync your watch history.",
83
+ "mal_login": "Connect to MAL",
84
+ "mal_logout": "Disconnect",
85
+ "mal_sync": "Sync Pending Updates",
86
+ "mal_pending": "{count} updates pending",
87
+ "mal_synced": "{count} updates synced",
88
+ "mal_opening_browser": "Opening browser...",
89
+ "mal_waiting": "Log in via browser, it will be detected automatically...",
90
+ "mal_login_success": "Successfully connected to MAL!",
91
+ "mal_login_failed": "Connection failed. Please try again.",
92
+ "mal_logged_out": "Disconnected from MAL."
63
93
  },
64
94
  "setup": {
65
95
  "welcome": "Welcome to Weeb CLI!",
@@ -26,6 +26,7 @@
26
26
  },
27
27
  "settings": {
28
28
  "title": "Ayarlar",
29
+ "trackers": "MyAnimeList & AniList",
29
30
  "language": "Dil Değiştir",
30
31
  "source": "Kaynak Seçimi",
31
32
  "aria2": "Aria2 İndirici",
@@ -59,7 +60,36 @@
59
60
  "remove_drive": "Diski Kaldır",
60
61
  "confirm_remove": "Bu diski kaldırmak istediğinize emin misiniz?",
61
62
  "drive_renamed": "Disk ismi değiştirildi.",
62
- "drive_removed": "Disk kaldırıldı."
63
+ "drive_removed": "Disk kaldırıldı.",
64
+ "anilist": "AniList",
65
+ "anilist_connected": "Bağlı: {user}",
66
+ "anilist_not_connected": "AniList hesabınıza bağlanarak izleme geçmişinizi senkronize edebilirsiniz.",
67
+ "anilist_login": "AniList'e Bağlan",
68
+ "anilist_logout": "Bağlantıyı Kes",
69
+ "anilist_sync": "Bekleyenleri Senkronize Et",
70
+ "anilist_pending": "{count} güncelleme bekliyor",
71
+ "anilist_synced": "{count} güncelleme senkronize edildi",
72
+ "anilist_opening_browser": "Tarayıcı açılıyor...",
73
+ "anilist_waiting": "Tarayıcıda giriş yapın, otomatik olarak algılanacak...",
74
+ "anilist_timeout": "Zaman aşımı. Lütfen tekrar deneyin.",
75
+ "anilist_paste_token": "Tarayıcıda giriş yaptıktan sonra URL'deki token'ı buraya yapıştırın:",
76
+ "anilist_login_success": "AniList'e başarıyla bağlandı!",
77
+ "anilist_login_failed": "Bağlantı başarısız. Token geçersiz olabilir.",
78
+ "anilist_logged_out": "AniList bağlantısı kesildi.",
79
+ "confirm_logout": "Bağlantıyı kesmek istediğinize emin misiniz?",
80
+ "mal": "MyAnimeList",
81
+ "mal_connected": "Bağlı: {user}",
82
+ "mal_not_connected": "MAL hesabınıza bağlanarak izleme geçmişinizi senkronize edebilirsiniz.",
83
+ "mal_login": "MAL'a Bağlan",
84
+ "mal_logout": "Bağlantıyı Kes",
85
+ "mal_sync": "Bekleyenleri Senkronize Et",
86
+ "mal_pending": "{count} güncelleme bekliyor",
87
+ "mal_synced": "{count} güncelleme senkronize edildi",
88
+ "mal_opening_browser": "Tarayıcı açılıyor...",
89
+ "mal_waiting": "Tarayıcıda giriş yapın, otomatik olarak algılanacak...",
90
+ "mal_login_success": "MAL'a başarıyla bağlandı!",
91
+ "mal_login_failed": "Bağlantı başarısız. Lütfen tekrar deneyin.",
92
+ "mal_logged_out": "MAL bağlantısı kesildi."
63
93
  },
64
94
  "setup": {
65
95
  "welcome": "Weeb CLI'a Hoş Geldiniz!",
@@ -54,6 +54,7 @@ def start():
54
54
 
55
55
  check_network()
56
56
  check_ffmpeg_silent()
57
+ sync_anilist_pending()
57
58
 
58
59
  show_main_menu()
59
60
 
@@ -76,6 +77,23 @@ def check_incomplete_downloads():
76
77
  except KeyboardInterrupt:
77
78
  queue_manager.cancel_incomplete()
78
79
 
80
+ def sync_anilist_pending():
81
+ from weeb_cli.services.tracker import anilist_tracker, mal_tracker
82
+
83
+ if anilist_tracker.is_authenticated():
84
+ pending = anilist_tracker.get_pending_count()
85
+ if pending > 0:
86
+ synced = anilist_tracker.sync_pending()
87
+ if synced > 0:
88
+ console.print(f"[dim]AniList: {synced} {i18n.get('settings.anilist_synced').split()[1]}[/dim]")
89
+
90
+ if mal_tracker.is_authenticated():
91
+ pending = mal_tracker.get_pending_count()
92
+ if pending > 0:
93
+ synced = mal_tracker.sync_pending()
94
+ if synced > 0:
95
+ console.print(f"[dim]MAL: {synced} {i18n.get('settings.mal_synced').split()[1]}[/dim]")
96
+
79
97
  @app.callback(invoke_without_command=True)
80
98
  def main(ctx: typer.Context):
81
99
  if ctx.invoked_subcommand is None: