Python字典指定值获取及Discord机器人代码报错解决
Let's break down and fix your issues step by step:
First, the TypeError: 'str' object is not callable
This error comes from your debug code where you tried to call data()—data here is the raw text string from the API response, not a function. You need to parse the JSON first, then iterate over the items in the parsed dictionary.
Key Fixes & Improvements
Here's the corrected approach to implement your desired functionality, along with fixes for other issues in your code:
- Fix URL Syntax: Replace
&with&(HTML entities don't belong in URLs). - Cache API Data: Load all items once when the cog initializes to avoid repeated API calls.
- Case-Insensitive Search: Match the user's input to item names regardless of capitalization.
- Avoid Built-in Variable Names: Don't use
dictor reusedata(this causes confusion and bugs). - Cleaner JSON Parsing: Use
response.json()instead ofjson.loads(response.text).
Corrected Code
import discord from discord.ext import commands import requests import json class Test: def __init__(self, bot): self.bot = bot self.items_cache = None # Cache to store all items from API self.load_items_cache() # Load cache when the cog starts def load_items_cache(self): """Fetch and store all items from the Torn API""" try: with open(r'.\\cogs\config.json','r') as json_file: config_data = json.load(json_file) key = config_data["key"] # Correct URL with & instead of & url = f"https://api.torn.com/torn/?selections=items&key={key}" response = requests.get(url) response.raise_for_status() # Raise error if API request fails self.items_cache = response.json()['items'] print("Successfully loaded items cache from API") except Exception as e: print(f"Failed to load items cache: {str(e)}") self.items_cache = {} @commands.command() @commands.has_any_role("Admin","Moderator") async def it(self, ctx, *, name): # Check if cache loaded properly if not self.items_cache: await ctx.send("Oops! Failed to load item data. Please try again later.") return target_name = name.lower() matched_item = None # Search through cached items for a matching name for item_id, item_details in self.items_cache.items(): if item_details['name'].lower() == target_name: matched_item = item_details break if not matched_item: await ctx.send("Item not found in the Torn database!") return # Build the Discord embed embed = discord.Embed( title=matched_item['name'], description=matched_item['description'], colour=discord.Color.dark_blue() ) embed.set_footer(text=ctx.author.name, icon_url=ctx.author.avatar_url) embed.add_field(name="Type", value=matched_item['type'], inline=False) embed.add_field(name="Market Value", value=f"${matched_item['market_value']}", inline=True) embed.add_field(name="Torn Buy Price", value=f"${matched_item['buy_price']}", inline=True) embed.add_field(name="Torn Sell Price", value=f"${matched_item['sell_price']}", inline=True) await ctx.send(embed=embed) # If you need to initialize config outside the cog (for other uses) with open(r'.\\cogs\config.json', 'r') as json_file: config_data = json.load(json_file) api_key = config_data["key"]
Explanation of Changes
- Caching: The
load_items_cachemethod fetches all items once when the cog starts, so we don't hit the API every time the command is run (faster and more efficient). - Search Logic: We iterate over
self.items_cache.items()to get both the item ID and its details, then compare the lowercase name to the user's lowercase input for case-insensitive matching. - Error Handling: Added checks for failed API requests and missing cache data to give clear feedback to users.
- Fixed URLs: Replaced
&with&to ensure the API request is properly formatted.
If You Want to Check Your Database First
If you still want to query your local database before checking the API, add this block right after the cache check:
# Check local database first db_item_id = await self.bot.pg_con.fetchval( "SELECT item_id FROM item WHERE LOWER(name) = $1", target_name ) if db_item_id: # Fetch details from cache using the DB's item ID matched_item = self.items_cache.get(str(db_item_id)) if matched_item: # Proceed to build embed pass else: await ctx.send("Item exists in local DB but not found in API data!") return
内容的提问来源于stack exchange,提问作者insanedood
相关产品推荐
相关产品推荐

