Google Apps ScriptでTwitter botを作ってみた

Google Apps Scriptだけで、Twitterのbotを作れないかなと思案してたら、作れてしまったので、記載

## どんなbotか
なんてことはない、好きなサイトの更新してる記事をランダムでつぶやいてくれるbot

こういうbotが欲しいと思った経緯としては、
- feedlyで記事の更新を全て取り込んでも、結局一括で削除しちゃって読まない
- Twitterを見ている時に、ふとつぶやかれている記事なら読んじゃう
- じゃあ、Twitterで適当に記事が目につく状況作れば、読んじゃうじゃないか


## 実際のスクリプト
今回作ったものは、「RSSをスクレイピングして、スプレッドシートに記事のリンクをExportして、そのリンクを定期的につぶやく」という仕組みです。

この仕組みは3つの役割から構成されています。
1.スプレッドシートのデータを削除する
2.RSSをスクレイピングし、スプレッドシートにExportする
3.スプレッドシートの値をランダムに取得し、それをツイートする

それでは、それぞれについて説明します。

## 1.スプレッドシートのデータを削除する
こちらは、すでにスプレッドシートに記事のURLがある場合、それを削除するためのスクリプトです。
これを用意する意図としては、過去の記事URLを全て削除することで、スプレッドシートには常に最新記事のURLが存在する状態を作り出すためです。

### 実際のクエリ
```GAS:clear.gs
function clear() {
    # シートを扱う準備
    var myActiveSpreadSheet = SpreadsheetApp.getActiveSpreadsheet();
    var myActiveSheet = myActiveSpreadSheet.getSheets()[0];
    
    # 取得したurlを全てクリアする
    myActiveSheet.clear();
}
```


## 2.RSSをスクレイピングし、スプレッドシートにExportする

こちらは、RSSをスクレイピングし、スプレッドシートに取得してきた記事URLをExportするためのスクリプトです。

### 実際のクエリ

```GAS:scraping.gs
function scraiping() {
  # シートを扱う準備
  var myActiveSpreadSheet = SpreadsheetApp.getActiveSpreadsheet();
  var myActiveSheet = myActiveSpreadSheet.getSheets()[0];

  # RSSからscraipingでurlを取得。今回は、筆者がヨーロッパのサッカーが好きなので、ゲキサカのRSS( http://web.gekisaka.jp/rsspage )を利用させていただいております。
  var response = UrlFetchApp.fetch("http://web.gekisaka.jp/feed?category=foreign");
  var myRegexp = /<guid isPermaLink=\"true\">([\s\S]*?)<\/guid>/gi;
  var match = response.getContentText().match(myRegexp);
  
  # 不必要な文字を置換し、ドライブシートに貼り付け
  for(var i in match) {
    var amount = match[i]
    amount = amount.replace("<guid isPermaLink=\"true\">", "");
    amount = amount.replace("<\/guid>", "");
    myActiveSheet.getRange(myActiveSheet.getLastRow()+1, 1).setValue(amount);
  }
}
```

## 3.スプレッドシートの値をランダムに取得し、それをツイートする

こちらは、スプレッドシート内の記事URLを取得し、それをランダムに取得し、定期的にツイートするためのスクリプトです。


### 実際のクエリ
```GAS:tweet.gs
var CONSUMER_KEY = 'Your_CONSUMER_KEY';                    # 取得したCONSUMER_KEYを入力してください
var CONSUMER_SECRET = 'Your_CONSUMER_SECRET';                 # 取得したCONSUMER_SECRETを入力してください

/**
 * Authorizes and makes a request to the Twitter API.
 */
function run(text) {                         
  var service = getService();
  if (service.hasAccess()) {
    var url = 'https://api.twitter.com/1.1/statuses/update.json';
    var payload = {
      status: text                           
    };
    payload = Object.keys(payload).map(function(key) {
      return encodeRfc3986(key) + '=' + encodeRfc3986(payload[key]);
    }).join('&');
    var response = service.fetch(url, {
      method: 'post',
      payload: payload,
      escaping: false
    });
    var result = JSON.parse(response.getContentText());
    Logger.log(JSON.stringify(result, null, 2));
  } else {
    var authorizationUrl = service.authorize();
    Logger.log('Open the following URL and re-run the script: %s',
        authorizationUrl);
  }
}

/**
 * Encodes a string using the RFC 3986 spec.
 */
function encodeRfc3986(str) {
  return encodeURIComponent(str).replace(/[!'()]/g, function(char) {
    return escape(char);
  }).replace(/\*/g, "%2A");
}

/**
 * Reset the authorization state, so that it can be re-tested.
 */
function reset() {
  var service = getService();
  service.reset();
}

/**
 * Configures the service.
 */
function getService() {
  return OAuth1.createService('Twitter')
      // Set the endpoint URLs.
      .setAccessTokenUrl('https://api.twitter.com/oauth/access_token')
      .setRequestTokenUrl('https://api.twitter.com/oauth/request_token')
      .setAuthorizationUrl('https://api.twitter.com/oauth/authorize')

      // Set the consumer key and secret.
      .setConsumerKey(CONSUMER_KEY)
      .setConsumerSecret(CONSUMER_SECRET)

      // Set the name of the callback function in the script referenced
      // above that should be invoked to complete the OAuth flow.
      .setCallbackFunction('authCallback')

      // Set the property store where authorized tokens should be persisted.
      .setPropertyStore(PropertiesService.getUserProperties());
}

/**
 * Handles the OAuth2 callback.
 */
function authCallback(request) {
  var service = getService();
  var authorized = service.handleCallback(request);
  if (authorized) {
    return HtmlService.createHtmlOutput('Success!');
  } else {
    return HtmlService.createHtmlOutput('Denied');
  }
}

function bot_news_link() {
 var ss = SpreadsheetApp.getActiveSpreadsheet();
 var sheet = ss.getSheets()[0];
 var cell = sheet.getRange("A1");
  
 all_urls = cell.offset(0, 0, sheet.getLastRow()-1);
 var urls = all_urls.getValues();

 # ランダム関数で取得。コンテンツのあるRowの最後までを範囲に指定
 var rand = Math.ceil(Math.random() * sheet.getLastRow() - 1);
  
 # ランダムurl
 var url = urls[rand][0];

 run("あなたにオススメの記事は" + url + "なんだな!!");
}

```


## 実際の運用
筆者の場合、以下のようなクローンスケジュールで設定している
1.削除は、朝の7 ~ 8時で1回行う
2.記事のURL取得は、朝の8 ~ 9時で1回行う
3.記事のツイートは、2時間おきに1回行う


## 参考記事
- https://sites.google.com/site/usakoyama/gastotwitterbot
- http://qiita.com/inamoo/items/23248b7290d8140f53fc