【悪用厳禁】複数アカウントでツイートするTwitterBotの作り方!

GAS/TwitterBot
two 3d humans give their hand for handshake
この記事は約10分で読めます。
スポンサーリンク

最近だと一番見て頂いたている記事になってしまいましたTwitterBot作成の記事ですが、

複数アカウントでBotを運用したいと思っています。
そこで以下の機能を実装したいです。
・同じシートから順番に複数アカウントで投稿する
・同時に同じツイートを複数アカウントで投稿することはTwitterの規約に引っかかるので回避したい

「同じシートから順番に複数アカウントで投稿する」ここが今回のポイントです。

Twitterの規約は以下を参考にどうぞ!(ご紹介ありがとうございます)

自動化と複数アカウントの使用について
情報の品質を改善する取り組みの一環として、TweetDeckとTwitter APIにおいて複数アカウントからの同様のアクションを制限する変更を発表しました。今回、この変更の詳細とともに、開発者の皆さんに守っていただきたいルールをご案内します。

今回のコードではそこまで大量のアカウントでの実行を想定していないので「大丈夫っしょ…」の気持ちを込めて3秒おきでの投稿をしていますが、作成/実行は自己責任でお願いします!

では本編をどうぞ!

これまでのTwitterBotでは出来ない

TwitterBotの認証の仕組み(OAuthとは)

複数のアカウントで投稿できるようにするには、これまで作ってきたTwitterBotがどのように認証していたかを理解している必要があります。

Twitterのアカウントの認証はこの図のように3ステップで認証を行います。

これまでの記事で一度でもAPIを実行した経験がある人はこの画像だけで何をやっていたのかがなんとなくわかると思います。

これはOAuthという仕組みでProgateやGitHubなどで使うGoogle認証も同じような仕組みで認証しています(自動でページ遷移されるけど流れは一緒のはず)

なぜ複数のアカウントを登録できないのか

原因はここです。

今の実装ではこのトークンを1つしか保存しておくことが出来ません。
(しかもスプレッドシート毎じゃなくアカウント毎に1つになっている)

詳しくは以下のコードに書いています。

https://github.com/gsuitedevs/apps-script-oauth1/blob/master/dist/OAuth1.gs

抜粋すると以下の場所になります

/**
 * Saves a token to the service's property store and cache.
 * @param {Object} token The token to save.
 * @private
 */
Service_.prototype.saveToken_ = function(token) {
	validate_({
		'Property store': this.propertyStore_
	});
	var key = this.getPropertyKey_();
	var value = JSON.stringify(token);
	this.propertyStore_.setProperty(key, value);
	if (this.cache_) {
		this.cache_.put(key, value, Service_.MAX_CACHE_TIME);
	}
};

/**
 * Gets the token from the service's property store or cache.
 * @return {Object} The token, or null if no token was found.
 * @private
 */
Service_.prototype.getToken_ = function() {
	validate_({
		'Property store': this.propertyStore_
	});
	var key = this.getPropertyKey_();
	var token;
	if (this.cache_) {
		token = this.cache_.get(key);
	}
	if (!token) {
		token = this.propertyStore_.getProperty(key);
	}
	if (token) {
		if (this.cache_) {
			this.cache_.put(key, token, Service_.MAX_CACHE_TIME);
		}
		return JSON.parse(token);
	} else {
		return null;
	}
};

ここでのgetToken、setTokenが画像の処理の②になっているのですが、

これまで紹介してきた TwitterWebService では createService(‘Twitter’) という場所で tokenを保存するkeyが『Twitter』固定になっています。

TwitterWebService_.prototype.getService = function() {
	return OAuth1.createService('Twitter')
		.setAccessTokenUrl('https://api.twitter.com/oauth/access_token')
		.setRequestTokenUrl('https://api.twitter.com/oauth/request_token')
		.setAuthorizationUrl('https://api.twitter.com/oauth/authorize')
		.setConsumerKey(this.consumer_key)
		.setConsumerSecret(this.consumer_secret)
		.setCallbackFunction('authCallback')
		.setPropertyStore(PropertiesService.getUserProperties())
}

そのため複数のアカウントでログインしようとしても区別付かない状態になっています。

Service not authorized. が出てしまう場合

複数のスプレッドシートで TwitterWebService を扱う場合、他のスプレッドシートで認証したトークンが既に “Twitter” の Key に入っている場合があります(※Keyはアカウント毎に共通)
そのため実行しようとしているスプレッドシートで行った認証結果が入っておらず、

