Unit3Dup 0.9.12__tar.gz → 0.9.14__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 (101) hide show
  1. {unit3dup-0.9.12 → unit3dup-0.9.14}/PKG-INFO +3 -3
  2. {unit3dup-0.9.12 → unit3dup-0.9.14}/README.rst +2 -2
  3. {unit3dup-0.9.12 → unit3dup-0.9.14}/Unit3Dup.egg-info/PKG-INFO +3 -3
  4. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/command.py +6 -9
  5. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/settings.py +119 -3
  6. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/tags.py +40 -96
  7. {unit3dup-0.9.12 → unit3dup-0.9.14}/pyproject.toml +1 -1
  8. {unit3dup-0.9.12 → unit3dup-0.9.14}/unit3dup/__main__.py +14 -3
  9. {unit3dup-0.9.12 → unit3dup-0.9.14}/unit3dup/bot.py +3 -2
  10. {unit3dup-0.9.12 → unit3dup-0.9.14}/unit3dup/media.py +0 -27
  11. {unit3dup-0.9.12 → unit3dup-0.9.14}/unit3dup/media_manager/DocuManager.py +3 -3
  12. {unit3dup-0.9.12 → unit3dup-0.9.14}/unit3dup/media_manager/GameManager.py +3 -3
  13. {unit3dup-0.9.12 → unit3dup-0.9.14}/unit3dup/media_manager/TorrentManager.py +3 -5
  14. {unit3dup-0.9.12 → unit3dup-0.9.14}/unit3dup/media_manager/VideoManager.py +6 -17
  15. {unit3dup-0.9.12 → unit3dup-0.9.14}/unit3dup/upload.py +3 -3
  16. {unit3dup-0.9.12 → unit3dup-0.9.14}/LICENSE +0 -0
  17. {unit3dup-0.9.12 → unit3dup-0.9.14}/Unit3Dup.egg-info/SOURCES.txt +0 -0
  18. {unit3dup-0.9.12 → unit3dup-0.9.14}/Unit3Dup.egg-info/dependency_links.txt +0 -0
  19. {unit3dup-0.9.12 → unit3dup-0.9.14}/Unit3Dup.egg-info/entry_points.txt +0 -0
  20. {unit3dup-0.9.12 → unit3dup-0.9.14}/Unit3Dup.egg-info/requires.txt +0 -0
  21. {unit3dup-0.9.12 → unit3dup-0.9.14}/Unit3Dup.egg-info/top_level.txt +0 -0
  22. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/__init__.py +0 -0
  23. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/bdinfo_string.py +0 -0
  24. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/bittorrent.py +0 -0
  25. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/constants.py +0 -0
  26. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/database.py +0 -0
  27. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/__init__.py +0 -0
  28. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/ftpx/__init__.py +0 -0
  29. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/ftpx/client.py +0 -0
  30. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/ftpx/core/__init__.py +0 -0
  31. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/ftpx/core/ftpx_service.py +0 -0
  32. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/ftpx/core/ftpx_session.py +0 -0
  33. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/ftpx/core/menu.py +0 -0
  34. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/ftpx/core/models/__init__.py +0 -0
  35. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/ftpx/core/models/list.py +0 -0
  36. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/igdb/__init__.py +0 -0
  37. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/igdb/client.py +0 -0
  38. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/igdb/core/__init__.py +0 -0
  39. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/igdb/core/api.py +0 -0
  40. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/igdb/core/models/__init__.py +0 -0
  41. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/igdb/core/models/search.py +0 -0
  42. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/igdb/core/platformid.py +0 -0
  43. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/igdb/core/tags.py +0 -0
  44. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/imageHost.py +0 -0
  45. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/mediaresult.py +0 -0
  46. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/sessions/__init__.py +0 -0
  47. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/sessions/agents.py +0 -0
  48. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/sessions/exceptions.py +0 -0
  49. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/sessions/session.py +0 -0
  50. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/theMovieDB/__init__.py +0 -0
  51. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/theMovieDB/core/__init__.py +0 -0
  52. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/theMovieDB/core/api.py +0 -0
  53. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/theMovieDB/core/keywords.py +0 -0
  54. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/theMovieDB/core/models/__init__.py +0 -0
  55. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/theMovieDB/core/models/movie/__init__.py +0 -0
  56. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/theMovieDB/core/models/movie/alternative_titles.py +0 -0
  57. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/theMovieDB/core/models/movie/details.py +0 -0
  58. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/theMovieDB/core/models/movie/movie.py +0 -0
  59. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/theMovieDB/core/models/movie/nowplaying.py +0 -0
  60. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/theMovieDB/core/models/movie/release_info.py +0 -0
  61. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/theMovieDB/core/models/tvshow/__init__.py +0 -0
  62. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/theMovieDB/core/models/tvshow/alternative.py +0 -0
  63. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/theMovieDB/core/models/tvshow/details.py +0 -0
  64. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/theMovieDB/core/models/tvshow/on_the_air.py +0 -0
  65. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/theMovieDB/core/models/tvshow/translations.py +0 -0
  66. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/theMovieDB/core/models/tvshow/tvshow.py +0 -0
  67. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/theMovieDB/core/videos.py +0 -0
  68. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/trailers/__init__.py +0 -0
  69. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/trailers/api.py +0 -0
  70. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/trailers/response.py +0 -0
  71. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/external_services/tvdb.py +0 -0
  72. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/extractor.py +0 -0
  73. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/frames.py +0 -0
  74. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/mediainfo.py +0 -0
  75. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/mediainfo_string.py +0 -0
  76. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/title.py +0 -0
  77. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/torrent_clients.py +0 -0
  78. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/trackers/__init__.py +0 -0
  79. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/trackers/data.py +0 -0
  80. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/trackers/itt.py +0 -0
  81. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/trackers/sis.py +0 -0
  82. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/trackers/trackers.py +0 -0
  83. {unit3dup-0.9.12 → unit3dup-0.9.14}/common/utility.py +0 -0
  84. {unit3dup-0.9.12 → unit3dup-0.9.14}/requirements.txt +0 -0
  85. {unit3dup-0.9.12 → unit3dup-0.9.14}/setup.cfg +0 -0
  86. {unit3dup-0.9.12 → unit3dup-0.9.14}/unit3dup/__init__.py +0 -0
  87. {unit3dup-0.9.12 → unit3dup-0.9.14}/unit3dup/automode.py +0 -0
  88. {unit3dup-0.9.12 → unit3dup-0.9.14}/unit3dup/duplicate.py +0 -0
  89. {unit3dup-0.9.12 → unit3dup-0.9.14}/unit3dup/exceptions.py +0 -0
  90. {unit3dup-0.9.12 → unit3dup-0.9.14}/unit3dup/media_manager/ContentManager.py +0 -0
  91. {unit3dup-0.9.12 → unit3dup-0.9.14}/unit3dup/media_manager/MediaInfoManager.py +0 -0
  92. {unit3dup-0.9.12 → unit3dup-0.9.14}/unit3dup/media_manager/SeedManager.py +0 -0
  93. {unit3dup-0.9.12 → unit3dup-0.9.14}/unit3dup/media_manager/__init__.py +0 -0
  94. {unit3dup-0.9.12 → unit3dup-0.9.14}/unit3dup/media_manager/common.py +0 -0
  95. {unit3dup-0.9.12 → unit3dup-0.9.14}/unit3dup/pvtDocu.py +0 -0
  96. {unit3dup-0.9.12 → unit3dup-0.9.14}/unit3dup/pvtTorrent.py +0 -0
  97. {unit3dup-0.9.12 → unit3dup-0.9.14}/unit3dup/pvtTracker.py +0 -0
  98. {unit3dup-0.9.12 → unit3dup-0.9.14}/unit3dup/pvtVideo.py +0 -0
  99. {unit3dup-0.9.12 → unit3dup-0.9.14}/unit3dup/torrent.py +0 -0
  100. {unit3dup-0.9.12 → unit3dup-0.9.14}/view/__init__.py +0 -0
  101. {unit3dup-0.9.12 → unit3dup-0.9.14}/view/custom_console.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Unit3Dup
