디스코드 베스트 포스트 추천 봇 만들기 6편 - 모든 게시글 수 확인 하기, 유연한 확장을 위한 구조 수정, 적절한 캐시 사용
현재 노트: KR-110.00 a 디스코드 베스트 포스트 추천 봇 만들기 6편 - 모든 게시글 수 확인 하기, 유연한 확장을 위한 구조 수정, 적절한 캐시 사용
상위 분류: KR-110.00 디스코드 베스트 포스트 추천 봇 제작기
디스코드 베스트 포스트 추천 봇 만들기 6편 - 모든 게시글 수 확인 하기, 유연한 확장을 위한 구조 수정, 적절한 캐시 사용
본 글의 내용은 일반적으로 다음과 같은 흐름으로 진행됩니다.
원하는 것을 구현 시도 -> 문제가 생김 -> 해결
또다른 기능등 시도-> 다시 새로운 문제가 생김 -> 해결
... 구현 또는 수정이나 해결될 때까지 적절하게 반복
결론
모든 게시글을 확인하느 과정에서 과거와는 다른 방식으로 기느응ㄹ 추가함. 이전에는 명확한 파일과, 구조가 정해진 json파일을 이용했는데 이는 확장과 수정등에 있어서 큰 어려움이있었슴. 그래서 이번에는 메모리상에 먼저 올려서 처리하는 기능 구현
하지만 이런경우 약 1700개의 메시지가 되는 순간 fetch에 5분정도가 걸려버림. 그래서 메모리에 올리되, 해당 내용을 write해서 json으로 만든후 이를 캐시처럼 사용하는 방식을 사용함.
이전 저장 기능 + 커맨드 기능 -> 현재 커맨드기능
게시글 총합 기능
- 채널별 게시글 총 수
- 기존의 active 게시글
- 추가 archive 게시글
- 총 게시글 수
기존의 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으로 캐싱
- 커맨드로딩하는 동안 캐싱중인 데이터 확인중이라는 메시지 표시
- 데이터 캐싱해서 있으면 그대로
JSON.parse
해서 사용. 없으면 fetch해서 약 4분 동안 사용한후, write
캐싱 즉 fetch할지 말지를 Y/N으로 입력받기
버튼 추가를 통해 cache기능의 사용에대한 선택지를 추가. 이전에는 데이터가 없으면 무조건 fetch수행이었음
디스코드 snowflacktime 기반으로 명령어 업데이트된 시간 확인
링크
간단 설명 discord에서 사용되는 고유 타임스탬프
- Discord 명령어 ID(version)는 Snowflake라는 고유 식별자 형식임.
- Snowflake는 Discord에서 시간을 기반으로 생성되는 64비트 ID.
- Snowflake를 변환하면 명령어가 마지막으로 업데이트된 대략적 시간 확인 가능.
캐싱 파일 경로 문제
봇이 실행되는 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
😁
열정통계 결과과
열정 게시글 결과
주로 인기가 많은것은 사용자의 유도를 쉽게 참여하며, 공유, 자랑과 같은 글들이 인기가 많았음을 알 수 있음. 서비스 설계시 참고가능능