ベトナム駐在者必読情報をGASでChatwork に通知する


必読情報源

  • 日本人ベトナム駐在者のほとんどが知っていると思われる VIETJO
  • たまにしか来ないんで見落としがちな外務省からのお知らせ
  • もっと色々見たい場合は、VN Express(英語版)

これくらいあれば十分でしょう。ベトナム語版ニュースは、今回はなしで。
Chatで見なくても、SNS等でいくらでも流れてくるので、必要ないと言えば必要ないんですが、社内のチャットで流れてくると、会話のきっかけにもなるし。上記3サイトは、よく日本人グループチャットで投稿されてました。
それに、この前やってみた Google App Script で RSS を読んでみたかったので。

方針

前述の3サイトは、RSS を配信しています。

じゃあ、RSSリーダーで読めばいいじゃんって話ですが、ほら、会話が生まれるきっかけをね…
なので、これを読みこんで、ポストしていくことにします。

XmlService で値を取得する際に、xml/RSS に Namespace が指定されていると、それを指定しないとエラーになるみたいです。今回の3サイトでは、VIETJO のみ指定がありました。他にも構造が違うので、そのあたり注意が必要です。

それほどリアルタイム性が重要な情報ではないので、1日1回朝取得して、通勤のタクシー内でなめるような使い方を想定しています。その後会話してもらうと。

一般的なRSSリーダーは、どこまで取ったか記録しておいて、同じ情報は通知しないようになっていると思いますが、記録しておくのが面倒だし、1日1回で良いので、24時間以内で取ってくることにします。

VN Express は情報量が極めて多いので、適当に省略します。

いきなり完成!

特別解説することもないので、いきなり完成です。

vietNews.gs
function getRssFeed() {
  const sources = getSources();
  const limitTs = new Date().getTime() - (24 * 60 * 60 *1000);
  for(var source of sources) {
    var response = UrlFetchApp.fetch(source[0]);
    var xml = XmlService.parse(response.getContentText());
    if(source[1]) {
      var ns = XmlService.getNamespace("soapenv", source[1]);
    }

    if(source[1] === "http://purl.org/rss/1.0/") {
      parsePurlOrgRss10(xml, ns, limitTs);
    } else {
      parseRss(xml, limitTs);
    }
  }  
}

// 情報源のセット
function getSources() {
  return [
    //["RSS feed url", "xmlns"],
    ["https://www.viet-jo.com/rss/headline7.rdf", "http://purl.org/rss/1.0/"],
    ["https://e.vnexpress.net/rss/news.rss", ""],
    ["https://www.anzen.mofa.go.jp/rss/country/country_region_015news.xml", ""]
  ];
}

function parsePurlOrgRss10(xml, ns, limitTs) {
  const dc = XmlService.getNamespace("dc", "http://purl.org/dc/elements/1.1/");
  const channel = xml.getRootElement().getChild("channel", ns);
  var text = channel.getChildText("title", ns) + "\n - " +
             channel.getChildText("link", ns) +
             "\n-------------------------------------------\n"

  const items = xml.getRootElement().getChildren("item", ns);

  var i = 0;
  for(var item of items) {
    var pubDate = item.getChildText("date", dc);
    if (new Date(pubDate).getTime() > limitTs && i < 5) {
      var text = text +
                 "" + item.getChildText("title", ns) +
                 "\n  at " + pubDate +
                 "\n  " + item.getChildText("link", ns) + "\n";
      i = i + 1;
    }
  }
  if (i > 4) var text = text + "...\n";
  if (i > 0) postNow(text);
}

function parseRss(xml, limitTs) {
  const channel = xml.getRootElement().getChild("channel");
  var text = channel.getChildText("title") + "\n - " +
             channel.getChildText("link") +
             "\n-------------------------------------------\n"

  const items = xml.getRootElement().getChild("channel").getChildren("item");
  var i = 0;
  for(var item of items) {
    var pubDate = item.getChildText("pubDate");
    if(new Date(pubDate).getTime() > limitTs && i < 5) {
      var text = text +
                 "" + item.getChildText("title") +
                 "\n  at " + pubDate +
                 "\n  " + item.getChildText("link") + "\n";
      i = i + 1;
    }
  }
  if (i > 4) var text = text + "...\n";
  if (i > 0) postNow(text);
}

function postNow(message) {
  postToChatwork(message);
  //Logger.log(message);
}

function postToChatwork(message) {
  const chatworkToken = '{Your Chatwork API Token}';
  const chatworkRoomId = '{Your Chatwork Chat Room ID(Number)}';
  const chatworkClient = ChatWorkClient.factory({token: chatworkToken});
  chatworkClient.sendMessage({room_id: chatworkRoomId, body: message});
}

関数名がイケてなかったり、コードが冗長な気もしますが、目をつぶりました。

Chatworkの設定や、ChatworkClient の導入方法は、以前の記事のこちらを見てください。

Google Chat や LINE に送りたい人も。これを定期実行する方法等も。

Google App Script でカレンダーの予定をGoogle Chat, Chatwork, LINE などに送りつける

パッと見、明るいニュースはあんまりないですね。頑張ろう。
それでは良いベトナムLIFEを!