Service not authorized.

が出ることがあります。
その場合一度reset()を実行して保存されたトークンを消して認証し直してみてください。

複数のアカウントを登録するために必要なこと

それぞれのアカウントでログインしたトークンを別々で保存できれば達成できます。

方法1:サービス名をアカウントごとに分けて作る

tokenを保存するKeyが『Twitter』になっていることが原因の1つのため、TwitterWebServiceのコードを書き換えることで解決できます。

方法2:トークンを別で管理してしまう

getToken、setTokenでトークンを保存する部分で上手くトークンを取得できないことが原因なのでトークンを独自の方法で管理することで解決も出来ます。

今回は方法1TwitterWebServiceのコードを書き換える方針で実装を行っていきます。

実装

だいぶ長いコードになってしまいましたが、これまでとの違いは2つあります。

1つ目はこれまで

var twitter = TwitterWebService.getInstance(
    'XXXXXXXXXXXXXXXXXXXX',       // 作成したアプリケーションのConsumer Key
    'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'  // 作成したアプリケーションのConsumer Secret
);

と書かれて来た場所で複数の TwitterWebService を作成して管理するようになりました。

  1. これまでtwitterという変数に入れてきたTwitterWebServiceを、サービス名毎に作る
  2. TwitterWebServiceの名前をTwitter固定ではなく、こちらが指定したKey名で発行する
  3. 発行したTwitterWebServiceを配列として保存する

ということを行っています。

2つ目は配列として管理するようになった TwitterWebService を for でそれぞれ実行するようにしています。

使い方

これまで通り authorize を実行する

authorizeを実行すると2つの認証URLが発行されるようになります。

それぞれのURLで2種類のアカウントを認証しましょう!

3つ以上のアカウントで作りたい場合は、accountsの要素を増やしてもらえるとその分登録できるアカウントが増えます。

これまで通り postUpdateStatus で投稿する

認証されたアカウント分 for で postUpdateStatus を使いツイートを投稿します。

同時ツイートがダメらしいので blockTime(3000); で3秒間だけ止めつつ実行しますので少々処理完了まで時間が掛かります。

おまけ

複数アカウントでフォローするTwitterBot

それと複数アカウントで指定した人(一人)をフォローも欲しいです…
こちらもTwitterの規約に引っかかるので時間をずらすなど必要みたいです…

という要望を頂いたのでコードを書いてみました!

↑のコードをこれまでのコードに貼り付けて postUpdateStatus を実行する代わりに followUsers を実行すると users に登録されたアカウントをフォローします!

使用しているAPIはこちら

POST friendships/create

認証自体が完了していればその後のAPIの実行は前回記事の応用になるため、いろいろ試してみましょう!

更に多くのアカウントで運用したい場合

趣味用とか仕事用でアカウントが10個ありまして全てのアカウントでAPI申請しキーを取得しています。
10個のConsumer Keyを使って特定のユーザーを3分おきにフォローを作りたいのですが
一斉にフォローしちゃったり1つのアカウントしかフォローしなかったりで作れませんでした。
Google Apps Scriptで6分以上の処理はできないようで、GASでやるのは難しいでしょうか?…

コメントより

6分以上の処理って出来ないんですね…知らなかった…(-_-;)

GASは処理が遅いため長い処理はあまり向いていません。

長い処理になる場合は進行状況をシートに保存しつつ少しずつ処理を進めましょう。

例えば、このようなシートを作って、1回の処理で1人分のアカウントの処理を行っていきます。

コードは以下の通り。

参考にしていただければ幸いです!

今後の計画 〜ライブラリ作ります〜

何回かに渡ってGASを使ってTwitterAPIを実行する方法を紹介してきましたが、色々と要望を受けていくにつれて、既存のライブラリの拡張性の高さが逆にTwitterBotを作成したい方のハードルになっているのではないか、と感じるようになりました。

今回の記事を書いていく中でも「本当はこう使われるために書かれているのではないんだろうなぁと思う実装を無理やり書き換える」ようなことも起き、元ライブラリにプルリクを送ると拡張性がなくなってしまう点も悩みどころでした。

サーバーを用意する必要がなく、無料で使えるGASは「ちょっとしたBotを作りたい」な方には最適だと思うので、GASでのTwitterBot開発は踏襲しつつ、もう少しTwitterBotの開発が簡単に出来るようになるライブラリを作ろうと思ってます(要はこれまで紹介してきたTwitterWebServiceの強化版を作ります)

