[JS] 디스코드 봇에 PLL 정보 출력하게 하기

2025. 3. 4. 17:38·Study/Javascript

KupoBot이라는 FF14 관련한 많은 기능을 제공하는 봇이 있다.

그런데 이것이 요즘은 꽤 답답하다.

시대가 언젠데 슬래시 커맨드도 안되고...

 

주로 요청하게 되는 정보는 점검과 PLL 관련 정보인데,

아마도 관리자가 직접 정보를 삽입하는 것 같다.

공지가 올라온 지 한참 지났음에도 정보를 가져오지 못한다.

 

점검 같은 경우는 정규식으로 RSS Feed를 파싱해 최신 점검 정보를 가져오게 해 놨다.

한번 파싱 하면 그걸 저장해 놨다가 재활용한다.

PLL도 그런 식으로 파싱 할 수 있으므로 똑같은 흐름으로 명령어를 만들게 됐다.

 

1. 그전에 점검 파싱부터

먼저 점검 정보 파싱이 어떻게 이루어지는지 보자.

 

async function getMaintData() {
  const feedUrl = "https://jp.finalfantasyxiv.com/lodestone/news/news.xml";
  const now = Date.now() / 1000;

  try {
    const savedData = await loadData();
    if (savedData.MAINTINFO?.end_stamp > now) {
      return savedData;
    }

    const feed = await parser.parseURL(feedUrl);
    const targetItem = feed.items.find((item) => item.title?.startsWith("全ワールド"));
    if (!targetItem) return null;
# ...

모든 FF14의 전체 점검 공지는 「全ワールド」라는 접두어를 가진다.

이를 기반해서 해당하는 점검 피드를 찾는다.

 

그럼 현재 기준으로 다음의 점검 공지를 찾을 수 있다.

[メンテナンス]全ワールド メンテナンス作業のお知らせ(3/4)

 

그럼 내용에서 시간 정보를 뽑아내야 한다.

중간 내용은 필요 없고 가장 아래의 시간 정보만 정규식으로 뽑아낸다.

 

function extractMaintenanceInfo(item) {
  const startTimeRegex = /日 時:(\d{4}年\d{1,2}月\d{1,2}日\(.\)) (\d{1,2}:\d{2})より/;
  const endTimeRegex = /(\d{4}年\d{1,2}月\d{1,2}日\(.\))? ?(\d{1,2}:\d{2})頃まで/;
  const startTimeMatch = item.content.match(startTimeRegex);
  const endTimeMatch = item.content.match(endTimeRegex);
  if (!startTimeMatch || !endTimeMatch) return null;

  // 중복되는 moment.tz 호출을 헬퍼 함수로 분리
  const parseDate = (dateStr, timeStr) =>
    moment.tz(`${dateStr} ${timeStr}`, "YYYY年MM月DD日(ddd) HH:mm", "ja", "Asia/Tokyo").unix();

  const startTime = parseDate(startTimeMatch[1], startTimeMatch[2]);
  const endTime = endTimeMatch[1]
    ? parseDate(endTimeMatch[1], endTimeMatch[2])
    : parseDate(startTimeMatch[1], endTimeMatch[2]);

  return { start_stamp: startTime, end_stamp: endTime };
}

이런 식으로 시간을 뽑아서 유닉스 타임스탬프 형태로 리턴한다.

이걸 바탕으로 디스코드 임베드에 정보들을 넣어 보여주게 된다.

 

이런 식으로 임베드로 출력하게 된다.

 

 

2. PLL도 같은 식으로

PLL은 다음과 같은 형식의 제목을 가진다.

[「第n回 FFXIV PLL」m月dd日(金)放送決定!]

 

그리고 가장 중요한 건 FFXIV PLL이 포함되는 부분이다.

저 부분은 형태가 바뀌지 않는다.

이걸 통해서 피드에서 PLL 관련 정보들을 가져올 수 있다.

 

현재 기준으로 다음의 PLL 공지를 확인할 수 있다.

「第86回 FFXIV PLL」3月14日(金)放送決定!

 

역시 필요한 건 시간 정보뿐이다.

 

// 회차 번호 추출
const $ = cheerio.load(summary, { decodeEntities: false });
const h3Element = $("h3.mdl-title__heading--lg").first();
let roundNumber = "";
const roundMatch = (h3Element.text() || title).match(/第(\d+)回/);
if (roundMatch) {
  roundNumber = roundMatch[1];
}

// 방송 시작 시각 추출 (전각 괄호 대응)
let start_stamp = null;
const dateRegex = /(\d{4}年\d{1,2}月\d{1,2}日([^)]+))\s?(\d{1,2}:\d{2})頃?~/;
const dateMatch = summary.match(dateRegex);
if (dateMatch) {
  // dateMatch[1] = "2025年3月14日(金)", dateMatch[2] = "19:00"
  const dateStrClean = dateMatch[1].replace(/([^)]+)/, ""); // → "2025年3月14日"
  const finalStr = `${dateStrClean} ${dateMatch[2]}`; // → "2025年3月14日 19:00"
  const parsed = moment.tz(finalStr, "YYYY年M月D日 HH:mm", "Asia/Tokyo");
  if (parsed.isValid()) {
    start_stamp = parsed.unix();
  }
}

