当前位置: 首页 > 知识库问答 >
问题:

如何发送不一致的消息。从事件循环外部(即从python电报bot线程)复制?

万坚壁
2023-03-14

我想使用python telegram bot和discord库制作一个机器人,在discord和telegram之间进行通信。py(版本1.0.0)。然而,问题在于这种不和谐。py使用异步函数和python电报bot线程。使用下面的代码,在discord中发布消息时一切正常(bot将消息正确地发送到telegram),但是另一种方法不起作用(bot从telegram获取消息并将其发送到discord)。我以前在尝试运行discords频道时遇到语法/运行时错误问题。在同步函数中发送函数(因此,要么仅返回生成器对象,要么抱怨无法在同步函数中使用wait)。然而,与此同时,python telegram bot的MessageHandler需要一个同步函数,因此当给他一个异步函数时,python抱怨异步函数从未调用“wait”。我现在尝试使用asgiref库中的async_to_sync方法从MessageHandler运行我的asyncbroadcastMsg,但是代码仍然不会将消息发送到discord!它似乎正确地调用了函数,但只有在第print行(“我到达这里”)之前才能调用。没有显示错误,也没有不一致的消息弹出。我想这与我必须在discord中将函数注册为任务这一事实有关。然而,py事件循环只有在botDiscord之前发生时才起作用。run(TOKENDISCORD)已经执行,当然之前必须执行。所以,把我的问题归结为一个问题:我如何才能与不和谐互动。来自另一个线程(来自电报MessageHandler)的py事件循环。或者,如果这是不可能的:我如何才能发送不和谐的消息。不要陷入不和谐。py事件循环?

谢谢你的帮忙

import asyncio
from asgiref.sync import async_to_sync
from telegram import Message as TMessage
from telegram.ext import (Updater,Filters,MessageHandler)
from discord.ext import commands
import discord

TChannelID = 'someTelegramChannelID'
DChannel = 'someDiscordChannelObject'

#%% define functions / commands
prefix = "?"
botDiscord = commands.Bot(command_prefix=prefix)
discordChannels = {}


async def broadcastMsg(medium,channel,message):
    ''' 
    Function to broadcast a message to all linked channels.
    '''
    if isinstance(message,TMessage):
        fromMedium = 'Telegram'
        author = message.from_user.username
        channel = message.chat.title
        content = message.text
    elif isinstance(message,discord.Message):
        fromMedium = 'Discord'
        author = message.author
        channel = message.channel.name
        content = message.content
    # check where message comes from        
    textToSend = '%s wrote on %s %s:\n%s'%(author,fromMedium,channel,content)
    # go through channels and send the message
    if 'telegram' in medium:
        # transform channel to telegram chatID and send
        updaterTelegram.bot.send_message(channel,textToSend)

    elif 'discord' in medium:
        print('I get to here')
        await channel.send(textToSend)

    print("I do not get there")


@botDiscord.event
async def on_message(message):
    await broadcastMsg('telegram',TChannelID,message)

def on_TMessage(bot,update):
    # check if this chat is already known, else save it
    # get channels to send to and send message
    async_to_sync(broadcastMsg)('discord',DChannel,update.message)


#%% initialize telegram and discord bot and run them
messageHandler = MessageHandler(Filters.text, on_TMessage)
updaterTelegram = Updater(token = TOKENTELEGRAM, request_kwargs={'read_timeout': 10, 'connect_timeout': 10})
updaterTelegram.dispatcher.add_handler(messageHandler)
updaterTelegram.start_polling()
botDiscord.run(TOKENDISCORD)  

共有2个答案

长孙波鸿
2023-03-14

您可以尝试将它们拆分为两个单独的*。py文件。

t2d.py#电报到迪斯科尔

import subprocess
from telethon import TelegramClient, events, sync

api_id = '...'
api_hash = '...'

with TelegramClient('name', api_id, api_hash) as client:     
    @client.on(events.NewMessage()) #inside .NewMessage() you can put specific channel like: chats="test_channel"
    async def handler(event):        
        print('test_channel raw text: ', event.raw_text) #this row is not necessary

        msg = event.raw_text

        subprocess.call(["python", "s2d.py", msg])

    client.run_until_disconnected()

s2d。py#发送到discord

import discord, sys

my_secret = '...'

clientdiscord = discord.Client()

@clientdiscord.event
async def on_ready():
    #print('We have logged in as {0.user}'.format(clientdiscord)) #this row is not necessary

    channel = clientdiscord.get_channel(123456789) # num of channel where you want to write message

    msg = sys.argv[1] #grab message
    
    msg = 's2d: ' + msg #only for test, you can delete this row 
    
    await channel.send(msg)

    quit() # very important quit this bot 

    
clientdiscord.run(my_secret)

它会稍微慢一点(子进程会造成延迟),但很容易解决

储毅
2023-03-14

我怎样才能发送不和谐的信息。不要陷入不和谐。py事件循环?

要从事件循环线程外部安全地调度协同路由,请使用asyncio。运行线程安全的协同程序

_loop = asyncio.get_event_loop()

def on_TMessage(bot, update):
    asyncio.run_coroutine_threadsafe(
        broadcastMsg('discord', DChannel, update.message), _loop)
 类似资料:
  • 我正在Python3.6中使用Discord.py库开发一个Discord bot,在试图从创建的线程向特定通道发送消息时遇到了问题。 基本上,我有一些线程监视网站,我想调用一个函数(我正在传递给线程),当我注意到网站上的变化时,它会向一个特定的通道发送消息。 我最初尝试直接调用,而不使用Async/await,但它根本不起作用,所以我编写了Async/await函数发送消息(测试了它,它起作用了

  • 嗨,我正在尝试建立一个网站登录系统,用户可以使用电报登录。我希望实现此工作流: < li >用户选择通过电报登录/注册。 < li >用户输入他们的用户名(@ExampleJoe)。 < li >通过我的电报机器人(@ExampleBot)向他们发送6位验证码。 < li >用户将收到的6位数字代码输入到我的网站,并被允许进入。 我在步骤 2-3 中遇到了问题,我的机器人可以仅使用其用户名向他们发

  • 我对discord机器人和python有点陌生,所以我在理解哪里出了问题时遇到了一些困难。基本上我想让我的机器人锁定一条消息。我找到了一个python代码的文档,上面说要使用pin_message(),所以我有: 但我得到以下错误AttributeError:“TextChannel”对象没有属性“pin_message” 当我查看Discord文档时,它会显示PUT/channels/{chan

  • 我是如何临时修复它的:考虑我已经实现了下面的方法 它向websocket会话发送一个TextMessage。我无法使整个方法同步,因为多个线程可以为不同的websocketSessions和消息调用它。我也不能将会话放在同步块中(尝试了但没有工作) 虽然,我这样解决了我的问题

  • 我不知道如何使用电报机器人诱导(触发)本地服务器向通道发送消息。 例如,从用户注册并连接电报的网站向用户发送通知。我们假设用户已经开始与bot对话,并准备好接收来自bot的消息。 我有一个单独的服务器,可以使用bot向服务器发送请求,但我不明白如何在这个电报机器人服务器上接收和处理请求。 我正在使用go电报-机器人-api库,此时服务器使用长轮询方法而不是webhooks。所以它通过更新通道接收一

  • 我试图使用Netty 4.0.8创建一个相当简单的WebSocket服务器。我有基本的握手设置和工作。但是从一个单独的线程发送的消息似乎没有传到客户端。 客户机/服务器交互的工作方式是,客户机启动连接,然后通过WebSocket发送初始消息(“hello”)。服务器立即响应。此消息通过Chrome开发工具传递并可见。写入此消息后,我将存储在中。此初始化如下: 然后添加,如下所示: 在单独的线程(在