You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Discord机器人!lek命令语法错误及Embed拆分需求求助

问题排查与解决方案

1. "invalid syntax (, line 1)" 语法错误

原因:原send_embed_segments函数中使用str(embed)将Embed对象转为字符串,再用eval解析分段后的字符串,这是错误逻辑。str(discord.Embed)生成的是人类可读的描述文本,并非可解析的Python代码,因此eval会抛出语法错误。

修复方案:放弃字符串转换和eval操作,直接提取Embed的结构化数据(标题、颜色、字段等),拆分后生成新的Embed对象发送。

2. "embed size exceeds maximum size of 6000" 内容过长错误

原因:Discord Embed的总字符限制为6000(包含标题、描述、所有字段的名称和值),药品信息的Embed内容超出了该限制。

修复方案:将原Embed拆分为多个Embed,每个Embed的总字符数控制在6000以内。


完整修正代码

替换原有的send_embed_segments函数,并修复get_tweets中的字符串语法问题:

import discord
from discord.ext import commands
import requests
import json
import tweepy
import os

# 获取脚本所在目录
current_directory = os.path.dirname(os.path.realpath(__file__))

# Twitter API密钥
twitter_consumer_key = "00000"
twitter_consumer_secret = "000000000000"
twitter_access_token = "00000000000000000"
twitter_access_token_secret = "000000000000000"

# News API密钥
news_api_key = "98166982a7e4455da7f8f65b95ed50a7"

# 专业医疗信息来源列表
medical_sources = [
    'medical-news-today.com',
    'sciencedaily.com',
    'medscape.com',
    'bmj.com',
    'nejm.org',
    'fda.gov',
    'cdc.gov'
]

# 配置Twitter API
auth = tweepy.OAuthHandler(twitter_consumer_key, twitter_consumer_secret)
auth.set_access_token(twitter_access_token, twitter_access_token_secret)
twitter_api = tweepy.API(auth)

intents = discord.Intents.all()
bot = commands.Bot(command_prefix='!', intents=intents)

# 机器人允许执行命令的频道ID
wybrany_kanal_id = 1172578358589145119

async def send_embed_segments(ctx, original_embed):
    MAX_EMBED_SIZE = 6000
    # 提取原Embed的基础信息
    base_info = {
        "title": original_embed.title,
        "color": original_embed.color.value,
        "description": original_embed.description or ""
    }
    
    # 计算初始字符占用(标题+描述)
    current_total = len(base_info["title"]) + len(base_info["description"])
    current_fields = []
    
    for field in original_embed.fields:
        # 计算当前字段的字符长度
        field_length = len(field.name) + len(field.value)
        
        # 如果添加当前字段会超出限制,先发送现有内容
        if current_total + field_length > MAX_EMBED_SIZE:
            new_embed = discord.Embed(**base_info)
            for f in current_fields:
                new_embed.add_field(name=f["name"], value=f["value"], inline=f["inline"])
            await ctx.send(embed=new_embed)
            
            # 重置计数器和字段列表
            current_total = len(base_info["title"]) + len(base_info["description"])
            current_fields = []
        
        # 将字段加入当前列表
        current_fields.append({
            "name": field.name,
            "value": field.value,
            "inline": field.inline
        })
        current_total += field_length
    
    # 发送剩余的字段
    if current_fields:
        new_embed = discord.Embed(**base_info)
        for f in current_fields:
            new_embed.add_field(name=f["name"], value=f["value"], inline=f["inline"])
        await ctx.send(embed=new_embed)

