Discourse REST API 종합 예제

다양한 API 사용법이나 설명을 다루는 여러 가이드가 있습니다.

이 가이드는 API를 사용하는 방법에 대한 실용적이고 포괄적인 예시를 제공합니다.

:warning: 이 가이드의 모든 코드 예시는 모범 사례를 보여주기 위한 것이거나 그대로 사용하도록 의도된 것이 아닙니다.
API 사용법에 집중하기 위해 많은 검사, 오류 처리 등이 의도적으로 무시되거나 생략되었습니다.

API는 무엇에 사용되는가?

Discourse에서의 대부분의 작업(게시, 좋아요, 설정 편집 등)은 엔드포인트[1]에 요청을 보내는 API를 통해 수행됩니다.

예를 들어, meta에서 주제를 생성할 때 https://meta.discourse.org/posts.json으로 POST 요청이 전송됩니다. 이 요청에는 게시물의 작성자, 제목, 카테고리, 태그 및 내용 등이 포함됩니다.

API를 커스텀으로 사용하는 것은 일반적으로 자동화된 작업을 수행하거나 웹훅, 스크립트, 제3자 소프트웨어 및 API 등 다른 서비스와 함께 사용하기 위해 이루어집니다.

API를 사용하려면 API 자격 증명이 필수적입니다. 다음 가이드를 따라 몇 번의 클릭으로 설정할 수 있습니다: Create and configure an API key

더 이상 기다리지 말고, API 사용 사례의 첫 번째 예시로 들어가 보겠습니다. :technologist:

월간 주제 생성

이 예시에서는 curl과 cron을 사용하여 포럼에 월간 “자유 토론” 주제를 생성하는 방법을 보여줍니다. 온라인 커뮤니티에서 인기 있는 관행입니다 :slight_smile:

API 키 생성

API 키 생성 가이드를 따르세요. **사용자 수준(User Level)**을 단일 사용자(Single User)로 설정합니다.
선택된 사용자는 월간 주제의 작성자가 됩니다.
그 다음 전역(Global) 범위를 선택하거나, 세분화(Granular) 범위를 선택할 수 있습니다. 후자의 경우 주제(Topics) → 쓰기(write) 액세스 권한이 최소한 필요합니다.
생성된 API 키를 적어 두세요. :writing_hand:

curl 명령 생성

서버의 명령줄에서 다음 명령을 실행하여 API 키와 함께 curl 및 Discourse REST 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\": \"Test topic creation with the API\", \"raw\": \"And here's the topic's content\", \"category\": CATEGORY_ID }"

다음 항목을 대체하세요:

  • your-discourse.com을 포럼 도메인으로
  • YOUR_API_KEY을 API 키로
  • YOUR_USERNAME을 API 키에 선택된 사용자 이름으로
  • CATEGORY_ID을 주제를 게시할 카테고리의 ID로

모든 것이 올바르게 설정되어 있다면, 포럼에 다음과 같은 새로운 테스트 주제가 생성되어야 합니다:

이 단계에서 대부분의 작업이 완료되었습니다! 이제 주제의 제목과 내용을 더 적절한 것으로 변경하고, 주제 생성의 반복 주기를 설정해야 합니다.

먼저 주제의 제목을 다음에서:
Test topic creation with the API
다음으로 변경합니다:
Free talk of the month - $(date +\%B).

내용도 마찬가지로 다음에서:
Test topic creation with the API
다음으로 변경해 보겠습니다:
What have you appreciated the most and the less during $(date +\%B -d 'last month')?\nFeel free to share your feelings and provide ideas. 🙂

:information_source: date Unix 명령을 사용하여 제목에 현재 월의 이름, 내용에 이전 월의 이름을 삽입하고 있습니다.

:information_source: 내용에서 \n은 새 줄을 생성합니다.

명령줄을 사용하여 업데이트된 curl 요청을 실행할 수 있습니다. 포럼에 다음과 같은 새로운 주제가 생성되었어야 합니다:

