更新ScriptProperty以避免检索重复的Twitter状态
Updating a ScriptProperty to avoid retrieving duplicate Twitter statuses
我有兴趣写一个推特机器人来帮助当地滑雪场的一些朋友。我从Amit Agarwal那里找到了这个教程,它给了我足够的时间来开始(由于我做了很多修改,它确实花了我5分钟多的时间)。我在谷歌文档上主持这个脚本。
FIRST我认为这是javascript(我的理解是谷歌应用程序脚本使用javascript…),到目前为止,当我的代码出现问题时,谷歌搜索javascript之类的东西很有帮助,但如果这实际上不是javascript,请告诉我,这样我就可以相应地更新标签!
我之前没有javascript的经验,所以我很高兴它能真正工作。但我想看看我做得对不对。
start
功能启动触发器,触发器每隔一段时间(30分钟)启动fetchTweets()
功能。为了避免重复(我遇到的第一个错误)&可能被标记为垃圾邮件,我需要一种方法来确保我不会一次又一次地发布相同的推文。在start()
函数中,分配初始since_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;
}
使用ScriptProperties.setProperty("KEY", "VALUE");
时,内部脚本属性将覆盖重复的键(即,如果旧属性具有相同的键,则新属性将替换它)。因此,在您的情况下,由于您对键(SINCE_TWITTER_ID
)使用相同的标识符,因此将替换该键的任何先前脚本属性。
此外,您还可以通过File
->Project properties
->Project properties (tab)
查看脚本属性。伊莫谷歌的名字不太好特定于谷歌用户的用户属性编写特定于正在处理的脚本项目的脚本属性。
此外,在设置属性时,在值中包含'n
可能不是一个好主意。这将导致未来出现各种各样的错误,因为你必须与以下内容进行比较:
var valToCompare = "My value'n";
而不是:
var valToCompare = "My value";
因为在调用fetchTweet()
函数后,SINCE_TWITTER_ID
中的值实际上将是"some value'n"
。
当然,我认为这似乎更合乎逻辑,除非你真的需要换行符(在这种情况下,你应该在其他地方使用它们,用于这个应用程序)。
你这样也没关系,我不知道你为什么在末尾添加。可能会混淆其他代码。您可以在脚本的文件菜单中看到脚本属性+属性
- 事件和状态
- 在Twitter上用ie9中的空白src访问iframe的contentWindow
- Twitter Bootstrap typeahead:使用“this”获取上下文/调用元素
- 获取选择框的状态
- 相位器状态未捕获参考错误
- 使用Twitter API进行推文时出现重复状态错误
- 通过Twitter API javascript从时间线获取Twitter状态
- 创建一个复选框按钮的散列,这些按钮在单击时在Twitter Bootstrap Button组中处于活动状态
- Twitter引导程序:删除/切换类似复选框的按钮组的活动状态
- 更新ScriptProperty以避免检索重复的Twitter状态
- 如何在页面重新加载后使用 Twitter 引导程序保持当前选项卡处于活动状态
- 强制 Twitter Epi 库发布状态更新,即使它是上一条推文的副本
- 问题显示twitter状态/user_timeline MVC3.Net
- 如何在JavaScript中创建Twitter状态更新,并从中接收响应
- Twitter REST API,更新状态
- 自动更新Twitter状态
- 更新twitter状态
- 使用codebird.php显示twitter列表状态
- 使用 URL 更新 Twitter 状态 - 绕过应用广告
- 我怎样才能使Twitter引导弹出框始终处于打开状态