디스코드 베스트 포스트 추천 봇 만들기 6편 - 모든 게시글 수 확인 하기, 유연한 확장을 위한 구조 수정, 적절한 캐시 사용

현재 노트: KR-110.00 a 디스코드 베스트 포스트 추천 봇 만들기 6편 - 모든 게시글 수 확인 하기, 유연한 확장을 위한 구조 수정, 적절한 캐시 사용
상위 분류: KR-110.00 디스코드 베스트 포스트 추천 봇 제작기

#프로젝트경험 #개인프로젝트 #디스코드봇

디스코드 베스트 포스트 추천 봇 만들기 6편 - 모든 게시글 수 확인 하기, 유연한 확장을 위한 구조 수정, 적절한 캐시 사용

본 글의 내용은 일반적으로 다음과 같은 흐름으로 진행됩니다.
원하는 것을 구현 시도 -> 문제가 생김 -> 해결
또다른 기능등 시도-> 다시 새로운 문제가 생김 -> 해결
... 구현 또는 수정이나 해결될 때까지 적절하게 반복

결론
모든 게시글을 확인하느 과정에서 과거와는 다른 방식으로 기느응ㄹ 추가함. 이전에는 명확한 파일과, 구조가 정해진 json파일을 이용했는데 이는 확장과 수정등에 있어서 큰 어려움이있었슴. 그래서 이번에는 메모리상에 먼저 올려서 처리하는 기능 구현
하지만 이런경우 약 1700개의 메시지가 되는 순간 fetch에 5분정도가 걸려버림. 그래서 메모리에 올리되, 해당 내용을 write해서 json으로 만든후 이를 캐시처럼 사용하는 방식을 사용함.

이전 저장 기능 + 커맨드 기능 -> 현재 커맨드기능

게시글 총합 기능

  1. 채널별 게시글 총 수
    1. 기존의 active 게시글
    2. 추가 archive 게시글
  2. 총 게시글 수
    기존의 json파일 이용방식대신 메모리 정보 사용. 쉽게 확장 가능
    단점은 느려짐

디스코드 커맨드 등록 안됨

global command update의 경우 1시간이 기본일 수 있다고함.
docs 검색-> reload라는 즉시 반영 기능 확인

        await rest.put(
          Routes.applicationCommands(
            process.env.CLIENT_ID,
            // 없었음 process.env.GUILD_ID
          ),
          { body: commands }
        );

왠지 모르겠지만 디스코드봇이 있는 해당 채널에서 ctrl+R 하니깐 바로 반영됨
출처: https://www.wikihow.com/Refresh-Discord#:~:text=You may also press Ctrl,on Mac to refresh Discord.&text=On Android%2C try force stopping the Discord app to refresh it.

응답 결과 캐싱 필요

모든 메시지및 이모지를 처리하는데 약 4분이 걸림.
해당 데이터JSON파일로 생성후 처리할 필요가 생김

커맨드가 진행되는 동안 메시지 표시

await interaction.deferReply({content: "일줄일 안에 캐싱된 데이터 확인중입니다..."});

3초이상 걸리는 메시지에 한해 적용 가능

수동으로 1번 데이터 JSON으로 캐싱

캐싱 즉 fetch할지 말지를 Y/N으로 입력받기

버튼 추가를 통해 cache기능의 사용에대한 선택지를 추가. 이전에는 데이터가 없으면 무조건 fetch수행이었음

디스코드 snowflacktime 기반으로 명령어 업데이트된 시간 확인

링크
간단 설명 discord에서 사용되는 고유 타임스탬프

캐싱 파일 경로 문제

봇이 실행되는 main.js인줄 알았는데, 커맨드가 실행되는 commands/archivecommand.js이였음
console.log로 확인


      console.log(
        `DATA_FILE_PATH ${DATA_FILE_PATH} \ncache ${JSON.stringify(
          cache,
          null,
          2
        )} ,cache.data ${
          cache.data
        }\n캐시된 데이터가 없거나 유효하지 않아, 파일 및 API에서 데이터를 가져올지 확인합니다.`
      );

__dirname에서 prcoess.cwd() 로 변경

before
const DATA_FILE_PATH = path.join(__dirname, "data", "thread_data.json");

after
const DATA_FILE_PATH = path.join(process.cwd(), "data", "thread_data.json");

스레드를 돌아다니면서 sort기반으로 5개의 스레드 업데이트

        for (const thread of archiveThreads.values()) {
          try {
            const messages = await fetchAllMessages(thread);
            const messageCount = messages.length;
            let totalReactions = 0;
            for (const message of messages) {
              totalReactions += message.reactions.cache.reduce(
                (acc, reaction) => acc + reaction.count,
                0
              );
            }

            allPosts.push({
              channelName: channel.name,
              threadName: thread.name,
              author: thread.ownerId
                ? (await interaction.guild.members.fetch(thread.ownerId))
                    .displayName
                : "알 수 없음",
              messageCount,
              reactionCount: totalReactions,
              threadLink: `https://discord.com/channels/${interaction.guild.id}/${thread.id}`,
              totalScore: messageCount + totalReactions,
            });
          } catch (error) {
            console.error(
              `스레드 ${thread.name} (ID: ${thread.id}) 처리 중 오류 발생:`,
              error
            );
            continue; // 오류 발생 시 다음 스레드로 건너뜀
          }
        }
      }

      allPosts.sort((a, b) => b.totalScore - a.totalScore);
      const bestPosts = allPosts.slice(0, 5);

      jsonData.bestPosts = bestPosts;
      jsonData.lastUpdated = new Date().toISOString();

      await fs.writeFile(
        DATA_FILE_PATH,
        JSON.stringify(jsonData, null, 2),
        "utf-8"
      );
      console.log("데이터를 파일에 저장했습니다.");

:smile

😁

열정통계 결과과

열정 게시글 결과

주로 인기가 많은것은 사용자의 유도를 쉽게 참여하며, 공유, 자랑과 같은 글들이 인기가 많았음을 알 수 있음. 서비스 설계시 참고가능능