在 SleekXMPP 中接收带有消息的“角色”和/或“从属关系”

Posted

技术标签:

【中文标题】在 SleekXMPP 中接收带有消息的“角色”和/或“从属关系”【英文标题】:Receiving "role" and/or "affiliation" with message in SleekXMPP 【发布时间】:2014-05-18 19:13:58 【问题描述】:

对于这个业余问题,我们深表歉意。我只是在学习 Python,我正在使用 XMPP 摸索这个 XMPP 机器人脚本。

我有一个使用 SleekXMPP 的 MUC 机器人示例构建的机器人:http://sleekxmpp.com/getting_started/muc.html

我的机器人与示例的不同之处在于我的脚本创建了一个 SQLite 数据库,并在每个 group_message 事件上解析 XML 以检索昵称和消息正文文本,并将其写入带有时间戳的数据库。

这是我的机器人记录 XMPP 通道的 msg 输出的部分:

def groupchat_message(self, msg):
    if msg['type'] in ('groupchat'):
        raw = str(msg) # Save raw XML as a string in the database for debugging purposes
        timestamp = datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S')
        fromuser = str(msg['from']) # Convert "from" attribute to string so it can be split
        author = fromuser.split('/')[1] # Split "from" attribute to remove channel address leaving only nick behind
        body = msg['body']

        msginsert = [timestamp, author, body, raw] # Database input list to be handed to placeholders.

        db.execute("INSERT INTO messages VALUES (?,?,?,?)", msginsert) # "?" placeholder is REQUIRED for automatic database sanitization.
        dbconn.commit()

        print("[",timestamp,"]",author,": ",body, sep='')
    else:
        print(msg)

打印语句仅用于调试目的,因此我可以在终端中查看消息滴答作响,因此我知道脚本正在运行。

在记录的信息中,我还想在 XMPP 频道中包含用户的角色或从属关系,以便可以挑选出管理员和版主。这就是我难以理解的问题。似乎我应该能够根据SleekXMPP stanza docs 做到这一点,但我无法弄清楚如何从消息 XML 获取角色/从属信息。

如何获取消息 XML 中提供的信息并找回发布该消息的用户的角色和/或从属关系?

作为参考,这是来自 XMPP 通道的消息的原始 XML 输出:

<message to="username@example.com" from="channelname@channels.example.com/User Nick" id="1453" type="groupchat">
    <body>This is the message body text</body>
    <x xmlns="jabber:x:event">
        <composing />
    </x>
</message>

【问题讨论】:

【参考方案1】:

角色/从属关系不包含在消息中,它是聊天状态的一部分。

提醒一下,XMPP 有三个不同的节可以发送:&lt;message&gt;,例如,&lt;iq&gt;,用于检索或设置事物,&lt;presence&gt;,表示事物的存在.角色/从属关系信息包含在存在节中。例如,在您的客户收到的第一个出席信息节中,通知它谁已经在房间里,请参阅Example 21 from XEP-0045 (Multi-User Chat)。每当某人的昵称、角色或隶属关系发生变化或当他们离开房间时,您的客户也会收到新的出席信息节。

您应该确保自己存储这些信息,因为 SleekXMPP 不会为您存储这些信息。这可以通过创建一个字典来完成,该字典存储每个昵称、他们的角色和一个他们的从属关系。在状态更改时,您应该确保更新此信息。然后,您可以在消息处理程序中使用这些字典来记录他们的角色/从属关系。

比如:

def __init__(...):
    self.roles = dict()
    self.affiliations = dict()
    self.add_event_handler(""groupchat_presence"", self.muc_presence)

...

def muc_presence(self, presence):
    nick = presence['muc']['nick']

    self.roles[nick] = presence['muc']['role']
    self.affiliations[nick] = presence['muc']['affiliation']

这是一般的想法,您需要做更多的工作才能让它处理昵称更改和人们正确离开房间。

【讨论】:

昵称更改不是问题,因为此服务器上不允许更改。通过处理用户退出,您的意思是从字典中删除信息?我很确定我知道该怎么做。 是的。严格来说,没有必要删除它们(因为它们会在发送消息之前再次加入),但如果你不这样做,你会浪费内存。 太棒了,谢谢。我已经设置了角色和从属关系日志,并且它正在工作。你知道在 Sleek 中是否有一个离开事件触发器,我可以用它来删除字典条目,还是我必须手动设置它来检测离开消息? 在我给出的 muc_presence 回调示例中检查是否存在['type'] == 'unavailable' 可以检测到部件。

以上是关于在 SleekXMPP 中接收带有消息的“角色”和/或“从属关系”的主要内容,如果未能解决你的问题,请参考以下文章

Sleekxmpp 管理节

SleekXMPP:将出席 ['muc']['jid'] 获取到每条消息的消息处理程序

如何使用聊天客户端未接收到的 slimXMPP 发送一些数据?

带有 Spring JMS 的 Azure 接收多次接收相同的消息并将消息移动到 DLQ

SleekXMPP 自动接受所有聊天室邀请

Sleekxmpp:使用多个自定义节