Skip to content

Conversation

@swannie-eire
Copy link

@swannie-eire swannie-eire commented Nov 5, 2025

dynamically create the following in trackersetup

tracker_class_map = {}
http_trackers = {}
api_trackers = {}
other_api_trackers = {}

i tested with bhd, ar, huno, bhdtv and 2 custom trackers and it worked as expect.

I expect there could be issues with PTP or an AZ tracker but i can not test with those.

for those of us with custom trackers this makes life a million times easier as we dont have to make any changes when we update UA.

Summary by CodeRabbit

  • Refactor
    • Dynamic discovery and runtime loading of trackers for simpler maintenance.
    • Automatic categorization of trackers by connection type (HTTP, API, alternate API).
    • Many trackers now expose explicit tracker-type flags to support categorization.
    • Tracker setup now accepts configuration on startup and registers trackers at runtime.
    • Minor class docstring cleanups and cosmetic tweaks; no changes to external behavior.

@coderabbitai
Copy link

coderabbitai bot commented Nov 5, 2025

Walkthrough

Class-level boolean flags (is_http, is_api, is_other_api) were added to many tracker classes; a small unused local variable was added in TTG.download_new_torrent; trackersetup.py was refactored to dynamically discover, import, categorize, and register tracker classes at module import time.

Changes

Cohort / File(s) Summary
HTTP-enabled trackers (class attribute added)
src/trackers/AR.py, src/trackers/ASC.py, src/trackers/BJS.py, src/trackers/BT.py, src/trackers/CZ.py, src/trackers/FF.py, src/trackers/FL.py, src/trackers/HDB.py, src/trackers/HDS.py, src/trackers/HDT.py, src/trackers/IS.py, src/trackers/MTV.py, src/trackers/PHD.py, src/trackers/PTER.py, src/trackers/PTS.py
Each class now declares is_http = True at class scope; no other behavior changes.
Single-file HTTP addition
src/trackers/AZ.py
AZ now has class-level is_http = True; no other logic changes.
API-based trackers (class attribute added)
src/trackers/BHD.py, src/trackers/UNIT3D.py
Each class now declares is_api = True at class scope; no other behavior changes.
Other-API / alternative trackers (class attribute added)
src/trackers/ANT.py, src/trackers/BHDTV.py, src/trackers/DC.py, src/trackers/GPW.py, src/trackers/NBL.py, src/trackers/RTF.py, src/trackers/SN.py, src/trackers/SPD.py, src/trackers/TL.py, src/trackers/TVC.py
Each class now declares is_other_api = True at class scope; several files also removed class docstrings or made minor formatting edits.
Function-local change
src/trackers/TTG.py
In TTG.download_new_torrent, added a comment and a local variable assignment is_http = True (unused); no control-flow change.
Dynamic tracker discovery & categorization
src/trackersetup.py
Replaced static per-tracker imports with runtime discovery/import via importlib/inspect; added module-level tracker_class_map, http_trackers, api_trackers, other_api_trackers; TRACKER_SETUP.init now accepts config; trackers are instantiated/categorized dynamically and COMMON resolved via tracker_class_map.get('COMMON').

Sequence Diagram(s)

sequenceDiagram
    participant Setup as trackersetup.py
    participant FS as FileSystem
    participant Importer as importlib
    participant Inspector as inspect
    participant Module as ModuleObj
    participant ClassObj as TrackerClass

    Setup->>FS: list modules in src/trackers/
    FS-->>Setup: module names

    loop each module (skips excluded)
        Setup->>Importer: import module
        Importer-->>Setup: ModuleObj
        Setup->>Inspector: inspect ModuleObj for classes
        Inspector-->>Setup: ClassObj(s)
        Setup->>ClassObj: read flags (is_http / is_api / is_other_api)
        ClassObj-->>Setup: flag values

        alt is_http == True
            Setup->>Setup: register in http_trackers (map)
        else is_api == True
            Setup->>Setup: register in api_trackers (map)
        else is_other_api == True
            Setup->>Setup: register in other_api_trackers (map)
        else
            Setup->>Setup: register in tracker_class_map only
        end

        Setup->>ClassObj: optionally instantiate with config
        ClassObj-->>Setup: instance (or None)
    end

    Note right of Setup: COMMON accessed via tracker_class_map.get('COMMON')
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

  • Review focus:
    • src/trackersetup.py: dynamic import loop, skip list, error handling, instantiation args, and replacing prior static usages (e.g., COMMON).
    • Classification logic relying on is_http / is_api / is_other_api.
    • Lint/cleanup for src/trackers/TTG.py (unused local is_http) and files where docstrings were removed.

Poem

🐰
I hopped through modules, flags held high,
Found HTTP, API, and paths awry,
I imported, sorted, then danced with pride,
Carrots in pockets, trackers by my side. 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.51% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: dynamic import of trackers. It directly relates to the core objective of replacing static imports with runtime discovery and is specific enough to convey the primary purpose.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a692b52 and d5de2b9.