정규식을 통해 현재 몇 회 차인지, 진행 시간은 언제인지 추출한다.

 

let fixedTitle = "제 XX회 프로듀서 레터 라이브 X월 XX일 방송 결정!";
if (start_stamp) {
  const formattedDate = moment.unix(start_stamp).tz("Asia/Seoul").format("M월 D일");
  const roundText = roundNumber ? `제 ${roundNumber}회` : `제 XX회`;
  fixedTitle = `${roundText} 프로듀서 레터 라이브 ${formattedDate} 방송 결정!`;
}

그리고 타이틀을 추출한 정보에 맞게 수정한다.

 

// 캐싱 만료 시간 설정
const expireTime = Math.floor(now + 12 * 60 * 60);
const newData = {
  PLLINFO: {
    fixedTitle,
    url: link,
    start_stamp,
    expireTime,
  },
};

await saveData(newData);
return newData.PLLINFO;

추후에 현재 저장된 정보가 만료된 것인지 판별하기 위해 만료 시간을 계산해 같이 캐싱한다.

 

추출한 정보를 통해 점검 정보와 유사하게 이런 식으로 출력할 수 있다.

 

답답하면 내가 만들면 되는 게 아닌가?

그래서 만들었다.
훨씬 보기도 좋다.

'Study > Javascript' 카테고리의 다른 글

티스토리 인라인 코드 태그 래핑 스크립트  (0) 2024.07.11
[Node.js] Python으로부터 넘어오다  (0) 2024.01.27
'Study/Javascript' 카테고리의 다른 글
  • 티스토리 인라인 코드 태그 래핑 스크립트
  • [Node.js] Python으로부터 넘어오다
BVM
BVM
  • BVM
    E:\
    BVM
  • 전체
    오늘
    어제
    • 분류 전체보기 (168)
      • Thoughts (14)
      • Study (69)
        • Japanese (3)
        • C++ & C# (46)
        • Javascript (3)
        • Python (14)
        • Others (3)
      • Play (1)
        • Battlefield (1)
      • Others (11)
      • Camp (73)
        • T.I.L. (57)
        • Temp (1)
        • Standard (10)
        • Challenge (3)
        • Project (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

    • 본 블로그 개설의 목적
  • 인기 글

  • 태그

    베데스다
    c#
    프로그래머스
    discord
    C++
    Server
    Python
    FF14
    docker
    boost
    7계층
    스타필드
    Asio
    JS
    OSI
    포인터
    서버
    db
    IOCP
    bot
    cloudtype
    Dalamud
    네트워크 프로그래밍
    암호화
    Selenium
    로깅
    discord py
    네트워크
    클라우드
    Network
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.2
BVM
[JS] 디스코드 봇에 PLL 정보 출력하게 하기
상단으로

티스토리툴바