Beat Saber 플레이어를 위한 한국어 Discord 봇. ScoreSaber 프로필을 Discord 계정에 연동해서 PP/랭킹을 조회하고, 등록된 유저의 PP 변동을 매일 기록해 전적 조회·그래프·유저 간 비교 기능을 제공한다.
discord.py 2.x 기반. 입력하면 Discord가 파라미터 힌트를 띄워주고, 세부 기능은 결과 메시지의 버튼으로 조작한다.
| 명령어 | 설명 | 버튼 |
|---|---|---|
/info [player] |
ScoreSaber 프로필 embed (비우면 !등록된 내 계정) |
📜 History · 📈 Graph · 🌾 Farm picks |
/recommend [map] [count] |
map에 ScoreSaber/BeatLeader 리더보드 주소·id를 주면 유사 곡 추천 (플랫폼 자동 판별), 비우면 내 계정 기준 유사 유저+farm 추천 |
📥 Playlist(.bplist) · ➕ More |
접두사는 !. 모든 명령은 한글/영문 축약형을 함께 지원한다.
| 명령어 | 축약형 | 설명 |
|---|---|---|
!등록 <스코어세이버 주소> |
!r |
내 Discord 계정에 ScoreSaber 프로필 연동 (재등록 가능) |
!검색 <닉네임> |
!s |
닉네임으로 ScoreSaber 검색, 상위 5명 중 이모지 반응으로 골라 등록 |
!타등록 <discord_id> <주소> |
!or |
다른 사람의 계정을 대신 등록 |
!추가 <스코어세이버 주소> |
!a |
일일 PP 기록 대상에 추가 (다음 날부터 기록) |
!내정보 |
!i |
내 프로필 embed — 세계/국내 랭킹, PP, 랭크곡 평균 정확도, 오늘 얻은 PP |
!타정보 <discord_id> |
!oi |
등록된 다른 유저의 프로필 embed |
!내전적 [개수] [csv|txt] |
!h |
일자별 PP·랭킹·증가량 기록 출력 (기본 20개, 파일로 저장 가능) |
!그래프 [개수] |
!g |
PP 변화 그래프 PNG (pchip 보간, 기본 최근 20개) |
!비교 [개수] - 주소1,주소2,... |
!c |
최대 7명의 PP 변화를 한 그래프에 비교 |
!랭킹 [국가코드] |
ScoreSaber 전체/국가 랭킹 링크 | |
!곡추천 <리더보드 주소|id> [개수] |
!rec |
ScoreSaber 랭크곡 추천 — 리더보드 유저 서열이 유사한 곡 + 플레이리스트 파일 |
!블곡추천 <리더보드 주소|id> [개수] |
!blrec |
BeatLeader 랭크곡 추천 (위와 동일 방식) + 플레이리스트 파일 |
!유저추천 [스코어세이버 주소] [개수] |
!urec |
나(또는 지정 유저)보다 pp 높은 유저 중 top곡 구성이 비슷한 유저 + farm 후보곡 플레이리스트 |
!유저정보갱신 [전적|추천|전체] |
!유저갱신 |
유저 PP 기록 또는 ScoreSaber 유저 추천 데이터를 백그라운드에서 최신화 (관리 권한 필요) |
!맵정보갱신 [전체|ss|bl] |
!맵갱신 |
ScoreSaber/BeatLeader 맵 추천 데이터를 백그라운드에서 최신화 (관리 권한 필요) |
!갱신상태 |
!updatestatus |
추천 데이터 갱신 작업 실행 상태와 최근 로그 확인 (관리 권한 필요) |
discord_bot.py # 엔트리포인트 — prefix 명령 정의·입력 파싱·응답 (discord.py 2.x)
slash_commands.py # /info, /recommend 슬래시 커맨드 + 버튼 UI (discord.ui.View)
bot_command_set.py # 명령 구현 — ScoreSaber API 조회, 전적 파일 읽기, matplotlib 그래프
kr_ranker.py # [일일 배치] 한국 랭킹 1~100위의 PP/순위를 기록
added_user.py # [일일 배치] !추가 로 등록된 유저(Added_User_List.txt)의 PP를 기록
userdata.bin # Discord ID → ScoreSaber ID 매핑 (pickle dict)
Added_User_List.txt # 일일 기록 대상 유저 목록 (한 줄당 ScoreSaber ID)
gulim.ttc # 그래프 한글 렌더링용 굴림 폰트
history.txt # 전적 기록 파일 예시
kr_ranker.py와added_user.py를 매일 1회(예: cron, 새벽 5:30) 실행하면 유저별 전적이data/PP_text/<scoresaber_id>.txt에 한 줄씩 누적된다:매월 1일에는2020-9-17, 4855.24, Rank: 76, Name: <닉네임>nextmonth구분선이 들어간다. 같은 날 중복 실행은 자동 스킵.- 봇의
!내전적/!그래프/!비교는 이 텍스트 파일을 읽어 증가량 계산·시각화만 수행한다 (조회 시 ScoreSaber 호출 없음).!내정보/!검색만 실시간 API 조회.
pip install -r requirements.txt # discord.py>=2.3, requests, bs4, matplotlib, scipy, numpy
# 1. 봇 토큰: 레포 루트에 token.txt 생성, 첫 줄에 토큰 입력 (# 뒤는 주석으로 무시)
# 개발자 포털에서 MESSAGE CONTENT INTENT 활성화 필요 (prefix 명령용)
# 2. 폰트: 시스템에 gulim.ttc 없으면 레포에 포함된 파일을 자동 사용
# 3. 데이터 디렉토리 생성
mkdir -p data/PP_text
# 봇 실행
python3 discord_bot.py
# 일일 기록 (crontab 예시 — 매일 05:30)
# 30 5 * * * cd /path/to/beatsaber_bot && python3 kr_ranker.py && python3 added_user.pytoken.txt, data/, graph.png 등 런타임 산출물은 .gitignore에 포함되어 있다.
리더보드 topology 기반 추천 기능. 곡 추천은 "두 곡의 리더보드에 공통으로
등장하는 유저들의 순위 순서가 얼마나 일치하는가"(Spearman 순위상관 + 실력
효과를 제거한 잔차 상관)로 유사도를 계산한다 — 같은 부류(acc형/연타형/테크형)
유저가 상위권에 오는 곡끼리 묶인다. 유저 추천은 top-100 pp곡을 위치 가중
(0.965^i) cosine으로 비교해 나보다 pp 높은 유사 유저 목록을 보여준다.
Farm picks는 그중 2명 이상에게 반복 등장하고, 해당 비교 유저 모두가 내
ScoreSaber +1PP 기준보다 높은 raw PP를 기록한 곡만 추천한다.
recommend/
├── ss_maps/ # ScoreSaber 곡 추천 — ★9–11 랭크 991곡 × 리더보드 상위 240명
├── bl_maps/ # BeatLeader 곡 추천 — ★10–12 랭크 648곡 × 상위 240명
└── ss_users/ # ScoreSaber 유저 추천 — 전역 상위 3000명 × top-100 pp곡
추천 명령은 결과 텍스트와 함께 .bplist 플레이리스트 파일을 첨부한다
(PlaylistManager 등 호환 — 곡추천은 타깃곡+추천곡, 유저추천은 유사 유저
여러 유사 유저에게 반복되는 farm 후보곡 최대 20개). 받은 파일을 Beat Saber/Playlists/에
넣으면 게임에서 바로 쓸 수 있다.
추천 데이터는 용량 문제로 git에 포함되지 않는다 (recommend/*/data/ gitignore).
봇 명령은 로컬 데이터만 읽으므로 조회 시 API 호출이 없다. 수집 스크립트는
각 사이트의 레이트리밋(ScoreSaber 400req/min, BeatLeader 50req/10s) 아래로
자동 페이싱되며, 중단돼도 재실행하면 이어받는다.
cd recommend/ss_maps && python3 fetch.py catalog && python3 fetch.py scores # ~80분
cd recommend/bl_maps && python3 fetch.py # ~9분
cd recommend/ss_users && python3 fetch.py # ~9분봇 안에서는 관리 권한이 있는 유저가 !유저정보갱신 전적, !유저정보갱신 추천,
!맵정보갱신을 실행해 같은 수집 작업을 백그라운드로 시작할 수 있다.
로그와 pid 파일은 recommend/update_jobs/ 아래에 저장되며, !갱신상태로 확인한다.
수집 범위(별 구간, 인원수)와 유사도 산식 세부는 recommend/README.md 참고.
갱신 주기는 주 1회면 충분하다 (갱신 시 기존 data/*.jsonl 삭제 후 재수집).
- 봇 상태 메시지대로 오전 5:30~40은 일일 기록 시간이라 응답이 느릴 수 있다.
bot_command_set.py/added_user.py의 프로필 조회는 구버전new.scoresaber.com/api엔드포인트를 사용한다. 현재는scoresaber.com/api로 통합되었으므로 (kr_ranker.py는 이미 신버전 사용) 동작하지 않으면 URL을 교체해야 한다.- 한국/일본 유저에게는 한국어, 그 외에는 영어로 프로필을 출력한다.
- 슬래시 커맨드는 봇 시작 시 자동 sync되며, 서버에 반영되기까지 최대 1시간 걸릴 수 있다 (Discord 캐시).
- log 메시지 파일로 보관하기
- prefix 명령들도 슬래시로 이전
MIT © 2021 greenhestu