Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1.2.5 #145

Merged
merged 24 commits into from
Nov 7, 2024
Merged

1.2.5 #145

merged 24 commits into from
Nov 7, 2024

Conversation

cohenaj194
Copy link
Contributor

@cohenaj194 cohenaj194 commented Oct 25, 2024

closes: #139

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Introduced a new attribute, required_lvl, for auction items in alert messages.
    • Enhanced alert construction to include required_lvl for item level information.
    • Updated the get_ilvl_items function to return required levels for items.
    • Added a new item entry in the data structure with specific attributes and required level.
    • Improved user interface by adding input fields for minimum and maximum player levels.
  • Bug Fixes

    • Improved validation of item level data by enforcing the presence of required_min_lvl and required_max_lvl.
  • Chores

    • Updated version number from "1.2.4" to "1.2.5" in relevant files.
    • Enhanced the build workflow for Windows executable with improved upload handling.

Copy link
Contributor

coderabbitai bot commented Oct 25, 2024

Walkthrough

The changes in this pull request enhance the alerting functionality and data handling within the auction system. In mega_alerts.py, a new attribute, required_lvl, is introduced for auction items, affecting how alerts are constructed and sent. The pull_single_realm_data function now incorporates this attribute into alert messages. In utils/mega_data_setup.py, the MegaData class is updated to include required_lvl in its data structures, ensuring it is validated and initialized correctly. These modifications improve the robustness and clarity of auction alerts and item level data.

Changes

File Change Summary
mega_alerts.py - Added handling for required_lvl in pull_single_realm_data, check_tertiary_stats_generic, and format_alert_messages.
- Updated alert messages to include required_lvl when applicable.
utils/mega_data_setup.py - Introduced required_min_lvl and required_max_lvl in ilvl_info within __set_desired_ilvl, initialized to default values.
- Updated snipe_info construction to include base_required_levels.
- Modified method signatures to accept base_required_levels.
.github/workflows/windows-exe-build.yml - Updated AAA_VERSION from "1.2.4" to "1.2.5".
AzerothAuctionAssassin.py - Updated AAA_VERSION from "1.2.4.1" to "1.2.5".
- Added code for dynamic import path adjustment for Windows C# binary execution.
- Adjusted UI dimensions and labels for item level management.
utils/api_requests.py - Updated return signature of get_ilvl_items to include base_required_levels.
AzerothAuctionAssassinData/example_desired_ilvl_list.json - Added new item with ilvl 400 and required_min_lvl 71, required_max_lvl 79.
- Duplicated entry for ilvl 483.

Assessment against linked issues

