안녕하세요

[MongoDB] twitch 방송 시간, 플레이한 게임, 최고 시청자 수 기록하기 본문

유튜브컨텐츠탐색-StelLife/Twitch API

[MongoDB] twitch 방송 시간, 플레이한 게임, 최고 시청자 수 기록하기

sakuraop 2023. 3. 27. 01:17

API요청

const twitch_channels_base_url = "https://api.twitch.tv/helix/streams";

exports.getTwitchLiveChannelsApi = async (user_id) => {
  const headers = {
    Authorization: `Bearer ${process.env.REACT_APP_TWITCH_ACCESS_TOKEN}`,
    "Client-Id": `${process.env.REACT_APP_TWITCH_CLIENT_ID}`,
  };
  const params = {
    user_id,
    type: "live",
  };

  try {
    const request = await axios.get(`${twitch_channels_base_url}`, { headers, params });
    if (!request.data.data.length) {
      return [];
    }

    const liveChannel = request.data.data.filter((data) => validIds.includes(data.user_id));
    if (liveChannel.length) {
      return liveChannel;
    }
  } catch (error) {
    console.error("getSearchChannelsData", error);
    return [];
  }
};
const twitch_channels_base_url = "https://api.twitch.tv/helix/streams";

steams api는 특정 user_id와 type:"live" params로 라이브를 진행 중인지 확인할 수 있다.

user_id ex) "13645765"

가능한 옵션 ex) type:"all" 또는 type:"live"

 

요청 결과가 빈 배열일 경우에는 []를 반환하도록 했다.

 

https://dev.twitch.tv/docs/api/reference/#get-streams

 

Reference

Twitch Developer tools and services to integrate Twitch into your development or create interactive experience on twitch.tv.

dev.twitch.tv

요청에 대해 반환받을 수 있는 데이터는 공식 레퍼런스 참고

 

데이터 저장하기

exports.updateTwitchLive = async (db) => {
  try {
    const twitchLivesCollection = await db.collection("twitch_lives");

    for (const validId of validIds) {
      await twitchLivesCollection.findOneAndUpdate({ id: validId }, { $set: { is_live: "" } });

      const liveData = await getTwitchLiveChannelsApi(validId);
      if (!liveData.length) {
        continue;
      }

      const currentTime = new Date().getTime();
      const { user_name, type, started_at, title, game_id, game_name, viewer_count } = liveData[0];
      let update;

      // started_at이 존재하면 => 기존 라이브가 존재 => duration, viewer_count,played_games 업데이트
      const startedAtFilter = { id: validId, "live_history.started_at": started_at };
      const existingHistoryItem = await twitchLivesCollection.findOne(startedAtFilter);

      if (existingHistoryItem) {
        const previousViewerCount = existingHistoryItem.live_history.filter((history) => JSON.stringify(history.started_at) === JSON.stringify(started_at));
        const max_viewer_count = Math.max(previousViewerCount[0].viewer_count || 0, viewer_count);
        const update = {
          $set: { "live_history.$.duration": currentTime - new Date(started_at).getTime(), "live_history.$.viewer_count": max_viewer_count },
          $addToSet: { "live_history.$.played_games": { game_id, game_name } },
        };

        await twitchLivesCollection.updateOne(startedAtFilter, update);
      }

      // started_at이 존재하지 않으면 => 새로운 라이브 정보 추가
      if (existingHistoryItem === null) {
        update = { $set: { id: validId, user_name, is_live: type, title } };
        update.$addToSet = {
          live_history: {
            title,
            duration: currentTime - new Date(started_at).getTime(),
            started_at,
            viewer_count,
            played_games: [{ game_id, game_name }],
          },
        };
        // started_at이 존재하면 => 채널 내용만 업데이트
      } else {
        update = { $set: { id: validId, user_name, is_live: type, title } };
      }

      await twitchLivesCollection.updateOne({ id: validId }, update);

      console.log(user_name + "의 Live 정보를 업데이트 했습니다.");
    }
  } catch (error) {
    console.error(error);
    console.log("updateTwitchLive 에러");
  }
};

1. db에 일치하는 id의 live 상태를 초기화한다. 

