Python > Obtenir le contenu du post s'il est mentionné

Je joue avec Python. Pour être précis :

Je consulte la documentation de l’API :

Discourse API Docs / Discourse API Docs

Je suis nouveau (j’apprends) en Python, et j’essaie simplement de recevoir les posts si @UserA est mentionné quelque part. Je pensais que j’avais besoin d’obtenir le post_number des notifications, puis de requêter ce post, pour récupérer et stocker le contenu du post.

À partir de là, je veux stocker ce contenu de post, comme une variable de données et à partir de là expérimenter certaines choses.

Une partie de mon code est la suivante :

# rechercher les mentions
mention = client.notifications.json.get()

# imprimer les posts
for post_number in mention:
    print(post_number)

La sortie actuelle de ce code :

notifications
total_rows_notifications
seen_notification_id
load_more_notifications

Désolé si c’est une question stupide, je suis relativement nouveau avec les API et encore plus nouveau avec Python. J’ai travaillé sur cela toute la journée sans succès, si quelqu’un peut m’orienter dans la bonne direction, ce serait très apprécié.

3 « J'aime »

Merci d’avoir posté le lien vers fluent-discourse !

J’essaie actuellement de me familiariser avec Python, il est donc possible qu’il existe de meilleures façons d’aborder ce problème que celles que j’expose ici.

mention = client.notifications.json.get()

Cela renvoie un dictionnaire de mentions pour le username que vous avez défini lors de la création du client. Je suppose que vous avez défini le username sur UserA lors de la création du client.

Pour confirmer qu’un dictionnaire est renvoyé, vous pouvez exécuter :

print(type(mention))

Cela devrait renvoyer <class 'dict'>

Vous pouvez voir les clés du dictionnaire en exécutant :

print(list(mention))

Cela renverra ['notifications', 'total_rows_notifications', 'seen_notification_id', 'load_more_notifications']

Dans votre cas, vous voulez les valeurs qui se trouvent sous la clé notifications :

notifications = mention['notifications']

Si vous exécutez ensuite type(notifications), vous verrez qu’il s’agit d’une liste. Pour obtenir les notifications qui ont été déclenchées par des mentions de UserA, vous devez parcourir la liste pour trouver les entrées où notification_type est défini sur 1. La manière la plus simple de voir les valeurs des types de notification Discourse est d’exécuter Notification.types à partir de la console rails de votre site Discourse :

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

Donc, pour obtenir les notifications de “mention” pour l’utilisateur dont le nom d’utilisateur que vous avez défini pour le client, essayez quelque chose comme ceci (je teste cela dans l’interpréteur Python pendant que je l’écris) :

data = client.notifications.json.get()
notifications = data['notifications']
# Créez une liste vide pour stocker les notifications de "mention"
mentions = []
# Parcourez la liste `notifications` pour trouver toutes les entrées où `notification_type` est défini sur `1`
for notification in notifications:
    if notification['notification_type'] == 1:
        mentions.append(notification)

Cela créera une liste de notifications qui ont été déclenchées par des mentions. Chaque élément de la liste sera un dictionnaire. Vous pouvez le vérifier avec quelque chose comme :

for mention in mentions:
    print(mention['topic_id'], mention['post_number'])
3 « J'aime »

C’est bien. Merci pour l’info. Il n’y a pas beaucoup d’informations sur Python x Discourse disponibles ici, donc je suis heureux d’apprendre, et peut-être que cela aidera d’autres personnes. Je viens d’essayer votre code, et il semble fonctionner comme prévu. Bien sûr, je n’ai pas arrêté de jouer, j’ai donc trouvé une solution de contournement pour aller jusqu’à l’étape 5, et une manière différente d’obtenir les valeurs dont j’avais besoin jusqu’à un simple copier-coller du contenu du message.

Ce que je veux, c’est essentiellement ceci.

  1. Recevoir des notifications
  2. Obtenir les numéros de message
  3. Obtenir le contenu du message
  4. Générer une réponse avec OpenAI
  5. Publier la réponse
  6. Marquer cette même notification comme lue ?
# Configurer une boucle pour exécuter le bot indéfiniment
while True:
    # Obtenir les actions utilisateur et récupérer l'ID du message
    data = {
    'username': 'theuser',
    # Pour les mentions et les réponses, j'ai besoin d'obtenir les filtres 6 + 7, mais pour une raison quelconque, une seule réponse JSON est donnée.
    'filter': 6 | 7,
    'limit': 10,
    }

    unread_mentions = client.user_actions.json.get(data)
    print(unread_mentions)

    user_actions = unread_mentions['user_actions']

    # Boucler sur chaque mention non lue
    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}')

        # Obtenir le contenu du message
        post = client.posts[post_id].json.get()

        # Afficher le contenu du message
        post_content = post['raw']

        # Générer une réponse au message
        response = generate_response(post_content)

        # Publier une réponse sur le forum
        content = {
            'topic_id': topic_id,
            'raw': response + ' @' + str(username)
        }
        make_post = client.posts.json.post(content)