@bot.command()
async def lek(ctx, *, nazwa_leku):
    try:
        if ctx.channel.id != wybrany_kanal_id:
            await ctx.send('Ta komenda może być używana tylko na określonym kanale.')
            return

        # 生成JSON文件路径列表
        lista_plikow = [
            os.path.join(current_directory, f'drug-label-000{i}-of-0011.json') for i in range(1, 12)
        ]

        pierwszy_wynik = None

        for nazwa_pliku in lista_plikow:
            with open(nazwa_pliku, 'r', encoding='utf-8') as file:
                data = json.load(file)

            found_results = [result for result in data.get('results', []) if nazwa_leku.lower() in result.get('openfda', {}).get('brand_name', [''])[0].lower()]

            if found_results:
                pierwszy_wynik = found_results[0]
                break

        if pierwszy_wynik:
            nazwa_handlowa = pierwszy_wynik.get('openfda', {}).get('brand_name', ['Brak informacji'])[0]
            opis = pierwszy_wynik.get('purpose', ['Brak informacji'])[0]

            producent = pierwszy_wynik.get('openfda', {}).get('manufacturer_name', ['Brak informacji'])[0]
            nazwa_generyczna = pierwszy_wynik.get('openfda', {}).get('generic_name', ['Brak informacji'])[0]
            ndc = pierwszy_wynik.get('openfda', {}).get('product_ndc', ['Brak informacji'])[0]
            typ_produktu = pierwszy_wynik.get('openfda', {}).get('product_type', ['Brak informacji'])[0]
            droga_podawania = pierwszy_wynik.get('openfda', {}).get('route', ['Brak informacji'])[0]
            substancja = pierwszy_wynik.get('openfda', {}).get('substance_name', ['Brak informacji'])[0]
            cel = pierwszy_wynik.get('purpose', ['Brak informacji'])[0]
            wskazania_i_uzytkowanie = pierwszy_wynik.get('indications_and_usage', ['Brak informacji'])[0]
            ostrzezenia = pierwszy_wynik.get('warnings', ['Brak informacji'])[0]
            zachowaj_poza_zasiegiem_dzieci = pierwszy_wynik.get('keep_out_of_reach_of_children', ['Brak informacji'])[0]
            dawkowanie_i_podawanie = pierwszy_wynik.get('dosage_and_administration', ['Brak informacji'])[0]
            przechowywanie_i_obsluga = pierwszy_wynik.get('storage_and_handling', ['Brak informacji'])[0]

            embed = discord.Embed(title=f'Informacje o leku: {nazwa_leku}', color=0x00ff00)
            embed.add_field(name='Nazwa handlowa', value=nazwa_handlowa, inline=False)
            embed.add_field(name='Opis', value=opis, inline=False)

            embed.add_field(name='Producent', value=producent, inline=False)
            embed.add_field(name='Nazwa generyczna', value=nazwa_generyczna, inline=False)
            embed.add_field(name='Numer NDC', value=ndc, inline=False)
            embed.add_field(name='Typ produktu', value=typ_produktu, inline=False)
            embed.add_field(name='Droga podawania', value=droga_podawania, inline=False)
            embed.add_field(name='Substancja', value=substancja, inline=False)
            embed.add_field(name='Cel', value=cel, inline=False)
            embed.add_field(name='Wskazania i użycie', value=wskazania_i_uzytkowanie, inline=False)
            embed.add_field(name='Ostrzeżenia', value=ostrzezenia, inline=False)
            embed.add_field(name='Zachowaj poza zasięgiem dzieci', value=zachowaj_poza_zasiegiem_dzieci, inline=False)
            embed.add_field(name='Dawkowanie i podawanie', value=dawkowanie_i_podawanie, inline=False)
            embed.add_field(name='Przechowywanie i obsługa', value=przechowywanie_i_obsluga, inline=False)

            await send_embed_segments(ctx, embed)
        else:
            await ctx.send(f'Nie znaleziono informacji o leku o nazwie "{nazwa_leku}".')

    except Exception as e:
        print(e)
        await ctx.send('Wystąpił błąd podczas wczytywania informacji o leku z pliku.')

@bot.command()
async def aktualnosci(ctx):
    try:
        sources = ','.join(medical_sources)
        url = f'https://newsapi.org/v2/top-headlines?sources={sources}&apiKey={news_api_key}'
        response = requests.get(url)
        news_data = response.json()

        if 'articles' in news_data:
            articles = news_data['articles']
            for article in articles[:5]:
                title = article.get('title', 'Brak tytułu')
                description = article.get('description', 'Brak opisu')
                url = article.get('url', '#')

                embed = discord.Embed(title=title, description=description, url=url, color=0x0000ff)
                await send_embed_segments(ctx, embed)

        else:
            await ctx.send('Nie udało się pobrać aktualności.')

    except Exception as e:
        print(e)
        await ctx.send('Wystąpił błąd podczas pobierania aktualności.')

@bot.command()
async def get_tweets(ctx, username, count=5):
    try:
        tweets = twitter_api.user_timeline(screen_name=username, count=count, tweet_mode="extended")

        for tweet in tweets:
            tweet_text = tweet.full_text
            tweet_url = f"https://twitter.com/{username}/status/{tweet.id}"

            if username.lower() == 'cdcgov':
                channel_id = 1172578344911519774
            elif username.lower() == 'fda':
                channel_id = 1172578358589145119
            else:
                channel_id = None

            if channel_id:
                channel = bot.get_channel(channel_id)
                # 修复字符串换行的语法错误
                await channel.send(f'Tweet od @{username}:\n{tweet_text}\nWięcej na: {tweet_url}')

    except Exception as e:
        print(f'Wystąpił błąd podczas pobierania tweetów: {e}')
        await ctx.send(f'Wystąpił błąd podczas pobierania tweetów: {e}')

@bot.event
async def on_ready():
    print(f'Zalogowano jako {bot.user.name} ({bot.user.id})')

@bot.event
async def on_command_error(ctx, error):
    if isinstance(error, commands.CommandInvokeError):
        print(f'Błąd podczas przetwarzania komendy: {error.original}')
        await ctx.send('Wystąpił błąd podczas przetwarzania komendy.')

    if isinstance(error, commands.CommandNotFound):
        await ctx.send('Nieprawidłowa komenda.')

bot.run('...')

额外优化说明

  • 使用列表推导式简化JSON文件路径的生成,减少重复代码。
  • 修复get_tweets中字符串换行的语法错误,用\n替代直接换行。
  • 新的send_embed_segments函数会自动拆分字段,确保每个Embed的总字符数不超过6000,同时保留原Embed的标题、颜色和描述。

内容的提问来源于stack exchange,提问作者Darklord

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 20:58:12