exports.updateTwitchLive = async (db) => {
  console.log("updateTwitchLive");
  try {
    const twitchLivesCollection = await db.collection("twitch_lives");

    for (const validId of validIds) {
      await twitchLivesCollection.findOneAndUpdate({ id: validId }, { $set: { is_live: "" } });

2. api로 원하는 id 를 검색합니다. 결과가 없다면 다음 id를 검색합니다.

      const liveData = await getTwitchLiveChannelsApi(validId);
      if (!liveData.length) {
        continue;
      }

=> 결과는 [ {data},{data},{data},...] 와 같은 형태로 전달받습니다.

3. 알아보기 쉽도록 api 결과를 이용할 데이터만 골라서 비구조화 할당 합니다.

      const currentTime = new Date().getTime();
      const { user_name, type, started_at, title, game_id, game_name, viewer_count } = liveData[0];
      let update;

=> user_name: 스트리머 이름 ex) "S2wordMast3rS2"

type: 라이브 방송 상태 "live"

started_at: 방송 시작시간 date 객체

title: 방송제목 ex) Morning Coffee Chat

game_id: twitch에서 지정한 game_id ex) "36461"

game_name: 게임 이름 ex) "GTA VIII"

viewer_count: 현재 방송 시청자 수 ex) 155

4. started_at이 일치하는 방송 정보가 있다면 방송 내용 업데이트 

      // started_at이 존재하면 => 기존 라이브가 존재 => duration, viewer_count,played_games 업데이트
      const startedAtFilter = { id: validId, "live_history.started_at": started_at };
      const existingHistoryItem = await twitchLivesCollection.findOne(startedAtFilter);

      if (existingHistoryItem) {
        const previousViewerCount = existingHistoryItem.live_history.filter((history) => JSON.stringify(history.started_at) === JSON.stringify(started_at));
        const max_viewer_count = Math.max(previousViewerCount[0].viewer_count || 0, viewer_count);
        const update = {
          $set: { "live_history.$.duration": currentTime - new Date(started_at).getTime(), "live_history.$.viewer_count": max_viewer_count },
          $addToSet: { "live_history.$.played_games": { game_id, game_name } },
        };

        await twitchLivesCollection.updateOne(startedAtFilter, update);
      }
const startedAtFilter = { id: validId, "live_history.started_at": started_at };
const existingHistoryItem = await twitchLivesCollection.findOne(startedAtFilter);

=> 일치하는 id의 live_history 배열 요소 중 started_at이 일치하는 요소 걸러내기

      if (existingHistoryItem) {
        const previousViewerCount = existingHistoryItem.live_history.filter((history) => JSON.stringify(history.started_at) === JSON.stringify(started_at));
        const max_viewer_count = Math.max(previousViewerCount[0].viewer_count || 0, viewer_count);

=> 방송을 시작한 시간이 일치하는 아이템이 있다면 최대 시청자 수를 기록합니다.

기존의 viewerCount와 현재 count를 Math.max() 메서드로 비교하여 최대 시청자 수를 기록합니다.

 

        const update = {
          $set: { "live_history.$.duration": currentTime - new Date(started_at).getTime(), "live_history.$.viewer_count": max_viewer_count },
          $addToSet: { "live_history.$.played_games": { game_id, game_name } },
        };

        await twitchLivesCollection.updateOne(startedAtFilter, update);
      }

방송이 지속된 시간을 현재시간 - 방송 시작 시간으로 구합니다.

최대 시청자 수를 기록합니다.

live_history의 played_games 배열에 플레이한 게임 타이틀과 id를 추가합니다.

5. 진행중인 라이브 정보가 없다면 새로운 라이브 정보 추가하기

      // started_at이 존재하지 않으면 => 새로운 라이브 정보 추가
      if (existingHistoryItem === null) {
        update = { $set: { id: validId, user_name, is_live: type, title } };
        update.$addToSet = {
          live_history: {
            title,
            duration: currentTime - new Date(started_at).getTime(),
            started_at,
            viewer_count,
            played_games: [{ game_id, game_name }],
          },
        };
        // started_at이 존재하면 => 채널 내용만 업데이트
      } else {
        update = { $set: { id: validId, user_name, is_live: type, title } };
      }

      await twitchLivesCollection.updateOne({ id: validId }, update);

      console.log(user_name + "의 Live 정보를 업데이트 했습니다.");

$set 연산자로 스트리머 이름, 라이브 상태, 방송 제목을 기록합니다.

$addToSet 연산자로 live_history 배열에 새로운 라이브 정보를 추가합니다.

 

진행중인 라이브가 존재하면 스트리머 이름, 라이브 상태, 방송 제목만 갱신합니다.