Actuellement, j’ai deux problèmes :

  • Une seule mention est récupérée. J’ai dû oublier quelque chose, mais je n’ai pas encore trouvé pourquoi.
  • Bien sûr, nous voulons répondre à un message une seule fois, et comme nous sommes en boucle, nous avons besoin de quelque chose ici pour éviter cela.
    • Nous pouvons stocker le post_id dans un fichier .txt (je ne sais pas combien de données cela peut stocker, je pense que vous pouvez gérer pas mal de mentions ici.
    • Ma solution idéale était de marquer la notification comme lue. Mais j’ai réalisé que dans aucun de nos codes, nous ne récupérons les mentions non lues (enfin, j’ai essayé au début, en récupérant les notifications non lues, mais je n’ai pas pu extraire/stocker la variable post_id que je devais utiliser /posts/get.json et récupérer le contenu “raw”).

Mon objectif final est d’alimenter la réponse avec l’API OpenAI. Mais je dois d’abord trouver un moyen de résoudre les problèmes ci-dessus.

Je suppose que ce que vous voulez faire est de générer une réponse d’OpenAI lorsqu’un nom d’utilisateur donné (par exemple, UserA) est mentionné dans un message. Si c’est le cas, au lieu de faire des requêtes API à Discourse pour obtenir les notifications, vous pourriez pointer un webhook d’événement de notification Discourse vers le serveur de votre application Python. L’application Python devrait examiner la charge utile du webhook. Si le notification_type de la charge utile était défini sur 1, et que son user_id correspondait à l’ID de l’utilisateur pour lequel vous souhaitez recevoir des notifications, vous feriez une requête API à Discourse pour obtenir le message défini dans le champ original_post_id de la charge utile. Ensuite, vous enverriez le contenu du message renvoyé par cette requête à OpenAI.

Voici un exemple de ce à quoi ressemble la charge utile d’une notification de mention :

{
  "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"
    }
  }
}

L’avantage de cette approche est qu’elle vous permettrait de recevoir des notifications en temps réel, sans avoir à effectuer un grand nombre de requêtes API à votre site Discourse.

Si vous optez pour l’approche par webhook, il serait judicieux de définir le champ “Secret” du webhook sur Discourse, puis de valider la requête sur votre application Python pour vous assurer que la clé secrète est correctement définie. Je n’ai pas encore essayé de configurer une route sur une application Python pour cela. Les détails sur la façon de valider un secret de webhook sur WordPress sont ici : wp-discourse-custom-webhook-request/wp-discourse-custom-webhook-request.php at master · scossar/wp-discourse-custom-webhook-request · GitHub.

1 « J'aime »

Merci pour votre réponse, j’apprécie beaucoup cela.

Je n’ai jamais examiné les webhooks Discourse. Je vais examiner cela.

1 « J'aime »

MODIFICATION : Je pense que je me trompe. Il semble que je cherche les types 1 et 2. Le type 2 se déclenche s’il y a une réponse à l’utilisateur. Cela rend ce post essentiellement non pertinent. En jouant avec cela, la question suivante m’est venue à l’esprit :

mentioned est clair comme de l’eau de roche, type == 1 s’il y a une @Mention claire.

Mais pour replied, je suis un peu confus.

Lorsque je réponds au sujet, via l’un des boutons généraux, cela arrive comme une réponse. Logique.

Mais si vous cliquez sur le bouton de réponse à un post spécifique d’un utilisateur, on pourrait penser que c’est une mention, mais c’est toujours une notification de type 2.

Cette notification devrait être de type mention

Une notification de « réponse à l’utilisateur » ne devrait-elle pas être de type 1 ? Parce que c’est essentiellement la même chose qu’une mention, juste sans la @Mention dans le post.

Pour référence, car ce n’est nulle part ailleurs sur meta, je poste ici les types de notifications. Peut-être que ces types de notifications peuvent obtenir un nouveau type, ou juste le type 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 « J'aime »

Je ne pense pas. Les notifications de mention ("notification_type": 1) sont destinées au cas spécifique où un @nomdutilisateur est ajouté à un message. Utiliser le même type de notification pour les réponses directes créerait de la confusion.

Il y a un cas limite à connaître. Si un nom d’utilisateur est ajouté à une réponse au sujet d’un utilisateur, la notification envoyée à l’utilisateur sera "notification_type": 1, et non "notification_type": 2. Par exemple, en mentionnant votre nom d’utilisateur ici, ce message devrait déclencher une notification vous informant que je vous ai mentionné, et non une notification indiquant que je vous ai répondu : @MarcP.

Notez que si un utilisateur autre que vous-même suivait ce sujet, il recevrait une notification avec son type défini sur 9 (posté).

2 « J'aime »

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