Skip to content
This repository was archived by the owner on Jun 14, 2026. It is now read-only.

refactor(BJS): simplify search_existing using direct HTML parsing - #1378

Open
wastaken7 wants to merge 2 commits into
masterfrom
refactor/bjs-direct-torrent-parsing
Open

refactor(BJS): simplify search_existing using direct HTML parsing#1378
wastaken7 wants to merge 2 commits into
masterfrom
refactor/bjs-direct-torrent-parsing

Conversation

@wastaken7

@wastaken7 wastaken7 commented May 24, 2026

Copy link
Copy Markdown
Collaborator

Description

This PR refactors and significantly simplifies the duplicate check logic (search_existing) for the BJS tracker.

Since the tracker now exposes the folder/file names directly on the torrent listing via the data-torrentname attribute, we no longer need to perform secondary AJAX requests or fetch individual torrent pages. Furthermore, all unnecessary filtering and metadata matching (resolution, season/episode, pack matching) have been removed, returning all search matches directly.

Changes

  • Simplification in BJS Tracker (src/trackers/BJS.py):
    • Refactored search_existing to directly extract data-torrentname and size from the list rows on the search page.
    • Inlined the search page request, removing the helper method _fetch_search_page.
    • Returned only the requested dictionary keys (name, size, link).
  • Code Cleanup:
    • Eliminated now obsolete helper methods (_extract_upload_params, _should_process_torrent, _extract_torrent_ids, _fetch_torrent_page, _extract_item_name, and _process_ajax_responses).
    • Removed unused imports (such as cast from typing).

Summary by CodeRabbit

  • Refactor
    • Streamlined duplicate-detection by removing multi-step filtering and secondary page fetches; duplicates are now built directly from search result rows.
    • On additional-check failures the flow now marks items as skipped and returns immediately.
    • Improved title extraction to prefer canonical/original titles from the page info box.
    • Updated year selection to prefer episode/Tv year when available, otherwise fall back to the provided year.

Review Change Stack

@github-actions

Copy link
Copy Markdown

Thanks for taking the time to contribute to this project. Upload Assistant is currently in a complete rewrite, and no new development is being conducted on this python source at this time.

If you have come this far, please feel free to leave open, any pull requests regarding new sites being added to the source, as these can serve as the baseline for later conversion.

If your pull request relates to a critical bug, this will be addressed in this code base, and a new release published as needed.

If your pull request only addresses a quite minor bug, it is not likely to be addressed in this code base.

Details for the new code base will follow at a later date.

@coderabbitai

coderabbitai Bot commented May 24, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Refactors the BJS tracker: removes an unused import, updates get_database_title() to parse the "Informações" box for original/canonical titles, simplifies search_existing() to build duplicates from the search-results page rows, and adjusts get_year() to prefer tvdb/imdb year values for TV or meta year for movies.

Changes

BJS Tracker Refactoring

Layer / File(s) Summary
Import cleanup and database title extraction
src/trackers/BJS.py
Removes unused cast from typing. get_database_title() now documents behavior and parses the BJS "Informações" table rows to extract Título Original: or Título: as the canonical title.
Simplified duplicate detection in search_existing()
src/trackers/BJS.py
On failed additional checks sets meta["skipping"] and returns. Replaces prior upload-param extraction, filtering, and AJAX detail-page fetches with a single fetch of the search-results page (div.main_column) and builds dupes directly from each tr row's id, data-torrentname, displayed size, and a constructed torrent link.
TV/Movie year resolution change
src/trackers/BJS.py
get_year() now returns meta["year"] for movies; for TV it prefers numeric tvdb_episode_year, then numeric imdb_info["tv_year"], otherwise falls back to meta["year"]. Removed end_year-based label formatting.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • Audionut/Upload-Assistant#1111: Both PRs modify src/trackers/BJS.py by enhancing get_database_title() and restructuring search_existing() duplicate-detection logic around database-title extraction.

Suggested reviewers

  • Audionut

Poem

🐰 A rabbit hops through rows of code and light,
Cuts a cast away to make the parser bright,
Reads "Título Original" where the title hides,
Gathers duplicates from tidy search-result tides,
Hums a tiny bug-free tune into the night.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main refactoring change: simplifying the search_existing method using direct HTML parsing instead of secondary requests.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/bjs-direct-torrent-parsing

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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/trackers/BJS.py (1)

476-521: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don't turn search failures into a clean “no dupes” result.

This path now returns [] for HTTP failures, auth regressions, and unexpected HTML without setting meta["skipping"]. In src/trackerstatus.py, that still flows through the normal dupe-check pipeline, so a broken BJS search can be mistaken for “safe to upload”.

Suggested fix
         try:
             cookie_jar = await self.cookie_validator.load_session_cookies(meta, self.tracker)
             if cookie_jar:
                 self.session.cookies = cookie_jar
@@
             search_url = f"{self.base_url}/torrents.php?searchstr={meta['imdb_info']['imdbID']}"
             response = await self.session.get(search_url, follow_redirects=True)
+            response.raise_for_status()
             soup = BeautifulSoup(response.text, "html.parser")

             torrent_details_table: Optional[Tag] = soup.find("div", class_="main_column")
@@
             if torrent_details_table:
                 BJS.database_title = self.get_database_title(soup)
                 BJS.already_has_the_info = bool(BJS.database_title)
             else:
+                meta["skipping"] = self.tracker
                 return dupes
@@
         except Exception as e:
+            meta["skipping"] = self.tracker
             console.print(f'[bold red]Ocorreu um erro inesperado ao processar a busca: {e}[/bold red]')
             import traceback
             traceback.print_exc()
             return dupes
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/trackers/BJS.py` around lines 476 - 521, The function currently swallows
HTTP/parser/auth failures and returns an empty dupes list, which makes failures
look like “no dupes”; update error handling so that on non-200 HTTP responses,
missing/invalid HTML (when torrent_details_table is falsy), or any exception you
set meta["skipping"] = True (to mark the search as failed) and then either
return immediately or re-raise after setting that flag; specifically change the
paths around cookie_validator.load_session_cookies, the response handling after
self.session.get(...), the branch that returns when torrent_details_table is
falsy, and the except block so they set meta["skipping"]=True before returning
or propagating the error (references: cookie_validator.load_session_cookies,
self.session.get, torrent_details_table, BJS.already_has_the_info,
get_database_title, meta["skipping"]).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/trackers/BJS.py`:
- Around line 488-493: The code currently sets BJS.already_has_the_info whenever
a generic "div.main_column" exists; change this so the flag is only set when the
page actually contains an info entry by verifying the real metadata before
marking it. Concretely, keep locating torrent_details_table = soup.find("div",
class_="main_column") but only set BJS.already_has_the_info = True and assign
BJS.database_title = self.get_database_title(soup) if get_database_title(soup)
returns a non-empty/truthy value (or if torrent_details_table contains a more
specific expected element indicating a BJS entry); otherwise leave
already_has_the_info False so downstream methods (get_cover, get_credits,
get_overview) don’t skip fields for search-result pages.

---

Outside diff comments:
In `@src/trackers/BJS.py`:
- Around line 476-521: The function currently swallows HTTP/parser/auth failures
and returns an empty dupes list, which makes failures look like “no dupes”;
update error handling so that on non-200 HTTP responses, missing/invalid HTML
(when torrent_details_table is falsy), or any exception you set meta["skipping"]
= True (to mark the search as failed) and then either return immediately or
re-raise after setting that flag; specifically change the paths around
cookie_validator.load_session_cookies, the response handling after
self.session.get(...), the branch that returns when torrent_details_table is
falsy, and the except block so they set meta["skipping"]=True before returning
or propagating the error (references: cookie_validator.load_session_cookies,
self.session.get, torrent_details_table, BJS.already_has_the_info,
get_database_title, meta["skipping"]).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 901e8081-a515-43bc-b5cc-d63d973338fa

📥 Commits