반복 이벤트 설정

매월 첫날에 curl 명령을 실행하는 cron 작업을 생성하겠습니다. :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\": \"Free talk of the month - $(date +\%B)\", \"raw\": \"What have you appreciated the most and the less during $(date +\%B -d 'last month')?\nFeel free to share your feelings and provide ideas. 🙂\", \"category\": 4 }"

:information_source: 0 0 1 * * 부분은 명령이 실행되는 간격을 정의합니다. 구문법에 대해 더 자세히 알아보려면 여기를 참조하세요: https://crontab.guru

완료되었습니다! 이제 서버는 Discourse REST API, 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 # Winter
                  when 4..6 then 15 # Spring
                  when 7..9 then 16 # Summer
                  else           17 # Autumn
                  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가 설치된 작동하는 웹 서버가 있다고 가정합니다.

이 예시에서는 PHP 페이지에서 Ko-Fi (기부 서비스) 웹훅 페이로드를 수신한 후, 수신된 데이터를 사용하여 Discourse API를 통해 주제의 제목과 내용을 업데이트하는 방법을 보여줍니다.

구체적으로, 주제의 제목을 기부 금액과 날짜로 업데이트하고, 이전 기부를 나열하는 표에 새 줄을 추가합니다 (주제를 자동으로 올리는 것까지 포함됩니다 :shushing_face:):

사용자가 기부를 할 때마다, Ko-Fi[2]는 우리의 PHP 스크립트로 요청을 전송합니다.

Ko-Fi 설정

Ko-Fi 웹훅 페이지에서 PHP 파일 URL을 단순히 추가하고 고급 섹션에 숨겨진 검증 토큰을 적어 두어 설정을 했습니다.

단일 기부의 경우, 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 페이로드 수신

먼저, Ko-Fi에서 요청을 수신하기 위해 다음 코드를 PHP 페이지에 넣습니다. 여기서 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가 제공한 토큰으로

주제 제목 업데이트

다음 단계는 주제의 제목을 업데이트하는 것입니다. PHP 스크립트에서 curl을 사용하여 올바른 엔드포인트에 PUT 요청을 보내겠습니다.

        $putData = json_encode(['title' => '🥳 New donation: ' . $amount . '€ on ' . $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로[3]

마지막으로, 금액과 날짜를 가진 새 줄을 표에 추가하여 게시물 내용을 업데이트해야 합니다. 이를 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' => '🥳 New donation: ' . $amount . '€ on ' . $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 "Invalid verification token.";
    }
} else {
    http_response_code(405);
    echo "Only POST requests are allowed.";
}
?>

이 가이드开头的에 있는 경고를 다시 강조하고 싶습니다 :stuck_out_tongue:

:warning: 이 가이드의 모든 코드 예시는 모범 사례를 보여주기 위한 것이거나 그대로 사용하도록 의도된 것이 아닙니다.
API 사용법에 집중하기 위해 많은 검사, 오류 처리 등이 의도적으로 무시되거나 생략되었습니다.

이제 Ko-Fi에서 테스트 요청을 트리거하여 제목과 내용 모두를 어떻게 업데이트하는지 확인해 볼 수 있습니다. :slight_smile:

이것으로 끝입니다!
Ko-Fi에서 누군가가 기부를 할 때마다 업데이트되고 올라가는 주제를 갖게 되었습니다! :partying_face:


:information_source: 이 주제는 위키입니다. 발견한 오류를 수정하고 이 가이드를 어떻게 개선할 수 있는지 논의하는 데 자유롭게 참여해 주세요.


  1. 이 맥락에서는 특정 URL을 의미합니다. 예를 들어, https://your-discourse.com/posts.json ↩︎

  2. 그들의 API에 대한 정보: https://help.ko-fi.com/hc/en-us/articles/360004162298-Does-Ko-fi-Have-an-API-or-Webhook- ↩︎

  3. 게시물 ID는 HTML 코드에서 찾을 수 있습니다. 다음 속성을 가진 <article> 요소입니다: data-post-id="POST_ID" ↩︎

10개의 좋아요

정말 멋지네요, @Canapin. 꼭 필요했던 것 같아요. 얼마 전에도 이런 걸 찾고 있었거든요. 감사합니다! :slight_smile:

3개의 좋아요

서브토픽을 어떻게 지정하나요?
jBASE에 AutoDoc라는 서브토픽이 있는 경우, 구분자를 사용해 두 가지를 토픽으로 합쳐야 하는지(jBASE>AutoDoc) 아니면 카테고리 태그가 따로 있는 건지 궁금합니다.

해결했어요. 카테고리 또는 하위 카테고리 페이지에 있으면 URL에 카테고리 이름 대신 #이 표시됩니다. 하위 카테고리는 각각 고유한 번호를 가지고 있으므로 아무것도 조합할 필요가 없어요.

기사가 최신 정보로 업데이트되도록 교체하려면 어떻게 해야 하나요?

현재 다음과 같은 응답을 받고 있습니다:
{“action”:“create_post”,“errors”:[“Title has already been used”]}
성공적인 업데이트 대신에요.

게시글을 업데이트하기 위한 다른 액션이 없나요?

이것이 응답 텍스트입니다. 요청한 curl 명령어에는 동작(action)이 지정되어 있지 않습니다.

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": " …

토픽을 업데이트하는 데 엔드포인트를 사용하는 것은 어떨까요?

아니면 게시물을 업데이트하는 것:

그걸 못 봤네요. 잘 찾았어요. 한번 시도해 볼게요. 감사합니다.

업데이트: 여전히 뭔가 빠진 것 같습니다. 유일한 차이점이 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.2023-12-26.","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”:[“Title has already been used”]}

1개의 좋아요

토픽이나 게시글을 수정하려면 PUT 메서드를 사용해야 합니다!

Firepup 님이 지적했듯이, 게시글의 내용을 수정하려면 다음 API를 활용할 수 있습니다: https://docs.discourse.org/#tag/Posts/operation/updatePost

문제는 PUT 요청에 ID#가 필요한데, 내가 그 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}”

그리고 페이지를 찾을 수 없는(404) HTML을 반환받습니다.

/posts/3244.json이어야 합니다.

해당 POST 요청에서 받는 id는 게시글 ID(첫 번째 게시글의)이며, 모든 게시글에서 고유합니다.

가이드의 두 비디오 모두 404 오류를 반환하는 것 같습니다.

1개의 좋아요

API를 통해 AI Helper를 호출할 수 있나요?

아니라고 생각해요. docs.discourse.org에 그런 언급이 없거든요. 물론 틀린 것일 수도 있지만요.

왜 AI 도우미를 API를 통해 사용해야 할까요? :thinking:

웹사이트에 연결된 봇을 만들어 포럼에 축적된 7년 치 지식을 활용하여 질문에 답하게 하거나, 포럼에 연결된 봇을 만들어 이메일에 응답하고 7년 치 지식을 활용하여 질문에 답하게 하는 것입니다.

그럼 아마 #ai-bot이 더 찾으시는 것일 수 있습니다. #ai-helper는 게시물을 읽거나 작성할 때 도움을 주는 봇입니다.

주석에 나와 있듯이, 그것은 전체 목록이 아닙니다.

참고: 목록에 없는 엔드포인트의 경우 Discourse API 역공학 가이드를 따라 API 엔드포인트 사용 방법을 파악할 수 있습니다.

2개의 좋아요

UX에서 할 수 있는 모든 작업은 API로도 수행할 수 있습니다. Discourse API 역공학하기

API에는 항상 새로운 기능이 추가되고 변경 사항이 발생합니다. 저는 브라우저에서 실제로 어떤 일이 일어나고 있는지 확인하는 것이 항상 더 쉽다고 생각합니다.

5개의 좋아요

훌륭한 아이디어네요, 감사합니다!