Python In the context of a forum post title, the phrase

我正在玩弄 Python。具体来说:

我正在查看这些 API 文档:

Discourse API Docs / Discourse API Docs

我刚开始学习 Python,我想简单地接收帖子,如果 @UserA 在某处被提及。我曾认为我需要从通知中获取 post_number,然后查询该帖子,以检索并存储帖子内容。

从那里我想将该帖子内容存储为一个数据变量,然后从中进行一些实验。

我的代码的一部分是:

# 查找提及
mention = client.notifications.json.get()

# 打印帖子
for post_number in mention:
    print(post_number)

此代码的当前输出:

notifications
total_rows_notifications
seen_notification_id
load_more_notifications

如果这是一个愚蠢的问题,我很抱歉,我相对不熟悉 API,对 Python 更是新手。我花了一整天的时间在这上面却没成功,如果有人能给我指明正确的方向,我将不胜感激。

3 个赞

感谢您发布 fluent-discourse 的链接!

我目前正在努力学习 Python,因此可能存在比我在此处概述的更好的方法。

mention = client.notifications.json.get()

这将返回您在创建 client 时设置的 username 的提及的字典。我假设您在创建 client 时将 username 设置为 UserA

要确认正在返回字典,您可以运行:

print(type(mention))

这应该会返回 <class 'dict'>

您可以通过运行以下命令查看字典的键:

print(list(mention))

这将返回 ['notifications', 'total_rows_notifications', 'seen_notification_id', 'load_more_notifications']

在您的情况下,您需要 notifications 键下的值:

notifications = mention['notifications']

如果您随后运行 type(notifications),您会看到它是一个列表。要获取由提及 UserA 触发的通知,您需要遍历列表以查找 notification_type 设置为 1 的条目。查看 Discourse 通知类型的最简单方法是从您的 Discourse 站点的 rails 控制台运行 Notification.types

 pry(main)> Notification.types