これまで「コピペで〜」と謳ってきたものが「ほんの数行で」実現出来るようになったりするので、もっと「作ってみようかな」と思ってくれる人が増えて貰えれば、そして「プログラミングちょっと楽しいじゃん」と思ってくれる人が増えればいいなぁと思ってます。

GitHubにも公開もする予定なので「これあったらみんな使うでしょ!」というアイディアがあれば追加してプルリク送ってくださってもいいので、そんな感じで運用していけたらいいなぁ( ´ー`)y-~~

一旦そんな予定でいるってことで、今回の記事は終わりにしたいと思います。

ここまで読んで頂きありがとうございました!

コメント

  1. ゆうちゃ より:

    リクエストに応えて頂きありがとうございます!
    とても分かりやすく参考になります!色々なBOT作成に挑戦しようと思います!
    複数のConsumer Keyでタイムラインのツイートをランダムにいいね、リツイートや指定した人をフォローなど(作れるか分かりませんが…
    これからも𝕊𝕦𝕫𝕦𝕜𝕚さんの記事楽しみにしてます!

  2. 𝕊𝕦𝕫𝕦𝕜𝕚 より:

    参考にして頂きありがとうございます!
    今回これまでの記事と比べるとちょっと複雑なので分かりにくいところとかあればご指摘お願いします!

    「作りたいものはあるけど、どうしても出来ない!」って時はまたリクエスト頂けたら一緒に考えることも出来ますので引き続きよろしくお願いいたします!

  3. ゆうちゃ より:

    参考にして頑張ったのですが作れませんでした…
    趣味用とか仕事用でアカウントが10個ありまして全てのアカウントでAPI申請しキーを取得しています。
    10個のConsumer Keyを使って特定のユーザーを3分おきにフォローを作りたいのですが
    一斉にフォローしちゃったり1つのアカウントしかフォローしなかったりで作れませんでした。
    Google Apps Scriptで6分以上の処理はできないようで、GASでやるのは難しいでしょうか?…
    良かったら何かいいアイデアがあれば教えてください…(o*。_。)o

    • 𝕊𝕦𝕫𝕦𝕜𝕚 より:

      コメントありがとうございます!
      10個のアカウントですか…!そのパターンは考えてなかったです…!

      アイディアとしては1回の実行では難しいので「前回の実行分をどこかに保存した上で数分毎に実行する」のがいいかなぁと思っています。
      この情報だけで実装ができればぜひやってみて頂きたいのですが、今度サンプルコードを作ってみようと思いますのでお待ちいただければと思います〜

  4. ゆうちゃ より:

    Beltzさんサンプルコードありがとうございます!凄いです!本当に感謝です!
    頑張ってみたのですがちょっと出来ない所がありまして…
    1個のConsumer Key使って10個のアカウント登録したら動くと思うのですが
    10個のConsumer Keyを使う場合はどうしたらいいでしょうか…??さすがに不可能な事でしょうか(笑)
    それととても感謝してて何かお礼がしたいです。投げ銭みたいな物はないのでしょうか!

    • 𝔹𝕖𝕝𝕥𝕫 より:

      10個のConsumerKeyを使うことも出来ると思います!
      今度またサンプルコード作って記事化しますのでお待ちいただけると!

      投げ銭みたいな物はないのでしょうか

      わわわ…(;´Д`)全然用意していなかったです。。。
      ですが大変励みになります!ありがとうございます!
      即席ですがPayPayで投げ銭リンクを作成しました!
      PayPay使ってない場合はご連絡ください!

  5. ゆうちゃ より:

    ありがとうございます、本当初心者すぎてごめんなさい、、(´;ω;`)
    私PayPay全然使ってなくてチャージがYahooカードと指定銀行なんで難しいんです。(少し残ってたのであげますww)
    Paypalでもいいですけどビジネスアカウントしか持ってないので…
    AmazonのAmazonギフト券(Eメールタイプ)はどうでしょうか?
    メールアドレスさえ分かればどのクレジットカードでも投げ銭可能なので!
    BeltzさんがAmazon使ってなかったらセブン銀行でPaypayチャージしてきます!(笑)

    • 𝔹𝕖𝕝𝕥𝕫 より:

      ありがとうございます〜〜(受け取りましたw)
      Amazonめっちゃ使ってます!メールアドレスですが tajukado@gmail.com に送って頂けると嬉しいです〜〜

タイトルとURLをコピーしました