Reviewing files that changed from the base of the PR and between 3e39d5d and dee6e75.

📒 Files selected for processing (1)
  • src/trackers/BJS.py

Comment thread src/trackers/BJS.py
Comment on lines +488 to 493
torrent_details_table: Optional[Tag] = soup.find("div", class_="main_column")

if torrent_details_table:
BJS.already_has_the_info = True
BJS.database_title = self.get_database_title(soup)
else:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Only set already_has_the_info when the info box was actually found.

div.main_column is the generic search-results container, so Line 491 currently marks the tracker as already having metadata even when this page only contains a search listing. Downstream, get_cover(), get_credits(), and get_overview() treat that flag as authoritative and can skip fields for uploads that do not already exist in BJS's database.

Suggested fix
             torrent_details_table: Optional[Tag] = soup.find("div", class_="main_column")

             if torrent_details_table:
-                BJS.already_has_the_info = True
                 BJS.database_title = self.get_database_title(soup)
+                BJS.already_has_the_info = bool(BJS.database_title)
             else:
                 return dupes
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/trackers/BJS.py` around lines 488 - 493, The code currently sets
BJS.already_has_the_info whenever a generic "div.main_column" exists; change
this so the flag is only set when the page actually contains an info entry by
verifying the real metadata before marking it. Concretely, keep locating
torrent_details_table = soup.find("div", class_="main_column") but only set
BJS.already_has_the_info = True and assign BJS.database_title =
self.get_database_title(soup) if get_database_title(soup) returns a
non-empty/truthy value (or if torrent_details_table contains a more specific
expected element indicating a BJS entry); otherwise leave already_has_the_info
False so downstream methods (get_cover, get_credits, get_overview) don’t skip
fields for search-result pages.

@wastaken7
wastaken7 requested a review from Audionut May 24, 2026 03:32

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

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

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

465-482: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Reset the shared BJS state before any early return.

BJS.already_has_the_info and BJS.database_title are class-level state, but they are only cleared after the subtitle and IMDb guards. If a previous upload populated them, returning early here can leak stale values into get_title(), get_cover(), get_credits(), and get_overview() on the next upload.

Suggested fix
     async def search_existing(self, meta: dict[str, Any], _) -> list[dict[str, str]]:
         dupes: list[dict[str, str]] = []
+        BJS.already_has_the_info = False
+        BJS.database_title = ""
+
         should_continue = self.get_additional_checks(meta)
         if not should_continue:
             meta["skipping"] = f"{self.tracker}"
             return dupes
@@
-            BJS.already_has_the_info = False
-            BJS.database_title = ""
-
             search_url = f"{self.base_url}/torrents.php?searchstr={meta['imdb_info']['imdbID']}"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/trackers/BJS.py` around lines 465 - 482, Reset the class-level state
BJS.already_has_the_info and BJS.database_title at the start of search_existing
(or at least before any early returns such as the subtitle guard and the IMDb ID
guard) to avoid leaking stale values; locate the async def search_existing(...)
and move or add assignments to set BJS.already_has_the_info = False and
BJS.database_title = "" before the checks that return early (the
get_additional_checks() branch and the imdbID presence check) so downstream
methods like get_title(), get_cover(), get_credits(), and get_overview() never
see stale class state.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/trackers/BJS.py`:
- Around line 465-482: Reset the class-level state BJS.already_has_the_info and
BJS.database_title at the start of search_existing (or at least before any early
returns such as the subtitle guard and the IMDb ID guard) to avoid leaking stale
values; locate the async def search_existing(...) and move or add assignments to
set BJS.already_has_the_info = False and BJS.database_title = "" before the
checks that return early (the get_additional_checks() branch and the imdbID
presence check) so downstream methods like get_title(), get_cover(),
get_credits(), and get_overview() never see stale class state.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 08412e34-79b3-450d-8670-fe5bdb01ad48

📥 Commits

Reviewing files that changed from the base of the PR and between dee6e75 and 7159dca.

📒 Files selected for processing (1)
  • src/trackers/BJS.py

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant