Conversation
* perf: restructured code and fixed yt-dlp download issue * feat: added Metadata Feature * chore(release): v1.4.0-x (final end version) Signed-off-by: Riajul <93116400+rjriajul@users.noreply.github.com> Co-authored-by: clyfly <denwahgenshin@gmail.com> Co-authored-by: SilentDemonSD <105407900+SilentDemonSD@users.noreply.github.com>
….com URL shorteners
…ents.com, reel2earn.com, shortner.in, and thalashort.com
This is the final update to the master branch. From now on, the master branch is deprecated — no further updates, pull requests, or pushes will be accepted. The master branch is now officially retired. Signed-off-by: Riajul <93116400+rjriajul@users.noreply.github.com>
Reviewer's GuideExtends URL shortener support for multiple new providers and enhances MEGA download handling to support sub-path selection within folder links and proper folder_api usage for downloads. Sequence diagram for enhanced MEGA folder download with sub-path selectionsequenceDiagram actor User participant Listener participant add_mega_download participant AsyncMega participant MegaApi_api participant MegaApi_folder participant MegaListener User->>Listener: Provide mega_link (optional sub_path using pipe) Listener->>add_mega_download: add_mega_download(listener, path) add_mega_download->>add_mega_download: Parse listener.link into mega_link and sub_path add_mega_download->>AsyncMega: Create AsyncMega instance add_mega_download->>MegaApi_api: Create api MegaApi instance add_mega_download->>AsyncMega: Assign api to AsyncMega add_mega_download->>MegaListener: Attach MegaListener to api add_mega_download->>AsyncMega: async_api.login(MEGA_EMAIL, MEGA_PASSWORD) alt mega_link is file add_mega_download->>AsyncMega: getPublicNode(mega_link) AsyncMega-->>MegaListener: Set public_node add_mega_download->>add_mega_download: node = mega_listener.public_node else mega_link is folder add_mega_download->>MegaApi_folder: Create folder_api MegaApi instance add_mega_download->>AsyncMega: Assign folder_api to async_api add_mega_download->>MegaApi_folder: folder_api.addListener(mega_listener) add_mega_download->>AsyncMega: run(folder_api.loginToFolder, mega_link) AsyncMega-->>MegaListener: Set node for folder root add_mega_download->>add_mega_download: node = mega_listener.node end opt sub_path provided and link is folder add_mega_download->>add_mega_download: resolve_subnode(api, node, sub_path) add_mega_download-->>add_mega_download: node set to sub_path node or None alt node is None add_mega_download->>Listener: on_download_error(Subfolder not found) add_mega_download->>AsyncMega: logout() add_mega_download-->>Listener: Return else node found add_mega_download->>add_mega_download: Log resolved node name end end alt mega_listener.error is set add_mega_download->>Listener: on_download_error(mega_listener.error) add_mega_download->>AsyncMega: logout() add_mega_download-->>Listener: Return else no listener error add_mega_download->>add_mega_download: Prepare download path and name alt folder_api exists add_mega_download->>AsyncMega: run(folder_api.startDownload, node, path, listener.name, None, False, None) else file or non folder_api add_mega_download->>AsyncMega: startDownload(node, path, listener.name, None, False, None) end AsyncMega-->>Listener: Download completes add_mega_download->>AsyncMega: logout() end Flow diagram for extended short_url provider handlingflowchart TD A[Start short_url with longurl and _shortener] --> B[Is provider modijiurl.com] B -- Yes --> B1[Encode longurl as long_url] B1 --> B2[Call modijiurl api with api and long_url] B2 --> B3[Check result status] B3 -- error --> B4[Log error message and return longurl] B3 -- success --> B5[Return result shortenedUrl] B -- No --> C[Is provider linkshortify.com] C -- Yes --> C1[Encode longurl as long_url] C1 --> C2[Call linkshortify api] C2 --> C3[Check result status] C3 -- error --> C4[Log error message and return longurl] C3 -- success --> C5[Return result shortenedUrl] C -- No --> D[Is provider inshorturl.com] D -- Yes --> D1[Encode longurl as long_url] D1 --> D2[Call inshorturl api] D2 --> D3[Check result status] D3 -- error --> D4[Log error message and return longurl] D3 -- success --> D5[Return result shortenedUrl] D -- No --> E[Is provider vplink.in] E -- Yes --> E1[Encode longurl as long_url] E1 --> E2[Call vplink api with alias CustomAlias] E2 --> E3[Check result status] E3 -- error --> E4[Log error message and return longurl] E3 -- success --> E5[Return result shortenedUrl] E -- No --> F[Is provider papajiurl.com] F -- Yes --> F1[Encode longurl as long_url] F1 --> F2[Call papajiurl api] F2 --> F3[Check result status] F3 -- error --> F4[Log error message and return longurl] F3 -- success --> F5[Return result shortenedUrl] F -- No --> G[Is provider linkcents.com] G -- Yes --> G1[Encode longurl as long_url] G1 --> G2[Call linkcents api] G2 --> G3[Check result status] G3 -- error --> G4[Log error message and return longurl] G3 -- success --> G5[Return result shortenedUrl] G -- No --> H[Is provider reel2earn.com] H -- Yes --> H1[Encode longurl as long_url] H1 --> H2[Call reel2earn api] H2 --> H3[Check result status] H3 -- error --> H4[Log error message and return longurl] H3 -- success --> H5[Return result shortenedUrl] H -- No --> I[Is provider shortner.in] I -- Yes --> I1[Encode longurl as long_url] I1 --> I2[Call shortner api] I2 --> I3[Check result status] I3 -- error --> I4[Log error message and return longurl] I3 -- success --> I5[Return result shortenedUrl] I -- No --> J[Is provider thalashort.com] J -- Yes --> J1[Encode longurl as long_url] J1 --> J2[Call thalashort api] J2 --> J3[Check result status] J3 -- error --> J4[Log error message and return longurl] J3 -- success --> J5[Return result shortenedUrl] J -- No --> K[Fallback to existing shortener handling] K --> L[Return result from fallback branch] File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey there - I've reviewed your changes - here's some feedback:
- The new shortener branches all duplicate the same pattern (quoting the URL, building an API URL, calling
cget, checkingstatus, and returningshortenedUrl); consider extracting this into a helper function or data-driven mapping of domain → API base to reduce repetition and ease future additions. - For the new shortener responses, using direct
result["status"]andresult["shortenedUrl"]lookups assumes the API always returns the expected shape; consider using.get()and validating keys or status codes to avoid unexpectedKeyErroror type issues when the remote service misbehaves. - In
add_mega_download, you now computemega_linkand callget_mega_link_type(mega_link)multiple times; caching the link type once and reusing it would simplify the branching, and you may also want to normalizesub_pathparts (e.g., case sensitivity or trimming extra slashes) to make subfolder resolution more robust.
Prompt for AI Agents
Please address the comments from this code review: ## Overall Comments - The new shortener branches all duplicate the same pattern (quoting the URL, building an API URL, calling `cget`, checking `status`, and returning `shortenedUrl`); consider extracting this into a helper function or data-driven mapping of domain → API base to reduce repetition and ease future additions. - For the new shortener responses, using direct `result["status"]` and `result["shortenedUrl"]` lookups assumes the API always returns the expected shape; consider using `.get()` and validating keys or status codes to avoid unexpected `KeyError` or type issues when the remote service misbehaves. - In `add_mega_download`, you now compute `mega_link` and call `get_mega_link_type(mega_link)` multiple times; caching the link type once and reusing it would simplify the branching, and you may also want to normalize `sub_path` parts (e.g., case sensitivity or trimming extra slashes) to make subfolder resolution more robust. ## Individual Comments ### Comment 1 <location> `bot/helper/mirror_leech_utils/download_utils/mega_download.py:65-74` </location> <code_context> child_nodes = [children.get(i) for i in range(children.size())] LOGGER.info(f"Found children: {[child.getName() for child in child_nodes]}") + if sub_path and get_mega_link_type(mega_link) == "folder": + def resolve_subnode(api_obj, base_node, rel_path): + current = base_node + for part in [p for p in rel_path.split("/") if p]: + kids = api_obj.getChildren(current) + match = None + for i in range(kids.size()): + child = kids.get(i) + if child.getName() == part: + match = child + break + if not match: + return None + current = match + return current + + node = await sync_to_async(resolve_subnode, api, node, sub_path) + if node is None: + await listener.on_download_error(f"Subfolder not found: {sub_path}") </code_context> <issue_to_address> **issue (bug_risk):** Use the correct MegaApi instance (folder_api vs api) when resolving subfolders for folder links. Here `node` originates from `folder_api` (via `async_api.folder_api`), but `resolve_subnode` is called with the main `api` instance: ```python node = await sync_to_async(resolve_subnode, api, node, sub_path) ``` If the node belongs to the `folder_api` tree, `api.getChildren(node)` may fail or always return no children, breaking subfolder resolution for folder links. Instead, choose the API based on where `node` came from, e.g.: ```python api_obj = folder_api or api node = await sync_to_async(resolve_subnode, api_obj, node, sub_path) ``` so traversal stays within the correct API context. </issue_to_address> ### Comment 2 <location> `bot/helper/mirror_leech_utils/download_utils/mega_download.py:31-35` </location> <code_context> async def add_mega_download(listener, path): + mega_link = listener.link + sub_path = None + if "|" in mega_link: + mega_link, sub_path = mega_link.split("|", 1) + mega_link, sub_path = mega_link.strip(), sub_path.strip().strip("/") + async_api = AsyncMega() </code_context> <issue_to_address> **suggestion:** Consider validating or warning when a sub_path is provided for a file link, instead of silently ignoring it. Right now `sub_path` is parsed from `listener.link` but only used when `get_mega_link_type(mega_link) == "folder"`, so a value like `file_link|some/subpath` is silently ignored. Consider explicitly rejecting subpaths for file links, e.g.: ```python link_type = get_mega_link_type(mega_link) if sub_path and link_type == "file": await listener.on_download_error("Subpath is only supported for folder links") return ``` This keeps behavior predictable and avoids silently discarding user input. Suggested implementation: ```python async def add_mega_download(listener, path): mega_link = listener.link sub_path = None if "|" in mega_link: mega_link, sub_path = mega_link.split("|", 1) mega_link, sub_path = mega_link.strip(), sub_path.strip().strip("/") link_type = get_mega_link_type(mega_link) if sub_path and link_type == "file": await listener.on_download_error("Subpath is only supported for folder links") return async_api = AsyncMega() ``` ```python if link_type == "file": ``` </issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| if sub_path and get_mega_link_type(mega_link) == "folder": | ||
| def resolve_subnode(api_obj, base_node, rel_path): | ||
| current = base_node | ||
| for part in [p for p in rel_path.split("/") if p]: | ||
| kids = api_obj.getChildren(current) | ||
| match = None | ||
| for i in range(kids.size()): | ||
| child = kids.get(i) | ||
| if child.getName() == part: | ||
| match = child |
There was a problem hiding this comment.
issue (bug_risk): Use the correct MegaApi instance (folder_api vs api) when resolving subfolders for folder links.
Here node originates from folder_api (via async_api.folder_api), but resolve_subnode is called with the main api instance:
node = await sync_to_async(resolve_subnode, api, node, sub_path)If the node belongs to the folder_api tree, api.getChildren(node) may fail or always return no children, breaking subfolder resolution for folder links. Instead, choose the API based on where node came from, e.g.:
api_obj = folder_api or api node = await sync_to_async(resolve_subnode, api_obj, node, sub_path)so traversal stays within the correct API context.
Resolved conflict in mega_download.py by taking upstream version
Summary by Sourcery
Extend URL shortening and Mega download handling with additional services and subfolder support.
New Features:
Enhancements: