【なんでも自動化してみたい🤖④】GAS x Disney API x LINE x Wikipedia毎日ディズニーキャラを教えてBot!!!!!

前回までは


1. Disney APIについて🐭

2. GASでDisney APIを取得❗️❗️❗️

function newDisney({
  return new Disney();
}


class Disney {

  constructor() {
    this.baseUrl = 'https://api.disneyapi.dev/characters';
  }

  /**
   * @typedef  {object} Args
   * @property {number} id
   * @property {number} page
   * 
   * @param args {Args} args
   */
  _callAPI(args) {
    args = args || {};
    return Http.getJson(`${this.baseUrl}/${args.id || ''}?page=${args.page ? args.page : 1}`);
  }

  getCharacters(page) {
    return (this._callAPI({ page }) || {}).data;
  }

  getCharacter(id) {
    if (!id) throw new Error('id is required');
    return this._callAPI({ id });
  }

  getTotalPages() {
    // TODO: キャッシュするべき
    return this._callAPI().totalPages;
  }

  getRamdomCharacter() {
    const total = this.getTotalPages();
    const idx = Math.floor(Math.random() * total);
    const characters = this.getCharacters(idx);
    const character = characters[Math.floor(Math.random() * characters.length)];
    return character;
  }
}

3. GASでWikipediaからの情報を取得🌐

function newWiki() {
  return new WikipediaDataSource();
}

class WikipediaDataSource {
  /**
   * @typedef  {object} WikiArgs
   * @property {number} query
   * 
   * @param args {WikiArgs} args
   */
  _callAPI(args) {
    if (!args || !args.query) {
      throw new Error('Query text is required');
    }
    const url      = `https://ja.wikipedia.org/w/api.php?action=query&format=json&list=search&srsearch=${args.query}&srlimit
=500`;
    return Http.getJson(encodeURI(url));
  }

  /**
   * @typedef  {object} Page
   * @property {string} title
   * @property {string} link
   * @property {string} summary
   * 
   * @param {string} text
   * @return {Array<Page>}
   */
  getPages(text) {
    const response = this._callAPI({ query : text });
    if (!response.query || !response.query.search || !response.query.search.length) {
      return [];
    }
    return response.query.search.map(info => (
      {
        title   : info.title,
        summary : info.snippet.replace(/(<([^>]+)>)/gi, ''),
        link    : `https://ja.wikipedia.org/wiki/${info.title}`,
      }
    ));
  }
}

参考


4. LINE Botについて

**
 * @param  {string} token
 * @param  {string} targetGroupId
 * @return {LineStreamer}
 */
function newLine(token, targetGroupId) {
  return new LineStreamer(token, targetGroupId);
}

const APIEndpointBase        = "https://api.line.me";
const APIEndpointPushMessage = "/v2/bot/message/push"

class LineStreamer {
  constructor(token, targetGroupId) {
    this.token = token;
    this.groupId = targetGroupId;
  }

  /**
   * @param {string} text
   * @param {string} to
   */
  publishTextMessage(text, to) {
    const headers = {
      Authorization  : `Bearer ${this.token}`,
      "Content-Type" : "application/json; charset=UTF-8",
    };
    const body = JSON.stringify({
      to       : to || this.groupId,
      messages : [{ type : 'text', text }],
    });
    return Http.post(`${APIEndpointBase}${APIEndpointPushMessage}`, { body, headers });
  }

  publishImageURL(url, to) {
    const headers = {
      Authorization  : `Bearer ${this.token}`,
      "Content-Type" : "application/json; charset=UTF-8",
    };
    const body = JSON.stringify({
      to       : to || this.groupId,
      messages : [
        {
          type               : "image",
          originalContentUrl : url,
          previewImageUrl    : url,
        },
      ],
    });
    return Http.post(`${APIEndpointBase}${APIEndpointPushMessage}`, { body, headers });
  }
}

5. DBの代わりにスプレッドシート田

6. 適当なユースケースをまとめる

function pushDisney(line, disney, db, wiki{
    const character = disney.getRamdomCharacter();
    const films = character.films.map(film => film).join('\n') +
      character.shortFilms.map(film => film).join('\n') +
      character.videoGames.map(film => film).join('\n') +
      character.tvShows.map(film => film).join('\n');
    const query = db.select(UseCase.disney_character_db.DB_NAME);

        // Wikipediaを検索
    const info = wiki.getPages(character.name) || [];
    const filmInfo = (character.films.length ? wiki.getPages(character.films.join(" ")) : []) || [];
    const tvInfo = (character.tvShows.length ? wiki.getPages(character.tvShows.join(" ")) : []) || [];
    const videoGamesInfo = (character.videoGames.length ? wiki.getPages(character.videoGames.join(" ")) : []) || [];
    
    // 既にお知らせ済みなら無効・それ以外はdbに挿入
    if (query.read(`characterID=${character._id}`)) return console.log('already ', character);
    query.insertValues(
      [
        UseCase.disney_character_db.toRecord(
          character._id,
          character.name,
          character.imageUrl,
          character.films.join(', '),
          character.tvShows.join(', '),
          character.videoGames.join(', '),
          character.parkAttractions.join(', '),
          character.allies.join(', '),
          character.enemies.join(', '),
          character.url,
        ),
      ],
    ); 

    // Wikipediaから関連記事を探す
    const foundInfo = (() => {
      const foundInfo = info ? info.find(value => value.summary.match(/ディズニー|Disney/)) : undefined; 
      const foundFilmInfo = filmInfo ? filmInfo.find(value => value.summary.match(/ディズニー|Disney/)) : undefined;
      const foundTVInfo = tvInfo ? tvInfo.find(value => value.summary.match(/ディズニー|Disney/)) : undefined;
      const foundvideoGamesInfo = videoGamesInfo ? videoGamesInfo.find(value => value.summary.match(/ディズニー|Disney/)) : undefined;
      if (foundInforeturn foundInfo;
      if (foundFilmInforeturn foundFilmInfo;
      if (foundTVInforeturn foundTVInfo;
      if (foundvideoGamesInforeturn foundvideoGamesInfo;
      return {};
    })();

    // Lineに画像・文字列を送信!
    line.publishImageURL(character.imageUrl);
    line.publishTextMessage('名前: ' +character.name + '\n\n作品:\n' + films + '\n' + 
      [foundInfo.title, foundInfo.summary, foundInfo.link].join("\n\n"));
  }

まとめ🙇‍♂️

今回はソースコード貼るだけですみません🙇‍♂️
許してください🙇‍♂️

これで、朝起きたら自動でディズにキャラクターについてお知らせがきます!
今まで、知らなかったキャラクターが分かることができて毎日ハッピーです?????
次回はGmailからGASを使って楽天カードの使用内容を調べてみる感じの記事を書こうかなと思います。

この記事が気に入ったらサポートをしてみませんか?