3
- Version: 0.9.12
3
+ Version: 0.9.14
4
4
  Summary: An uploader for the Unit3D torrent tracker
5
5
  Author: Parzival
6
6
  License-Expression: MIT
@@ -60,8 +60,8 @@ It performs the following tasks:
60
60
  - Seeding in qBittorrent, Transmission or rTorrent
61
61
  - Reseeding one or more torrents at a time
62
62
  - Seed your torrents across different OS
63
- - Add a custom title to your seasons
64
- - Generate info for a title using MediaInfo
63
+ - Generate various tags for titles: ``version``, ``resolution``, ``uhd``, ``platform``, ``source``, ``remux``, ``multi``, ``acodec``, ``channels``, ``flag``, ``subtitle``, ``vcodec``, ``hdr``, ``video_encoder``
64
+
65
65
 
66
66
  unit3dup can grab the first page, convert it to an image (using xpdf),
67
67
  and then the bot can upload it to an image host, then add the link to the torrent page description.
@@ -29,8 +29,8 @@ It performs the following tasks:
29
29
  - Seeding in qBittorrent, Transmission or rTorrent
30
30
  - Reseeding one or more torrents at a time
31
31
  - Seed your torrents across different OS
32
- - Add a custom title to your seasons
33
- - Generate info for a title using MediaInfo
32
+ - Generate various tags for titles: ``version``, ``resolution``, ``uhd``, ``platform``, ``source``, ``remux``, ``multi``, ``acodec``, ``channels``, ``flag``, ``subtitle``, ``vcodec``, ``hdr``, ``video_encoder``
33
+
34
34
 
35
35
  unit3dup can grab the first page, convert it to an image (using xpdf),
36
36
  and then the bot can upload it to an image host, then add the link to the torrent page description.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Unit3Dup
3
- Version: 0.9.12
3
+ Version: 0.9.14
4
4
  Summary: An uploader for the Unit3D torrent tracker
5
5
  Author: Parzival
6
6
  License-Expression: MIT
@@ -60,8 +60,8 @@ It performs the following tasks:
60
60
  - Seeding in qBittorrent, Transmission or rTorrent
61
61
  - Reseeding one or more torrents at a time
62
62
  - Seed your torrents across different OS
63
- - Add a custom title to your seasons
64
- - Generate info for a title using MediaInfo
63
+ - Generate various tags for titles: ``version``, ``resolution``, ``uhd``, ``platform``, ``source``, ``remux``, ``multi``, ``acodec``, ``channels``, ``flag``, ``subtitle``, ``vcodec``, ``hdr``, ``video_encoder``
64
+
65
65
 
66
66
  unit3dup can grab the first page, convert it to an image (using xpdf),
67
67
  and then the bot can upload it to an image host, then add the link to the torrent page description.
@@ -1,10 +1,10 @@
1
1
  # -*- coding: utf-8 -*-
2
-
3
2
  import os
4
3
  import argparse
5
4
  from common.utility import System
6
5
  from common.settings import Load
