Python > Ottieni il contenuto del post se menzionato

Sto sperimentando con Python. Per essere specifici:

Sto guardando la documentazione dell’API:

Discourse API Docs / Discourse API Docs

Sono nuovo (sto imparando) con Python e sto cercando di ricevere semplicemente i post se @UserA viene menzionato da qualche parte. Stavo pensando che avrei bisogno di ottenere il post_number dalle notifiche, e poi interrogare quel post, per recuperare e memorizzare il contenuto del post.

Da lì voglio memorizzare quel contenuto del post, come variabile di dati e da lì sperimentare alcune cose.

Una parte del mio codice è questa:

# cerca menzioni
mention = client.notifications.json.get()

# stampa i post
for post_number in mention:
    print(post_number)

L’output attuale di questo codice:

notifications
total_rows_notifications
seen_notification_id
load_more_notifications

Scusate se questa è una domanda stupida, sono relativamente nuovo con le API e ancora più nuovo con Python. Ci sto lavorando tutto il giorno senza successo, se qualcuno può indicarmi la giusta direzione, sarebbe molto apprezzato.

3 Mi Piace

Grazie per aver pubblicato il link a fluent-discourse!

Attualmente sto cercando di aggiornarmi su Python, quindi è possibile che ci siano modi migliori per affrontare questo problema rispetto a quelli che sto delineando qui.

mention = client.notifications.json.get()

Questo restituisce un dizionario di menzioni per il username che hai impostato quando hai creato il client. Presumo che tu abbia impostato il username su UserA quando hai creato il client.

Per confermare che viene restituito un dizionario, puoi eseguire:

print(type(mention))

Questo dovrebbe restituire <class 'dict'>

Puoi vedere le chiavi del dizionario eseguendo:

print(list(mention))

Questo restituirà ['notifications', 'total_rows_notifications', 'seen_notification_id', 'load_more_notifications']

Nel tuo caso, vuoi i valori che si trovano sotto la chiave notifications:

notifications = mention['notifications']

Se esegui type(notifications), vedrai che è una lista. Per ottenere le notifiche che sono state attivate da menzioni di UserA, devi scorrere la lista per trovare le voci in cui notification_type è impostato su 1. Il modo più semplice per vedere i valori per i tipi di notifica di Discourse è eseguire Notification.types dalla console rails del tuo sito Discourse:

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

Quindi, per ottenere le notifiche di “menzione” per l’utente il cui nome utente hai impostato per il client, prova qualcosa di simile (lo sto testando nell’interprete Python mentre lo scrivo):

data = client.notifications.json.get()
notifications = data['notifications']
# Crea un oggetto lista vuoto per memorizzare le notifiche di "menzione"
mentions = []
# Scorri la lista `notifications` per trovare tutte le voci in cui `notification_type` è impostato su `1`
for notification in notifications:
    if notification['notification_type'] == 1:
        mentions.append(notification)

Questo creerà una lista di notifiche che sono state attivate da menzioni. Ogni elemento della lista sarà un dizionario. Puoi controllarlo con qualcosa di simile:

for mention in mentions:
    print(mention['topic_id'], mention['post_number'])
3 Mi Piace

Questo è fantastico. Grazie per le informazioni. Non ci sono molte informazioni su Python x Discourse disponibili qui, quindi sono felice di imparare, e forse questo aiuterà altri. Ho appena provato il tuo codice e sembra funzionare come previsto. Naturalmente, non ho smesso di giocare, quindi ho trovato un modo per arrivare fino al passaggio 5 e un modo diverso per ottenere i valori di cui avevo bisogno fino a un semplice copia-incolla del contenuto del post.

Quello che voglio è fondamentalmente questo.

  1. Ricevere notifiche
  2. Ottenere i numeri dei post
  3. Ottenere il contenuto del post
  4. Generare una risposta con OpenAI
  5. Pubblicare la risposta
  6. Segnare la stessa notifica come letta?
# Imposta un ciclo per eseguire il bot all'infinito
while True:
    # Ottieni le azioni dell'utente e recupera l'ID del post    
    data = {
    'username': 'theuser',
    # Per menzioni e risposte, ho bisogno di ottenere i filtri 6 + 7, ma per qualche motivo viene fornita solo 1 risposta json.
    'filter': 6 | 7,
    'limit': 10,
    }
    
    unread_mentions = client.user_actions.json.get(data)
    print(unread_mentions)

    user_actions = unread_mentions['user_actions']

    # Cicla su ogni menzione non letta
    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}')
    
        # Ottieni il contenuto del post   
        post = client.posts[post_id].json.get()

        # Stampa il contenuto del post
        post_content = post['raw']

        # Genera una risposta al post
        response = generate_response(post_content)
    
        # Pubblica una risposta al forum
        content = {
            'topic_id': topic_id,
            'raw': response + ' @' + str(username)
        }
        make_post = client.posts.json.post(content)

Attualmente ho due problemi:

  • Viene recuperata solo 1 menzione. Devo aver dimenticato qualcosa, ma non ho ancora capito perché.
  • Ovviamente vogliamo rispondere a un post solo una volta, e poiché stiamo ciclando, abbiamo bisogno di qualcosa qui per evitarlo.
    • Possiamo memorizzare il post_id in un file .txt (non sono sicuro di quanti dati possa memorizzare, penso che tu possa gestire un bel po’ di menzioni qui.
    • La mia soluzione ideale era quella di contrassegnare la notifica come letta. Ma mi sono reso conto che in nessuno dei nostri codici stiamo recuperando le menzioni non lette (beh, ho provato all’inizio, recuperando le notifiche non lette, ma non sono riuscito a estrarre/memorizzare la variabile post_id che mi serviva per usare /posts/get.json e recuperare il contenuto “raw”).

Il mio obiettivo finale è alimentare la risposta con l’API di OpenAI. Ma prima devo trovare un modo per risolvere i problemi di cui sopra.

Presumo che quello che vuoi fare sia generare una risposta da OpenAI quando un determinato nome utente (ad esempio, UserA) viene menzionato in un post. Se è corretto, invece di effettuare richieste API a Discourse per ottenere le notifiche, potresti puntare un webhook di Discourse Notification Event al server della tua applicazione Python. L’applicazione Python dovrebbe esaminare il payload del webhook. Se il notification_type del payload è impostato su 1 e il suo user_id corrisponde all’ID dell’utente per cui desideri ricevere notifiche, effettueresti una richiesta API a Discourse per ottenere il post impostato nel campo original_post_id del payload. Quindi invieresti il contenuto del post restituito da quella richiesta a OpenAI.

Ecco un esempio di come appare il payload per una notifica di menzione:

{
  "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": "Dovrei essere in grado di chiamare questo argomento come voglio",
    "slug": "i-should-be-able-to-call-this-topic-anything",
    "data": {
      "topic_title": "Dovrei essere in grado di chiamare questo argomento come voglio",
      "original_post_id": 10999,
      "original_post_type": 1,
      "original_username": "scossar",
      "revision_number": null,
      "display_username": "scossar"
    }
  }
}

Il vantaggio di questo approccio è che ti consentirebbe di ricevere notifiche in tempo reale, senza dover effettuare un gran numero di richieste API al tuo sito Discourse.

Se scegli l’approccio webhook, sarebbe una buona idea impostare il campo “Secret” del webhook su Discourse, quindi convalidare la richiesta sulla tua applicazione Python per assicurarti che la chiave segreta sia impostata correttamente. Non ho ancora provato a configurare un percorso su un’applicazione Python per farlo. I dettagli su come convalidare un “Secret” webhook su WordPress sono qui: wp-discourse-custom-webhook-request/wp-discourse-custom-webhook-request.php at master · scossar/wp-discourse-custom-webhook-request · GitHub.

1 Mi Piace

Grazie per la tua risposta, lo apprezzo molto.

Non ho mai approfondito le webhook di Discourse. Ci darò un’occhiata.

1 Mi Piace

MODIFICA: Penso di essermi sbagliato. Sembra che stia cercando il tipo 1 e 2. Il tipo 2 si attiverà se c’è una risposta all’utente. Questo rende questo post fondamentalmente irrilevante. Giocando con questo, mi è venuta la seguente domanda:

mentioned è chiaro come il sole, tipo == 1 se c’è una chiara @Menzione

Ma per replied sono un po’ confuso.

Quando rispondo all’argomento, tramite uno dei pulsanti generali, arriva come risposta. Ha senso.

Ma se fai clic sul pulsante di risposta a un post specifico di un utente, si potrebbe pensare che sia una menzione, ma è ancora una notifica di tipo 2.

Questa dovrebbe essere una notifica di tipo menzione

Non dovrebbe una notifica di “risposta all’utente” ottenere il tipo 1? Perché è fondamentalmente la stessa cosa di una menzione, solo senza la @Menzione nel post.

Come riferimento, poiché non è da nessun’altra parte su meta, pubblico qui i tipi di notifica. Forse questi tipi di notifiche possono ottenere un nuovo tipo, o solo il tipo 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 Mi Piace

Non credo. Le notifiche di menzione ("notification_type": 1) sono destinate al caso specifico in cui un @nomeutente viene aggiunto a un post. L’utilizzo dello stesso tipo di notifica per le risposte dirette causerebbe confusione.

C’è un caso limite da tenere presente. Se un nome utente viene aggiunto a una risposta a un argomento di un utente, la notifica inviata all’utente sarà "notification_type": 1, non "notification_type": 2. Ad esempio, menzionando il tuo nome utente qui, questo post dovrebbe attivare una notifica che ti informa che ti ho menzionato, e non una notifica che dice che ti ho risposto: @MarcP.

Nota che se un utente diverso da te stesse seguendo questo argomento, riceverebbe una notifica con il suo tipo impostato su 9 (postato).

2 Mi Piace

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