2009-04-18 06:09:05 +00:00
|
|
|
|
// vim:foldmethod=marker:syntax=lpc:noexpandtab
|
|
|
|
|
//
|
|
|
|
|
// yeah yeah twitter.. why twitter?
|
|
|
|
|
// http://about.psyc.eu/Twitter
|
|
|
|
|
|
|
|
|
|
#include <net.h>
|
|
|
|
|
|
2009-06-16 18:07:03 +00:00
|
|
|
|
persistent mixed lastid;
|
2009-04-18 06:09:05 +00:00
|
|
|
|
|
|
|
|
|
volatile object feed;
|
|
|
|
|
|
2009-04-20 06:18:13 +00:00
|
|
|
|
parse(string body, mapping headers) {
|
2009-04-18 06:09:05 +00:00
|
|
|
|
mixed wurst;
|
|
|
|
|
string nick;
|
|
|
|
|
object o;
|
|
|
|
|
mapping d, p;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (!body || body == "") {
|
2009-04-20 06:18:13 +00:00
|
|
|
|
P1(("%O failed to get its timeline from %O.\n", ME,
|
|
|
|
|
previous_object()))
|
2009-04-22 03:49:51 +00:00
|
|
|
|
PT(("Got headers: %O\n", headers))
|
2009-04-18 06:09:05 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
//#if DEBUG > 0
|
2009-04-26 11:53:18 +00:00
|
|
|
|
rm(DATA_PATH "twitter/timeline.json");
|
|
|
|
|
write_file(DATA_PATH "twitter/timeline.json", body);
|
2009-04-18 06:09:05 +00:00
|
|
|
|
P4((body))
|
|
|
|
|
//#endif
|
|
|
|
|
unless (pointerp(wurst = parse_json(body))) {
|
2009-12-31 18:28:27 +00:00
|
|
|
|
monitor_report("_failure_network_fetch_twitter_broken",
|
2009-06-15 09:58:03 +00:00
|
|
|
|
"[_source] failed to parse its timeline");
|
2009-04-18 06:09:05 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2009-04-22 04:25:04 +00:00
|
|
|
|
unless (sizeof(wurst)) {
|
2009-06-15 09:58:03 +00:00
|
|
|
|
monitor_report("_failure_network_fetch_twitter_empty",
|
|
|
|
|
"[_source] received an empty structure.");
|
2009-04-22 04:25:04 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2009-06-16 18:07:03 +00:00
|
|
|
|
// this used to fail on MAX_INT turning the ints to negative.. it would work for
|
|
|
|
|
// a while longer using floats, but since floating point mantissa in lpc is only
|
|
|
|
|
// 32 bits wide, it's just a question of time until we hit that roof again (when
|
2010-03-09 17:55:51 +00:00
|
|
|
|
// status_id reaches 4294967296). so let's use bignums instead. funny to run into
|
2009-06-16 18:07:03 +00:00
|
|
|
|
// such a weird problem only after years that twitter has been in existence.
|
2010-03-09 17:55:51 +00:00
|
|
|
|
if (lastid && bignum_cmp(wurst[0]["id"], lastid) <= 0) {
|
2009-06-16 18:07:03 +00:00
|
|
|
|
P1(("%O received %d old updates (id0 %O <= lastid %O).\n",
|
|
|
|
|
ME, sizeof(wurst), wurst[0]["id"], lastid))
|
2009-04-18 06:09:05 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2009-04-22 03:49:51 +00:00
|
|
|
|
lastid = wurst[0]["id"];
|
2009-04-18 06:09:05 +00:00
|
|
|
|
save_object(DATA_PATH "twitter");
|
2009-04-22 03:49:51 +00:00
|
|
|
|
for (i=sizeof(wurst)-1; i>=0; i--) {
|
2009-04-18 06:09:05 +00:00
|
|
|
|
d = wurst[i];
|
|
|
|
|
unless (mappingp(d)) {
|
|
|
|
|
P1(("%O got a broken tweet: %O.\n", ME, d))
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
p = d["user"];
|
|
|
|
|
unless (mappingp(p)) {
|
|
|
|
|
P1(("%O got a userless tweet.\n", ME))
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
unless (nick = p["screen_name"]) {
|
|
|
|
|
P1(("%O got a nickless tweeter.\n", ME))
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2009-04-22 03:49:51 +00:00
|
|
|
|
P4((" %O", nick))
|
2009-04-18 06:09:05 +00:00
|
|
|
|
o = find_place(nick);
|
|
|
|
|
|
2009-04-26 11:53:18 +00:00
|
|
|
|
// _message_twitter ? not so convincing.. a lot of the
|
|
|
|
|
// things are converted rss newsfeeds, and when private
|
|
|
|
|
// people are "chatting" over twitter, they are still
|
|
|
|
|
// "broadcasting" each message to a random conjunction
|
|
|
|
|
// of friends and strangers (we don't follow private
|
|
|
|
|
// twitters with this gateway!) ... thus it is quite
|
|
|
|
|
// appropriate that twitters are not given the same
|
|
|
|
|
// relevance as a _message. still you can /highlight
|
|
|
|
|
// particular senders in your client...
|
|
|
|
|
//
|
|
|
|
|
sendmsg(o,
|
|
|
|
|
// "_notice_headline_twitter", "([_nick]) [_headline]",
|
|
|
|
|
"_message_twitter", d["text"],
|
|
|
|
|
([
|
|
|
|
|
"_headline": d["text"], // should i send text as _action?
|
2009-04-18 06:09:05 +00:00
|
|
|
|
"_nick": nick,
|
|
|
|
|
// _count seems to be the better word for this
|
2009-04-20 06:18:13 +00:00
|
|
|
|
"_amount_updates": p["statuses_count"],
|
2009-04-18 06:09:05 +00:00
|
|
|
|
"_amount_followers": p["followers_count"],
|
2009-04-20 06:18:13 +00:00
|
|
|
|
"_amount_sources": p["friends_count"],
|
|
|
|
|
"_color": "#"+ p["profile_sidebar_fill_color"],
|
|
|
|
|
"_description": p["description"] || "",
|
|
|
|
|
"_page": p["url"] || "",
|
|
|
|
|
"_name": p["name"] || "",
|
2009-04-18 06:09:05 +00:00
|
|
|
|
// "_contact_twitter": p["id"],
|
|
|
|
|
"_description_agent_HTML": d["source"],
|
|
|
|
|
"_reference_reply": d["in_reply_to_screen_name"],
|
|
|
|
|
// "_twit": d["id"],
|
2009-04-20 06:18:13 +00:00
|
|
|
|
"_uniform_photo": p["profile_image_url"] || "",
|
|
|
|
|
"_uniform_photo_background":
|
|
|
|
|
p["profile_background_image_url"] || ""
|
2009-04-18 06:09:05 +00:00
|
|
|
|
]), "/"); // send as root
|
|
|
|
|
|
|
|
|
|
// der spiegel u.a. twittern <20>brigens in latin-1
|
|
|
|
|
// w<>hrend psyc utf-8 erwartet.. eine char guess engine
|
|
|
|
|
// muss her.. FIXME
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fetch() {
|
2009-10-15 09:48:35 +00:00
|
|
|
|
P2(("%O going to fetch from %O since %O\n", ME, feed, lastid))
|
2010-03-09 17:55:51 +00:00
|
|
|
|
call_out( #'fetch, 9 * 59 ); // odd is better.. was 4*59
|
2009-04-22 03:49:51 +00:00
|
|
|
|
feed -> content( #'parse, 1, 1 );
|
|
|
|
|
// twitter ignores since_id if count is present. stupid.
|
|
|
|
|
feed -> fetch("http://twitter.com/statuses/friends_timeline.json?"
|
2009-06-16 18:07:03 +00:00
|
|
|
|
// +( lastid? ("since_id="+ lastid) : "count=23"));
|
|
|
|
|
"count="+( lastid? ("23&since_id="+ lastid) : "23"));
|
2009-04-18 06:09:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
create() {
|
|
|
|
|
mapping config;
|
|
|
|
|
object o = find_object(CONFIG_PATH "config");
|
|
|
|
|
|
|
|
|
|
if (o) config = o->qConfig();
|
2010-03-09 17:55:51 +00:00
|
|
|
|
if (!config || !config["password"]) {
|
2009-04-20 06:18:13 +00:00
|
|
|
|
P1(("\nNo configuration for twitter gateway found.\n"))
|
|
|
|
|
//destruct(ME);
|
2009-04-18 06:09:05 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
restore_object(DATA_PATH "twitter");
|
|
|
|
|
|
|
|
|
|
// we could even choose to inherit this instead...
|
2009-04-20 06:18:13 +00:00
|
|
|
|
feed = clone_object(NET_PATH "http/fetch");
|
2009-04-18 06:09:05 +00:00
|
|
|
|
//feed -> sAgent(SERVER_VERSION " builtin Twitter to PSYC gateway");
|
2010-03-09 17:55:51 +00:00
|
|
|
|
|
|
|
|
|
// http://apiwiki.twitter.com/OAuth-FAQ#WhenareyougoingtoturnoffBasicAuth
|
|
|
|
|
// we should be using oauth by june 2010!
|
|
|
|
|
P1(("Using twitter account %O for %O ...\n", config["nickname"], ME))
|
2009-04-18 06:09:05 +00:00
|
|
|
|
feed -> sAuth(config["nickname"], config["password"]);
|
|
|
|
|
call_out( #'fetch, 14 );
|
|
|
|
|
}
|
|
|
|
|
|