7
6
 
7
+
8
8
  class CommandLine:
9
9
  """
10
10
  Class to handle user input from the command line
@@ -30,7 +30,6 @@ class CommandLine:
30
30
  parser.add_argument("-b", "--buildtags", action="store_true", help="Auto build torrent name")
31
31
 
32
32
  parser.add_argument("-reseed", "--reseed", action="store_true", help="reseed folder")
33
- parser.add_argument("-gentitle", "--gentitle", action="store_true", help="")
34
33
  parser.add_argument("-watcher", "--watcher", action="store_true", help="Start watcher")
35
34
 
36
35
  parser.add_argument("-notitle", "--notitle", type=str, help="")
@@ -99,8 +98,6 @@ class CommandLine:
99
98
  "-pr", "--prelease", action="store_true", help="Personal release torrent"
100
99
  )
101
100
 
102
-
103
-
104
101
  # Parsing the User cli
105
102
  self.args: parser = parser.parse_args()
106
103
 
@@ -114,10 +111,10 @@ class CommandLine:
114
111
  # Test -force flag
115
112
  if self.args.force:
116
113
  self.args.force = self.args.force[:10]
117
- if self.args.force.lower() not in [ System.category_list[System.MOVIE],
118
- System.category_list[System.GAME],
119
- System.category_list[System.TV_SHOW],
120
- System.category_list[System.DOCUMENTARY]]:
114
+ if self.args.force.lower() not in [System.category_list[System.MOVIE],
115
+ System.category_list[System.GAME],
116
+ System.category_list[System.TV_SHOW],
117
+ System.category_list[System.DOCUMENTARY]]:
121
118
  self.args.force = None
122
119
  print("Invalid -force category")
123
- exit()
120
+ exit()
@@ -15,7 +15,8 @@ from common.utility import ManageTitles
15
15
  from common import trackers
16
16
 
17
17
  config_file = "Unit3Dbot.json"
18
- version = "0.9.12"
18
+ user_tags_file = "tags_list.json"
19
+ version = "0.9.14"
19
20
 
20
21
  if os.name == "nt":
21
22
  WATCHER_DESTINATION_PATH: Path = Path(os.getenv("LOCALAPPDATA", ".")) / "Unit3Dup_config" / "watcher_destination_path"
@@ -23,6 +24,7 @@ if os.name == "nt":
23
24
  CACHE_PATH: Path = Path(os.getenv("LOCALAPPDATA", ".")) / "Unit3Dup_config" / "cache_path"
24
25
  TORRENT_ARCHIVE_PATH: Path = Path(os.getenv("LOCALAPPDATA", ".")) / "Unit3Dup_config" / "torrent_archive_path"
25
26
  DEFAULT_JSON_PATH: Path = Path(os.getenv("LOCALAPPDATA", ".")) / "Unit3Dup_config" / f"{config_file}"
27
+ USER_TAGS_PATH: Path = Path(os.getenv("LOCALAPPDATA", ".")) / "Unit3Dup_config" / f"{user_tags_file}"
26
28
 
27
29
  else:
28
30
  WATCHER_DESTINATION_PATH: Path = Path.home() / "Unit3Dup_config" / "watcher_destination_path"
@@ -30,7 +32,7 @@ else:
30
32
  CACHE_PATH: Path = Path.home() / "Unit3Dup_config" / "cache_path"
31
33
  TORRENT_ARCHIVE_PATH: Path = Path.home() / "Unit3Dup_config" / "torrent_archive_path"
32
34
  DEFAULT_JSON_PATH: Path = Path.home() / "Unit3Dup_config" / f"{config_file}"
33
-
35
+ USER_TAGS_PATH: Path = Path.home() / "Unit3Dup_config" / f"{user_tags_file}"
34
36
 
35
37
  def get_default_path(field: str)-> str:
36
38
  default_paths = {
@@ -522,6 +524,116 @@ class Load:
522
524
  def _load_config(self):
523
525
  self.config = self.load_config()
524
526
 
527
+ @staticmethod
528
+ def create_tags_list_file(path: Path):
529
+ """
530
+ Creates a tags list file
531
+ """
532
+ TAG_TYPES = {
533
+ "REMUX": "remux",
534
+ "WEB-DL": "source",
535
+ "WEB-DLMUX": "source",
536
+ "WEBMUX": "source",
537
+ "WEBRIP": "source",
538
+ "BD-UNTOUCHED": "source",
539
+ "TS": "source",
540
+ "CAM": "source",
541
+ "HDTS": "source",
542
+ "MD": "source",
543
+ "UHDRIP": "source",
544
+ "BLURAY": "source",
545
+ "BRRIP": "source",
546
+ "BDRIP": "source",
547
+ "FHDRIP": "source",
548
+ "PDTV": "source",
549
+ "SATRIP": "source",
550
+ "DVBRIP": "source",
551
+ "DVB-S": "source",
552
+ "DTTRIP": "source",
553
+ "WP": "source",
554
+ "DVDSCR": "source",
555
+ "TVRIP": "source",
556
+ "VHSRIP": "source",
557
+ "DVDRIP": "source",
558
+ "HDTV": "source",
559
+ "DVD5": "source",
560
+ "DVD9": "source",
561
+
562
+ "ATVP": "platform",
563
+ "AMZN": "platform",
564
+ "AMC": "platform",
565
+ "CN": "platform",
566
+ "CR": "platform",
567
+ "DCU": "platform",
568
+ "DISC": "platform",
569
+ "DSCP": "platform",
570
+ "DSNY": "platform",
571
+ "DSNP": "platform",
572
+ "DPLY": "platform",
573
+ "ESPN": "platform",
574
+ "FOOD": "platform",
575
+ "FOX": "platform",
576
+ "PLAY": "platform",
577
+ "HBO": "platform",
578
+ "HMAX": "platform",
579
+ "HGTV": "platform",
580
+ "HIST": "platform",
581
+ "HULU": "platform",
582
+ "MTOD": "platform",
583
+ "NATG": "platform",
584
+ "NF": "platform",
585
+ "NICK": "platform",
586
+ "NOW": "platform",
587
+ "PMNT": "platform",
588
+ "PMTP": "platform",
589
+ "PCOK": "platform",
590
+ "RKTN": "platform",
591
+ "SHO": "platform",
592
+ "SKST": "platform",
593
+ "STAN": "platform",
594
+ "STRP": "platform",
595
+ "STZ": "platform",
596
+ "TIMV": "platform",
597
+
598
+ "REPACK": "version",
599
+ "EXTENDED": "version",
600
+ "EXTENDED EDITION": "version",
601
+ "EXTENDED CUT": "version",
602
+ "DIRECTOR'S CUT": "version",
603
+ "SUBBED": "version",
604
+ "MUX": "version",
605
+ "REMASTERED": "version",
606
+ "READNFO": "version",
607
+ "UNRATED": "version",
608
+ "UNCUT": "version",
609
+ "LIMITED": "version",
610
+ "ANNIVERSARY": "version",
611
+ "SPECIAL EDITION": "version",
612
+ "4k RESTORATION": "version",
613
+ "IMAX": "version",
614
+ "OPEN MATTE": "version",
615
+ "2IN1": "version",
616
+
617
+ "VU": "version",
618
+ "STV": "version",
619
+ "RECODE": "version",
620
+ "INTERNAL": "version",
621
+ "PROPER": "version",
622
+ "DUAL": "version",
623
+ "UNTOUCHED": "version",
624
+ "COMPLETE": "version",
625
+ "COMPLETA": "version",
626
+
627
+ "X264": "video_encoder",
628
+ "X265": "video_encoder",
629
+ }
630
+
631
+ path.parent.mkdir(parents=True, exist_ok=True)
632
+ with open(path, "w", encoding="utf-8") as tags_list_file:
633
+ json.dump(TAG_TYPES, tags_list_file, ensure_ascii=False, indent=4)
634
+
635
+
636
+
525
637
 
526
638
  @staticmethod
527
639
  def create_default_json_file(path: Path):
@@ -580,7 +692,7 @@ class Load:
580
692
  "IMARIDE_PRIORITY": 6,
581
693
  "NUMBER_OF_SCREENSHOTS": 4,
582
694
  "TAGS_POSITION": ["title", "year", "season", "version", "resolution", "uhd", "platform", "source", "remux",
583
- "multi", "acodec", "channels", "flag", "subtitle", "vcodec", "hdr", "video_encoder"],
695
+ "multi", "acodec", "channels", "flag", "subtitle", "hdr", "vcodec", "video_encoder"],
584
696
  "YOUTUBE_FAV_CHANNEL_ID": "UCGCbxpnt25hWPFLSbvwfg_w",
585
697
  "YOUTUBE_CHANNEL_ENABLE": "False",
586
698
  "DUPLICATE_ON": "true",
@@ -655,6 +767,10 @@ class Load:
655
767
  print(f"Create default configuration file: {DEFAULT_JSON_PATH}")
656
768
  Load.create_default_json_file(DEFAULT_JSON_PATH)
657
769
 
770
+ if not USER_TAGS_PATH.exists():
771
+ print(f"Create default Tags_list file: {USER_TAGS_PATH}")
772
+ Load.create_tags_list_file(USER_TAGS_PATH)
773
+
658
774
  # Since the last bot version there might are new attributes
659
775
  # Load the json file, find the difference between json file and the code. Update the user's json file
660
776
  update_config = JsonConfig(default_json_path=DEFAULT_JSON_PATH)
@@ -3,92 +3,21 @@ import os
3
3
  import re
4
4
  from common.mediainfo import MediaFile
5
5
  from common.utility import ManageTitles
6
-
7
- TAG_TYPES = {
8
- "REMUX": "remux",
9
- "WEB-DL": "source",
10
- "WEB-DLMUX": "source",
11
- "WEBMUX": "source",
12
- "WEBRIP": "source",
13
- "BD-UNTOUCHED": "source",
14
- "TS": "source",
15
- "CAM": "source",
16
- "HDTS": "source",
17
- "MD": "source",
18
- "UHDRIP": "source",
19
- "BLURAY": "source",
20
- "BRRIP": "source",
21
- "BDRIP": "source",
22
- "FHDRIP": "source",
23
-
24
- "ATVP": "platform",
25
- "AMZN": "platform",
26
- "AMC": "platform",
27
- "CN": "platform",
28
- "CR": "platform",
29
- "DCU": "platform",
30
- "DISC": "platform",
31
- "DSCP": "platform",
32
- "DSNY": "platform",
33
- "DSNP": "platform",
34
- "DPLY": "platform",
35
- "ESPN": "platform",
36
- "FOOD": "platform",
37
- "FOX": "platform",
38
- "PLAY": "platform",
39
- "HBO": "platform",
40
- "HMAX": "platform",
41
- "HGTV": "platform",
42
- "HIST": "platform",
43
- "HULU": "platform",
44
- "MTOD": "platform",
45
- "NATG": "platform",
46
- "NF": "platform",
47
- "NICK": "platform",
48
- "NOW": "platform",
49
- "PMNT": "platform",
50
- "PMTP": "platform",
51
- "PCOK": "platform",
52
- "RKTN": "platform",
53
- "SHO": "platform",
54
- "SKST": "platform",
55
- "STAN": "platform",
56
- "STRP": "platform",
57
- "STZ": "platform",
58
- "TIMV": "platform",
59
-
60
- "REPACK": "version",
61
- "EXTENDED": "version",
62
- "SUBBED": "version",
63
- "MUX": "version",
64
- "REMASTERED": "version",
65
- "READNFO": "version",
66
- "UNRATED": "version",
67
- "LIMITED": "version",
68
- "VU": "version",
69
- "STV": "version",
70
- "RECODE": "version",
71
- "INTERNAL": "version",
72
- "PROPER": "version",
73
- "DUAL": "version",
74
- "UNTOUCHED": "version",
75
- "COMPLETE": "version",
76
- "COMPLETA": "version",
77
-
78
- "X264": "video_encoder",
79
- "X265": "video_encoder",
80
- }
6
+ from view import custom_console
81
7
 
82
8
  # From hdr format
83
9
  hdr_map = {
84
10
  "DOLBY VISION": "DV",
85
11
  "DOLBY VISION HDR": "DV HDR",
86
12
  "DOLBY VISION HDR10": "DV HDR10",
13
+ "DOLBY VISION HDR10+": "DV HDR",
87
14
  "HDR10PLUS": "HDR10+",
88
15
  "HDRPLUS+": "HDR10+",
89
16
  "HDR10+": "HDR10+",
90
17
  "HDR10": "HDR10",
91
18
  "HDR10 / HDR10": "HDR10",
19
+ "HDR10 / HDR10 / HDR10+": "HDR10+",
20
+
92
21
  "DOVI": "DV",
93
22
  "HDR": "HDR",
94
23
  }
@@ -96,6 +25,7 @@ hdr_map = {
96
25
  audio_translate = {
97
26
  "AC3": "DD",
98
27
  "AAC LC": "AAC",
28
+ "AAC LC SBR": "HE-AAC",
99
29
  "AC-3": "DD",
100
30
  "EAC3": "DD+",
101
31
  "E-AC3": "DD+",
@@ -124,7 +54,7 @@ video_encoder_translate = {
124
54
 
125
55
  class SearchTags(object):
126
56
  def __init__(self, filename, title: str, year: str, season: int, episode: int,
127
- mediafile: MediaFile, tags_position: list, releaser_sign: str):
57
+ mediafile: MediaFile, tags_position: list, tags_list: dict, releaser_sign: str):
128
58
 
129
59
  self.tags_position = tags_position
130
60
  self.releaser_sign = releaser_sign
@@ -136,25 +66,30 @@ class SearchTags(object):
136
66
  self.year = year
137
67
  self.tags_dict = {}
138
68
  self.tags_position = tags_position
69
+ self.TAG_TYPES = tags_list
139
70
 
140
- def normalize_version_tag(self, tag: str) -> str:
71
+ @staticmethod
72
+ def normalize_version_tag(tag: str) -> str:
141
73
  tag_esc = re.escape(tag)
142
74
  # Filter hyphenated,space compounds
143
75
  tag_esc = tag_esc.replace(r'\ ', r'[.\s_-]*')
144
76
  return tag_esc
145
77
 
146
- def normalize_platform_tag(self, tag: str) -> str:
78
+ @staticmethod
79
+ def normalize_platform_tag(tag: str) -> str:
147
80
  # escape
148
81
  tag_esc = re.escape(tag)
149
82
  return tag_esc
150
83
 
151
- def normalize_sources(self, tag: str) -> str:
84
+ @staticmethod
85
+ def normalize_sources(tag: str) -> str:
152
86
  tag_esc = re.escape(tag)
153
87
  # Filter hyphenated,space compounds
154
88
  tag_esc = tag_esc.replace(r'\ ', r'[.\s_-]*')
155
89
  return tag_esc
156
90
 
157
- def normalize_video_encoder(self, tag: str) -> str:
91
+ @staticmethod
92
+ def normalize_video_encoder(tag: str) -> str:
158
93
  tag_esc = re.escape(tag)
159
94
  tag_esc = re.sub(r'([A-Z])(\d+)', r'\1[._-]?\2', tag_esc)
160
95
  return tag_esc
@@ -164,7 +99,7 @@ class SearchTags(object):
164
99
 
165
100
  # loop sorted TAG_TYPES dictionary
166
101
  for i, (tag, category) in enumerate(
167
- sorted(TAG_TYPES.items(), key=lambda x: len(x[0]), reverse=True)
102
+ sorted(self.TAG_TYPES.items(), key=lambda x: len(x[0]), reverse=True)
168
103
  ):
169
104
  if category == "version":
170
105
  norm = self.normalize_version_tag(tag)
@@ -195,6 +130,10 @@ class SearchTags(object):
195
130
  elif category == "vcodec":
196
131
  updated_category = self.mediainfo_video(category=category)
197
132
 
133
+ elif category == "video_encoder":
134
+ if self.tags_dict.get('video_encoder', None):
135
+ self.tags_dict['video_encoder'][0] = self.tags_dict['video_encoder'][0].lower()
136
+
198
137
  elif category == "hdr":
199
138
  updated_category = self.mediainfo_hdr(category=category)
200
139
 
@@ -202,7 +141,8 @@ class SearchTags(object):
202
141
  updated_category = self.mediainfo_uhd(category=category)
203
142
 
204
143
  elif category == "subtitle":
205
- updated_category = {'subtitle': "SUBS" if len(self.mediafile.subtitle_track) > 1 else "SUB"}
144
+ if self.mediafile.subtitle_track:
145
+ updated_category = {'subtitle': "SUBS" if len(self.mediafile.subtitle_track) > 1 else "SUB"}
206
146
 
207
147
  if updated_category:
208
148
  self.tags_dict.update(updated_category)
@@ -226,7 +166,7 @@ class SearchTags(object):
226
166
  if not self.releaser_sign:
227
167
  filename, _ = os.path.splitext(os.path.basename(self.filename))
228
168
  m = re.search(r'-([A-Za-z0-9]+)$', filename)
229
- self.releaser_sign = f"-{m.group(1)}" if m and m.group(1) not in TAG_TYPES else ""
169
+ self.releaser_sign = f"-{m.group(1)}" if m and m.group(1) not in self.TAG_TYPES else ""
230
170
  else:
231
171
  self.releaser_sign = f"-{self.releaser_sign}"
232
172
 
@@ -249,7 +189,7 @@ class SearchTags(object):
249
189
  return refactored
250
190
 
251
191
  def mediainfo_audio(self, category: str) -> dict:
252
- langs = set()
192
+ languages = []
253
193
  audio_codecs = []
254
194
  if self.mediafile.audio_track:
255
195
  for audio in self.mediafile.audio_track:
@@ -267,22 +207,23 @@ class SearchTags(object):
267
207
  ch = {2: "2.0", 6: "5.1", 8: "7.1"}.get(channel_s, "")
268
208
  if f"{codec_translated} {ch} {atmos}".strip() not in audio_codecs:
269
209
  audio_codecs.append(f"{codec_translated} {ch} {atmos}".strip())
270
- print(f"Mediainfo {other_format} -> {codec_translated} {ch} {atmos}")
210
+ # print(f"Mediainfo {other_format} -> {codec_translated} {ch} {atmos}")
271
211
 
272
212
  # Add flags
273
213
  for l in audio.get('other_language', []):
274
214
  c = ManageTitles.convert_iso(l)
275
215
  if c:
276
216
  if isinstance(c, list):
277
- langs.update(c)
217
+ languages.append(c[0])
278
218
  else:
279
- langs.add(c)
219
+ languages.append(c)
280
220
  break
221
+ languages = list(dict.fromkeys(languages))
281
222
  # Add multilanguage tag when languages > 2
282
- if len(langs) > 2:
223
+ if len(languages) > 2:
283
224
  self.tags_dict.update({'multi': 'MULTI'})
284
225
 
285
- audio_codecs.extend(list(langs))
226
+ audio_codecs.extend(languages)
286
227
  return {category: audio_codecs}
287
228
 
288
229
  def mediainfo_video(self, category: str) -> dict:
@@ -302,17 +243,19 @@ class SearchTags(object):
302
243
  hdr_format = video.get('hdr_format', "")
303
244
  # Check hdr
304
245
  if hdr_format_commercial:
305
- print(f"hdr_format_commercial: {hdr_format_commercial}")
306
- print(f"hdr_format: {hdr_format}")
246
+ # print(f"hdr_format_commercial: {hdr_format_commercial}")
247
+ # print(f"hdr_format: {hdr_format}")
307
248
  hdr = ''
308
249
  if hdr_format_commercial in hdr_map:
309
- print(f"hdr_format_commercial: {hdr_format_commercial} -> Tag: {hdr_map[hdr_format_commercial]}")
250
+ # print(
251
+ # f"hdr_format_commercial: {hdr_format_commercial} -> Tag: {hdr_map[hdr_format_commercial]}")
310
252
  hdr = hdr_map[hdr_format_commercial]
311
253
  # Check dolby vision
254
+ if hdr not in hdr_map:
255
+ custom_console.bot_warning_log(f"<> HDR Warning: '{hdr_format_commercial}' not found in hdr_map")
312
256
  if 'DOLBY VISION' in hdr_format_commercial.upper() or 'DOLBY VISION' in hdr_format.upper():
313
257
  hdr = f"DOLBY VISION {hdr}"
314
- print(hdr)
315
- return {category: hdr_map[hdr]}
258
+ return {category: hdr_map.get(hdr, '*HDR')}
316
259
  return {}
317
260
 
318
261
  def mediainfo_uhd(self, category: str) -> dict:
@@ -323,7 +266,8 @@ class SearchTags(object):
323
266
  if self.mediafile.video_track:
324
267
  video_height = int(self.mediafile.video_track[0].get('height', 0))
325
268
  video_width = int(self.mediafile.video_track[0].get('width', 0))
326
- print(f"VideoTrack : W{video_width} x H{video_height}")
269
+
270
+ # print(f"VideoTrack : W{video_width} x H{video_height}")
327
271
 
328
272
  # Calculate range 5%
329
273
  def in_range(value, standard):
@@ -354,4 +298,4 @@ class SearchTags(object):
354
298
  result[category] = 'unknown'
355
299
  result['resolution'] = f'{video_width}x{video_height}'
356
300
 
357
- return result
301
+ return result
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
5
5
  [project]
6
6
  dynamic = ["dependencies"]
7
7
  name = "Unit3Dup"
8
- version = "0.9.12"
8
+ version = "0.9.14"
9
9
  description = "An uploader for the Unit3D torrent tracker"
10
10
  readme = "README.rst"
11
11
  requires-python = ">=3.10"
@@ -1,8 +1,9 @@
1
1
  # -*- coding: utf-8 -*-
2
+ import json
2
3
 
3
4
  from common.torrent_clients import TransmissionClient, QbittorrentClient, RTorrentClient
4
5
  from common.command import CommandLine
5
- from common.settings import Load,DEFAULT_JSON_PATH
6
+ from common.settings import Load,DEFAULT_JSON_PATH, USER_TAGS_PATH
6
7
 
7
8
  from unit3dup.torrent import View
8
9
  from unit3dup import pvtTracker
@@ -94,10 +95,19 @@ def main():
94
95
  if cli.args.mt:
95
96
  tracker_name_list = config.tracker_config.MULTI_TRACKER
96
97
 
98
+ # Load User Tags list
99
+ tags_list = None
100
+ if cli.args.buildtags:
101
+ try:
102
+ with open(USER_TAGS_PATH, "r", encoding="utf-8") as f:
103
+ tags_list = json.load(f)
104
+ except FileNotFoundError:
105
+ custom_console.bot_error_log(f"User tags file {USER_TAGS_PATH} not found. Please update your configuration file")
106
+
97
107
  # Manual upload mode
98
108
  if cli.args.upload:
99
109
  bot = Bot(path=cli.args.upload, cli=cli.args, trackers_name_list=tracker_name_list,
100
- torrent_archive_path=tracker_archive)
110
+ torrent_archive_path=tracker_archive, tags_list=tags_list)
101
111
  bot.run()
102
112
 
103
113
  # Manual folder mode
@@ -108,13 +118,14 @@ def main():
108
118
  mode="folder",
109
119
  trackers_name_list=tracker_name_list,
110
120
  torrent_archive_path=tracker_archive,
121
+ tags_list=tags_list
111
122
  )
112
123
  bot.run()
113
124
 
114
125
  # Auto mode
115
126
  if cli.args.scan and not cli.args.ftp:
116
127
  bot = Bot(path=cli.args.scan, cli=cli.args, mode="auto", trackers_name_list=tracker_name_list,
117
- torrent_archive_path=tracker_archive)
128
+ torrent_archive_path=tracker_archive, tags_list=tags_list)
118
129
  bot.run()
119
130
 
120
131
  # Watcher
@@ -29,7 +29,7 @@ class Bot:
29
29
  """