=> {:mentioned=>1,
 :replied=>2,
 :quoted=>3,
 :edited=>4,
 :liked=>5,
 ...

因此,要获取您为 client 设置的用户的“提及”通知,请尝试执行类似以下操作(我正在键入时在 Python 解释器中进行测试):

data = client.notifications.json.get()
notifications = data['notifications']
# 创建一个空的列表对象来存储“提及”通知
mentions = []
# 遍历 `notifications` 列表以查找 `notification_type` 设置为 `1` 的所有条目
for notification in notifications:
    if notification['notification_type'] == 1:
        mentions.append(notification)

这将创建一个由提及触发的通知列表。列表中的每个项目都将是一个字典。您可以使用类似以下内容进行检查:

for mention in mentions:
    print(mention['topic_id'], mention['post_number'])
3 个赞

这很棒。感谢您的信息。关于 Python x Discourse 的信息不多,很高兴能学到,也许这对其他人也有帮助。我刚试了您的代码,它似乎按预期工作。当然,我没有停止玩,所以找到了一种方法来完成第 5 步,以及另一种方法来获取所有内容直到原始帖子内容的粘贴。

我想要的就是这个。

  1. 获取通知
  2. 获取帖子编号
  3. 获取帖子内容
  4. 使用 OpenAI 生成回复
  5. 发布回复
  6. 将同一通知标记为已读?
# 设置一个无限运行机器人的循环
while True:
    # 获取用户操作并获取帖子 ID    
    data = {
    'username': 'theuser',
    # 对于提及和回复,我需要获取过滤器 6 + 7,但不知何故只返回 1 个 JSON 响应。
    'filter': 6 | 7,
    'limit': 10,
    }
    
    unread_mentions = client.user_actions.json.get(data)
    print(unread_mentions)

    user_actions = unread_mentions['user_actions']

    # 循环遍历每个未读提及
    for user_action in unread_mentions['user_actions']:
        topic_id = user_action['topic_id']
        post_number = user_action['post_number']
        post_id = user_action['post_id']
        username = user_action['username']

        print(f'Topic ID: {topic_id}, Post Number: {post_number}, Post ID: {post_id}, Reply to: {username}')
    
        # 获取帖子内容   
        post = client.posts[post_id].json.get()

        # 打印帖子内容
        post_content = post['raw']

        # 生成对帖子的回复
        response = generate_response(post_content)
    
        # 在论坛上发布回复
        content = {
            'topic_id': topic_id,
            'raw': response + ' @' + str(username)
        }
        make_post = client.posts.json.post(content)

目前我遇到了两个问题:

  • 只获取了 1 条提及。我可能忘记了什么,但还没弄清楚原因。
  • 当然,我们希望只回复一个帖子一次,并且由于我们正在循环,我们需要在这里做些什么来防止这种情况。
    • 我们可以将 post_id 存储在 .txt 文件中(不确定它能存储多少数据,我认为您可以处理很多提及)。
    • 我理想的解决方案是标记通知为已读。但我意识到,在我们现有的代码中,我们并没有获取未读提及(嗯,我一开始尝试过,获取未读通知,但我无法提取/存储我需要的 post_id 变量来使用 /posts/get.json 并获取“raw”内容)。

我的最终目标是用 OpenAI API 提供响应。但首先我需要找到一种方法来解决上述问题。

我假设您想在帖子中提及某个用户名(例如 UserA)时,由 OpenAI 生成回复。如果正确,那么您不必向 Discourse 发出 API 请求来获取通知,而是可以将 Discourse 通知事件 webhook 指向您的 Python 应用程序服务器。Python 应用程序需要查看 webhook 的载荷。如果载荷的 notification_type 设置为 1,并且其 user_id 与您要获取通知的用户 ID 匹配,您就可以向 Discourse 发出 API 请求,以获取载荷的 original_post_id 字段中设置的帖子。然后将该请求返回的帖子内容发送给 OpenAI。

以下是提及通知载荷的示例:

{
  "notification": {
    "id": 55267,
    "user_id": 2,
    "notification_type": 1,
    "read": false,
    "high_priority": false,
    "created_at": "2022-12-08T23:23:36.379Z",
    "post_number": 5,
    "topic_id": 277,
    "fancy_title": "I should be able to call this topic anything",
    "slug": "i-should-be-able-to-call-this-topic-anything",
    "data": {
      "topic_title": "I should be able to call this topic anything",
      "original_post_id": 10999,
      "original_post_type": 1,
      "original_username": "scossar",
      "revision_number": null,
      "display_username": "scossar"
    }
  }
}

这种方法的优点是,您可以实时获取通知,而无需向您的 Discourse 站点发出大量 API 请求。

如果您选择 webhook 方法,最好在 Discourse 上设置 webhook 的“Secret”字段,然后在您的 Python 应用程序上验证请求,以确保密钥设置正确。我还没有尝试设置 Python 应用程序上的路由来实现这一点。有关如何在 WordPress 上验证 webhook 的 Secret 的详细信息,请参见:wp-discourse-custom-webhook-request/wp-discourse-custom-webhook-request.php at master · scossar/wp-discourse-custom-webhook-request · GitHub

1 个赞

感谢您的回复,我非常感激。

我从未研究过 Discourse 的 webhook。我会研究一下。

1 个赞

编辑:我想我弄错了。看起来我正在寻找类型 1 和 2。类型 2 会在用户回复时触发。这使得此帖子基本无关紧要。在玩这个的时候,我脑子里冒出了一个问题:

mentioned 清晰明了,当有明确的 @提及时,类型 == 1。

但对于 replied,我有点困惑。

当我通过通用按钮之一回复主题时,它会作为回复出现。这很合理。

但如果你点击回复特定用户帖子的回复按钮,你会认为这是一个提及,但它仍然是类型 2 通知。

This should be a mention type notification

“回复用户”通知不应该获得类型 1 吗?因为它基本上与提及完全相同,只是帖子中没有 @提及

供参考,因为在元(meta)上别处没有,所以在此处发布通知类型。也许这些类型的通知可以获得一个新类型,或者只是类型 1?

[1] pry(main)> Notification.types
=> {:mentioned =>1,
 :replied =>2,
 :quoted =>3,
 :edited =>4,
 :liked =>5,
 :private_message =>6,
 :invited_to_private_message =>7,
 :invitee_accepted =>8,
 :posted =>9,
 :moved_post =>10,
 :linked =>11,
 :granted_badge =>12,
 :invited_to_topic =>13,
 :custom =>14,
 :group_mentioned =>15,
 :group_message_summary =>16,
 :watching_first_post =>17,
 :topic_reminder =>18,
 :liked_consolidated =>19,
 :post_approved =>20,
 :code_review_commit_approved =>21,
 :membership_request_accepted =>22,
 :membership_request_consolidated =>23,
 :bookmark_reminder =>24,
 :reaction =>25,
 :votes_released =>26,
 :event_reminder =>27,
 :event_invitation =>28,
 :chat_mention =>29,
 :chat_message =>30,
 :chat_invitation =>31,
 :chat_group_mention =>32,
 :chat_quoted =>33,
 :assigned =>34,
 :question_answer_user_commented =>35,
 :watching_category_or_tag =>36}
1 个赞

我不这么认为。提及通知("notification_type": 1)是针对在帖子中添加了 @username 的特定情况。将相同的通知类型用于直接回复会导致混淆。

有一个需要注意的极端情况。如果用户名被添加到对用户主题的回复中,发送给用户的通知将是 "notification_type": 1,而不是 "notification_type": 2。例如,通过在此处提及您的用户名,此帖子应触发一个通知告诉您我提到了您,而不是一个说我回复了您的通知:@MarcP

请注意,如果除了您自己以外的用户正在关注此主题,他们将收到一个类型设置为 9(已发布)的通知。

2 个赞

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.