서버나 서비스를 사용하지 않고 정기적으로 Twitter의 자동 팔로우 되돌려 보자 (2017)
13093 단어 트위터TwitterAPIGoogleAppsScript
정기적으로 트위터 팔로우 반환
일부 서비스와 구현 예가 있지만 정보가 오래되었습니다.
가려운 곳에 손이 닿지 않는 느낌이었기 때문에 자작했습니다.
서버에서 Twitter API 스크립트를 시작하는 방법도 있지만,
서버를 세우는 것도 힘들었기 때문에
Google Apps Script로 구현했습니다.
이전 준비
새로 스프레드시트를 Google Drive에서 생성합니다.
스프레드시트 도구 → 스크립트 편집기에서 Google Apps Script(.gs)를 만듭니다.
Google Apps Script URL을 복사합니다. (나중에 사용합니다.)
Twitter API를 활용하기 위해
Twitter 애플리케이션 관리 에서 새 앱을 만듭니다.
새로 앱을 만듭니다.
Website가 없는 경우는 적당한 URL에서도 괜찮습니다.
Callback URL은 이전에 복사한 Google Apps Script의 URL을 지정합니다.
Consumer Key와 Consumer Secret을 메모해 둡니다(나중에 사용합니다.)
Twitter API를 사용하려면 OAuth1 인증을 위해 Google Apps Script 라이브러리를 추가합니다.
리소스 → 라이브러리를 엽니다.
다음 스크립트 ID로 OAuth1 for Apps Script을 추가합니다.
1CXDCY5sqT9ph64fFwSzVtXnbjpSfWdRymafDrtIZ7Z_hwysTY7IIhi7s
구현
Google Apps Script에 다음 스크립트를 작성합니다.
1CXDCY5sqT9ph64fFwSzVtXnbjpSfWdRymafDrtIZ7Z_hwysTY7IIhi7s
방금 지불한 것을 사용하십시오.
트위터 팔로우 반환.gs
// 最初にこの関数を実行し、ログに出力されたURLにアクセスしてOAuth認証する
function twitterAuthorizeUrl() {
Twitter.oauth.showUrl();
}
// OAuth認証成功後のコールバック関数
function twitterAuthorizeCallback(request) {
return Twitter.oauth.callback(request);
}
// OAuth認証のキャッシュをを削除する場合はこれを実行(実行後は再度認証が必要)
function twitterAuthorizeClear() {
Twitter.oauth.clear();
}
var Twitter = {
consumerKey: "(先程払い出したConsumer Key)",
consumerSecret: "(先程払い出したConsumer Secret)",
apiUrl: "https://api.twitter.com/1.1/",
oauth: {
name: "twitter",
service: function(screen_name) {
// 参照元:https://github.com/googlesamples/apps-script-oauth1
return OAuth1.createService(this.name)
// 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(this.parent.consumerKey)
.setConsumerSecret(this.parent.consumerSecret)
// Set the name of the callback function in the script referenced
// above that should be invoked to complete the OAuth flow.
.setCallbackFunction('twitterAuthorizeCallback')
// Set the property store where authorized tokens should be persisted.
.setPropertyStore(PropertiesService.getUserProperties());
},
showUrl: function() {
var service = this.service();
if (!service.hasAccess()) {
Logger.log(service.authorize());
} else {
Logger.log("認証済みです");
}
},
callback: function (request) {
var service = this.service();
var isAuthorized = service.handleCallback(request);
if (isAuthorized) {
return HtmlService.createHtmlOutput("認証に成功しました!このタブは閉じてかまいません。");
} else {
return HtmlService.createHtmlOutput("認証に失敗しました・・・");
}
},
clear: function(){
OAuth1.createService(this.name)
.setPropertyStore(PropertiesService.getUserProperties())
.reset();
}
},
api: function(path, data) {
var that = this, service = this.oauth.service();
if (!service.hasAccess()) {
Logger.log("先にOAuth認証してください");
return false;
}
path = path.toLowerCase().replace(/^\//, '').replace(/\.json$/, '');
var method = (
/^statuses\/(destroy\/\d+|update|retweet\/\d+)/.test(path)
|| /^media\/upload/.test(path)
|| /^direct_messages\/(destroy|new)/.test(path)
|| /^friendships\/(create|destroy|update)/.test(path)
|| /^account\/(settings|update|remove)/.test(path)
|| /^blocks\/(create|destroy)/.test(path)
|| /^mutes\/users\/(create|destroy)/.test(path)
|| /^favorites\/(destroy|create)/.test(path)
|| /^lists\/[^\/]+\/(destroy|create|update)/.test(path)
|| /^saved_searches\/(create|destroy)/.test(path)
|| /^geo\/place/.test(path)
|| /^users\/report_spam/.test(path)
) ? "post" : "get";
var url = this.apiUrl + path + ".json";
var options = {
method: method,
muteHttpExceptions: true
};
if ("get" === method) {
if (!this.isEmpty(data)) {
url += '?' + Object.keys(data).map(function(key) {
return that.encodeRfc3986(key) + '=' + that.encodeRfc3986(data[key]);
}).join('&');
}
} else if ("post" == method) {
if (!this.isEmpty(data)) {
options.payload = Object.keys(data).map(function(key) {
return that.encodeRfc3986(key) + '=' + that.encodeRfc3986(data[key]);
}).join('&');
if (data.media) {
options.contentType = "multipart/form-data;charset=UTF-8";
}
}
}
try {
var result = service.fetch(url, options);
var json = JSON.parse(result.getContentText());
if (json) {
if (json.error) {
throw new Error(json.error + " (" + json.request + ")");
} else if (json.errors) {
var err = [];
for (var i = 0, l = json.errors.length; i < l; i++) {
var error = json.errors[i];
err.push(error.message + " (code: " + error.code + ")");
}
throw new Error(err.join("\n"));
} else {
return json;
}
}
} catch(e) {
this.error(e);
}
return false;
},
error: function(error) {
var message = null;
if ('object' === typeof error && error.message) {
message = error.message + " ('" + error.fileName + '.gs:' + error.lineNumber +")";
} else {
message = error;
}
Logger.log(message);
},
isEmpty: function(obj) {
if (obj == null) return true;
if (obj.length > 0) return false;
if (obj.length === 0) return true;
for (var key in obj) {
if (hasOwnProperty.call(obj, key)) return false;
}
return true;
},
encodeRfc3986: function(str) {
return encodeURIComponent(str).replace(/[!'()]/g, function(char) {
return escape(char);
}).replace(/\*/g, "%2A");
},
init: function() {
this.oauth.parent = this;
return this;
}
}.init();
/********************************************************************
以下はサポート関数
*/
// ツイート検索
Twitter.search = function(data) {
if ("string" === typeof data) {
data = {q: data};
}
return this.api("search/tweets", data);
};
// 自分のタイムライン取得
Twitter.tl = function(since_id) {
var data = null;
if ("number" === typeof since_id || /^\d+$/.test(''+since_id)) {
data = {since_id: since_id};
} else if("object" === typeof since_id) {
data = since_id;
}
return this.api("statuses/home_timeline", data);
};
// ユーザーのタイムライン取得
Twitter.usertl = function(user, since_id) {
var path = "statuses/user_timeline";
var data = {};
if (user) {
if (/^\d+$/.test(user)) {
data.user_id = user;
} else {
data.screen_name = user;
}
} else {
var path = "statuses/home_timeline";
}
if (since_id) {
data.since_id = since_id;
}
return this.api(path, data);
};
// ツイートする
Twitter.tweet = function(data, reply) {
var path = "statuses/update";
if ("string" === typeof data) {
data = {status: data};
} else if(data.media) {
path = "statuses/update_with_media ";
}
if (reply) {
data.in_reply_to_status_id = reply;
}
return this.api(path, data);
};
// トレンド取得(日本)
Twitter.trends = function(woeid) {
data = {id: woeid || 1118108};
var res = this.api("trends/place", data);
return (res && res[0] && res[0].trends && res[0].trends.length) ? res[0].trends : null;
};
// トレンドのワードのみ取得
Twitter.trendWords = function(woeid) {
data = {id: woeid || 1118108};
var res = this.api("trends/place", data);
if (res && res[0] && res[0].trends && res[0].trends.length) {
var trends = res[0].trends;
var words = [];
for(var i = 0, l = trends.length; i < l; i++) {
words.push(trends[i].name);
}
return words;
}
};
Twitter.follower = function(screenName) {
var data = {
screen_name: screenName,
stringify_ids: true
};
return this.api("followers/ids",data);
};
Twitter.outgoing = function(screenName) {
var data = {
screen_name: screenName,
stringify_ids: true
};
return this.api("friendships/outgoing",data);
};
Twitter.friends = function(screenName) {
var data = {
"screen_name":screenName
};
return this.api("friends/list",data);
};
Twitter.follow = function(userId) {
var data = {
"follow":true,
"user_id":userId
};
return this.api("friendships/create",data);
};
// 定期実行でフォロワー返し
function exec(){
// フォロワー一覧
var follower = Twitter.follower("meetsmore");
Logger.log(follower)
// フォロー許可待ち一覧
var outgoings = Twitter.outgoing("meetsmore");
Logger.log(outgoings)
// フォロー済み一覧
var friends = Twitter.friends("meetsmore");
Logger.log(friends)
// フォロー済みとフォローリクエスト送信済みを除外
var follow_ids = []
for(var i = friends.users.length; i--;){
follow_ids.push(friends.users[i].id_str)
}
for(var i = outgoings.ids.length; i--;){
follow_ids.push(outgoings.ids[i])
}
// 未フォロワーにフォローリクエスト
for(var i = 0; i < follow_ids.length; i++){
var idx = follower.ids.indexOf(follow_ids[i]);
if(idx !== -1){
follower.ids.splice(idx,1);
}
}
var ids = follower.ids;
for(var i = ids.length; i--;) {
var id = ids[i];
// フォローする
var result = Twitter.follow(id);
// フォローしたユーザの情報を表示
Logger.log(result);
// シートに書き込み
var Spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var Sheet = Spreadsheet.getSheetByName("Twitter");
if(Sheet){
var LastRow = Sheet.getLastRow();
Sheet.getRange(LastRow + 1,1,1,1).setValue('@' + result.screen_name);
}
}
}
OAuth 인증이 필요하기 때문에
먼저 twitterAuthorizeURL 함수를 시작합니다.
보기 → 로그에서 OAuth 인증용 URL의 로그가 표시됩니다.
브라우저에서 URL에 액세스
OAuth 인증을 완료합니다. (트위터 계정과 트위터 앱 연계)
exec 함수를 실행하면 팔로우되고 팔로우되지 않은 사용자를 일괄 적으로 팔로우합니다.
팔로우한 결과의 사용자는 스프레드시트에 내보냅니다.
정기적으로 실행
편집 → 모든 트리거를 선택합니다.
정기 실행하는 함수를 exec
이벤트를 시간 주도형으로 설정합니다.
시간은 적당히 결정해 주세요(나는 1시간마다 했습니다)
Reference
이 문제에 관하여(서버나 서비스를 사용하지 않고 정기적으로 Twitter의 자동 팔로우 되돌려 보자 (2017)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/teradonburi/items/04ec6c042631a8900242텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)