30
30
 
31
31
  # Bot Manager
32
- def __init__(self, path: str, cli: argparse.Namespace, trackers_name_list: list, mode="man",
32
+ def __init__(self, path: str, cli: argparse.Namespace, trackers_name_list: list, tags_list = None, mode="man",
33
33
  torrent_archive_path = None):
34
34
  """
35
35
  Initializes the Bot instance with path, command-line interface object, and mode
@@ -42,6 +42,7 @@ class Bot:
42
42
  self.trackers_name_list = trackers_name_list
43
43
  self.torrent_archive_path = torrent_archive_path
44
44
  self.content_manager = None
45
+ self.tags_list: dict = tags_list
45
46
  self.path = path.strip()
46
47
  self.cli = cli
47
48
  self.mode = mode
@@ -101,7 +102,7 @@ class Bot:
101
102
  return False
102
103
 
103
104
  # Instance a new run
104
- torrent_manager = TorrentManager(cli=self.cli, tracker_archive=self.torrent_archive_path)
105
+ torrent_manager = TorrentManager(cli=self.cli, tracker_archive=self.torrent_archive_path, tags_list=self.tags_list)
105
106
  # Process the torrents content (files)
106
107
  torrent_manager.process(contents=contents)
107
108
 
@@ -177,33 +177,6 @@ class Media:
177
177
  def igdb_id(self, value):
178
178
  self._igdb_id = value
179
179
 
180
- @property
181
- def generate_title(self) -> str:
182
-
183
- if not self._generate_title:
184
- # Read video and audio data from mediainfo
185
- video_f = self.mediafile.video_track[0]['format']
186
- audio_f = self.mediafile.audio_track[0]['format']
187
- audio_lang = self.mediafile.audio_track[0]['language']
188
- available_lang = ' '.join(lang for lang in self.mediafile.available_languages if lang is not None)
189
-
190
- # Search for Season and Episode o torrent_pack
191
- if 'tv' in self.category:
192
- serie = f"S{str(self.guess_season).zfill(2)}" if self.guess_season else ''
193
- if not self.torrent_pack:
194
- serie += f"E{str(self.guess_episode).zfill(2)}"
195
- else:
196
- serie = ''
197
-
198
- # Build the title
199
- self._generate_title = (f"{self.guess_title} {serie} {self.resolution} {video_f} "
200
- f"{available_lang} {audio_f} {audio_lang.upper()}")
201
- return self._generate_title
202
-
203
- @generate_title.setter
204
- def generate_title(self, value):
205
- self._generate_title = value
206
-
207
180
  @property
208
181
  def guess_filename(self):
209
182
  if not self._guess_filename:
@@ -1,5 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
- import argparse
2
+ from argparse import Namespace
3
3
  import os
4
4
 
5
5
  from common.bittorrent import BittorrentData
@@ -14,10 +14,10 @@ from view import custom_console
14
14
 
15
15
  class DocuManager:
16
16
 
17
- def __init__(self, contents: list[Media], cli: argparse.Namespace):
17
+ def __init__(self, contents: list[Media], cli: Namespace):
18
18
  self._my_tmdb = None
19
19
  self.contents: list['Media'] = contents
20
- self.cli: argparse = cli
20
+ self.cli: Namespace = cli
21
21
 
22
22
  def process(self, selected_tracker: str, tracker_name_list: list, tracker_archive: str) -> list[BittorrentData]:
23
23
 
@@ -1,5 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
- import argparse
2
+ from argparse import Namespace
3
3
  import os
4
4
 
5
5
  from common.external_services.igdb.client import IGDBClient
@@ -14,7 +14,7 @@ from view import custom_console
14
14
 
15
15
  class GameManager:
16
16
 
17
- def __init__(self, contents: list["Media"], cli: argparse.Namespace):
17
+ def __init__(self, contents: list["Media"], cli: Namespace):
18
18
  """
19
19
  Initialize the GameManager with the given contents
20
20
 
@@ -23,7 +23,7 @@ class GameManager:
23
23
  cli (argparse.Namespace): user flag Command line
24
24
  """
25
25
  self.contents: list[Media] = contents
26
- self.cli: argparse = cli
26
+ self.cli: Namespace = cli
27
27
  self.igdb = IGDBClient()
28
28
 
29
29
  def process(self, selected_tracker: str, tracker_name_list: list, tracker_archive: str) -> list[BittorrentData]:
@@ -1,9 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  import argparse
4
-
5
- import requests
6
-
7
4
  from unit3dup.media_manager.VideoManager import VideoManager
8
5
  from unit3dup.media_manager.GameManager import GameManager
9
6
  from unit3dup.media_manager.DocuManager import DocuManager
@@ -21,10 +18,11 @@ from view import custom_console
21
18
 
22
19
 
23
20
  class TorrentManager:
24
- def __init__(self, cli: argparse.Namespace, tracker_archive: str):
21
+ def __init__(self, cli: argparse.Namespace, tracker_archive: str, tags_list: dict):
25
22
 
26
23
  self.preferred_lang = my_language(config_settings.user_preferences.PREFERRED_LANG)
27
24
  self.tracker_archive = tracker_archive
25
+ self.tags_list = tags_list
28
26
  self.videos: list[Media] = []
29
27
  self.games: list[Media] = []
30
28
  self.doc: list[Media] = []
@@ -93,7 +91,7 @@ class TorrentManager:
93
91
  # Build the torrent file and upload each VIDEO to the trackers
94
92
  if self.videos:
95
93
  video_manager = VideoManager(contents=self.videos[:self.fast_load],
96
- cli=self.cli)
94
+ cli=self.cli, tags_list= self.tags_list)
97
95
  video_process_results = video_manager.process(selected_tracker=selected_tracker,
98
96
  tracker_name_list=trackers_name_list,
99
97
  tracker_archive=self.tracker_archive)
@@ -1,5 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
- import argparse
2
+ from argparse import Namespace
3
3
  import os
4
4
 
5
5
  from common.external_services.theMovieDB.core.api import DbOnline
@@ -18,7 +18,7 @@ from view import custom_console
18
18
 
19
19
  class VideoManager:
20
20
 
21
- def __init__(self, contents: list[Media], cli: argparse.Namespace):
21
+ def __init__(self, contents: list[Media], cli: Namespace, tags_list: dict):
22
22
  """
23
23
  Initialize the VideoManager with the given contents
24
24
 
@@ -29,7 +29,8 @@ class VideoManager:
29
29
 
30
30
  self.torrent_found: bool = False
31
31
  self.contents: list[Media] = contents
32
- self.cli: argparse.Namespace = cli
32
+ self.cli: Namespace = cli
33
+ self.tags_list: dict = tags_list
33
34
 
34
35
  def process(self, selected_tracker: str, tracker_name_list: list, tracker_archive: str) -> list[BittorrentData]:
35
36
  """
@@ -57,7 +58,8 @@ class VideoManager:
57
58
  episode=content.guess_episode,
58
59
  releaser_sign=config_settings.user_preferences.RELEASER_SIGN,
59
60
  tags_position=config_settings.user_preferences.TAGS_POSITION,
60
- mediafile=content.mediafile
61
+ tags_list=self.tags_list,
62
+ mediafile=content.mediafile,
61
63
  )
62
64
  content.display_name = search_tags.process()
63
65
 
@@ -91,19 +93,6 @@ class VideoManager:
91
93
  if not db:
92
94
  continue
93
95
 
94
- # Update display name with Serie Title when requested by the user (-notitle)
95
- if self.cli.notitle:
96
- # Add generated metadata to the display_title
97
- if self.cli.gentitle:
98
- content.display_name = (f"{db_online.media_result.result.get_title()} "
99
- f"{db_online.media_result.year} ")
100
- content.display_name += " " + content.generate_title
101
- else:
102
- # otherwise keep the old meta_data and add the new display_title to it
103
- print()
104
- content.display_name = (f"{db_online.media_result.result.get_title()}"
105
- f" {db_online.media_result.year} {content.guess_title}")
106
-
107
96
  # Get meta from the media video
108
97
  video_info = Video(media=content, tmdb_id=db.video_id, trailer_key=db.trailer_key)
109
98
  video_info.build_info()
@@ -1,6 +1,6 @@
1
- import argparse
2
- import json
1
+ from argparse import Namespace
3
2
  import requests
3
+ import json
4
4
 
5
5
  from common.external_services.igdb.core.models.search import Game
6
6
  from common.trackers.trackers import TRACKData
@@ -15,7 +15,7 @@ from view import custom_console
15
15
 
16
16
 
17
17
  class UploadBot:
18
- def __init__(self, content: Media, tracker_name: str, cli: argparse.ArgumentParser):
18
+ def __init__(self, content: Media, tracker_name: str, cli: Namespace):
19
19
  self.cli = cli
20
20
  self.content = content
21
21
  self.tracker_name = tracker_name
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