| 플랫폼 | 구분 | 연동 방식 | 지원 기능 |
|---|---|---|---|
| 치지직 (CHZZK) | 공식 | OpenAPI OAuth + WebSocket | 치즈(후원) |
| 숲 (SOOP) | 공식 | OpenAPI OAuth + Binary WebSocket | 별풍선 |
| 씨미 (CIME) | 공식 | OpenAPI OAuth + WebSocket | 빔(후원) |
| SSAPI | 통합 | Socket.io 기반 통합 중계 | 치지직 + 숲 통합 |
| 투네이션 (Toonation) | 비공식 | 페이로드 토큰 + WebSocket | 일반 후원 |
| 유튜브 (YouTube) | 비공식 | 라이브챗 폴링 | 슈퍼챗 |
| 항목 | 최소 버전 |
|---|---|
| Minecraft | 1.20.1+ (Paper/Folia) |
| Java | 21 |
| RSFramework | 4.7.17+ |
- 최신 릴리즈에서
DonationAPI-1.6.1.jar를 다운로드합니다. - 서버의
plugins/폴더에 JAR 파일을 배치합니다. - 서버를 시작하면 기본 설정 파일이 자동 생성됩니다.
plugins/DonationAPI/Config/Services/하위의 플랫폼별 설정 파일을 편집합니다./후원API reload또는 서버 재시작으로 설정을 적용합니다.
OAuth 기반 플랫폼(치지직, 숲, 씨미)을 사용하려면, 먼저 각 플랫폼의 개발자 사이트에서 어플리케이션을 생성하고 Client ID와 Client Secret을 발급받아야 합니다.
| 플랫폼 | 개발자 포털 | 비고 |
|---|---|---|
| 치지직 (CHZZK) | https://developers.chzzk.naver.com/application | 네이버 로그인 필요 |
| 숲 (SOOP) | https://developers.sooplive.com/?szWork=myinfo | SOOP 계정 필요 |
| 씨미 (CIME) | https://developers.ci.me/applications | 씨미 계정 필요 |
Redirect URI 설정: 어플리케이션 생성 시 Redirect URI(콜백 주소)를 설정해야 합니다. 설정 파일의
base-uri값을 기준으로 자동 생성되며, 기본값은http://localhost:3663입니다. 외부 접속이 필요한 경우 포트포워딩 후 공인 IP 또는 도메인으로 변경하세요.
플러그인을 처음 실행하면 아래와 같은 설정 파일이 자동 생성됩니다.
plugins/DonationAPI/Config/
├── Global.yml # 전역 설정 (후원 알림 등)
└── Services/
├── CHZZK.yml # 치지직 설정
├── SOOP.yml # 숲 설정
├── CIME.yml # 씨미 설정
├── SSAPI.yml # SSAPI 설정
├── Toonation.yml # 투네이션 설정
└── YouTube.yml # 유튜브 설정
사전 준비: 치지직 개발자 포털에서 어플리케이션을 생성하고
Client ID와Client Secret을 발급받으세요.
plugins/DonationAPI/Config/Services/CHZZK.yml:
# 서비스 활성화 여부
enabled: true
# 브랜드 색상 (HEX)
color: "#00FFA3"
# 클라이언트 ID (개발자 포털에서 발급)
client-id: "00000000-0000-0000-0000-000000000000"
# 클라이언트 시크릿 (개발자 포털에서 발급)
client-secret: "secret"
# OAuth 콜백을 받을 접속용 주소
base-uri: "http://localhost:3663"
# 내장 HTTP 서버 바인드 호스트
host: "0.0.0.0"
# 내장 HTTP 서버 바인드 포트
port: 3663
# 라이브 상태 확인 주기 (ms)
live-check-interval: 15000
# 소켓 옵션
socket:
# 소켓 연결 타임아웃 (ms)
timeout: 3000
keepalive:
# 서버-클라이언트 간 keepalive(ping) 사용 여부
enabled: false
# keepalive 주기 (ms)
interval: 60000
reconnection:
# 자동 재연결 활성화 여부
enabled: false
# 재연결 최초 지연 (ms)
delay: 1000
# 재연결 최대 지연 (ms)
max-delay: 3000설정 방법:
- 개발자 포털에서 발급받은 값을
client-id,client-secret에 입력 - Redirect URI에
{base-uri}/auth/chzzk/callback형태로 등록 (ex:http://localhost:3663/auth/chzzk/callback) - 외부 접속 시
base-uri를 공인 IP/도메인으로 변경하고port에 맞게 포트포워딩 설정 - 인게임에서
/후원API 치지직 연동명령어로 OAuth 인증 진행
사전 준비: 숲 개발자 포털에서 어플리케이션을 생성하고
Client ID와Client Secret을 발급받으세요.
plugins/DonationAPI/Config/Services/SOOP.yml:
# 서비스 활성화 여부
enabled: true
# 브랜드 색상 (HEX)
color: "#0050FF"
# 클라이언트 ID (개발자 포털에서 발급)
client-id: "00000000000000000000000000000000"
# 클라이언트 시크릿 (개발자 포털에서 발급)
client-secret: "secret"
# OAuth 콜백을 받을 접속용 주소
base-uri: "http://localhost:3663"
# 내장 HTTP 서버 바인드 호스트
host: "0.0.0.0"
# 내장 HTTP 서버 바인드 포트
port: 3663
# 라이브 상태 확인 주기 (ms)
live-check-interval: 30000
# 소켓 옵션
socket:
# 소켓 연결 타임아웃 (ms)
timeout: 3000
keepalive:
# 서버-클라이언트 간 keepalive(ping) 사용 여부
enabled: true
# keepalive 주기 (ms)
interval: 60000
reconnection:
# 자동 재연결 활성화 여부
enabled: true
# 재연결 최초 지연 (ms)
delay: 1000
# 재연결 최대 지연 (ms)
max-delay: 30000설정 방법:
- 개발자 포털에서 발급받은 값을
client-id,client-secret에 입력 - Redirect URI에
{base-uri}/auth/soop/callback형태로 등록 (ex:http://localhost:3663/auth/soop/callback) - 외부 접속 시
base-uri를 공인 IP/도메인으로 변경하고port에 맞게 포트포워딩 설정 - 인게임에서
/후원API 숲 연동명령어로 OAuth 인증 진행
사전 준비: 씨미 개발자 포털에서 어플리케이션을 생성하고
Client ID와Client Secret을 발급받으세요.
plugins/DonationAPI/Config/Services/CIME.yml:
# 서비스 활성화 여부
enabled: true
# 브랜드 색상 (HEX)
color: "#8A2BE2"
# 클라이언트 ID (개발자 포털에서 발급)
client-id: "00000000-0000-0000-0000-000000000000"
# 클라이언트 시크릿 (개발자 포털에서 발급)
client-secret: "secret"
# OAuth 콜백을 받을 접속용 주소
base-uri: "http://localhost:3663"
# 내장 HTTP 서버 바인드 호스트
host: "0.0.0.0"
# 내장 HTTP 서버 바인드 포트
port: 3663
# 라이브 상태 확인 주기 (ms)
live-check-interval: 30000
# 소켓 옵션
socket:
# 소켓 연결 타임아웃 (ms)
timeout: 3000
keepalive:
# 서버-클라이언트 간 keepalive(ping) 사용 여부
# (씨미 API 10분 유휴 타임아웃 방지)
enabled: true
# keepalive 주기 (ms)
interval: 60000
reconnection:
# 자동 재연결 활성화 여부
enabled: true
# 재연결 최초 지연 (ms)
delay: 1000
# 재연결 최대 지연 (ms)
max-delay: 30000설정 방법:
- 개발자 포털에서 발급받은 값을
client-id,client-secret에 입력 - Redirect URI에
{base-uri}/auth/cime/callback형태로 등록 (ex:http://localhost:3663/auth/cime/callback) - 외부 접속 시
base-uri를 공인 IP/도메인으로 변경하고port에 맞게 포트포워딩 설정 - 인게임에서
/후원API 씨미 연동명령어로 OAuth 인증 진행
참고: 씨미 WebSocket은 10분간 데이터가 없으면 유휴 타임아웃으로 연결이 끊길 수 있습니다.
keepalive.enabled: true를 유지하는 것을 강력히 권장합니다.
SSAPI는 스트리머 지원 API 통합 중계 서비스로, 별도의 OAuth 과정 없이 API 키 하나로 치지직과 숲 후원을 동시에 수신할 수 있습니다.
plugins/DonationAPI/Config/Services/SSAPI.yml:
# 서비스 활성화 여부
enabled: true
# 브랜드 색상 (HEX)
color: "#FFFFFF"
# SSAPI API 키
api-key: ""
# 로그인 재시도 간격 (ms)
login-retry-delay: 1000
# 소켓 옵션
socket:
# 소켓 연결 타임아웃 (ms)
timeout: 3000
keepalive:
enabled: true
interval: 60000
reconnection:
enabled: true
delay: 1000
max-delay: 3000설정 방법:
- SSAPI 사이트에서 API 키를 발급받아
api-key에 입력 - 인게임에서
/후원API SSAPI(치지직) 연동 <ID>또는/후원API SSAPI(숲) 연동 <ID>명령어로 연동
투네이션은 비공식 연동으로, 알림 위젯 페이지에서 발급하는 페이로드 토큰을 사용합니다.
plugins/DonationAPI/Config/Services/Toonation.yml:
# 서비스 활성화 여부
enabled: true
# 브랜드 색상 (HEX)
color: "#00C7ED"
# 소켓 옵션
socket:
# 소켓 연결 타임아웃 (ms)
timeout: 3000
keepalive:
enabled: false
interval: 60000
reconnection:
enabled: true
delay: 1000
max-delay: 30000설정 방법:
- 투네이션 알림 위젯 페이지에서 페이로드 토큰을 복사
- 인게임에서
/후원API 투네이션 연동 <토큰>명령어로 연동
토큰 획득 방법: 투네이션 대시보드 → 위젯 → 알림 위젯 → 임의 알림 위젯을 선택하고 주소(URL)의
payload파라미터 값이 토큰입니다.
유튜브는 비공식 연동으로, 별도의 인증 없이 채널 ID만으로 라이브 슈퍼챗을 수신합니다.
plugins/DonationAPI/Config/Services/YouTube.yml:
# 서비스 활성화 여부
enabled: true
# 브랜드 색상 (HEX)
color: "#FF0000"
# 유튜브 라이브챗 폴링 간격 (ms)
polling-interval-ms: 5000
# 라이브 상태 확인 주기 (ms)
live-check-interval: 60000설정 방법:
- 유튜브 채널의 채널 ID를 확인 (채널 URL의
@handle또는UC...형태의 ID) - 인게임에서
/후원API 유튜브 연동 <채널ID>명령어로 연동
참고: 유튜브 연동은 라이브 방송 중에만 슈퍼챗을 수신합니다. 폴링 방식이므로 실시간성이 다소 떨어질 수 있습니다.
plugins/DonationAPI/Config/Global.yml:
# 후원 알림 설정 (서버 전체 브로드캐스트)
donation-notify: false기본 명령어: /donationapi (별칭: /후원API)
| 명령어 | 설명 |
|---|---|
/후원API 치지직 연동 |
치지직 OAuth 인증 링크 생성 |
/후원API 숲 연동 |
숲 OAuth 인증 링크 생성 |
/후원API 씨미 연동 |
씨미 OAuth 인증 링크 생성 |
/후원API 투네이션 연동 <토큰> |
투네이션 위젯 토큰으로 연동 |
/후원API 유튜브 연동 <채널ID> |
유튜브 채널 연동 |
/후원API SSAPI(치지직) 연동 <ID> |
SSAPI 치지직 통합 연동 |
/후원API SSAPI(숲) 연동 <ID> |
SSAPI 숲 통합 연동 |
/후원API [플랫폼] 연동해제 |
해당 플랫폼의 연결 해제 |
| 명령어 | 설명 |
|---|---|
/후원API 이벤트 <닉네임> <금액> [메시지] |
테스트용 후원 이벤트 발생 |
/후원API reload |
설정 및 서비스 전체 재로드 |
모든 명령어는 OP 권한이 필요합니다.
PlaceholderAPI가 설치되면 자동으로 Placeholder가 등록됩니다.
| Placeholder | 설명 |
|---|---|
%donationapi_chzzk% |
치지직 연결 상태 |
%donationapi_soop% |
숲 연결 상태 |
%donationapi_cime% |
씨미 연결 상태 |
%donationapi_toonation% |
투네이션 연결 상태 |
%donationapi_youtube% |
유튜브 연결 상태 |
%donationapi_ssapi_chzzk% |
SSAPI 치지직 연결 상태 |
%donationapi_ssapi_soop% |
SSAPI 숲 연결 상태 |
참고: 연결 상태는 테스트 후원 또는 실제 후원이 최소 1회 이상 인식되어야
true로 표시됩니다.
| Placeholder | 설명 |
|---|---|
%donationapi_live_[플랫폼]% |
방송 중 여부 (true/false) |
%donationapi_title_[플랫폼]% |
방송 제목 |
%donationapi_viewers_[플랫폼]% |
시청자 수 |
%donationapi_url_[플랫폼]% |
방송 채널 URL |
[플랫폼]에는chzzk,soop,cime,youtube를 사용할 수 있습니다.
모든 플랫폼의 후원은 Bukkit의 DonationEvent로 통합됩니다.
import kr.rtustudio.donation.bukkit.event.DonationEvent;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
public class DonationListener implements Listener {
@EventHandler
public void onDonation(DonationEvent event) {
String nickname = event.getNickname();
int amount = event.getAmount(); // 플랫폼 단위 수량
int price = event.getPrice(); // 원 환산 금액
String unit = event.getUnit(); // 단위명 (치즈, 개 등)
String message = event.getMessage();
if (event.getPlayer() != null) {
event.getPlayer().sendMessage(
String.format("§e%s§f님이 §d%,d§f%s를 후원! §7%s",
nickname, amount, unit, message)
);
}
}
}DonationEvent 메서드:
| 메서드 | 반환 타입 | 설명 |
|---|---|---|
getPlayer() |
@Nullable Player |
후원 대상 플레이어 |
getDonation() |
Donation |
통합 후원 데이터 |
getService() |
Services |
서비스 유형 (CHZZK, SOOP 등) |
getPlatform() |
Platform |
실제 플랫폼 |
getNickname() |
String |
후원자 닉네임 |
getAmount() |
int |
후원 수량 (플랫폼 단위) |
getPrice() |
int |
원 환산 금액 |
getUnit() |
String |
단위명 |
getMessage() |
String |
후원 메시지 |
isCancelled() |
boolean |
이벤트 취소 여부 |
Donation은 불변 record로 정의됩니다.
public record Donation(
@Nullable UUID uniqueId, // 후원 대상 플레이어 UUID
Services service, // 서비스 유형
Platform platform, // 실제 플랫폼
DonationType type, // CHAT 또는 VIDEO
String streamer, // 스트리머 식별자
String donator, // 후원자 식별자
String nickname, // 후원자 닉네임 (기본: "익명의 후원자")
String message, // 후원 메시지
int amount // 후원 수량
) {
public String unit() { return platform.unit(); }
public int price() { return amount * platform.rate(); }
}플랫폼별 단위 및 환산:
| 플랫폼 | 단위 | 환산(rate) | 예시 |
|---|---|---|---|
| 치지직 | 치즈 | ×1 | 1,000치즈 → 1,000원 |
| 숲 | 개 | ×100 | 5개 → 500원 |
| 씨미 | 빔 | ×1 | 1,000빔 → 1,000원 |
| 투네이션 | 캐시 | ×1 | 5,000캐시 → 5,000원 |
| 유튜브 | 원 | ×1 | 1,000원 → 1,000원 |
Services vs Platform:
Services는 연동 서비스를 나타내고, Platform은 후원이 발생한 실제 플랫폼을 나타냅니다.
예를 들어 SSAPI 서비스는 치지직과 숲 두 플랫폼을 모두 지원합니다.
| Services | 지원 Platform |
|---|---|
CHZZK |
CHZZK |
SOOP |
SOOP |
CIME |
CIME |
SSAPI |
CHZZK, SOOP |
Toonation |
TOONATION |
YOUTUBE |
YOUTUBE |
LiveStatusManager를 통해 연결된 스트리머의 방송 상태를 조회할 수 있습니다.
LiveStatusManager manager = BukkitDonationAPI.getInstance().getLiveStatusManager();
LiveStatus status = manager.getLiveStatus(Services.CHZZK, player.getUniqueId());
if (status != null && status.live()) {
player.sendMessage(
String.format("방송 중: %s (시청자 %,d명)", status.title(), status.viewerCount())
);
}LiveStatus 필드:
| 필드 | 타입 | 설명 |
|---|---|---|
live() |
boolean |
방송 중 여부 |
title() |
@Nullable String |
방송 제목 |
viewerCount() |
int |
시청자 수 |
channelUrl() |
String |
채널 URL |
updatedAt() |
long |
캐시 갱신 시각 (epoch ms) |
라이브 상태는 플랫폼별 설정의
liveCheckInterval에 지정된 주기로 자동 폴링됩니다.
DonationAPI는 자체적으로 Skript 연동을 지원하므로, 애드온 없이 플러그인 환경에서 직접 스크립트로 후원 이벤트를 감지할 수 있습니다.
이벤트 구문:
on donation:
if player is set:
send "&e&l[후원] &f%donation nickname%님이 &d%donation amount%%donation unit%&f를 후원했습니다!" to player
broadcast "&7메시지: %donation message%"
broadcast "&7플랫폼: %donation platform%"지원 수식어(Expression):
| 구문 | 반환 타입 | 설명 |
|---|---|---|
event-player 또는 player |
Player | 이벤트를 연동한 대상 플레이어 |
donation message |
String | 후원 메시지 |
donation amount |
Number | 후원 수량 (플랫폼 기준 단위) |
donation price |
Number | 원(KRW) 환산 금액 |
donation unit |
String | 단위명 (치즈, 개, 캐시 등) |
donation nickname |
String | 후원자 닉네임 |
donation donator |
String | 후원자 고유 식별자 |
donation streamer |
String | 후원 대상 스트리머 / 방송국 |
donation platform |
String | 결제 플랫폼 (CHZZK, SOOP 등) |
DonationAPI/
├── Services/ # 프레임워크 독립 코어 서비스 (순수 Java)
│ ├── Common/ # 통합 모델 (Donation, Platform, AsyncExecutor)
│ ├── CHZZK/ # 치지직 — OpenAPI + WebSocket
│ ├── SOOP/ # 숲 — OpenAPI + Binary WebSocket
│ ├── CIME/ # 씨미 — OpenAPI + WebSocket
│ ├── SSAPI/ # SSAPI — Socket.io 통합 중계
│ ├── Toonation/ # 투네이션 — WebSocket
│ └── YouTube/ # 유튜브 — 라이브챗 폴링
│
└── Platform/ # 프레임워크 종속 어댑터
├── Common/ # 플랫폼 공통 API (DonationAPI 레지스트리)
└── Bukkit/ # Bukkit 통합 계층
├── command/ # 명령어 처리
├── configuration/ # GlobalConfig + 플랫폼별 Config
├── event/ # DonationEvent
├── handler/ # PlayerJoinQuit 리스너
├── integration/ # PlaceholderAPI 연동
├── manager/ # DonationManager, LiveStatusManager
└── platform/ # ServiceBuilder, PlatformRegistry
- BukkitDonationAPI — RSPlugin 메인 클래스. 서비스 생명주기와 설정 관리를 담당합니다.
- PlatformRegistry —
DonationPlatform인스턴스를 관리하며 플레이어 연결/해제 상태를 추적합니다. - DonationAPI —
Service인스턴스 레지스트리. 등록된 서비스의 시작/종료를 관리합니다. - ServiceBuilder — 서비스 생성, 핸들러 연결, 플랫폼 등록을 선언적으로 처리하는 빌더입니다.
- ServiceHandler<R> — 후원(
donation), 성공(success), 실패(failure), 알림(messenger) 콜백을 묶는 record입니다. - AsyncExecutor — Java 21 Virtual Thread 기반 공유 Executor. 모든 I/O 비동기 작업에 사용됩니다.
새 후원 플랫폼을 추가할 때 ServiceBuilder로 서비스 등록을 선언적으로 처리합니다.
register(ServiceBuilder.builder()
.config(ChzzkConfig.class) // 설정 클래스
.data(ChzzkPlayer.class) // 플레이어 데이터 타입
.factory(ChzzkService::new) // 서비스 팩토리
.reconnect((service, data) -> // 재연결 콜백 (선택)
service.reconnect(data.uuid(), data))
.build(this)
);빌더 흐름:
builder()→ 공통 빌더 생성.config(Class)→ 설정 클래스 바인딩.data(Class)→ 데이터 타입 바인딩 →TypedBuilder전환.factory(ServiceFactory)→ 서비스 팩토리 설정.reconnect(ReconnectFunction)→ 재연결 로직 설정 (선택).build(plugin)→ServiceBuilder<D, S>완성
# 빌드 (테스트 포함)
./gradlew build
# 빌드 (테스트 제외)
./gradlew build -x test빌드 결과물: build/libs/DonationAPI-1.6.1.jar
이 프로젝트는 GNU General Public License v3.0 하에 배포됩니다.
Made with ❤️ by RTU Studio