Objective Addressed Explanation
Support required player levels in alerts (#139)
Validate item level data with required levels (#139)

Possibly related PRs

  • 1.2.4 #136: The changes in AzerothAuctionAssassin.py include updates to item level processing logic, which may relate to the new required_lvl attribute introduced in the main PR, as both involve item level management and enhancements in auction data handling.

Poem

In the realm of auctions bright,
A new level shines with light.
Alerts now sing of levels due,
With required_lvl, we start anew.
Data dances, robust and clear,
Thanks to changes we hold dear! 🐇✨


🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@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

🧹 Outside diff range and nitpick comments (2)
utils/mega_data_setup.py (2)

371-373: Simplify dictionary key check and document the default value.

  1. Simplify the dictionary key check.
  2. Consider adding a comment explaining why 1000 was chosen as the default value.
-        if "required_lvl" not in ilvl_info.keys():
+        if "required_lvl" not in ilvl_info:  # Default to max level requirement
             ilvl_info["required_lvl"] = 1000
🧰 Tools
🪛 Ruff

371-371: Use key not in dict instead of key not in dict.keys()

Remove .keys()

(SIM118)


Line range hint 374-383: Consider using a schema validator for better maintainability.

The current approach of using an example dictionary for schema validation works but could be improved. Consider using a schema validation library like pydantic or dataclasses for better type safety and maintainability.

Example using dataclasses:

from dataclasses import dataclass
from typing import List, Optional

@dataclass
class IlvlInfo:
    ilvl: int
    buyout: int
    sockets: bool
    speed: bool
    leech: bool
    avoidance: bool
    item_ids: List[int]
    required_lvl: int = 1000  # Default to max level requirement
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 62c6b3a and e8ee1bb.

📒 Files selected for processing (2)
  • mega_alerts.py (5 hunks)
  • utils/mega_data_setup.py (3 hunks)
🧰 Additional context used
🪛 Ruff
mega_alerts.py

84-84: Comparison to None should be cond is not None

Replace with cond is not None

(E711)

utils/mega_data_setup.py

371-371: Use key not in dict instead of key not in dict.keys()

Remove .keys()

(SIM118)

🔇 Additional comments (7)
mega_alerts.py (5)

282-289: LGTM! Clear and efficient level requirement extraction

The code efficiently extracts the required level from item modifiers with good documentation.


330-333: LGTM! Proper validation of level requirement

The level requirement validation is well-placed and follows the established pattern of other validation checks.


345-345: LGTM! Consistent dictionary field addition

The required_lvl field is properly added to the return dictionary.


480-480: LGTM! Consistent results dictionary field addition

The required_lvl field is properly added to the ilvl_results_dict.


84-85: Verify alert handling with new required_lvl field

The implementation of required_lvl is consistent throughout the code. However, let's verify that existing alerts are not affected by this change.

Also applies to: 282-289, 330-333, 345-345, 480-480

✅ Verification successful

Let me gather more information about the alert message formatting to ensure the changes are consistent.


Based on the results, I can now provide the final response:

✓ Alert handling with required_lvl field is correctly implemented

The implementation is consistent and safe because:

  • The required_lvl field is properly handled in message formatting with null checks
  • It follows the existing pattern of conditional field inclusion
  • The field is consistently used across auction processing (buyouts, modifiers)
  • No existing alert message construction patterns are affected as required_lvl is only added as an optional field
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any existing alert handling code that might be affected by the new required_lvl field

# Test 1: Look for alert message construction patterns
echo "Checking alert message construction patterns..."
rg -l "def.*alert" | xargs rg -l "required_lvl"

# Test 2: Check for any potential message formatting in tests
echo "Checking test files for alert message patterns..."
fd -e test.py -e spec.py | xargs rg "alert.*message"

Length of output: 557


Script:

#!/bin/bash
# Check the implementation of format_alert_messages and its usage
echo "Checking format_alert_messages implementation..."
rg -A 10 "def format_alert_messages" mega_alerts.py

# Check all occurrences of required_lvl to verify consistent handling
echo "Checking all required_lvl usages..."
rg "required_lvl" mega_alerts.py

# Look for test cases related to alert formatting
echo "Checking test cases for alert formatting..."
rg -B 2 -A 5 "test.*alert.*message" tests/

Length of output: 1309

🧰 Tools
🪛 Ruff

84-84: Comparison to None should be cond is not None

Replace with cond is not None

(E711)

utils/mega_data_setup.py (2)

392-392: LGTM!

The addition of required_lvl to int_vars is consistent with the validation approach and maintains alphabetical ordering.


Line range hint 371-392: Verify handling of required_lvl in the auction system.

The addition of required_lvl looks good, but let's verify its integration with the auction system.

✅ Verification successful

Based on the search results, I can now generate the final response as the integration of required_lvl is clearly visible in the codebase.

The required_lvl attribute is properly integrated in the auction system

The attribute is well-handled across the codebase:

  • In mega_alerts.py, it's used for filtering items based on level requirements against DESIRED_ILVL_ITEMS["required_lvl"]
  • It's included in alert messages when available
  • The value is properly extracted from item modifiers (type 9)
  • The default value of 1000 in mega_data_setup.py serves as a safe fallback
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check how required_lvl is used in the codebase
echo "Searching for required_lvl usage in Python files..."
rg -t py "required_lvl" -A 3

echo "Searching for auction item level checks..."
ast-grep --pattern 'if $_.required_lvl $$$'

Length of output: 2460

mega_alerts.py Outdated Show resolved Hide resolved
@cohenaj194
Copy link
Contributor Author

Ill need to fix remove_ilvl_to_list to handle the new feature, but we have to allow backwards compatibility too so this will work for people who dont have a required_lvl set for anything in the AzerothAuctionAssassinData/desired_ilvl_list.json

@coderabbitai recommend a fix.

https://github.com/ff14-advanced-market-search/AzerothAuctionAssassin/blob/main/AzerothAuctionAssassin.py#L1375-L1407

[
// cant remove
    {
        "ilvl": 400,
        "buyout": 10000,
        "sockets": false,
        "speed": false,
        "leech": false,
        "avoidance": false,
        "item_ids": [
            1111
        ],
        "required_lvl": 70
    },
// can remove
    {
        "ilvl": 400,
        "buyout": 1000,
        "sockets": false,
        "speed": true,
        "leech": false,
        "avoidance": false,
        "item_ids": []
    }
]

cohenaj194 and others added 4 commits October 25, 2024 09:24
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link
Contributor

@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

🧹 Outside diff range and nitpick comments (9)
.github/workflows/windows-exe-build.yml (3)

Line range hint 7-11: Document the rationale for commented push trigger

Consider adding a comment explaining why the push trigger is disabled. This helps future maintainers understand if this is intentional for controlled releases or if it should be enabled under certain conditions.


Line range hint 89-93: Enhance certificate security practices

Consider these security improvements:

  1. Clean up certificate files after signing
  2. Use secure file deletion (like shred on Unix or similar Windows alternatives)
  3. Consider using separate certificates for Windows and macOS signing

Add cleanup steps after signing:

    - name: Sign Executable
      run: |
        $cert_path = "certificate.pfx"
        $password = "${{ secrets.CERT_PASSWORD }}"
        $timestamp_url = "http://timestamp.digicert.com"
        $executable_path = ".\AzerothAuctionAssassin-windows\AzerothAuctionAssassin\bin\Release\net8.0-windows\publish\win-x86\AzerothAuctionAssassin.exe"
        $signtoolPath = Resolve-Path "C:\Program Files (x86)\Windows Kits\10\bin\*\x64\signtool.exe" | Select-Object -Last 1
        & $signtoolPath sign /f $cert_path /p $password /tr $timestamp_url /td sha256 /fd sha256 /v $executable_path
+       # Securely delete the certificate file
+       if (Test-Path $cert_path) {
+           $bytes = [byte[]](Get-Content $cert_path -Encoding Byte)
+           $bytes = @(0) * $bytes.Length
+           [System.IO.File]::WriteAllBytes($cert_path, $bytes)
+           Remove-Item $cert_path -Force
+       }
      shell: pwsh

Also applies to: 134-135


Line range hint 146-159: Improve documentation for macOS signing issues

The current comment "broken probably needs a different cert" is not sufficiently descriptive. Consider:

  1. Creating a GitHub issue to track the macOS signing requirement
  2. Adding detailed documentation about the required certificate type
  3. Documenting the steps needed to resolve this

Would you like me to create a GitHub issue to track the macOS signing requirements and implementation?

mega_alerts.py (1)

285-292: LGTM: Consider adding a comment about modifier type 9

The code correctly and safely extracts the required level from item modifiers. Consider adding a brief comment explaining that modifier type 9 represents the player level requirement, as this isn't immediately obvious from the code.

 # Check for a modifier with type 9 and get its value (modifier 9 value equals playerLevel)
+# Note: In WoW's item system, modifier type 9 specifically represents the player level requirement
AzerothAuctionAssassin.py (5)

Line range hint 1-20: Improve error handling in Windows binary integration.

The generic exception handler silently passes all exceptions, which could mask important initialization errors. Consider:

  1. Logging the exception details for debugging
  2. Handling specific exceptions that are expected
  3. Re-raising critical exceptions that should halt execution

Apply this diff to improve error handling:

 try:
     if sys.argv[1] == "run-from-windows-bin":
         sys.path.append(f"{sys.argv[2]}")
         sys.path.append(f"{sys.argv[3]}")
         windowsApp_Path = f"{sys.argv[2]}"
     else:
         pass
-except Exception as ex:
-    pass
+except IndexError:
+    # Expected when not running from Windows binary
+    pass
+except Exception as ex:
+    print(f"Error initializing paths: {ex}")
+    raise  # Re-raise critical initialization errors

Line range hint 1012-1034: Update function to handle missing required_lvl key.

Based on the PR objectives, the function needs to handle cases where users don't have required_lvl set in their JSON data.

Apply this diff to ensure backward compatibility:

     def remove_ilvl_to_list(self):
         if len(self.ilvl_input.text()) == 0:
             QMessageBox.critical(
                 self,
                 "Ilvl Removal Issue",
                 "Please double click an ilvl json to remove it!",
             )
             return
         if self.ilvl_item_input.text() == "":
             item_ids_list = []
         else:
             item_ids_list = list(
                 map(int, self.ilvl_item_input.text().replace(" ", "").split(","))
             )
 
         ilvl_dict_data = {
             "ilvl": int(self.ilvl_input.text()),
             "buyout": int(self.ilvl_price_input.text()),
             "sockets": self.ilvl_sockets.isChecked(),
             "speed": self.ilvl_speed.isChecked(),
             "leech": self.ilvl_leech.isChecked(),
             "avoidance": self.ilvl_avoidance.isChecked(),
             "item_ids": item_ids_list,
+            "required_lvl": None  # Add this field with None as default
         }

Line range hint 1035-1048: Improve error handling in item removal.

The current implementation might fail silently if the item is not found in the list. Add proper error handling and user feedback.

Apply this diff to improve error handling:

         if ilvl_dict_data in self.ilvl_list:
             string_with_data = f"Item ID: {','.join(map(str, ilvl_dict_data['item_ids']))}; Price: {ilvl_dict_data['buyout']}; ILvl: {ilvl_dict_data['ilvl']}; Sockets: {ilvl_dict_data['sockets']}; Speed: {ilvl_dict_data['speed']}; Leech: {ilvl_dict_data['leech']}; Avoidance: {ilvl_dict_data['avoidance']}"
-            print(string_with_data)
+            found = False
             for x in range(self.ilvl_list_display.count()):
                 if self.ilvl_list_display.item(x).text() == string_with_data:
                     self.ilvl_list_display.takeItem(x)
                     self.ilvl_list.remove(ilvl_dict_data)
-                    return
+                    found = True
+                    break
+            if not found:
+                QMessageBox.warning(self, "Item Not Found", "The selected item was not found in the list.")
+        else:
+            QMessageBox.warning(self, "Item Not Found", "The selected item was not found in the list.")

Line range hint 1583-1592: Add error handling for JSON file operations.

The save_json_file method lacks error handling for file operations, which could lead to data loss or corruption.

Apply this diff to improve file operations:

     def save_json_file(self, path, data):
-        with open(path, "w", encoding="utf-8") as json_file:
-            json.dump(data, json_file, ensure_ascii=False, indent=4)
+        try:
+            # First write to a temporary file
+            temp_path = f"{path}.tmp"
+            with open(temp_path, "w", encoding="utf-8") as json_file:
+                json.dump(data, json_file, ensure_ascii=False, indent=4)
+            # Then rename it to the target file (atomic operation)
+            import os
+            os.replace(temp_path, path)
+        except Exception as e:
+            QMessageBox.critical(self, "Save Error", f"Failed to save file {path}: {str(e)}")
+            raise

Line range hint 1493-1507: Add input validation for authentication token.

The authentication token is sent to an external API without proper validation, which could be a security risk.

Apply this diff to add validation:

     def start_alerts(self):
+        # Validate token format before sending
+        token = self.authentication_token.text().strip()
+        if not token or len(token) < 32:  # Adjust minimum length as per your token format
+            QMessageBox.critical(
+                self,
+                "Invalid Token",
+                "Please provide a valid authentication token of sufficient length.",
+            )
+            return
+
         response = requests.post(
             self.token_auth_url,
-            json={"token": f"{self.authentication_token.text()}"},
+            json={"token": token},
         )
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between e8ee1bb and d4b670c.

📒 Files selected for processing (3)
  • .github/workflows/windows-exe-build.yml (1 hunks)
  • AzerothAuctionAssassin.py (1 hunks)
  • mega_alerts.py (5 hunks)
🔇 Additional comments (4)
.github/workflows/windows-exe-build.yml (1)

4-4: LGTM: Version update to 1.2.5

The version update is consistent with the PR objectives and is properly reflected in the workflow.

mega_alerts.py (3)

84-88: LGTM: Backward compatible required_lvl handling

The code correctly handles the optional required_lvl field by checking both its presence and value, maintaining backward compatibility for users without this field.


333-336: LGTM: Proper level requirement filtering

The code correctly filters out items with level requirements exceeding the desired threshold while safely handling cases where required_lvl is not set.


348-348: LGTM: Consistent required_lvl propagation

The required level is correctly propagated through the result dictionaries, ensuring this information is available for alert generation.

Also applies to: 483-483

Copy link
Contributor

@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

🧹 Outside diff range and nitpick comments (2)
utils/api_requests.py (1)

154-158: Add docstring to document the return values.

Consider adding a docstring to clearly document the function's return values, especially since it now returns 4 different values.

 def get_ilvl_items(ilvl=201, item_ids=[]):
+    """Get item information based on item level and optional item IDs.
+    
+    Args:
+        ilvl (int, optional): The item level threshold. Defaults to 201.
+        item_ids (list, optional): Specific item IDs to query. Defaults to [].
+    
+    Returns:
+        tuple: Contains:
+            - dict[int, str]: Mapping of item IDs to names
+            - set[int]: Set of item IDs
+            - dict[int, int]: Mapping of item IDs to base item levels
+            - dict[int, int]: Mapping of item IDs to required levels
+    """
utils/mega_data_setup.py (1)

375-377: Document the default value choice.

The default value of 1000 for required_lvl seems arbitrary. Consider adding a comment explaining why this value was chosen as the default.

🧰 Tools
🪛 Ruff

375-375: Use key not in dict instead of key not in dict.keys()

Remove .keys()

(SIM118)

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between d4b670c and 1b03d1c.

📒 Files selected for processing (2)
  • utils/api_requests.py (1 hunks)
  • utils/mega_data_setup.py (5 hunks)
🧰 Additional context used
🪛 Ruff
utils/mega_data_setup.py

372-372: Use key not in dict instead of key not in dict.keys()

Remove .keys()

(SIM118)


375-375: Use key not in dict instead of key not in dict.keys()

Remove .keys()

(SIM118)

🔇 Additional comments (3)
utils/api_requests.py (1)

154-158: Verify all callers handle the new return value.

The implementation looks good and maintains consistency with existing patterns. However, since this function now returns 4 values instead of 3, we should verify that all callers have been updated accordingly.

✅ Verification successful

Based on the search results, I can generate the final response as we have clear evidence about all callers of get_ilvl_items:

All callers properly handle the new return value ✅

The codebase scan shows that all callers of get_ilvl_items() have been correctly updated to handle the new 4-value return tuple. Both instances in utils/mega_data_setup.py properly unpack all values including the new base_required_levels:

  • item_names, item_ids, base_ilvls, base_required_levels = get_ilvl_items(ilvl, all_item_ids)
  • item_names, item_ids, base_ilvls, base_required_levels = get_ilvl_items()
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all callers of get_ilvl_items to verify they handle the new return value

# Search for function calls with different unpacking patterns
echo "Searching for get_ilvl_items calls..."
rg -A 2 "get_ilvl_items\(" 

# Search for specific unpacking patterns that might miss the new return value
echo "Checking for potential missed unpacking..."
rg "item_names,.*=.*get_ilvl_items"

Length of output: 1222

utils/mega_data_setup.py (2)

344-364: LGTM! Consistent handling of required levels.

The changes correctly handle the new base_required_levels parameter across both item-specific and broad group cases.


Line range hint 369-425: LGTM! Well-structured implementation with proper validation.

The changes properly handle the new required_lvl field with appropriate type validation and maintain backward compatibility for users without this field set.

🧰 Tools
🪛 Ruff

372-372: Use key not in dict instead of key not in dict.keys()

Remove .keys()

(SIM118)


375-375: Use key not in dict instead of key not in dict.keys()

Remove .keys()

(SIM118)

utils/mega_data_setup.py Outdated Show resolved Hide resolved
Copy link
Contributor

@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

🧹 Outside diff range and nitpick comments (1)
mega_alerts.py (1)

Line range hint 285-342: Improve required level validation logic.

The current implementation has a few potential issues:

  1. The early return at line 285 before required level extraction could skip valid items that don't have bonus lists but have a valid required level.
  2. The validation against the required level threshold happens before falling back to the base level, which could lead to incorrect filtering.
  3. The base_required_levels dictionary access could raise KeyError if the item ID is not present.

Consider this improved implementation:

     if "bonus_lists" not in auction["item"]:
-        return False
+        item_bonus_ids = set()
+    else:
+        item_bonus_ids = set(auction["item"]["bonus_lists"])

     # Check for a modifier with type 9 and get its value (modifier 9 value equals playerLevel)
     required_lvl = None
     for modifier in auction["item"].get("modifiers", []):
         if modifier["type"] == 9:
             required_lvl = modifier["value"]
             break

-    item_bonus_ids = set(auction["item"]["bonus_lists"])
     # look for intersection of bonus_ids and any other lists
     tertiary_stats = {
         "sockets": len(item_bonus_ids & socket_ids) != 0,
         "leech": len(item_bonus_ids & leech_ids) != 0,
         "avoidance": len(item_bonus_ids & avoidance_ids) != 0,
         "speed": len(item_bonus_ids & speed_ids) != 0,
     }

     # ... (rest of the tertiary stats validation)

     # if no modifier["type"] == 9 found, use the base required level for report
     if not required_lvl:
-        required_lvl = DESIRED_ILVL_ITEMS["base_required_levels"][auction["item"]["id"]]
+        required_lvl = DESIRED_ILVL_ITEMS["base_required_levels"].get(auction["item"]["id"])
+        if required_lvl is None:
+            return False

     # skip if required_lvl is too high
     if required_lvl > DESIRED_ILVL_ITEMS["required_lvl"]:
         return False
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 1b03d1c and 9b8e5c9.

📒 Files selected for processing (1)
  • mega_alerts.py (5 hunks)
🔇 Additional comments (4)
mega_alerts.py (4)

84-88: LGTM! Required level display logic is well-implemented.

The code correctly handles the presence of the required_lvl attribute and follows Python best practices for None comparison.


354-354: LGTM! Required level is correctly included in the return dictionary.

The addition maintains consistency with the function's data structure.


489-489: LGTM! Required level is correctly propagated to the results dictionary.

The addition ensures that the required level information flows through to the final alert message.


333-342: 🛠️ Refactor suggestion

Enhance error handling for better backward compatibility.

While the code handles missing modifiers, it could be more robust in handling cases where required_lvl is not set in the DESIRED_ILVL_ITEMS configuration.

Let's verify the potential impact:

Consider adding a safety check:

     # skip if required_lvl is too high
-    if required_lvl and required_lvl > DESIRED_ILVL_ITEMS["required_lvl"]:
+    if required_lvl and "required_lvl" in DESIRED_ILVL_ITEMS and required_lvl > DESIRED_ILVL_ITEMS["required_lvl"]:
         return False

Copy link
Contributor

@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

🧹 Outside diff range and nitpick comments (1)
utils/mega_data_setup.py (1)

379-387: Ensure backward compatibility for existing JSON files.

The default value of 1000 for required_lvl ensures backward compatibility with existing JSON files that don't have this field. However, consider documenting this default value and its significance.

Consider adding a comment explaining the default value:

 if "required_lvl" not in ilvl_info.keys():
-    ilvl_info["required_lvl"] = 1000
+    # Default to 1000 to maintain backward compatibility
+    # This value ensures that items without a required level are still considered
+    ilvl_info["required_lvl"] = 1000
🧰 Tools
🪛 Ruff

382-382: Use key not in dict instead of key not in dict.keys()

Remove .keys()

(SIM118)


385-385: Use key not in dict instead of key not in dict.keys()

Remove .keys()

(SIM118)

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 9b8e5c9 and dd08e8c.

📒 Files selected for processing (2)
  • utils/api_requests.py (1 hunks)
  • utils/mega_data_setup.py (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • utils/api_requests.py
🧰 Additional context used
🪛 Ruff
utils/mega_data_setup.py

382-382: Use key not in dict instead of key not in dict.keys()

Remove .keys()

(SIM118)


385-385: Use key not in dict instead of key not in dict.keys()

Remove .keys()

(SIM118)

🔇 Additional comments (2)
utils/mega_data_setup.py (2)

354-356: LGTM! Function call updated correctly.

The get_ilvl_items function call has been properly updated to handle the new base_required_levels return value.


432-435: LGTM! Proper dictionary comprehension for required levels.

The implementation correctly maps item IDs to their required levels using dictionary comprehension, maintaining consistency with the existing codebase style.

utils/mega_data_setup.py Outdated Show resolved Hide resolved
Copy link
Contributor

@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

🧹 Outside diff range and nitpick comments (1)
AzerothAuctionAssassinData/example_desired_ilvl_list.json (1)

29-30: Document the new required_lvl field.

The introduction of the required_lvl field represents a significant change in the data structure. Consider adding documentation to explain:

  1. The purpose and usage of the required_lvl field
  2. That this field is optional for backward compatibility
  3. The expected value range for required_lvl

Consider adding a comment block at the top of the file:

// Example desired_ilvl_list.json
// Configuration format:
// {
//   "ilvl": number,          // Required: Item level requirement
//   "buyout": number,        // Required: Maximum buyout price
//   "sockets": boolean,      // Required: Socket requirement
//   "speed": boolean,        // Required: Speed requirement
//   "leech": boolean,        // Required: Leech requirement
//   "avoidance": boolean,    // Required: Avoidance requirement
//   "item_ids": number[],    // Required: Array of specific item IDs
//   "required_lvl": number   // Optional: Minimum character level requirement
// }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between dd08e8c and 51ad38c.

📒 Files selected for processing (2)
  • AzerothAuctionAssassinData/example_desired_ilvl_list.json (1 hunks)
  • mega_alerts.py (6 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • mega_alerts.py
🔇 Additional comments (1)
AzerothAuctionAssassinData/example_desired_ilvl_list.json (1)

30-30: Verify the handling of the new required_lvl field.

The addition of the required_lvl field requires careful verification of the implementation.

Let's verify the implementation:

✅ Verification successful

The required_lvl field is properly handled across the codebase

The verification shows that:

  • required_lvl has proper fallback handling in utils/mega_data_setup.py with a default value of 1000
  • The field is correctly validated and processed in mega_alerts.py
  • The implementation includes proper null checks and comparisons before accessing the field
  • The field is properly integrated with the base required levels system
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the handling of required_lvl field

# Check if remove_ilvl_to_list function handles the required_lvl field
echo "Checking remove_ilvl_to_list implementation..."
rg -l "remove_ilvl_to_list" | xargs rg -A 10 "remove_ilvl_to_list"

# Check for any direct dictionary access that might cause KeyError
echo "Checking for potential KeyError issues..."
rg "required_lvl.*\[" --type py

# Look for related test files
echo "Checking test coverage..."
fd "test.*\.py" | xargs rg "required_lvl"

Length of output: 3019

Copy link
Contributor

@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

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 1101864 and 96f355c.

📒 Files selected for processing (3)
  • AzerothAuctionAssassinData/example_desired_ilvl_list.json (1 hunks)
  • mega_alerts.py (6 hunks)
  • utils/mega_data_setup.py (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • AzerothAuctionAssassinData/example_desired_ilvl_list.json
  • mega_alerts.py
🧰 Additional context used
🪛 Ruff
utils/mega_data_setup.py

382-382: Use key not in dict instead of key not in dict.keys()

Remove .keys()

(SIM118)


385-385: Use key not in dict instead of key not in dict.keys()

Remove .keys()

(SIM118)


388-388: Use key not in dict instead of key not in dict.keys()

Remove .keys()

(SIM118)

🔇 Additional comments (5)
utils/mega_data_setup.py (5)

354-356: LGTM: Function call updated to handle required levels.

The get_ilvl_items function call has been correctly updated to receive the new base_required_levels parameter.


361-361: LGTM: Method calls consistently updated.

All calls to __set_desired_ilvl have been consistently updated to pass the new base_required_levels parameter.

Also applies to: 369-369, 373-373


379-381: LGTM: Method signature updated.

The __set_desired_ilvl method signature has been correctly updated to include the base_required_levels parameter.


399-400: LGTM: Example and validation updated.

The example dictionary and validation list have been properly updated to include the new required level fields.

Also applies to: 410-410


427-427: LGTM: Base required levels handling added.

The code correctly handles the base_required_levels dictionary for both scenarios:

  1. When no specific item IDs are provided (using the complete dictionary)
  2. When specific item IDs are provided (filtering the dictionary)

Also applies to: 436-439

utils/mega_data_setup.py Outdated Show resolved Hide resolved
utils/mega_data_setup.py Outdated Show resolved Hide resolved
Copy link
Contributor

@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

🧹 Outside diff range and nitpick comments (1)
AzerothAuctionAssassin.py (1)

Line range hint 8-21: Improve exception handling in Windows binary initialization.

The generic exception handler silently ignores all errors, which could mask important initialization issues. Consider:

  1. Logging the exception for debugging
  2. Only catching specific exceptions you expect
  3. Adding a fallback mechanism
 try:
     if sys.argv[1] == "run-from-windows-bin":
         sys.path.append(f"{sys.argv[2]}")
         sys.path.append(f"{sys.argv[3]}")
         windowsApp_Path = f"{sys.argv[2]}"
     else:
         pass
-except Exception as ex:
+except (IndexError, ValueError) as ex:
+    # Log the error for debugging
+    print(f"Windows binary initialization error: {ex}")
     pass
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 96f355c and 691cbad.

📒 Files selected for processing (2)
  • AzerothAuctionAssassin.py (5 hunks)
  • mega_alerts.py (6 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • mega_alerts.py
🔇 Additional comments (3)
AzerothAuctionAssassin.py (3)

89-90: LGTM: Window dimensions adjusted for new UI elements.

The increased dimensions (650x750) provide adequate space for the new item level input fields.


721-746: LGTM: New player level input fields properly implemented.

The implementation includes:

  • Clear labels and tooltips explaining the purpose
  • Consistent styling with other input fields
  • Proper size constraints

750-775: Verify button layout adjustments.

The button positions have been updated to accommodate the new input fields. However, there might be potential UI overflow issues on smaller screens.

✅ Verification successful

No UI overflow concerns with current button layout.

The code analysis shows that the UI implementation has proper size constraints:

  • Fixed button sizes (150x25 pixels) are consistently applied across the interface
  • Grid layout is used which handles spacing and alignment automatically
  • The list widget is positioned with adequate space (spans 11 rows and 2 columns)
  • Input fields have consistent fixed sizes (120x15/25 pixels)

The layout implementation follows Qt best practices and maintains consistent spacing, making it unlikely to have overflow issues on standard desktop resolutions.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for minimum window size constraints
# Look for any window size constraints or responsive layout handling
rg -A 2 "setMinimumSize|minimumSize|sizeHint"

Length of output: 47


Script:

#!/bin/bash
# Search for window/layout size related settings in the UI code
rg -A 5 "QMainWindow|setGeometry|resize|setFixedSize|setLayout"

# Search for any responsive layout adjustments
rg -A 3 "setSizePolicy|setStretch|setSpacing|setContentsMargins"

Length of output: 11906

Copy link
Contributor

@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

🧹 Outside diff range and nitpick comments (3)
AzerothAuctionAssassin.py (3)

680-681: Consider using dynamic sizing instead of fixed sizes for UI elements

Setting fixed sizes for labels and input fields may cause layout issues on different screens or resolutions. Consider using layouts that adapt to the content and window size.


Line range hint 1378-1385: Correct the comment to match the validation logic

The comment mentions checking if all items are between 100k and 500k, but the code validates item IDs between 1 and 500,000. Update the comment to reflect the correct range.

Apply this diff to correct the comment:

-        # Check if all items are between 100k and 500k
+        # Check if all item IDs are between 1 and 500k

Line range hint 1503-1544: Potential issue when removing ilvl entries without level requirements

In remove_ilvl_to_list, existing entries without required_min_lvl and required_max_lvl may not match the constructed ilvl_dict_data, preventing their removal.

To ensure backward compatibility and correct removal functionality, consider normalizing existing entries by adding default values before comparison.

Apply this diff to set default values for missing keys:

 def remove_ilvl_to_list(self):
     if len(self.ilvl_input.text()) == 0:
         QMessageBox.critical(
             self,
             "Ilvl Removal Issue",
             "Please double click an ilvl json to remove it!",
         )
         return
     if self.ilvl_item_input.text() == "":
         item_ids_list = []
     else:
         item_ids_list = list(
             map(int, self.ilvl_item_input.text().replace(" ", "").split(","))
         )

+    # Normalize existing entries by adding default values
+    for entry in self.ilvl_list:
+        entry.setdefault("required_min_lvl", 1)
+        entry.setdefault("required_max_lvl", 999)

     required_min_lvl = self.ilvl_min_required_lvl_input.text()
     if required_min_lvl == "":
         required_min_lvl = 1
     else:
         required_min_lvl = int(required_min_lvl)
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 691cbad and 8264c2b.

📒 Files selected for processing (1)
  • AzerothAuctionAssassin.py (11 hunks)
🔇 Additional comments (3)
AzerothAuctionAssassin.py (3)

89-90: Verify UI scaling with updated window dimensions

The application window dimensions have been increased to width 650 and height 750. Ensure that all UI elements adjust appropriately to the new size without layout issues on different screen resolutions.


721-746: Added input fields for Min and Max Player Level

The introduction of Min Player Level and Max Player Level fields enhances the functionality for item level filtering. Ensure that tooltips and labels accurately describe their purpose.


1283-1308: Ensured backward compatibility when loading item level data

Adding default values for missing keys ('item_ids', 'required_min_lvl', 'required_max_lvl') maintains compatibility with existing desired_ilvl_list.json files that may not include these keys.

Copy link
Contributor

@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

🧹 Outside diff range and nitpick comments (4)
utils/mega_data_setup.py (2)

379-384: Improve error handling for required level validation.

The method now uses .get() for safe dictionary access with default values, which is good. However, consider adding validation to ensure required_min_lvl is not greater than required_max_lvl.

 def __set_desired_ilvl(
     self, ilvl_info, item_names, base_ilvls, base_required_levels
 ):
     ilvl_info["item_ids"] = ilvl_info.get("item_ids", [])
     ilvl_info["required_min_lvl"] = ilvl_info.get("required_min_lvl", 1)
     ilvl_info["required_max_lvl"] = ilvl_info.get("required_max_lvl", 1000)
+    if ilvl_info["required_min_lvl"] > ilvl_info["required_max_lvl"]:
+        raise ValueError(f"required_min_lvl ({ilvl_info['required_min_lvl']}) cannot be greater than required_max_lvl ({ilvl_info['required_max_lvl']})")

422-422: Consider documenting the required level structure.

Add docstring documentation to explain the structure and purpose of the base_required_levels dictionary.

 def __set_desired_ilvl(
     self, ilvl_info, item_names, base_ilvls, base_required_levels
 ):
+    """
+    Set up desired item level information with required level constraints.
+    
+    Args:
+        ilvl_info (dict): Item level configuration
+        item_names (dict): Mapping of item IDs to names
+        base_ilvls (dict): Mapping of item IDs to base item levels
+        base_required_levels (dict): Mapping of item IDs to required character levels
+    """

Also applies to: 431-434

AzerothAuctionAssassin.py (2)

Line range hint 8-21: Improve exception handling for Windows C# binary initialization.

The current implementation silently ignores all exceptions, which could hide important initialization errors. Consider:

  1. Logging the exception for debugging
  2. Only catching specific exceptions that are expected
-try:
-    if sys.argv[1] == "run-from-windows-bin":
-        sys.path.append(f"{sys.argv[2]}")
-        sys.path.append(f"{sys.argv[3]}")
-
-        windowsApp_Path = f"{sys.argv[2]}"
-    else:
-        pass
-except Exception as ex:
-    pass
+try:
+    if sys.argv[1] == "run-from-windows-bin":
+        sys.path.append(f"{sys.argv[2]}")
+        sys.path.append(f"{sys.argv[3]}")
+        windowsApp_Path = f"{sys.argv[2]}"
+except IndexError:
+    # Expected when not running from Windows binary
+    pass
+except Exception as ex:
+    print(f"Warning: Failed to initialize Windows binary paths: {ex}")

727-730: Enhance tooltip clarity for minimum player level.

The tooltip could be more specific about the relationship between required levels and item usage.

-            "Set the minimum required character level to use gear.\n"
-            + "Ex: required level 80 for TWW items, 70 for DF items, etc."
+            "Set the minimum required character level to equip/use the item.\n"
+            + "Examples:\n"
+            + "- Level 80 for Time-Walking items\n"
+            + "- Level 70 for Dragonflight items"
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between a31765c and 05f361f.

📒 Files selected for processing (2)
  • AzerothAuctionAssassin.py (17 hunks)
  • utils/mega_data_setup.py (5 hunks)
🔇 Additional comments (3)
utils/mega_data_setup.py (3)

354-356: LGTM: Function call updated to handle required levels.

The function call to get_ilvl_items has been properly updated to handle the new base_required_levels return value.


394-395: LGTM: Example and validation updated for required level fields.

The example dictionary and validation variables have been correctly updated to include the new required level fields.

Also applies to: 405-405


422-422: Verify the base_required_levels dictionary structure.

The code assumes that base_required_levels is a dictionary with item IDs as keys. Let's verify this assumption across the codebase.

Also applies to: 431-434

✅ Verification successful

The base_required_levels dictionary structure is correctly implemented.

Looking at the implementation in utils/api_requests.py, base_required_levels is indeed a dictionary with item IDs as keys and required levels as values. The structure is explicitly defined in the get_ilvl_items function:

base_required_levels = {
    int(itemID): item_info["required_level"]
    for itemID, item_info in results.items()
}

All usages across the codebase consistently treat it as a dictionary with integer item IDs as keys.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check the structure of base_required_levels in get_ilvl_items implementations
# Test: Search for get_ilvl_items function definitions to verify return value structure
ast-grep --pattern 'def get_ilvl_items($$$) {
  $$$
  return $$$base_required_levels
}'

Length of output: 89


Script:

#!/bin/bash
# Let's search for the definition and usage of base_required_levels
rg -A 5 "base_required_levels" --type python

Length of output: 75


Script:

#!/bin/bash
# Let's also check the context where this variable is created/modified
ast-grep --pattern 'base_required_levels = $_'

Length of output: 285


Script:

#!/bin/bash
# Search for get_ilvl_items function with more context
rg -A 20 "def get_ilvl_items" --type python

Length of output: 76


Script:

#!/bin/bash
# Let's try without file type specification
rg -A 20 "def get_ilvl_items"

Length of output: 1266


Script:

#!/bin/bash
# Let's also check where base_required_levels is used
rg "base_required_levels"

Length of output: 1031


Script:

#!/bin/bash
# Let's see the full content of api_requests.py where we found the dictionary creation
cat utils/api_requests.py

Length of output: 5947

AzerothAuctionAssassin.py Show resolved Hide resolved
AzerothAuctionAssassin.py Outdated Show resolved Hide resolved
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
10.6% Duplication on New Code (required ≤ 3%)

See analysis details on SonarCloud

Copy link
Contributor

@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: 3

🧹 Outside diff range and nitpick comments (1)
AzerothAuctionAssassin.py (1)

727-730: Consider enhancing the tooltip text for clarity.

The tooltip could be more specific about the use cases. For example:

-            "Set the minimum required character level to use gear.\n"
-            + "Ex: required level 80 for TWW items, 70 for DF items, etc."
+            "Set the minimum required character level to use gear.\n"
+            + "Examples:\n"
+            + "- Level 80 for Timewalking (TWW) items\n"
+            + "- Level 70 for Dragonflight (DF) items\n"
+            + "This helps filter items based on character level requirements."
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 05f361f and 029aee7.

📒 Files selected for processing (1)
  • AzerothAuctionAssassin.py (17 hunks)
🔇 Additional comments (2)
AzerothAuctionAssassin.py (2)

Line range hint 8-90: LGTM: Version bump and window size adjustments.

The version update to "1.2.5" and window size increase (650x750) are appropriate to accommodate the new player level requirement fields.


1287-1298: Verify handling of new fields in dependent code.

The addition of required_min_lvl and required_max_lvl fields needs verification in code that processes the item level data.

✅ Verification successful

New fields are properly handled across the codebase

The verification shows comprehensive handling of the new level requirement fields:

  • utils/mega_data_setup.py properly initializes the fields with defaults
  • AzerothAuctionAssassin.py has complete UI integration and validation logic
  • mega_alerts.py correctly uses the fields for filtering alerts
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usage of ilvl_list to ensure compatibility with new fields
rg -l "ilvl_list" | xargs rg "required_(min|max)_lvl"

# Search for potential data processing of item level data
ast-grep --pattern 'def process_$_($_, ilvl_list, $_) {
  $$$
}'

Length of output: 4438

Comment on lines +1411 to +1457
required_min_lvl = self.ilvl_min_required_lvl_input.text()
if required_min_lvl == "":
required_min_lvl = 1
else:
# Validate min level
try:
required_min_lvl = int(required_min_lvl)
if not 1 <= required_min_lvl <= 999:
QMessageBox.critical(
self,
"Invalid Min Level",
"Min level must be between 1 and 999.",
)
return False
except ValueError:
QMessageBox.critical(
self, "Invalid Input", "Min level should be a number."
)
return False

required_max_lvl = self.ilvl_max_required_lvl_input.text()
if required_max_lvl == "":
required_max_lvl = 999
else:
# Validate max level
try:
required_max_lvl = int(required_max_lvl)
if not 1 <= required_max_lvl <= 999:
QMessageBox.critical(
self,
"Invalid Max Level",
"Max level must be between 1 and 999.",
)
return False
elif required_max_lvl <= required_min_lvl:
QMessageBox.critical(
self,
"Invalid Level Range",
"Max level must be greater than Min level.",
)
return False
except ValueError:
QMessageBox.critical(
self, "Invalid Input", "Max level should be a number."
)
return False

Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Extract validation logic into reusable methods.

The level validation logic is repeated in multiple places. Consider extracting it into a dedicated method.

+    def validate_player_level(self, level, level_type="Level"):
+        """Validate a player level value.
+        
+        Args:
+            level: The level value to validate
+            level_type: Description of the level type for error messages
+            
+        Returns:
+            tuple: (is_valid, error_message)
+        """
+        try:
+            level_int = int(level)
+            if not 1 <= level_int <= 999:
+                return False, f"{level_type} must be between 1 and 999."
+            return True, None
+        except ValueError:
+            return False, f"{level_type} should be a number."

     def add_ilvl_to_list(self):
         # ... existing code ...
-        try:
-            required_min_lvl = int(required_min_lvl)
-            if not 1 <= required_min_lvl <= 999:
-                QMessageBox.critical(
-                    self,
-                    "Invalid Min Level",
-                    "Min level must be between 1 and 999.",
-                )
-                return False
-        except ValueError:
-            QMessageBox.critical(
-                self, "Invalid Input", "Min level should be a number."
-            )
-            return False
+        is_valid, error_message = self.validate_player_level(required_min_lvl, "Min level")
+        if not is_valid:
+            QMessageBox.critical(self, "Invalid Input", error_message)
+            return False

Committable suggestion was skipped due to low confidence.

Comment on lines +1287 to +1314
# Load item level list from file
with open(self.path_to_desired_ilvl_list) as file:
self.ilvl_list = json.load(file)
# Process each item level data dictionary
for ilvl_dict_data in self.ilvl_list:
# Add missing 'item_ids' key if not present
if "item_ids" not in ilvl_dict_data:
ilvl_dict_data["item_ids"] = []
string_with_data = f"Item ID: {','.join(map(str, ilvl_dict_data['item_ids']))}; Price: {ilvl_dict_data['buyout']}; ILvl: {ilvl_dict_data['ilvl']}; Sockets: {ilvl_dict_data['sockets']}; Speed: {ilvl_dict_data['speed']}; Leech: {ilvl_dict_data['leech']}; Avoidance: {ilvl_dict_data['avoidance']}"
if "required_min_lvl" not in ilvl_dict_data:
ilvl_dict_data["required_min_lvl"] = 1
if "required_max_lvl" not in ilvl_dict_data:
ilvl_dict_data["required_max_lvl"] = 999
# Create a formatted string with the item data
item_ids = ",".join(map(str, ilvl_dict_data["item_ids"]))
display_string = (
f"Item ID: {item_ids}; "
f"Price: {ilvl_dict_data['buyout']}; "
f"ILvl: {ilvl_dict_data['ilvl']}; "
f"Sockets: {ilvl_dict_data['sockets']}; "
f"Speed: {ilvl_dict_data['speed']}; "
f"Leech: {ilvl_dict_data['leech']}; "
f"Avoidance: {ilvl_dict_data['avoidance']}; "
f"MinLevel: {ilvl_dict_data['required_min_lvl']}; "
f"MaxLevel: {ilvl_dict_data['required_max_lvl']}"
)
# Insert the string into the display list
self.ilvl_list_display.insertItem(
self.ilvl_list_display.count(), string_with_data
self.ilvl_list_display.count(), display_string
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add error handling for file operations.

The file loading operations should be wrapped in a try-catch block to handle potential file system errors gracefully.

 if os.path.exists(self.path_to_desired_ilvl_list):
-    # Load item level list from file
-    with open(self.path_to_desired_ilvl_list) as file:
-        self.ilvl_list = json.load(file)
+    try:
+        # Load item level list from file
+        with open(self.path_to_desired_ilvl_list) as file:
+            self.ilvl_list = json.load(file)
+    except (IOError, json.JSONDecodeError) as e:
+        QMessageBox.critical(
+            self,
+            "File Error",
+            f"Error loading item level list: {str(e)}"
+        )
+        self.ilvl_list = []

Committable suggestion was skipped due to low confidence.

Comment on lines +1475 to +1487
# Format the display string
item_ids = ",".join(map(str, ilvl_dict_data["item_ids"]))
display_string = (
f"Item ID: {item_ids}; "
f"Price: {ilvl_dict_data['buyout']}; "
f"ILvl: {ilvl_dict_data['ilvl']}; "
f"Sockets: {ilvl_dict_data['sockets']}; "
f"Speed: {ilvl_dict_data['speed']}; "
f"Leech: {ilvl_dict_data['leech']}; "
f"Avoidance: {ilvl_dict_data['avoidance']}; "
f"MinLevel: {ilvl_dict_data['required_min_lvl']}; "
f"MaxLevel: {ilvl_dict_data['required_max_lvl']}"
)
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Extract string formatting into a dedicated method.

The display string formatting is repeated in multiple places. Consider extracting it into a helper method.

+    def format_ilvl_display_string(self, ilvl_dict_data):
+        """Format item level data into a display string."""
+        return (
+            f"Item ID: {','.join(map(str, ilvl_dict_data['item_ids']))}; "
+            f"Price: {ilvl_dict_data['buyout']}; "
+            f"ILvl: {ilvl_dict_data['ilvl']}; "
+            f"Sockets: {ilvl_dict_data['sockets']}; "
+            f"Speed: {ilvl_dict_data['speed']}; "
+            f"Leech: {ilvl_dict_data['leech']}; "
+            f"Avoidance: {ilvl_dict_data['avoidance']}; "
+            f"MinLevel: {ilvl_dict_data['required_min_lvl']}; "
+            f"MaxLevel: {ilvl_dict_data['required_max_lvl']}"
+        )

     def add_ilvl_to_list(self):
         # ... existing code ...
-        display_string = (
-            f"Item ID: {item_ids}; "
-            f"Price: {ilvl_dict_data['buyout']}; "
-            # ... rest of the formatting
-        )
+        display_string = self.format_ilvl_display_string(ilvl_dict_data)

Committable suggestion was skipped due to low confidence.

@cohenaj194 cohenaj194 merged commit 0b347d4 into main Nov 7, 2024
2 of 3 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Nov 7, 2024
This was referenced Nov 15, 2024
@cohenaj194 cohenaj194 mentioned this pull request Nov 22, 2024
@coderabbitai coderabbitai bot mentioned this pull request Nov 22, 2024
This was referenced Dec 6, 2024
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.

Match exact ilvl or character level limits
1 participant