mirror of
https://github.com/ChronosX88/psyced.git
synced 2024-11-08 19:41:00 +00:00
twitter newsfeed daemon
This commit is contained in:
parent
a32a31794e
commit
217f34fd42
17
CHANGESTODO
17
CHANGESTODO
@ -35,6 +35,23 @@ ________________________________________________________________________
|
|||||||
im psyc://psyced.org/~lynx Context festgestellt.
|
im psyc://psyced.org/~lynx Context festgestellt.
|
||||||
|
|
||||||
? who's gonna clean up the mess of having too many websites ?
|
? who's gonna clean up the mess of having too many websites ?
|
||||||
|
|
||||||
|
- when provided with a _focus pointing to yourself, _request_execute will
|
||||||
|
still try to forward a command to the "current place" - a uniform or
|
||||||
|
object is passed to parsecmd(data, dest) but dest is ignored later in cmd()
|
||||||
|
|
||||||
|
- _source_relay should point to tg, not foo (only happens with local users)
|
||||||
|
.
|
||||||
|
:_source.psyc://x-net.hu/~foo
|
||||||
|
:_target.psyc://3e44aa49.XXX:-52801/
|
||||||
|
:_source_relay.psyc://x-net.hu/~foo
|
||||||
|
|
||||||
|
:_nick.tg
|
||||||
|
:_time_INTERNAL.1239787956
|
||||||
|
:_nick_target.psyc://x-net.hu/~foo
|
||||||
|
_message_private
|
||||||
|
halo
|
||||||
|
.
|
||||||
________________________________________________________________________
|
________________________________________________________________________
|
||||||
== psyced 1.0 ==========================================================
|
== psyced 1.0 ==========================================================
|
||||||
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||||
|
@ -696,6 +696,9 @@ _message_public
|
|||||||
_message_friends
|
_message_friends
|
||||||
|[_nick] {_TEXT_action_shouts}: [_data]
|
|[_nick] {_TEXT_action_shouts}: [_data]
|
||||||
|
|
||||||
|
_message_twitter
|
||||||
|
|[_nick] ... [_data]
|
||||||
|
|
||||||
_message_echo_private
|
_message_echo_private
|
||||||
|You tell [_nick_target]: [_data]
|
|You tell [_nick_target]: [_data]
|
||||||
|
|
||||||
|
@ -95,6 +95,7 @@
|
|||||||
// nosave? static? volatile. only for variables, not methods!
|
// nosave? static? volatile. only for variables, not methods!
|
||||||
// another nice word for the opposite of persistent would be "shed"
|
// another nice word for the opposite of persistent would be "shed"
|
||||||
#define volatile nosave
|
#define volatile nosave
|
||||||
|
#define persistent
|
||||||
|
|
||||||
// every lpc dialect has its own foreach syntax. aint that cute?
|
// every lpc dialect has its own foreach syntax. aint that cute?
|
||||||
#define each(ITERATOR, LIST) foreach(ITERATOR : LIST)
|
#define each(ITERATOR, LIST) foreach(ITERATOR : LIST)
|
||||||
|
@ -372,6 +372,8 @@ object compile_object(string file) {
|
|||||||
// match both http:/ and https:/ objects ;D
|
// match both http:/ and https:/ objects ;D
|
||||||
if (abbrev("http", file)) {
|
if (abbrev("http", file)) {
|
||||||
rob = clone_object(HTTP_PATH "fetch");
|
rob = clone_object(HTTP_PATH "fetch");
|
||||||
|
// driver has the habit of removing double slash in object name
|
||||||
|
file = replace(file, ":/", "://");
|
||||||
if (rob) rob->fetch(file[..<3]);
|
if (rob) rob->fetch(file[..<3]);
|
||||||
return rob;
|
return rob;
|
||||||
}
|
}
|
||||||
|
@ -83,6 +83,7 @@
|
|||||||
|
|
||||||
// nosave? static? volatile. no idea if pike has something like this
|
// nosave? static? volatile. no idea if pike has something like this
|
||||||
#define volatile static
|
#define volatile static
|
||||||
|
#define persistent
|
||||||
|
|
||||||
// every lpc dialect has its own foreach syntax. aint that cute?
|
// every lpc dialect has its own foreach syntax. aint that cute?
|
||||||
#define each(ITEM, LIST) foreach(LIST; ; ITEM)
|
#define each(ITEM, LIST) foreach(LIST; ; ITEM)
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
//
|
//
|
||||||
// generic HTTP GET client, mostly used for RSS -
|
// generic HTTP GET client, mostly used for RSS -
|
||||||
// but we could fetch any page or data with it, really
|
// but we could fetch any page or data with it, really
|
||||||
// tobij even made the object have the URL as its object name. fancy! ;)
|
// tobij even allowed the object to have the URL as its object name. fancy! ;)
|
||||||
//
|
|
||||||
#include <ht/http.h>
|
#include <ht/http.h>
|
||||||
#include <net.h>
|
#include <net.h>
|
||||||
#include <uniform.h>
|
#include <uniform.h>
|
||||||
@ -24,7 +24,7 @@ volatile string modificationtime, etag, http_message;
|
|||||||
volatile string useragent = SERVER_VERSION;
|
volatile string useragent = SERVER_VERSION;
|
||||||
volatile int http_status, port, fetching, ssl;
|
volatile int http_status, port, fetching, ssl;
|
||||||
volatile string buffer, thehost, url, fetched, host, resource;
|
volatile string buffer, thehost, url, fetched, host, resource;
|
||||||
volatile string basicauth;
|
volatile string basicauth = "";
|
||||||
|
|
||||||
int parse_status(string all);
|
int parse_status(string all);
|
||||||
int parse_header(string all);
|
int parse_header(string all);
|
||||||
@ -33,22 +33,23 @@ int buffer_content(string all);
|
|||||||
string qHost() { return thehost; }
|
string qHost() { return thehost; }
|
||||||
|
|
||||||
void fetch(string murl) {
|
void fetch(string murl) {
|
||||||
if (url) return;
|
if (url) return;
|
||||||
url = replace(murl, ":/", "://");
|
// accept.c does this for us:
|
||||||
P3(("%O: fetch(%O)\n", ME, url))
|
//url = replace(murl, ":/", "://");
|
||||||
connect();
|
// so we can use this method also in a normal way
|
||||||
|
url = murl;
|
||||||
|
P3(("%O: fetch(%O)\n", ME, url))
|
||||||
|
connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
object load() { return ME; }
|
object load() { return ME; }
|
||||||
|
|
||||||
void setHTTPBasicAuth(string user, string password) {
|
void sAuth(string user, string password) {
|
||||||
basicauth = "Authorization: Basic " + encode_base64(user + ":" + password) + "\r\n";
|
basicauth = "Authorization: Basic "+
|
||||||
|
encode_base64(user +":"+ password) +"\r\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
string sAgent(string a) {
|
string sAgent(string a) { return useragent = a; }
|
||||||
PT(("sAgent(%O) in %O\n", a, ME))
|
|
||||||
return useragent = a;
|
|
||||||
}
|
|
||||||
|
|
||||||
// net/place/news code follows.
|
// net/place/news code follows.
|
||||||
|
|
||||||
@ -65,7 +66,7 @@ void connect() {
|
|||||||
thehost = lower_case(thehost);
|
thehost = lower_case(thehost);
|
||||||
ssl = t == "s";
|
ssl = t == "s";
|
||||||
}
|
}
|
||||||
P3(("URL, THEHOST: %O, %O\n", url, thehost))
|
PT(("URL, THEHOST: %O, %O\n", url, thehost))
|
||||||
unless (port)
|
unless (port)
|
||||||
unless (sscanf(thehost, "%s:%d", thehost, port) == 2)
|
unless (sscanf(thehost, "%s:%d", thehost, port) == 2)
|
||||||
port = ssl? HTTPS_SERVICE: HTTP_SERVICE;
|
port = ssl? HTTPS_SERVICE: HTTP_SERVICE;
|
||||||
@ -84,7 +85,7 @@ varargs int real_logon(int arg) {
|
|||||||
unless (url) return -3;
|
unless (url) return -3;
|
||||||
unless (resource) sscanf(url, "%s://%s/%s", scheme, host, resource);
|
unless (resource) sscanf(url, "%s://%s/%s", scheme, host, resource);
|
||||||
|
|
||||||
buffer = "";
|
buffer = basicauth;
|
||||||
if (modificationtime)
|
if (modificationtime)
|
||||||
buffer += "If-Modified-Since: "+ modificationtime + "\r\n";
|
buffer += "If-Modified-Since: "+ modificationtime + "\r\n";
|
||||||
if (useragent) buffer += "User-Agent: "+ useragent +"\r\n";
|
if (useragent) buffer += "User-Agent: "+ useragent +"\r\n";
|
||||||
@ -93,7 +94,7 @@ varargs int real_logon(int arg) {
|
|||||||
// we won't need connection: close w/ http/1.0
|
// we won't need connection: close w/ http/1.0
|
||||||
//emit("Connection: close\r\n\r\n");
|
//emit("Connection: close\r\n\r\n");
|
||||||
PT(("%O using %O\n", ME, buffer))
|
PT(("%O using %O\n", ME, buffer))
|
||||||
emit("GET /"+ resource +" HTTP/1.0\r\n"
|
emit("GET /"+ resource +" HTTP/1.1\r\n"
|
||||||
"Host: "+ host +"\r\n"
|
"Host: "+ host +"\r\n"
|
||||||
+ buffer +
|
+ buffer +
|
||||||
"\r\n");
|
"\r\n");
|
||||||
|
@ -367,6 +367,7 @@ mapping jsonObject()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (nextClean() != ':') {
|
if (nextClean() != ':') {
|
||||||
|
PT(("jsonFAIL: '%c' at %O\n", nextClean(), myIndex))
|
||||||
THROW("Expected a ':' after a key.\n");
|
THROW("Expected a ':' after a key.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1315,6 +1315,7 @@ case "_message_echo_private":
|
|||||||
// fall thru
|
// fall thru
|
||||||
case "_message_echo_public":
|
case "_message_echo_public":
|
||||||
case "_message_echo":
|
case "_message_echo":
|
||||||
|
case "_message_twitter":
|
||||||
case "_message_public":
|
case "_message_public":
|
||||||
// avoid treating this as _message here
|
// avoid treating this as _message here
|
||||||
break;
|
break;
|
||||||
@ -1323,6 +1324,9 @@ case "_message_audio":
|
|||||||
// not being displayed to users other than psyc clients
|
// not being displayed to users other than psyc clients
|
||||||
data = 0;
|
data = 0;
|
||||||
break;
|
break;
|
||||||
|
// we should judge our messages by their routing method, not by their
|
||||||
|
// name! thus, the _public and _private distinction has to exist only
|
||||||
|
// for display. FIXME
|
||||||
case "_message":
|
case "_message":
|
||||||
// this is only visible in person.c, not user.c
|
// this is only visible in person.c, not user.c
|
||||||
// therefore probably useless
|
// therefore probably useless
|
||||||
|
@ -1354,6 +1354,7 @@ msg(source, mc, data, mapping vars) {
|
|||||||
else unless (!source
|
else unless (!source
|
||||||
|| qAllowExternal(&source, mc, vars) // mayExternal hook
|
|| qAllowExternal(&source, mc, vars) // mayExternal hook
|
||||||
|| MEMBER(source)
|
|| MEMBER(source)
|
||||||
|
|| source == "/" // allow root to send everywhere
|
||||||
|| isValidRelay(source)
|
|| isValidRelay(source)
|
||||||
|| isValidRelay(vars["_source_relay"])
|
|| isValidRelay(vars["_source_relay"])
|
||||||
|| isValidRelay(vars["_context"])) {
|
|| isValidRelay(vars["_context"])) {
|
||||||
|
106
world/net/twitter/polly.c
Normal file
106
world/net/twitter/polly.c
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
// vim:foldmethod=marker:syntax=lpc:noexpandtab
|
||||||
|
//
|
||||||
|
// yeah yeah twitter.. why twitter?
|
||||||
|
// http://about.psyc.eu/Twitter
|
||||||
|
|
||||||
|
#include <net.h>
|
||||||
|
|
||||||
|
persistent int lastid;
|
||||||
|
|
||||||
|
volatile object feed;
|
||||||
|
|
||||||
|
parse(string body) {
|
||||||
|
mixed wurst;
|
||||||
|
string nick;
|
||||||
|
object o;
|
||||||
|
mapping d, p;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
//body = read_file("/net/twitter/many.json");
|
||||||
|
if (!body || body == "") {
|
||||||
|
P1(("%O failed to get its timeline.\n", ME))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//#if DEBUG > 0
|
||||||
|
rm(DATA_PATH "timeline.json");
|
||||||
|
write_file(DATA_PATH "timeline.json", body);
|
||||||
|
P4((body))
|
||||||
|
//#endif
|
||||||
|
unless (pointerp(wurst = parse_json(body))) {
|
||||||
|
P1(("%O failed to parse its timeline.\n", ME))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
i=sizeof(wurst)-1;
|
||||||
|
if (wurst[i]["id"] <= lastid) {
|
||||||
|
P1(("%O received old stuff.\n", ME))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lastid = wurst[i]["id"];
|
||||||
|
save_object(DATA_PATH "twitter");
|
||||||
|
for (; i>=0; i--) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
PT((" %O", nick))
|
||||||
|
o = find_place(nick);
|
||||||
|
|
||||||
|
// _notice_update_twitter ?
|
||||||
|
sendmsg(o, "_message_twitter", d["text"], ([
|
||||||
|
// should i send text as _action?
|
||||||
|
"_nick": nick,
|
||||||
|
// _count seems to be the better word for this
|
||||||
|
"_amount_followers": p["followers_count"],
|
||||||
|
"_color": "#"+ p["profile_text_color"],
|
||||||
|
"_description": p["description"],
|
||||||
|
"_uniform_photo": p["profile_image_url"],
|
||||||
|
"_page": p["url"],
|
||||||
|
"_name": p["name"],
|
||||||
|
// "_contact_twitter": p["id"],
|
||||||
|
"_description_agent_HTML": d["source"],
|
||||||
|
"_reference_reply": d["in_reply_to_screen_name"],
|
||||||
|
// "_twit": d["id"],
|
||||||
|
]), "/"); // send as root
|
||||||
|
|
||||||
|
// der spiegel u.a. twittern übrigens in latin-1
|
||||||
|
// während psyc utf-8 erwartet.. eine char guess engine
|
||||||
|
// muss her.. FIXME
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch() {
|
||||||
|
feed -> content( #'parse, 0, 1 );
|
||||||
|
feed -> fetch("http://twitter.com/statuses/friends_timeline.json"
|
||||||
|
"?since_id="+ lastid +"&count=123");
|
||||||
|
call_out( #'fetch, 9 * 60 );
|
||||||
|
}
|
||||||
|
|
||||||
|
create() {
|
||||||
|
mapping config;
|
||||||
|
object o = find_object(CONFIG_PATH "config");
|
||||||
|
|
||||||
|
if (o) config = o->qConfig();
|
||||||
|
if (!config) {
|
||||||
|
P1(("No configuration for twitter gateway found.\n");
|
||||||
|
destruct(ME);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
restore_object(DATA_PATH "twitter");
|
||||||
|
|
||||||
|
// we could even choose to inherit this instead...
|
||||||
|
feed = clone_object(HTTP_PATH "fetch");
|
||||||
|
//feed -> sAgent(SERVER_VERSION " builtin Twitter to PSYC gateway");
|
||||||
|
feed -> sAuth(config["nickname"], config["password"]);
|
||||||
|
call_out( #'fetch, 14 );
|
||||||
|
}
|
||||||
|
|
@ -753,6 +753,7 @@ case "_message_announcement":
|
|||||||
case "_message_behaviour_warning":
|
case "_message_behaviour_warning":
|
||||||
case "_message_behaviour_punishment":
|
case "_message_behaviour_punishment":
|
||||||
case "_message_behaviour":
|
case "_message_behaviour":
|
||||||
|
case "_message_twitter":
|
||||||
unless (stringp(data)) variant = "_default";
|
unless (stringp(data)) variant = "_default";
|
||||||
else variant = "";
|
else variant = "";
|
||||||
#ifdef USE_THE_NICK
|
#ifdef USE_THE_NICK
|
||||||
|
Loading…
Reference in New Issue
Block a user