📒 Files selected for processing (1)
  • src/trackersetup.py (3 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-11T08:09:03.381Z
Learnt from: Audionut
Repo: Audionut/Upload-Assistant PR: 991
File: src/trackers/THR.py:263-263
Timestamp: 2025-11-11T08:09:03.381Z
Learning: For src/trackers/THR.py in Audionut's pull requests, do not flag issues about mixing synchronous requests calls (like requests.post, requests.get) with async functions. The file needs a refactor, and these issues should be ignored until then.

Applied to files:

  • src/trackersetup.py
🔇 Additional comments (2)
src/trackersetup.py (2)

9-10: LGTM! Necessary imports for dynamic loading.

The addition of importlib and inspect is appropriate for the dynamic tracker discovery feature. These are standard library modules with no version concerns.


848-851: LGTM! Clean initialization of tracker mappings.

The four dictionaries align with the PR objectives and will be populated by the dynamic discovery loop.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
src/trackers/NBL.py (1)

32-32: LGTM: Flag added for dynamic tracker categorization.

The is_other_api flag has been added to enable dynamic tracker discovery, consistent with the PR's objective. Consider adding a brief comment explaining the purpose of this flag for future maintainers.

+        # Flag for dynamic tracker categorization in trackersetup
         self.is_other_api = True
src/trackers/FL.py (1)

29-29: LGTM - Simple flag addition for dynamic tracker categorization.

The is_http flag is added consistently with the broader pattern across trackers to support dynamic loading.

Consider adding a brief docstring or inline comment explaining the purpose of this flag for future maintainers, e.g.:

# Flag for dynamic tracker categorization (http vs api)
self.is_http = True
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7a8cb9c and 390fc9c.

📒 Files selected for processing (30)
  • src/trackers/ANT.py (1 hunks)
  • src/trackers/AR.py (1 hunks)
  • src/trackers/ASC.py (1 hunks)
  • src/trackers/AZ.py (1 hunks)
  • src/trackers/BHD.py (1 hunks)
  • src/trackers/BHDTV.py (1 hunks)
  • src/trackers/BJS.py (1 hunks)
  • src/trackers/BT.py (1 hunks)
  • src/trackers/CZ.py (1 hunks)
  • src/trackers/DC.py (1 hunks)
  • src/trackers/FF.py (1 hunks)
  • src/trackers/FL.py (1 hunks)
  • src/trackers/GPW.py (1 hunks)
  • src/trackers/HDB.py (1 hunks)
  • src/trackers/HDS.py (1 hunks)
  • src/trackers/HDT.py (1 hunks)
  • src/trackers/IS.py (1 hunks)
  • src/trackers/MTV.py (1 hunks)
  • src/trackers/NBL.py (1 hunks)
  • src/trackers/PHD.py (1 hunks)
  • src/trackers/PTER.py (1 hunks)
  • src/trackers/PTS.py (1 hunks)
  • src/trackers/RTF.py (1 hunks)
  • src/trackers/SN.py (1 hunks)
  • src/trackers/SPD.py (1 hunks)
  • src/trackers/TL.py (1 hunks)
  • src/trackers/TTG.py (1 hunks)
  • src/trackers/TVC.py (2 hunks)
  • src/trackers/UNIT3D.py (1 hunks)
  • src/trackersetup.py (3 hunks)
🔇 Additional comments (22)
src/trackers/HDT.py (1)

35-35: LGTM! Dynamic tracker categorization flag added.

The addition of self.is_http = True correctly categorizes this tracker for the dynamic loading system. The flag appropriately reflects that this tracker uses HTTP with cookie-based authentication.

src/trackers/BHDTV.py (1)

30-30: LGTM! API tracker flag added correctly.

The self.is_other_api = True flag correctly categorizes this API-based tracker for dynamic discovery.

src/trackers/HDB.py (1)

32-32: LGTM! HTTP tracker flag added.

The self.is_http = True flag is correctly added for this HTTP-based tracker.

src/trackers/IS.py (1)

28-28: LGTM! HTTP tracker categorization added.

The self.is_http = True flag correctly categorizes this cookie-authenticated HTTP tracker.

src/trackers/AR.py (1)

36-36: LGTM! HTTP tracker flag initialized.

The addition of self.is_http = True correctly identifies this as an HTTP-based tracker for dynamic loading.

src/trackers/RTF.py (1)

32-32: LGTM! API tracker flag added.

The self.is_other_api = True flag appropriately categorizes this API-based tracker.

src/trackers/PHD.py (1)

18-18: LGTM! HTTP tracker flag initialized.

The self.is_http = True flag correctly categorizes this HTTP-based tracker that inherits from AZTrackerBase.

src/trackers/PTS.py (1)

28-28: LGTM! HTTP tracker flag added.

The self.is_http = True flag correctly identifies this HTTP cookie-based tracker for dynamic discovery.

Consider verifying that all 28 trackers mentioned in the PR summary have been correctly categorized with the appropriate flag (is_http, is_api, or is_other_api). You can use the following script to check for consistency:

src/trackers/TTG.py (1)

31-31: LGTM: Flag added for dynamic tracker categorization.

The is_http flag has been added to categorize this tracker as HTTP-based for dynamic discovery, aligning with the PR's objectives.

src/trackers/SPD.py (1)

33-33: LGTM: Flag added for dynamic tracker categorization.

The is_other_api flag has been added for dynamic tracker discovery, consistent with the PR pattern.

src/trackers/BHD.py (1)

32-32: LGTM: Flag added for dynamic tracker categorization.

The is_api flag has been added for dynamic tracker discovery. Note that the codebase now has three flag types (is_http, is_api, is_other_api), and the distinction between is_api and is_other_api may warrant documentation in trackersetup.py.

src/trackers/CZ.py (1)

18-18: LGTM: Flag added for dynamic tracker categorization.

The is_http flag has been added to enable dynamic tracker discovery, consistent with the PR's objectives.

src/trackers/PTER.py (1)

32-32: LGTM: Flag added for dynamic tracker categorization.

The is_http flag has been added for dynamic tracker discovery, aligning with the PR's objectives.

src/trackers/ASC.py (1)

35-35: LGTM: Flag added for dynamic tracker categorization.

The is_http flag has been added to enable dynamic tracker discovery, consistent with the PR's objectives.

src/trackers/TVC.py (1)

36-36: LGTM: Flag added for dynamic tracker categorization.

The is_other_api flag has been added for dynamic tracker discovery, consistent with the PR's objectives.

src/trackers/MTV.py (1)

48-48: LGTM - Consistent flag addition.

The is_http flag follows the same pattern as other HTTP-based trackers in this PR.

src/trackers/SN.py (1)

19-19: LGTM - API tracker flag added correctly.

The is_other_api flag appropriately categorizes this as an API-based tracker, distinct from HTTP-based trackers.

src/trackers/ANT.py (1)

36-36: LGTM - API tracker categorization.

The is_other_api flag is correctly added for this API-based tracker.

src/trackers/BT.py (1)

36-36: LGTM - HTTP tracker flag added.

The is_http flag is appropriately placed and consistent with other HTTP-based trackers.

src/trackers/GPW.py (1)

47-47: LGTM - API tracker flag correctly added.

The is_other_api flag follows the established pattern for API-based trackers.

src/trackers/DC.py (1)

23-23: LGTM - API flag addition.

The is_other_api flag is correctly set for this API-based tracker.

src/trackers/AZ.py (1)

17-17: LGTM - HTTP tracker flag added consistently.

The is_http flag is correctly added for this HTTP-based tracker. The flag is set on the instance, so there's no concern about conflicts with the parent class AZTrackerBase.

resolution_id = await self.get_res_id(meta['tv_pack'] if 'tv_pack' in meta else 0, meta['resolution'])
# this is a different function that common function
await self.unit3d_edit_desc(meta, self.tracker, self.signature, image_list, approved_image_hosts=approved_image_hosts)
await self.unit3d_edit_desc(meta, self.tracker, self.signature, image_list)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Good fix: Removed invalid parameter from function call.

The unit3d_edit_desc function (defined at line 392) does not accept an approved_image_hosts parameter. Removing this argument fixes a bug where an invalid parameter was being passed, which would have caused a TypeError at runtime.

🤖 Prompt for AI Agents
In src/trackers/TVC.py around line 157, the call to unit3d_edit_desc was passing
an invalid approved_image_hosts parameter; update the call to match the function
signature (as defined at line 392) by removing the extraneous argument so only
the accepted parameters are passed, and scan for other invocations that might
still pass approved_image_hosts to ensure consistency.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
src/trackersetup.py (2)

28-62: Critical: Eager instantiation still crashes on unconfigured trackers.

This is the same issue flagged in the previous review. Line 52 instantiates every discovered tracker at import time. Trackers like TL call self.config['TRACKERS'][self.tracker] in __init__, which raises KeyError if that tracker isn't configured. This forces users to configure every bundled tracker, which is a regression from the static mapping.

The previous review suggested deriving the tracker code without instantiating (e.g., via class-level attributes like tracker = "TL" on the class itself) or wrapping the entire discovery in logic that checks configuration first.

Recommended approach: Add class-level metadata to tracker classes so you can read tracker, is_http, is_api, and is_other_api without instantiation:

 for mod_name in tracker_module_names:
     if mod_name == 'AVISTAZ_NETWORK' or mod_name == 'UNIT3D_TEMPLATE' or mod_name == 'UNIT3D':
         continue  # Skip this module entirely
 
     full_mod_name = f'src.trackers.{mod_name}'
     module = importlib.import_module(full_mod_name)
 
     for name, obj in inspect.getmembers(module, inspect.isclass):
         if obj.__module__ == full_mod_name:
-            # Determine __init__ parameters excluding 'self'
-            sig = inspect.signature(obj.__init__)
-            params = sig.parameters
-            # Prepare args for __init__
-            init_args = {}
-
-            # Example: config variable should be defined in your scope
-            if 'config' in params:
-                init_args['config'] = config
-
-            if 'tracker_name' in params:
-                # Provide a value for tracker_name, e.g., class name or tracker_code
-                init_args['tracker_name'] = name  # or some other appropriate string
-
-            # Instantiate with necessary args
-            instance = obj(**init_args)
-
-            tracker_code = getattr(instance, 'tracker', name).upper()
+            # Read class-level metadata instead of instantiating
+            tracker_code = getattr(obj, 'tracker', name).upper()
             tracker_class_map[tracker_code] = obj
 
-            if getattr(instance, 'is_http', False):
+            if getattr(obj, 'is_http', False):
                 http_trackers[tracker_code] = obj
-            elif getattr(instance, 'is_api', False):
+            elif getattr(obj, 'is_api', False):
                 api_trackers[tracker_code] = obj
-            elif getattr(instance, 'is_other_api', False):
+            elif getattr(obj, 'is_other_api', False):
                 other_api_trackers[tracker_code] = obj

Then update all tracker classes to define these as class attributes rather than instance attributes.


28-62: Add error handling to prevent import failures.

If any tracker module has a syntax error, import error, or if the instantiation fails for any reason, the entire trackersetup module import fails, breaking the application. Wrap the loop body in try/except to skip problematic trackers gracefully.

 for mod_name in tracker_module_names:
     if mod_name == 'AVISTAZ_NETWORK' or mod_name == 'UNIT3D_TEMPLATE' or mod_name == 'UNIT3D':
         continue  # Skip this module entirely
 
+    try:
         full_mod_name = f'src.trackers.{mod_name}'
         module = importlib.import_module(full_mod_name)
 
         for name, obj in inspect.getmembers(module, inspect.isclass):
             if obj.__module__ == full_mod_name:
                 # ... existing instantiation code ...
                 tracker_class_map[tracker_code] = obj
                 # ... existing categorization code ...
+    except Exception as e:
+        console.print(f"[yellow]Warning: Failed to load tracker module '{mod_name}': {e}[/yellow]")
+        continue
🧹 Nitpick comments (1)
src/trackersetup.py (1)

29-30: Replace hardcoded exclusions with a more maintainable approach.

Hardcoding module names to skip is brittle and requires code changes when new templates are added. Consider using a naming convention (e.g., modules ending in _TEMPLATE) or a module-level flag (e.g., __tracker_template__ = True).

Option 1: Use naming convention:

-    if mod_name == 'AVISTAZ_NETWORK' or mod_name == 'UNIT3D_TEMPLATE' or mod_name == 'UNIT3D':
-        continue  # Skip this module entirely
+    if mod_name.endswith('_TEMPLATE') or mod_name.endswith('_NETWORK') or mod_name == 'UNIT3D':
+        continue  # Skip templates and base classes

Option 2: Check for a module-level flag after import:

     full_mod_name = f'src.trackers.{mod_name}'
     module = importlib.import_module(full_mod_name)
+    
+    if getattr(module, '__skip_discovery__', False):
+        continue
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 390fc9c and d70a71e.

📒 Files selected for processing (2)
  • src/trackers/TVC.py (1 hunks)
  • src/trackersetup.py (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/trackers/TVC.py
🔇 Additional comments (1)
src/trackersetup.py (1)

227-227: Confirm if SPD removal from banned group checks was intentional.

SPD has a complete banned group infrastructure (banned_url and banned_groups attributes) matching AITHER and LST. The removal at line 227 prevents SPD from performing banned group validation, which appears to be an unintended regression unless this was a deliberate change. Please clarify whether this removal should be reverted.

Comment on lines 17 to 21
tracker_dir = os.path.join(os.path.dirname(__file__), 'trackers')
tracker_module_names = [
f[:-3] for f in os.listdir(tracker_dir)
if f.endswith('.py') and f != '__init__.py'
]
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add validation that the tracker directory exists.

If the directory structure is malformed or tracker_dir doesn't exist, os.listdir will raise a FileNotFoundError at import time with an unclear error message.

Consider adding a check:

 tracker_dir = os.path.join(os.path.dirname(__file__), 'trackers')
+if not os.path.isdir(tracker_dir):
+    raise RuntimeError(f"Tracker directory not found: {tracker_dir}")
 tracker_module_names = [
     f[:-3] for f in os.listdir(tracker_dir)
     if f.endswith('.py') and f != '__init__.py'
 ]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
tracker_dir = os.path.join(os.path.dirname(__file__), 'trackers')
tracker_module_names = [
f[:-3] for f in os.listdir(tracker_dir)
if f.endswith('.py') and f != '__init__.py'
]
tracker_dir = os.path.join(os.path.dirname(__file__), 'trackers')
if not os.path.isdir(tracker_dir):
raise RuntimeError(f"Tracker directory not found: {tracker_dir}")
tracker_module_names = [
f[:-3] for f in os.listdir(tracker_dir)
if f.endswith('.py') and f != '__init__.py'
]
🤖 Prompt for AI Agents
In src/trackersetup.py around lines 17 to 21, add validation that tracker_dir
exists before calling os.listdir; if not, raise a clear, early error (e.g.,
RuntimeError or FileNotFoundError with a descriptive message stating the
expected trackers directory path and suggesting how to fix the project layout)
so import-time failures are explicit and actionable, then proceed to build
tracker_module_names as before.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/trackersetup.py (1)

79-80: Add None check before instantiating tracker.

If tracker.upper() is not in tracker_class_map, line 80 will raise TypeError: 'NoneType' object is not callable with an unclear error message.

Apply this diff:

         tracker_class = tracker_class_map.get(tracker.upper())
+        if not tracker_class:
+            console.print(f"[red]Tracker '{tracker}' not found in tracker_class_map[/red]")
+            return None
         tracker_instance = tracker_class(self.config)
♻️ Duplicate comments (1)
src/trackersetup.py (1)

17-21: Add validation that the tracker directory exists.

If tracker_dir doesn't exist, os.listdir will raise an unclear FileNotFoundError at import time. This past review comment remains unaddressed.

Apply this diff:

 tracker_dir = os.path.join(os.path.dirname(__file__), 'trackers')
+if not os.path.isdir(tracker_dir):
+    raise RuntimeError(f"Tracker directory not found: {tracker_dir}")
 tracker_module_names = [
     f[:-3] for f in os.listdir(tracker_dir)
     if f.endswith('.py') and f != '__init__.py'
 ]
🧹 Nitpick comments (1)
src/trackers/AZ.py (1)

20-20: Remove redundant instance attribute assignment.

The class-level is_http = True (line 8) is sufficient for the dynamic loader in trackersetup.py, which uses getattr(obj, 'is_http', False) on the class itself. Setting self.is_http = True here is redundant.

Apply this diff:

         self.base_url = 'https://avistaz.to'
         self.torrent_url = f'{self.base_url}/torrent/'
         self.requests_url = f'{self.base_url}/requests'
-        self.is_http = True
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d70a71e and f4d5108.

📒 Files selected for processing (30)
  • src/trackers/ANT.py (1 hunks)
  • src/trackers/AR.py (1 hunks)
  • src/trackers/ASC.py (1 hunks)
  • src/trackers/AZ.py (2 hunks)
  • src/trackers/BHD.py (1 hunks)
  • src/trackers/BHDTV.py (1 hunks)
  • src/trackers/BJS.py (1 hunks)
  • src/trackers/BT.py (1 hunks)
  • src/trackers/CZ.py (1 hunks)
  • src/trackers/DC.py (1 hunks)
  • src/trackers/FF.py (1 hunks)
  • src/trackers/FL.py (1 hunks)
  • src/trackers/GPW.py (1 hunks)
  • src/trackers/HDB.py (1 hunks)
  • src/trackers/HDS.py (1 hunks)
  • src/trackers/HDT.py (1 hunks)
  • src/trackers/IS.py (1 hunks)
  • src/trackers/MTV.py (1 hunks)
  • src/trackers/NBL.py (1 hunks)
  • src/trackers/PHD.py (1 hunks)
  • src/trackers/PTER.py (1 hunks)
  • src/trackers/PTS.py (1 hunks)
  • src/trackers/RTF.py (1 hunks)
  • src/trackers/SN.py (1 hunks)
  • src/trackers/SPD.py (1 hunks)
  • src/trackers/TL.py (1 hunks)
  • src/trackers/TTG.py (1 hunks)
  • src/trackers/TVC.py (1 hunks)
  • src/trackers/UNIT3D.py (1 hunks)
  • src/trackersetup.py (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (17)
  • src/trackers/TL.py
  • src/trackers/TTG.py
  • src/trackers/DC.py
  • src/trackers/PTER.py
  • src/trackers/GPW.py
  • src/trackers/RTF.py
  • src/trackers/FL.py
  • src/trackers/ANT.py
  • src/trackers/TVC.py
  • src/trackers/ASC.py
  • src/trackers/BJS.py
  • src/trackers/BHD.py
  • src/trackers/BT.py
  • src/trackers/IS.py
  • src/trackers/CZ.py
  • src/trackers/BHDTV.py
  • src/trackers/FF.py
🔇 Additional comments (15)
src/trackers/HDB.py (1)

23-24: LGTM! Class-level flag addition looks good.

The is_http = True attribute correctly marks this tracker as HTTP-based for dynamic discovery. This is a clean, minimal change that enables the dynamic tracker loading mechanism described in the PR objectives.

Since the dynamic discovery mechanism in src/trackersetup.py isn't included in this review, please verify that:

  1. The tracker is correctly categorized as an HTTP tracker during runtime discovery
  2. All existing HDB functionality continues to work with the new dynamic loading system

You can verify this by testing uploads/searches with HDB after the changes, as mentioned in the PR description.

src/trackers/HDT.py (1)

17-19: LGTM! Consistent with the dynamic tracker pattern.

The is_http = True class attribute correctly identifies HDT as an HTTP-based tracker for the dynamic discovery system.

src/trackers/SN.py (1)

11-13: LGTM! API tracker classification looks correct.

The is_other_api = True attribute appropriately marks Swarmazon (SN) as using an alternative API pathway rather than standard HTTP cookie-based authentication. This aligns with the tracker's API-based upload mechanism visible in the upload method (line 106 uses the API endpoint).

src/trackers/HDS.py (1)

15-17: LGTM! HTTP tracker flag added correctly.

The is_http = True class attribute properly categorizes HD-Space as an HTTP-based tracker for dynamic discovery.

src/trackers/AR.py (1)

20-22: LGTM! AlphaRatio correctly flagged as HTTP tracker.

The is_http = True attribute is properly placed and aligns with AR's cookie-based authentication mechanism.

src/trackers/MTV.py (1)

23-24: LGTM! MTV properly categorized as HTTP tracker.

The is_http = True class attribute correctly identifies MoreThanTV as an HTTP-based tracker for the dynamic loading system.

src/trackers/PTS.py (1)

14-16: LGTM! PTSKIT correctly marked as HTTP tracker.

The is_http = True class attribute appropriately categorizes PTSKIT as an HTTP-based tracker.

src/trackers/SPD.py (1)

18-20: LGTM! API-based tracker classification is appropriate.

The is_other_api = True attribute correctly identifies SpeedApp (SPD) as using an API-based authentication and upload mechanism (visible in the API key usage at line 34 and API endpoint at line 27), distinguishing it from cookie-based HTTP trackers.

src/trackers/PHD.py (1)

8-9: LGTM! Class-level flag properly declares HTTP-based tracker.

The is_http flag correctly marks this tracker for HTTP-based access, enabling the dynamic categorization in trackersetup.py.

src/trackers/AZ.py (1)

7-8: LGTM! Class-level flag properly added.

The is_http class attribute correctly marks this tracker as HTTP-based for dynamic categorization.

src/trackers/NBL.py (1)

11-12: LGTM! Class-level flag properly declares alternative API usage.

The is_other_api flag correctly marks this tracker as using a non-standard API flow, enabling proper categorization in the dynamic loader.

src/trackers/UNIT3D.py (1)

15-16: LGTM! Class-level flag properly declares API-based tracker.

The is_api flag correctly marks this tracker as API-based, enabling proper categorization during dynamic discovery.

src/trackersetup.py (3)

23-26: LGTM! Proper initialization of categorization dictionaries.

The four dictionaries are correctly initialized to hold the dynamically discovered tracker classes.


210-210: Verify removal of SPD from banned group check.

SPD was removed from the list of trackers that fetch banned groups via API. Ensure this is intentional and that SPD either no longer requires this check or handles banned groups differently.


28-45: The original review comment is incorrect and misrepresents the categorization behavior.

The categorization logic works correctly through Python's attribute inheritance. When getattr(obj, 'is_api', False) is called on tracker classes like AITHER, it finds the inherited is_api = True from the UNIT3D base class. All UNIT3D subclasses (ACM, AITHER, AL, BLU, etc.) will be properly categorized as API trackers via this inheritance.

The initial observation about trackers "without" flags being uncategorized is misleading because the script only looks for flags defined directly in each file, not inherited attributes. Most flagged trackers actually inherit their categorization from their parent class.

COMMON is correctly uncategorized as it's a utility helper class, not a tracker implementation. AVISTAZ_NETWORK is skipped entirely by the import loop (line 29), so it's not added to any maps.

The only potential concern is that PTP and THR are independent tracker implementations with no flags and no parent base class—but whether this is intentional requires clarification from the developer.

Likely an incorrect or invalid review comment.


# Initialize request log for this tracker
common = COMMON(config)
common = tracker_class_map.get('COMMON')(config)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add None check before instantiating COMMON.

If COMMON is not in tracker_class_map (e.g., due to discovery failure), this line will raise TypeError: 'NoneType' object is not callable.

Apply this diff:

-            common = tracker_class_map.get('COMMON')(config)
+            common_class = tracker_class_map.get('COMMON')
+            if not common_class:
+                console.print("[red]COMMON tracker class not found in tracker_class_map[/red]")
+                return False
+            common = common_class(config)
             log_path = f"{meta['base_dir']}/tmp/{tracker}_request_results.json"

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/trackersetup.py around line 626, the code directly calls
tracker_class_map.get('COMMON')(config) which will raise TypeError if 'COMMON'
is missing; first assign the result of tracker_class_map.get('COMMON') to a
local (e.g., common_cls), check if common_cls is None and handle it (raise a
clear ValueError or log and exit/return), otherwise instantiate with
common_cls(config); ensure the error message explains that COMMON was not
discovered and includes context (config or available keys) to aid debugging.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/trackers/AZ.py (1)

18-18: Remove redundant instance attribute.

The is_http attribute is set both as an instance attribute in __init__ (Line 18) and as a class attribute (Line 181). This duplication is unnecessary since the class-level attribute alone is sufficient and consistent with other tracker implementations.

Apply this diff to remove the redundant instance attribute:

     self.source_flag = 'AvistaZ'
     self.banned_groups = ['']
     self.base_url = 'https://avistaz.to'
     self.torrent_url = f'{self.base_url}/torrent/'
     self.requests_url = f'{self.base_url}/requests'
-    self.is_http = True

Also applies to: 179-181

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f4d5108 and e3dab63.

📒 Files selected for processing (29)
  • src/trackers/ANT.py (2 hunks)
  • src/trackers/AR.py (2 hunks)
  • src/trackers/ASC.py (2 hunks)
  • src/trackers/AZ.py (3 hunks)
  • src/trackers/BHD.py (1 hunks)
  • src/trackers/BHDTV.py (1 hunks)
  • src/trackers/BJS.py (2 hunks)
  • src/trackers/BT.py (2 hunks)
  • src/trackers/CZ.py (2 hunks)
  • src/trackers/DC.py (2 hunks)
  • src/trackers/FF.py (2 hunks)
  • src/trackers/FL.py (1 hunks)
  • src/trackers/GPW.py (2 hunks)
  • src/trackers/HDB.py (1 hunks)
  • src/trackers/HDS.py (2 hunks)
  • src/trackers/HDT.py (2 hunks)
  • src/trackers/IS.py (2 hunks)
  • src/trackers/MTV.py (1 hunks)
  • src/trackers/NBL.py (1 hunks)
  • src/trackers/PHD.py (2 hunks)
  • src/trackers/PTER.py (1 hunks)
  • src/trackers/PTS.py (2 hunks)
  • src/trackers/RTF.py (1 hunks)
  • src/trackers/SN.py (2 hunks)
  • src/trackers/SPD.py (2 hunks)
  • src/trackers/TL.py (2 hunks)
  • src/trackers/TTG.py (1 hunks)
  • src/trackers/TVC.py (1 hunks)
  • src/trackers/UNIT3D.py (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (16)
  • src/trackers/BHD.py
  • src/trackers/TL.py
  • src/trackers/FL.py
  • src/trackers/CZ.py
  • src/trackers/ANT.py
  • src/trackers/SN.py
  • src/trackers/TVC.py
  • src/trackers/UNIT3D.py
  • src/trackers/GPW.py
  • src/trackers/NBL.py
  • src/trackers/MTV.py
  • src/trackers/BJS.py
  • src/trackers/HDB.py
  • src/trackers/FF.py
  • src/trackers/BT.py
  • src/trackers/PTS.py
🔇 Additional comments (11)
src/trackers/PHD.py (1)

348-350: LGTM! Class attribute correctly defined for tracker type mapping.

The is_http = True attribute is properly defined at class scope to support dynamic tracker discovery.

src/trackers/DC.py (1)

320-322: LGTM! Class attribute correctly defined for tracker type mapping.

The is_other_api = True attribute is properly defined at class scope to categorize DC as an alternate API tracker during dynamic discovery.

src/trackers/IS.py (1)

300-302: LGTM! Class attribute correctly defined for tracker type mapping.

The is_http = True attribute is properly defined at class scope to support dynamic tracker discovery.

src/trackers/ASC.py (1)

909-911: LGTM! Class attribute correctly defined for tracker type mapping.

The is_http = True attribute is properly defined at class scope to support dynamic tracker discovery.

src/trackers/RTF.py (1)

236-238: LGTM! Class attribute correctly defined for tracker type mapping.

The is_other_api = True attribute is properly defined at class scope to categorize RTF as an alternate API tracker during dynamic discovery.

src/trackers/HDS.py (1)

335-337: LGTM! Class attribute correctly defined for tracker type mapping.

The is_http = True attribute is properly defined at class scope to support dynamic tracker discovery.

src/trackers/AR.py (1)

451-453: LGTM! Class attribute correctly defined for tracker type mapping.

The is_http = True attribute is properly defined at class scope to support dynamic tracker discovery.

src/trackers/SPD.py (1)

337-339: LGTM!

The class-level is_other_api attribute is correctly added to support dynamic tracker type mapping.

src/trackers/HDT.py (1)

351-353: LGTM!

The class-level is_http attribute is correctly added to support dynamic tracker type mapping.

src/trackers/PTER.py (1)

410-412: LGTM!

The class-level is_http attribute is correctly added to support dynamic tracker type mapping.

src/trackers/BHDTV.py (1)

197-199: LGTM!

The class-level is_other_api attribute is correctly added to support dynamic tracker type mapping.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
src/trackers/TTG.py (1)

354-355: Critical: Move is_http to class level (issue persists from previous review).

The is_http attribute remains incorrectly scoped inside the download_new_torrent method. For the dynamic tracker-type mapping introduced in this PR to work, is_http must be a class-level attribute accessible to the discovery logic in trackersetup.py. As it stands, TTG will not be categorized correctly.

Move the attribute outside the method and align it with other method definitions at class level:

     async def download_new_torrent(self, id, torrent_path):
         download_url = f"https://totheglory.im/dl/{id}/{self.passkey}"
         r = requests.get(url=download_url)
         if r.status_code == 200:
             with open(torrent_path, "wb") as tor:
                 tor.write(r.content)
         else:
             console.print("[red]There was an issue downloading the new .torrent from TTG")
             console.print(r.text)
-
-    # required for tracker type mapping
-    is_http = True
+
+# required for tracker type mapping
+is_http = True
🧹 Nitpick comments (1)
src/trackers/AZ.py (1)

178-180: Consider moving class attribute to the top of the class definition.

The is_http = True attribute works correctly here, and the dynamic tracker mapping approach looks good. However, Python convention typically places class-level attributes at the beginning of the class (right after the class declaration, before __init__), making them easier to discover.

Optional refactor to improve discoverability:

 class AZ(AZTrackerBase):
+    # required for tracker type mapping
+    is_http = True

     def __init__(self, config):

And remove from the end:

         return
-
-    # required for tracker type mapping
-    is_http = True
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e3dab63 and 2693b74.

📒 Files selected for processing (2)
  • src/trackers/AZ.py (2 hunks)
  • src/trackers/TTG.py (1 hunks)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/trackersetup.py (2)

49-50: Add None check before instantiating tracker class.

If the tracker is not found in tracker_class_map, this will raise TypeError: 'NoneType' object is not callable.

Apply this diff:

 tracker_class = tracker_class_map.get(tracker.upper())
+if not tracker_class:
+    console.print(f"[red]Tracker {tracker} is not registered in tracker_class_map[/red]")
+    return None
 tracker_instance = tracker_class(self.config)

278-279: Add None check before instantiating tracker class.

If the tracker is not found in tracker_class_map, this will raise TypeError: 'NoneType' object is not callable.

Apply this diff:

 tracker_class = tracker_class_map.get(tracker.upper())
+if not tracker_class:
+    console.print(f"[red]Tracker {tracker} is not registered in tracker_class_map[/red]")
+    return None
 tracker_instance = tracker_class(self.config)
♻️ Duplicate comments (2)
src/trackersetup.py (2)

596-596: Add None check before instantiating COMMON.

If COMMON is not in tracker_class_map (e.g., due to discovery failure), this line will raise TypeError: 'NoneType' object is not callable.

Apply this diff:

-            common = tracker_class_map.get('COMMON')(config)
+            common_class = tracker_class_map.get('COMMON')
+            if not common_class:
+                console.print("[red]COMMON tracker class not found in tracker_class_map[/red]")
+                return False
+            common = common_class(config)

842-846: Add validation that the tracker directory exists.

If the directory structure is malformed or tracker_dir doesn't exist, os.listdir will raise a FileNotFoundError at import time with an unclear error message.

Apply this diff:

 tracker_dir = os.path.join(os.path.dirname(__file__), 'trackers')
+if not os.path.isdir(tracker_dir):
+    raise RuntimeError(f"Tracker directory not found: {tracker_dir}")
 tracker_module_names = [
     f[:-3] for f in os.listdir(tracker_dir)
     if f.endswith('.py') and f != '__init__.py'
 ]
🧹 Nitpick comments (1)
src/trackersetup.py (1)

862-863: Consider validating the tracker attribute type.

The code falls back to using the class name if the tracker attribute is missing, but doesn't validate that the tracker attribute (if present) is a string. If someone accidentally sets tracker to a non-string value, calling .upper() would raise an AttributeError.

Consider adding type validation:

-            tracker_code = getattr(obj, 'tracker', name).upper()
+            tracker_attr = getattr(obj, 'tracker', name)
+            if not isinstance(tracker_attr, str):
+                console.print(f"[yellow]Warning: {name}.tracker is not a string, using class name instead[/yellow]")
+                tracker_attr = name
+            tracker_code = tracker_attr.upper()
             tracker_class_map[tracker_code] = obj
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2693b74 and a692b52.

📒 Files selected for processing (1)
  • src/trackersetup.py (4 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-11T08:09:03.381Z
Learnt from: Audionut
Repo: Audionut/Upload-Assistant PR: 991
File: src/trackers/THR.py:263-263
Timestamp: 2025-11-11T08:09:03.381Z
Learning: For src/trackers/THR.py in Audionut's pull requests, do not flag issues about mixing synchronous requests calls (like requests.post, requests.get) with async functions. The file needs a refactor, and these issues should be ignored until then.

Applied to files:

  • src/trackersetup.py
🔇 Additional comments (2)
src/trackersetup.py (2)

2-2: LGTM! Necessary imports for dynamic tracker loading.

The new imports support the dynamic discovery pattern: importlib for loading modules, inspect for introspection, and aiofiles for async file operations.

Also applies to: 9-10


18-22: LGTM! Constructor properly stores config.

The addition of the config parameter aligns with the dynamic tracker loading pattern where config is needed for tracker instantiation.

Comment on lines +853 to +870
for mod_name in tracker_module_names:
if mod_name in ('AVISTAZ_NETWORK', 'UNIT3D_TEMPLATE', 'UNIT3D'):
continue # Skip this module entirely

api_trackers = {
'ACM', 'AITHER', 'AL', 'BHD', 'BLU', 'CBR', 'DP', 'EMUW', 'FNP', 'FRIKI', 'HHD', 'HUNO', 'ITT', 'LCD', 'LDU', 'LST', 'LT',
'OE', 'OTW', 'PT', 'PTT', 'RAS', 'RF', 'R4E', 'SAM', 'SHRI', 'SP', 'STC', 'TIK', 'TTR', 'ULCX', 'UTP', 'YOINK', 'YUS'
}
full_mod_name = f'src.trackers.{mod_name}'
module = importlib.import_module(full_mod_name)

other_api_trackers = {
'ANT', 'BHDTV', 'DC', 'GPW', 'NBL', 'RTF', 'SN', 'SPD', 'TL', 'TVC'
}
for name, obj in inspect.getmembers(module, inspect.isclass):
if obj.__module__ == full_mod_name:
tracker_code = getattr(obj, 'tracker', name).upper()
tracker_class_map[tracker_code] = obj

http_trackers = {
'AR', 'ASC', 'AZ', 'BJS', 'BT', 'CZ', 'FF', 'FL', 'HDB', 'HDS', 'HDT', 'IS', 'MTV', 'PHD', 'PTER', 'PTS', 'TTG'
}
if getattr(obj, 'is_http', False):
http_trackers[tracker_code] = obj
elif getattr(obj, 'is_api', False):
api_trackers[tracker_code] = obj
elif getattr(obj, 'is_other_api', False):
other_api_trackers[tracker_code] = obj
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add error handling for module imports.

If a tracker module fails to import (e.g., syntax error, missing dependency), the loop continues silently and that tracker won't be available. This makes debugging difficult and could lead to confusing runtime errors when users try to use an unavailable tracker.

Apply this diff to add error handling:

 for mod_name in tracker_module_names:
     if mod_name in ('AVISTAZ_NETWORK', 'UNIT3D_TEMPLATE', 'UNIT3D'):
         continue  # Skip this module entirely
 
     full_mod_name = f'src.trackers.{mod_name}'
-    module = importlib.import_module(full_mod_name)
+    try:
+        module = importlib.import_module(full_mod_name)
+    except Exception as e:
+        console.print(f"[yellow]Warning: Failed to import tracker module {mod_name}: {e}[/yellow]")
+        continue
 
     for name, obj in inspect.getmembers(module, inspect.isclass):
         if obj.__module__ == full_mod_name:
             tracker_code = getattr(obj, 'tracker', name).upper()
             tracker_class_map[tracker_code] = obj
 
             if getattr(obj, 'is_http', False):
                 http_trackers[tracker_code] = obj
             elif getattr(obj, 'is_api', False):
                 api_trackers[tracker_code] = obj
             elif getattr(obj, 'is_other_api', False):
                 other_api_trackers[tracker_code] = obj
🤖 Prompt for AI Agents
In src/trackersetup.py around lines 853 to 870, the loop imports tracker modules
without error handling so import failures silently skip trackers; wrap the
importlib.import_module(full_mod_name) call in a try/except that catches
Exception, log an error including full_mod_name and the exception/traceback
(using the module logger or existing process logger), and continue to the next
mod_name so the app remains stable and the failure is visible for debugging.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant