Подробные примеры REST API Discourse

Существует несколько руководств, посвященных различным вариантам использования API или его объяснениям.

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

:warning: Все примеры кода в этом руководстве не предназначены для демонстрации лучших практик или для использования в таком виде.
Многие проверки, обработка ошибок и т. д. намеренно опущены или пропущены, чтобы сосредоточиться исключительно на использовании API.

Для чего используется API?

Большинство ваших действий в Discourse (создание постов, лайки, изменение настроек и т. д.) выполняются с помощью API путем отправки запросов к конечной точке[1].

Например, при создании темы на meta отправляется POST-запрос на https://meta.discourse.org/posts.json. Запрос содержит, среди прочего, автора, заголовок, категорию, теги и содержимое вашего поста.

Использование API для нестандартных задач обычно осуществляется для автоматизации действий и часто в сочетании с другими сервисами, такими как вебхуки, скрипты, стороннее программное обеспечение и API.

Для использования API обязательно наличие учетных данных API. Это можно сделать в несколько кликов, следуя этому руководству: Create and configure an API key

Не ждите больше, давайте перейдем к первому примеру использования API. :technologist:

Создание ежемесячной темы

В этом примере мы используем curl и cron для создания ежемесячной темы “свободное общение” на вашем форуме. Популярная практика в онлайн-сообществах :slight_smile:

Создание ключа API

Следуйте руководству по созданию ключа API. Установите Уровень пользователя как “Один пользователь”.
Выбранный пользователь будет автором ежемесячной темы.
Затем вы можете выбрать Глобальную область действия или Детальную область действия; в последнем случае она должна иметь как минимум доступ Темызапись.
Запишите сгенерированный ключ API. :writing_hand:

Создание команды curl

Из командной строки вашего сервера выполните эту команду, чтобы проверить, работает ли она и создается ли тема правильно с помощью curl и REST API Discourse с вашим ключом API:

curl -X POST "https://your-discourse.com/posts.json" -H "Content-Type: application/json" -H "Api-Key: YOUR_API_KEY" -H "Api-Username: YOUR_USERNAME" -d "{\"title\": \"Тестовое создание темы через API\", \"raw\": \"А вот и содержимое темы\", \"category\": CATEGORY_ID }"

Замените:

  • your-discourse.com на домен вашего форума
  • YOUR_API_KEY на ваш ключ API
  • YOUR_USERNAME на имя пользователя, выбранное для ключа API
  • CATEGORY_ID на ID категории, в которую вы хотите опубликовать тему.

Если все правильно настроено, на вашем форуме должна быть создана новая тестовая тема, например:

Большая часть работы на этом этапе выполнена! Теперь нам нужно изменить заголовок и содержимое темы на более подходящие и настроить периодичность создания темы.

Начните с изменения заголовка темы с:
Тестовое создание темы через API
на:
Свободное общение месяца - $(date +\%B).

Сделайте то же самое для содержимого:
Тестовое создание темы через API
на:
Что вам больше всего понравилось и не понравилось в $(date +\%B -d 'прошлый месяц')?\nНе стесняйтесь делиться своими мыслями и предлагать идеи. 🙂

:information_source: Я использую Unix-команду date, чтобы вставить название текущего месяца в заголовок и название предыдущего месяца в содержимое.

:information_source: \n в содержимом создает новую строку.

Вы можете использовать командную строку и выполнить обновленный запрос curl. На вашем форуме должна быть создана новая тема, например:

Настройка повторяющегося события

Мы создадим задачу cron, которая будет запускать команду curl в первый день каждого месяца. :calendar:

Отредактируйте файл cron следующей командой:

crontab -e

Добавьте эту строку в конец файла (при необходимости измените содержимое запроса) и сохраните изменения.

0 0 1 * * curl -X POST "https://your-discourse.com/posts.json" -H "Content-Type: application/json" -H "Api-Key: YOUR_API_KEY" -H "Api-Username: YOUR_USERNAME" -d "{\"title\": \"Свободное общение месяца - $(date +\%B)\", \"raw\": \"Что вам больше всего понравилось и не понравилось в $(date +\%B -d 'прошлый месяц')?\nНе стесняйтесь делиться своими мыслями и предлагать идеи. 🙂\", \"category\": 4 }"

:information_source: Часть 0 0 1 * * определяет интервал, с которым будет выполняться команда. Подробнее о синтаксисе можно узнать здесь: https://crontab.guru

Готово! Теперь ваш сервер будет создавать новую тему “свободное общение” в первый день каждого месяца, используя REST API Discourse, запрос curl и задачу cron. :partying_face:

Автоматическая смена цветовой схемы темы

Давайте настроим нашу тему по умолчанию так, чтобы она использовала цветовую схему, соответствующую текущему сезону :snowflake: :hibiscus: :sunny: :fallen_leaf:

Мы будем использовать Ruby для проверки месяцев и задачу cron для выполнения скрипта.

Мы могли бы использовать множество других способов вместо Ruby и cron, но это руководство также призвано показать, как использовать API с различными инструментами.

Подготовка темы и цветовых схем

Выберите тему, цветовую схему которой вы хотите изменить, и получите её ID. ID вы найдете в URL-адресе темы. Например, ID этой темы — 1:

Создайте 4 цветовые палитры и запишите их ID.
Здесь ID палитры осени — 17:

Создание скрипта

Установите Ruby на ваш сервер.

Создайте файл seasons.rb. Для этого примера предположим, что он находится в ~/scripts/.

Вставьте следующее содержимое в этот файл. Мы отправим PUT-запрос к конечной точке нашей темы и передадим полезную нагрузку, содержащую ID цветовой схемы:

require 'net/http'
require 'json'
require 'date'

current_month = Date.today.month
color_scheme_id = case current_month
                  when 1..3 then 18 # Зима
                  when 4..6 then 15 # Весна
                  when 7..9 then 16 # Лето
                  else           17 # Осень
                  end

uri = URI('https://your-discourse.com/admin/themes/THEME_ID.json')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Put.new(uri, {
  'Api-Key' => 'YOUR_API_KEY',
  'Api-Username' => 'YOUR_USERNAME',
  'Content-Type' => 'application/json'
})

request.body = JSON.generate({
  "theme" => {
    "color_scheme_id" => color_scheme_id
  }
})

response = http.request(request)

Замените:

  • your-discourse.com на домен вашего форума
  • YOUR_API_KEY на ваш ключ API
  • YOUR_USERNAME на имя пользователя, выбранное для ключа API
  • THEME_ID на ID вашей темы. Вы можете найти его в конце URL-адреса страницы настроек темы.
    Например, в https://your-discourse.com/admin/customize/themes/38 ID темы — 38.

Давайте вручную протестируем ваш скрипт.
Сначала установите не сезонную цветовую схему в интерфейсе Discourse, если это еще не сделано.

Затем запустите скрипт следующей командой:

ruby ~/scripts/seasons.rb

Обновите браузер. Цветовая схема, используемая вашей темой, должна измениться. :slight_smile:

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

Посмотрите еще раз на первый пример, если вы не помните, как создать задачу cron.

0 0 1 1,4,7,10 * ruby ~/scripts/seasons.rb

Готово! Теперь ваш форум будет менять цвета в начале каждого нового сезона! :sunny: :partying_face:

Получение веб-запроса на веб-сервере и использование его данных для обновления темы Discourse

Этот пример более сложный! :technologist:

Нашим инструментом будет PHP, что означает, что мы предполагаем, что у вас где-то есть рабочий веб-сервер с установленным PHP.

В этом примере мы получим полезную нагрузку вебхука Ko-Fi (сервис пожертвований) на PHP-странице, которая затем использует полученные данные для вызова API Discourse и обновления заголовка и содержимого темы.

Конкретнее, она обновит заголовок темы суммой пожертвования и датой, а также добавит новую строку в таблицу, перечисляющую предыдущие пожертвования (она даже автоматически поднимет тему наверх :shushing_face:):

Каждый раз, когда пользователь делает пожертвование, Ko-Fi[^ko-fi-api] отправит запрос нашему PHP-скрипту.

[^ko-fi-api: Немного информации об их API: https://help.ko-fi.com/hc/en-us/articles/360004162298-Does-Ko-fi-Have-an-API-or-Webhook-

Настройка Ko-Fi

Я настроил конфигурацию на странице вебхуков Ko-Fi, просто добавив URL-адрес моего PHP-файла и записав токен проверки, скрытый в разделе “Дополнительно”.

При единичном пожертвовании Ko-Fi отправит нашу PHP-скрипту полезную нагрузку следующего вида:

data = {
  "verification_token": "d8546b84-c698-4df5-9811-39d35813e2ff",
  "message_id": "a499df4c-7bbb-4061-b4a6-8b9d969da689",
  "timestamp": "2023-10-19T13:35:06Z",
  "type": "Donation",
  "is_public": true,
  "from_name": "Jo Example",
  "message": "Good luck with the integration!",
  "amount": "3.00",
  "url": "https://ko-fi.com/Home/CoffeeShop?txid=00000000-1111-2222-3333-444444444444",
  "email": "jo.example@example.com",
  "currency": "USD",
  "is_subscription_payment": false,
  "is_first_subscription_payment": false,
  "kofi_transaction_id": "00000000-1111-2222-3333-444444444444",
  "shop_items": null,
  "tier_name": null,
  "shipping": null
}

Мы получим эту полезную нагрузку, затем извлечем две необходимые нам информации:

  • Сумму (3.00), которую мы округлим до целого числа.

  • Временную метку (2023-10-19T13:35:06Z), которую мы отформатируем в более красивый формат даты.

Получение полезной нагрузки от Ko-Fi

Сначала поместим следующий код на нашу PHP-страницу для получения запроса от Ko-Fi, где мы убедимся, что получили POST-запрос и что значение токена совпадает с тем, что указано на странице вебхуков Ko-Fi. Мы также отформатируем сумму и дату, как сказано выше.

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $jsonData = json_decode($_POST['data'], true);

    if ($jsonData['verification_token'] === 'YOUR_VERIFICATION_TOKEN') {
        $amount = floor(floatval($jsonData['amount']));
        $date = (new DateTime($jsonData['timestamp']))->format('d/m/Y');
    }
}

Замените:

  • YOUR_VERIFICATION_TOKEN на токен, предоставленный Ko-Fi

Обновление заголовка темы

Следующий шаг — обновить заголовок нашей темы. Мы используем curl в нашем PHP-скрипте для отправки PUT-запроса к правильной конечной точке.

        $putData = json_encode(['title' => '🥳 Новое пожертвование: ' . $amount . '€ от ' . $date]);
        $ch = curl_init('https://your-discourse.com/t/test-new-topic/TOPIC_ID');
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
        curl_setopt($ch, CURLOPT_POSTFIELDS, $putData);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
            'Content-Length: ' . strlen($putData),
            'Api-Key: YOUR_API_KEY',
            'Api-Username: YOUR_USERNAME'
        ]);
        curl_exec($ch);

Замените:

  • your-discourse.com на домен вашего форума
  • TOPIC_ID на правильный ID темы
  • YOUR_API_KEY на ваш ключ API
  • YOUR_USERNAME на имя пользователя, выбранное для ключа API

Обновление содержимого поста

Чтобы добавить новое содержимое к первому посту темы, нам сначала нужно получить его текущее содержимое с помощью GET-запроса.

        $ch_get = curl_init('https://your-discourse.com/posts/POST_ID.json');
        curl_setopt($ch_get, CURLOPT_RETURNTRANSFER, true);
        $currentContent = json_decode(curl_exec($ch_get), true)['raw'];

Замените:

  • POST_ID на правильный ID поста[2]

Наконец, нам нужно обновить содержимое поста, добавив новую строку в таблицу с суммой и датой. Мы сделаем это с помощью PUT-запроса.

        $updatedContent = $currentContent . "\n| " . $amount . "€ | " . $date . " |";
        $putPostData = json_encode(['post' => ['raw' => $updatedContent]]);
        $ch_put = curl_init('https://your-discourse.com/posts/POST_ID');
        curl_setopt($ch_put, CURLOPT_CUSTOMREQUEST, 'PUT');
        curl_setopt($ch_put, CURLOPT_POSTFIELDS, $putPostData);
        curl_setopt($ch_put, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
            'Content-Length: ' . strlen($putPostData),
            'Api-Key: YOUR_API_KEY',
            'Api-Username: YOUR_USERNAME'
        ]);
        curl_exec($ch_put);

Замените:

  • your-discourse.com на домен вашего форума
  • POST_ID на правильный ID поста
  • YOUR_API_KEY на ваш ключ API
  • YOUR_USERNAME на имя пользователя, выбранное для ключа API

Итоговый код выглядит следующим образом:

<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $jsonData = json_decode($_POST['data'], true);

    if ($jsonData['verification_token'] === 'YOUR_VERIFICATION_TOKEN') {
        $amount = floor(floatval($jsonData['amount']));
        $date = (new DateTime($jsonData['timestamp']))->format('d/m/Y');

        $putData = json_encode(['title' => '🥳 Новое пожертвование: ' . $amount . '€ от ' . $date]);
        $ch = curl_init('https://your-discourse.com/t/test-new-topic/TOPIC_ID');
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
        curl_setopt($ch, CURLOPT_POSTFIELDS, $putData);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
            'Content-Length: ' . strlen($putData),
            'Api-Key: YOUR_API_KEY',
            'Api-Username: YOUR_USERNAME'
        ]);
        curl_exec($ch);

        $ch_get = curl_init('https://your-discourse.com/posts/POST_ID.json');
        curl_setopt($ch_get, CURLOPT_RETURNTRANSFER, true);
        $currentContent = json_decode(curl_exec($ch_get), true)['raw'];

        $updatedContent = $currentContent . "\n| " . $amount . "€ | " . $date . " |";
        $putPostData = json_encode(['post' => ['raw' => $updatedContent]]);
        $ch_put = curl_init('https://your-discourse.com/posts/POST_ID');
        curl_setopt($ch_put, CURLOPT_CUSTOMREQUEST, 'PUT');
        curl_setopt($ch_put, CURLOPT_POSTFIELDS, $putPostData);
        curl_setopt($ch_put, CURLOPT_HTTPHEADER, [
            'Content-Type: application/json',
            'Content-Length: ' . strlen($putPostData),
            'Api-Key: YOUR_API_KEY',
            'Api-Username: YOUR_USERNAME'
        ]);
        curl_exec($ch_put);

        curl_close($ch);
        curl_close($ch_get);
        curl_close($ch_put);
    } else {
        http_response_code(403);
        echo "Неверный токен проверки.";
    }
} else {
    http_response_code(405);
    echo "Разрешены только POST-запросы.";
}
?>

Еще раз напомню предупреждение в начале этого руководства :stuck_out_tongue:

:warning: Все примеры кода в этом руководстве не предназначены для демонстрации лучших практик или для использования в таком виде.
Многие проверки, обработка ошибок и т. д. намеренно опущены или пропущены, чтобы сосредоточиться исключительно на использовании API.

Теперь мы можем отправить тестовый запрос от Ko-Fi и посмотреть, как он обновит нашу тему, как заголовок, так и содержимое. :slight_smile:

На этом всё!
У вас есть тема, которая будет обновляться и подниматься наверх каждый раз, когда кто-то делает пожертвование на Ko-Fi! :partying_face:


:information_source: Эта тема является вики-страницей. Пожалуйста, не стесняйтесь исправлять любые ошибки, которые вы видите, и обсуждать, как можно улучшить это руководство.


  1. Конкретный URL-адрес, в данном контексте. Например, https://your-discourse.com/posts.json ↩︎

  2. ID поста можно найти в HTML-коде. Это элемент <article> со следующим атрибутом: data-post-id="POST_ID" ↩︎

10 лайков

Это потрясающе, @Canapin, и, думаю, очень нужно. Я давно искал что-то подобное. Спасибо! :slight_smile:

3 лайка

Как указать подтему?
Если у меня есть jBASE с подтемой AutoDoc, нужно ли объединять их в одну тему с помощью какого-либо разделителя (jBASE>AutoDoc) или существует специальный тег категории?

Я разобрался. Когда вы находитесь на странице категории или подкатегории, в URL отображается символ # вместо названия категории. Поскольку у подкатегорий есть свои собственные номера, вам не нужно ничего совмещать.

Как мне заменить статью обновлённой информацией?

В данный момент я получаю
{“action”:“create_post”,“errors”:[“Заголовок уже используется”]}
вместо успешного обновления.

Разве для обновления постов нет другого действия?

Это текст ответа. В запросе curl не указано действие.

curl -X POST “http://LOCATION.local/posts.json” -H “Content-Type:
application/json” -H “Api-Key: APIKEY” -H “Api-Username: BOB” -d “{"title": "PL AUTO.DOC.FUN SCS
-TEST Autodoc","raw": " …”

Что, если вы используете endpoint для обновления темы?

Или, возможно, для обновления поста:

Я этого не заметил. Хорошее замечание. Попробую. Спасибо.

Обновление: чего-то всё ещё не хватает. Похоже, единственное отличие — добавление edit_reason. Я попробовал это, но разницы нет.

Вот полный curl:

curl -X POST “http://localhost.local/posts.json” -H “Content-Type:
application/json” -H “Api-Key: API KEY” -H “Api-Username: BOB” -d "{"title": "Title of the Article","raw": "The quick brown fox jumped over the lazy dog.\u003cb\u003e2023-12-26\u003c/b\u003e.","edit_reason": "auto","category": 66}

% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1927 0 65 100 1862 1177 33729 --:–:-- --:–:-- --:–:-- 34481

{“action”:“create_post”,“errors”:[“Заголовок уже использовался”]}

1 лайк

Для обновления темы или сообщения используйте метод PUT!

Как указал Firepup, если вы хотите обновить содержимое сообщения, вы можете воспользоваться следующим API: https://docs.discourse.org/#tag/Posts/operation/updatePost

Проблема в том, что для запроса PUT требуется ID#, а у меня их нет.
При создании новой темы через POST я собираю этот номер, но он, похоже, не работает.
Когда я открываю тему в браузере, там отображается другой номер, но и он, похоже, не работает.

Например: я создал тему, и ответ POST-запроса содержит {“id”:3244, …}.
В URL для доступа к ней указано …test-pl-auto-doc-fun/2803.

Таким образом, я отправляю этот PUT-запрос:
curl -X PUT “http://LOCATION.local/posts.json/3244” -H “Content-Type: application/json” -H “Api-Key: KEY” -H “Api-Username: system” -d
“{"title": "Autodoc SCS-TEST PL AUTO.DOC.FUN","raw": "…","edit_reason": "auto","category": 66}”

В ответ я получаю HTML-страницу с ошибкой «Страница не найдена».

Должно быть /posts/3244.json.

id, который вы получаете из этого POST-запроса, — это ID поста (первого поста); он уникален для всех постов.

Оба видео в руководстве возвращают ошибку 404.

1 лайк

Можно ли использовать API для вызова AI Helper?

Я так не думаю, потому что на docs.discourse.org об этом не упоминается. Хотя, возможно, я ошибаюсь.

Почему AI-помощник следует использовать через API :thinking:

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

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

Тогда, вероятно, ai-bot — это именно то, что вам нужно. ai-helper помогает при чтении и написании постов.

Как указано в примечании, это не полный список.

Примечание: Для любых конечных точек, не перечисленных здесь, вы можете следовать руководству по реверс-инжинирингу API Discourse, чтобы понять, как использовать конечную точку API.

2 лайка

Всё, что можно сделать через UX, можно сделать и через API. Реверс-инжиниринг API Discourse

В API постоянно что-то добавляется и меняется. Мне проще всегда просто посмотреть, что именно происходит в браузере.

5 лайков

Отличная идея, спасибо!