Javascript 更新ScriptProperty以避免检索重复的Twitter状态
我有兴趣写一个推特机器人来帮助当地滑雪胜地的一些朋友。我从Amit Agarwal那里找到了这本教程,它给了我足够的时间开始学习(自从我做了很多修改之后,我确实花了5分钟多的时间)。我在谷歌文档上托管脚本 首先我认为这是javascript(我的理解是google apps脚本使用javascript…),当我到目前为止遇到代码问题时,google搜索javascript之类的东西很有帮助,但是如果这不是javascript,请让我知道,这样我可以相应地更新标签 我以前没有使用javascript的经验,所以我很高兴它能真正工作。但我想看看我做得对不对Javascript 更新ScriptProperty以避免检索重复的Twitter状态,javascript,twitter,google-apps-script,Javascript,Twitter,Google Apps Script,我有兴趣写一个推特机器人来帮助当地滑雪胜地的一些朋友。我从Amit Agarwal那里找到了这本教程,它给了我足够的时间开始学习(自从我做了很多修改之后,我确实花了5分钟多的时间)。我在谷歌文档上托管脚本 首先我认为这是javascript(我的理解是google apps脚本使用javascript…),当我到目前为止遇到代码问题时,google搜索javascript之类的东西很有帮助,但是如果这不是javascript,请让我知道,这样我可以相应地更新标签 我以前没有使用javascrip
start
函数启动触发器,每隔30分钟启动一次fetchTweets()
函数。为了避免重复(我遇到的第一个错误)&可能被标记为垃圾邮件,我需要一种方法来确保我不会一次又一次地发布相同的tweet。在start()
函数中,初始since\u id
值被分配:
ScriptProperties.setProperty("SINCE_TWITTER_ID", "404251049889759234");
在fetchTweet()
函数中,我想我正在用以下语句更新此属性:
ScriptProperties.setProperty("SINCE_TWITTER_ID", lastID + '\n');
这是一个好方法吗?还是有更好/更可靠的方法?如果是这样,我如何确定它正在更新属性?(我可以检查日志文件,它似乎正在这样做,因此我可能只需要为记录器创建一个永久文本文件)
非常感谢您的帮助
/** A S I M P L E T W I T T E R B O T **/
/** ======================================= **/
/** Written by Amit Agarwal @labnol on 03/08/2013 **/
/** Modified by David Zemens @agnarchy on 11/21/2013 **/
/** Tutorial link: http://www.labnol.org/?p=27902 **/
/** Live demo at http://twitter.com/DearAssistant **/
/** Last updated on 09/07/2013 - Twitter API Fix **/
function start() {
Logger.log("start!" + '\n')
// REPLACE THESE DUMMY VALUES
// https://script.google.com/macros/d/18DGYaa-jbaAK9rEv0HZ2cMcWjFGgkvVcvr6TfksMNbbu2Brk3gZeZ46R/edit
var TWITTER_CONSUMER_KEY = "___REDACTED___";
var TWITTER_CONSUMER_SECRET = "___REDACTED___";
var TWITTER_HANDLE = "___REDACTED___";
var SEARCH_QUERY = "___REDACTED___" + TWITTER_HANDLE;
// Store variables
ScriptProperties.setProperty("TWITTER_CONSUMER_KEY", TWITTER_CONSUMER_KEY);
ScriptProperties.setProperty("TWITTER_CONSUMER_SECRET", TWITTER_CONSUMER_SECRET);
ScriptProperties.setProperty("TWITTER_HANDLE", TWITTER_HANDLE);
ScriptProperties.setProperty("SEARCH_QUERY", SEARCH_QUERY);
ScriptProperties.setProperty("SINCE_TWITTER_ID", "404251049889759234");
// Delete exiting triggers, if any
var triggers = ScriptApp.getScriptTriggers();
for(var i=0; i < triggers.length; i++) {
ScriptApp.deleteTrigger(triggers[i]);
}
// Setup trigger to read Tweets every 2 hours
ScriptApp.newTrigger("fetchTweets")
.timeBased()
.everyMinutes(30)
//.everyHours(2)
.create();
}
function oAuth() {
//Authentication
var oauthConfig = UrlFetchApp.addOAuthService("twitter");
oauthConfig.setAccessTokenUrl("https://api.twitter.com/oauth/access_token");
oauthConfig.setRequestTokenUrl("https://api.twitter.com/oauth/request_token");
oauthConfig.setAuthorizationUrl("https://api.twitter.com/oauth/authorize");
oauthConfig.setConsumerKey(ScriptProperties.getProperty("TWITTER_CONSUMER_KEY"));
oauthConfig.setConsumerSecret(ScriptProperties.getProperty("TWITTER_CONSUMER_SECRET"));
}
function fetchTweets() {
oAuth();
// I put this line in to monitor whether the property is getting "stored" so as to avoid
// reading in duplicate tweets.
Logger.log("Getting tweets since " + ScriptProperties.getProperty("SINCE_TWITTER_ID"))
var twitter_handle = ScriptProperties.getProperty("TWITTER_HANDLE");
var search_query = ScriptProperties.getProperty("SEARCH_QUERY")
Logger.log("searching tweets to " + search_query + '\n');
// form the base URL
// restrict to a certain radius ---:
//var search = "https://api.twitter.com/1.1/search/tweets.json?count=5&geocode=42.827934,-83.564306,75mi&include_entities=false&result_type=recent&q=";
// unrestricted radius:
var search = "https://api.twitter.com/1.1/search/tweets.json?count=5&include_entities=false&result_type=recent&q=";
search = search + encodeString(search_query) + "&since_id=" + ScriptProperties.getProperty("SINCE_TWITTER_ID");
var options =
{
"method": "get",
"oAuthServiceName":"twitter",
"oAuthUseToken":"always"
};
try {
var result = UrlFetchApp.fetch(search, options);
var lastID = ScriptProperties.getProperty("SINCE_TWITTER_ID");
if (result.getResponseCode() === 200) {
var data = Utilities.jsonParse(result.getContentText());
if (data) {
var tweets = data.statuses;
//Logger.log(data.statuses);
for (var i=tweets.length-1; i>=0; i--) {
// Make sure this is a NEW tweet
if (tweets[i].id > ScriptProperties.getProperty("SINCE_TWITTER_ID")) {
lastID = (tweets[i].id_str);
var answer = tweets[i].text.replace(new RegExp("\@" + twitter_handle, "ig"), "").replace(twitter_handle, "");
// I find this TRY block may be necessary since a failure to send one of the tweets
// may abort the rest of the loop.
try {
Logger.log("found >> " + tweets[i].text)
Logger.log("converted >> " + answer + '\n');
sendTweet(tweets[i].user.screen_name, tweets[i].id_str, answer.substring(0,140));
// Update the script property to avoid duplicates.
ScriptProperties.setProperty("SINCE_TWITTER_ID", lastID);
Logger.log("sent to @" + tweets[i].user.screen_name + '\n');
} catch (e) {
Logger.log(e.toString() + '\n');
}
}
}
}
}
} catch (e) {
Logger.log(e.toString() + '\n');
}
Logger.log("Last used tweet.id: " + lastID + + "\n")
}
function sendTweet(user, reply_id, tweet) {
var options =
{
"method": "POST",
"oAuthServiceName":"twitter",
"oAuthUseToken":"always"
};
var status = "https://api.twitter.com/1.1/statuses/update.json";
status = status + "?status=" + encodeString("RT @" + user + " " + tweet + " - Thanks\!");
status = status + "&in_reply_to_status_id=" + reply_id;
try {
var result = UrlFetchApp.fetch(status, options);
Logger.log("JSON result = " + result.getContentText() + '\n');
}
catch (e) {
Logger.log(e.toString() + '\n');
}
}
// Thank you +Martin Hawksey - you are awesome
function encodeString (q) {
// Update: 09/06/2013
// Google Apps Script is having issues storing oAuth tokens with the Twitter API 1.1 due to some encoding issues.
// Henc this workaround to remove all the problematic characters from the status message.
var str = q.replace(/\(/g,'{').replace(/\)/g,'}').replace(/\[/g,'{').replace(/\]/g,'}').replace(/\!/g, '|').replace(/\*/g, 'x').replace(/\'/g, '');
return encodeURIComponent(str);
// var str = encodeURIComponent(q);
// str = str.replace(/!/g,'%21');
// str = str.replace(/\*/g,'%2A');
// str = str.replace(/\(/g,'%28');
// str = str.replace(/\)/g,'%29');
// str = str.replace(/'/g,'%27');
// return str;
}
/**A S I M P L E T W I T T R B O T**/
/** ======================================= **/
/**Amit Agarwal@labnol于2013年8月3日撰写**/
/**由David Zemens@agnarchy于2013年11月21日修改**/
/**教程链接:http://www.labnol.org/?p=27902 **/
/**现场演示http://twitter.com/DearAssistant **/
/**最后更新于2013年7月9日-Twitter API修复**/
函数start(){
Logger.log(“开始!”+“\n”)
//替换这些虚拟值
// https://script.google.com/macros/d/18DGYaa-jbaAK9rEv0HZ2cMcWjFGgkvVcvr6TfksMNbbu2Brk3gZeZ46R/edit
var TWITTER_CONSUMER_KEY=“\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;
var TWITTER_CONSUMER_SECRET=“\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;
var TWITTER\u HANDLE=“\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu”;
var SEARCH\u QUERY=“\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;
//存储变量
setProperty(“TWITTER\u CONSUMER\u KEY”,TWITTER\u CONSUMER\u KEY);
setproperties(“TWITTER\u CONSUMER\u SECRET”,TWITTER\u CONSUMER\u SECRET);
setProperty(“TWITTER\u句柄”,TWITTER\u句柄);
setProperty(“搜索查询”,搜索查询);
setProperties(“自TWITTER_ID”,“404251049889759234”);
//删除退出触发器(如果有)
var triggers=ScriptApp.getScriptTriggers();
对于(var i=0;i=0;i--){
//确保这是一条新的推文
if(tweets[i].id>ScriptProperties.getProperty(“自TWITTER\u id”)){
lastID=(tweets[i].id_str);
var answer=tweets[i].text.replace(新的RegExp(“\@”+twitter\u句柄,“ig”),”).replace(twitter\u句柄“”);
//我发现这个TRY块可能是必要的,因为发送一条tweet失败
//可能会中止循环的其余部分。
试一试{
Logger.log(“找到>>”+推文[i].text)
Logger.log(“已转换>>”+answer+'\n');
sendTweet(tweets[i].user.screen_name,tweets[i].id_str,answer.substring(0140));
//更新脚本属性以避免重复。
ScriptProperties.setProperty