Interact with discourse from Python?

Hi everyone! Love discourse, it’s the backbone of our community.

We are an open source project with a strong presence on Github. We have a robot written in Python which manages our Github repositories and does things like merge pull requests automatically if they have been approved. Since we have a lot of repositories and not everyone follows every repository it would be awesome if the robot could post in the forums when a new project is created or when a pull request needs to be reviewed.

Can anyone point me in the direction of how I could best call the Discourse API from Python?

There is a python discourse api library that is a few years old:

And a forked version that has been updated somewhat recently:

Hopefully the latter one will work for you.

Also this plugin may be of interest to you:

https://meta.discourse.org/t/the-github-linkback-plugin/66081

Thanks @blake! That is exactly the kind of thing I needed to get started.

I will report back with my successes.

Я недавно начал этот проект и активно его обновляю. В настоящее время работаю над следующим точечным релизом:

У вас получилось? Я тоже пытаюсь это сделать. У меня постоянно появляется ошибка “DiscourseClientError: Payload Too Large”.

Я тоже внезапно столкнулся с этой ошибкой в выходные при попытке получить тему. Код получения темы не менялся более года, значит, что-то в API изменилось. Я разбираюсь.

Ошибка «Payload Too Large» вызвана этим изменением.

Я не знаю о проекте, упомянутом выше, но вот статус проекта bennylope. Возможно, аналогичное исправление потребуется и для других обёрток.

В задаче #38 репозитория GitHub - pydiscourse/pydiscourse: A Python library for the Discourse API · GitHub проблема решена, но исправленная версия ещё не выложена в PyPI — pydiscourse.exceptions.DiscourseClientError: Payload Too Large · Issue #38 · pydiscourse/pydiscourse · GitHub. Ждём, пока @bennylope сделает это на GitHub. Так что вы можете либо дождаться обновления в PyPI, либо выполнить git pull master.

Спасибо! Это сработало. Я удалил pydiscourse и использовал локальную копию на основе ваших рекомендаций. Теперь всё работает!
Я пытаюсь использовать анализатор тональности Python для анализа тональности последних сообщений. Буду держать вас в курсе результатов.

Кто-нибудь ещё этим пользуется? Удаётся ли вам получать больше 20 постов в теме с его помощью?

Вероятно, вам нужно использовать пагинацию. Я не пробовал это именно для сообщений, но что-то вроде:

pagesize = 20
for page in range(100):
    client.posts(topic_id, limit=pagesize, offset=page*pagesize)

Да, я знаю, что это старый пост, но поскольку он по сути отвечает на мой вопрос, нет смысла создавать новый, если этот работает, но его нужно просто актуализировать.

Хотя я умею программировать на многих языках, к сожалению, Ruby не входит в их число. Хотелось бы узнать, есть ли более новые или лучшие ответы на этот вопрос.

Взаимодействие с Discourse из Python?


В качестве дополнительного вопроса: можно ли создавать плагины и/или темы для Discourse с помощью Python?

Темы — точно нет, они пишутся только на JavaScript, CSS и HTML.

Плагины — отчасти.

В плагин Discourse, основанный на Ruby (on Rails), можно импортировать модули Python и вызывать функции Python с помощью Pycall: GitHub - red-data-tools/pycall.rb: Calling Python functions from the Ruby language · GitHub

Я использую это в продакшене для очень специфичной задачи, так как в экосистеме RoR нет аналогичного модуля. Это избавляет меня от необходимости переводить и затем поддерживать весь этот специализированный код на Ruby.

Работает это удивительно хорошо.

Тем не менее, основа этого плагина всё ещё написана на Ruby.

Я бы порекомендовал вам также изучить Ruby on Rails — это действительно приятный язык, и, на мой взгляд, код на нём читается лучше, чем на Python :slight_smile:

Мне тоже стоит найти время, чтобы больше узнать о Python, если возникнет такая необходимость.

Интересный побочный факт: часть кода в Discourse Chatbot 🤖, отвечающая за поведение агента, была основана на Python-агенте под названием “Funkagent”, который я сначала перевёл на Ruby on Rails (а затем модифицировал и улучшил). Так что перевод, конечно, может быть вариантом, если это имеет смысл. В данном случае это имело смысл.

Спасибо.

Это разумный ответ и возможный вариант, который я оставлю в качестве альтернативы.

Я написал несколько скриптов импорта, прежде чем действительно «научился» Ruby. В зависимости от того, что вы хотите сделать, вы, возможно, сможете сделать больше с вашим текущим набором навыков, чем думаете. Скорее всего, проще использовать Ruby, чем разбираться, как использовать что-то другое.

Однако, если вы взаимодействуете с API, то можете использовать любой язык программирования, какой захотите.

Ruby имеет прекрасный дизайн и, на мой взгляд, её очень легко изучить.

Ruby on Rails требует чуть больше времени на обучение, и как фреймворк, основанный на соглашениях, иногда может быть капризным, но при этом очень мощным, как только вы в нём разберётесь.

Вы можете посмотреть GitHub - discourse/all-the-plugins · GitHub, чтобы ознакомиться с возможными вариантами.

Выберите задачу, которую вы хотите решить, и которая кажется вам простой. Если вы хотите что-то вроде cakeday, которое меняет определение годовщины, то cakeday может стать хорошей отправной точкой. Выберите одну небольшую вещь, которую вы хотите изменить, и двигайтесь шаг за шагом.

Ха! Я сейчас учу Ruby самостоятельно, это действительно увлекательно. :exploding_head:

Всем привет! Меня тоже интересует получение данных из Discourse (в основном статистики по просмотрам и количеству пользователей) через Python. Многие из перечисленных здесь пакетов, похоже, больше не поддерживаются. Есть ли новый стандартный способ решения этой задачи в 2026 году?

Спасибо!

Вам не всегда нужно использовать интерфейс кого-то другого.

Это не слишком сложно сделать с помощью встроенной библиотеки requests, и если вы используете какой-то инструмент (например, Postman, который у меня уже настроен), вы можете импортировать нашу спецификацию API в него, а затем сгенерировать код:

а затем адаптировать его под свои нужды:

import json
import pandas
import requests

url = "https://try.discourse.org/categories.json?include_subcategories=false"

payload = {}
headers = {
  'Accept': 'application/json'
}

response = requests.request("GET", url, headers=headers, data=payload)
response_data = json.loads(response.text)
data = pandas.DataFrame(response_data['category_list']['categories']).set_index('id')

Теперь у меня есть информация о категориях:

            name   color text_color  ... uploaded_background_dark                                             topics can_vote
id                                   ...                                                                                     
5        general  25AAE2     FFFFFF  ...                     None  [{'fancy_title': 'Testing dulu ya jangan di hi...      NaN
4         videos  258af1     FFFFFF  ...                     None  [{'fancy_title': 'Ikan ganteng yang’&rdq...      NaN
86      calendar  12A89D     FFFFFF  ...                     None  [{'fancy_title': 'Category Calendar demo topic...      NaN
2           tech     444     FFFFFF  ...                     None  [{'fancy_title': 'Poll: What’s your pref...      NaN
1      discourse  00B355     FFFFFF  ...                     None  [{'fancy_title': 'Welcome to our demo!', 'id':...      NaN
53  Topic Voting  F7941D     FFFFFF  ...                     None  [{'fancy_title': 'Is this topic worth voting f...     True
6         gaming  800080     FFFFFF  ...                     None  [{'fancy_title': 'Impressions Games City Build...      NaN
8         movies  B22222     FFFFFF  ...                     None  [{'fancy_title': 'What’s your all-time f...      NaN
9         sports  0000FF     FFFFFF  ...                     None  [{'fancy_title': 'Modernizing the antiquated b...      NaN

[9 строк x 45 столбцов]

Если вы хотите получить доступ к защищённой информации, вам следует использовать API-ключ.