diff --git a/CHANGESTODO b/CHANGESTODO index d294745..090d13f 100644 --- a/CHANGESTODO +++ b/CHANGESTODO @@ -35,6 +35,23 @@ ________________________________________________________________________ im psyc://psyced.org/~lynx Context festgestellt. ? 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 ========================================================== ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ diff --git a/world/default/en/plain.textdb b/world/default/en/plain.textdb index dcdb5ba..23a3a5e 100644 --- a/world/default/en/plain.textdb +++ b/world/default/en/plain.textdb @@ -696,6 +696,9 @@ _message_public _message_friends |[_nick] {_TEXT_action_shouts}: [_data] +_message_twitter +|[_nick] ... [_data] + _message_echo_private |You tell [_nick_target]: [_data] diff --git a/world/drivers/ldmud/include/interface.h b/world/drivers/ldmud/include/interface.h index a1dd9e0..493f7df 100644 --- a/world/drivers/ldmud/include/interface.h +++ b/world/drivers/ldmud/include/interface.h @@ -95,6 +95,7 @@ // nosave? static? volatile. only for variables, not methods! // another nice word for the opposite of persistent would be "shed" #define volatile nosave +#define persistent // every lpc dialect has its own foreach syntax. aint that cute? #define each(ITERATOR, LIST) foreach(ITERATOR : LIST) diff --git a/world/drivers/ldmud/master/accept.c b/world/drivers/ldmud/master/accept.c index 00fff09..429a3fb 100644 --- a/world/drivers/ldmud/master/accept.c +++ b/world/drivers/ldmud/master/accept.c @@ -372,6 +372,8 @@ object compile_object(string file) { // match both http:/ and https:/ objects ;D if (abbrev("http", file)) { 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]); return rob; } diff --git a/world/drivers/pike/include/interface.h b/world/drivers/pike/include/interface.h index 2bfbefa..2fbd5a4 100644 --- a/world/drivers/pike/include/interface.h +++ b/world/drivers/pike/include/interface.h @@ -83,6 +83,7 @@ // nosave? static? volatile. no idea if pike has something like this #define volatile static +#define persistent // every lpc dialect has its own foreach syntax. aint that cute? #define each(ITEM, LIST) foreach(LIST; ; ITEM) diff --git a/world/net/http/fetch.c b/world/net/http/fetch.c index 5800b77..34a382c 100644 --- a/world/net/http/fetch.c +++ b/world/net/http/fetch.c @@ -2,8 +2,8 @@ // // generic HTTP GET client, mostly used for RSS - // 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 #include #include @@ -24,7 +24,7 @@ volatile string modificationtime, etag, http_message; volatile string useragent = SERVER_VERSION; volatile int http_status, port, fetching, ssl; volatile string buffer, thehost, url, fetched, host, resource; -volatile string basicauth; +volatile string basicauth = ""; int parse_status(string all); int parse_header(string all); @@ -33,22 +33,23 @@ int buffer_content(string all); string qHost() { return thehost; } void fetch(string murl) { - if (url) return; - url = replace(murl, ":/", "://"); - P3(("%O: fetch(%O)\n", ME, url)) - connect(); + if (url) return; + // accept.c does this for us: + //url = replace(murl, ":/", "://"); + // 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; } -void setHTTPBasicAuth(string user, string password) { - basicauth = "Authorization: Basic " + encode_base64(user + ":" + password) + "\r\n"; +void sAuth(string user, string password) { + basicauth = "Authorization: Basic "+ + encode_base64(user +":"+ password) +"\r\n"; } -string sAgent(string a) { - PT(("sAgent(%O) in %O\n", a, ME)) - return useragent = a; -} +string sAgent(string a) { return useragent = a; } // net/place/news code follows. @@ -65,7 +66,7 @@ void connect() { thehost = lower_case(thehost); ssl = t == "s"; } - P3(("URL, THEHOST: %O, %O\n", url, thehost)) + PT(("URL, THEHOST: %O, %O\n", url, thehost)) unless (port) unless (sscanf(thehost, "%s:%d", thehost, port) == 2) port = ssl? HTTPS_SERVICE: HTTP_SERVICE; @@ -84,7 +85,7 @@ varargs int real_logon(int arg) { unless (url) return -3; unless (resource) sscanf(url, "%s://%s/%s", scheme, host, resource); - buffer = ""; + buffer = basicauth; if (modificationtime) buffer += "If-Modified-Since: "+ modificationtime + "\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 //emit("Connection: close\r\n\r\n"); 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" + buffer + "\r\n"); diff --git a/world/net/library/jsonparser.pike b/world/net/library/jsonparser.pike index 0cd2b75..dacd0d7 100644 --- a/world/net/library/jsonparser.pike +++ b/world/net/library/jsonparser.pike @@ -367,6 +367,7 @@ mapping jsonObject() } if (nextClean() != ':') { + PT(("jsonFAIL: '%c' at %O\n", nextClean(), myIndex)) THROW("Expected a ':' after a key.\n"); } diff --git a/world/net/person.c b/world/net/person.c index 100c5fc..76b8f60 100644 --- a/world/net/person.c +++ b/world/net/person.c @@ -1315,6 +1315,7 @@ case "_message_echo_private": // fall thru case "_message_echo_public": case "_message_echo": +case "_message_twitter": case "_message_public": // avoid treating this as _message here break; @@ -1323,6 +1324,9 @@ case "_message_audio": // not being displayed to users other than psyc clients data = 0; 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": // this is only visible in person.c, not user.c // therefore probably useless diff --git a/world/net/place/archetype.gen b/world/net/place/archetype.gen index 44a5b24..d5c2b53 100644 --- a/world/net/place/archetype.gen +++ b/world/net/place/archetype.gen @@ -1354,6 +1354,7 @@ msg(source, mc, data, mapping vars) { else unless (!source || qAllowExternal(&source, mc, vars) // mayExternal hook || MEMBER(source) + || source == "/" // allow root to send everywhere || isValidRelay(source) || isValidRelay(vars["_source_relay"]) || isValidRelay(vars["_context"])) { diff --git a/world/net/twitter/polly.c b/world/net/twitter/polly.c new file mode 100644 index 0000000..4c2203f --- /dev/null +++ b/world/net/twitter/polly.c @@ -0,0 +1,106 @@ +// vim:foldmethod=marker:syntax=lpc:noexpandtab +// +// yeah yeah twitter.. why twitter? +// http://about.psyc.eu/Twitter + +#include + +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 ); +} + diff --git a/world/net/user.c b/world/net/user.c index a2e132d..0566f19 100644 --- a/world/net/user.c +++ b/world/net/user.c @@ -753,6 +753,7 @@ case "_message_announcement": case "_message_behaviour_warning": case "_message_behaviour_punishment": case "_message_behaviour": +case "_message_twitter": unless (stringp(data)) variant = "_default"; else variant = ""; #ifdef USE_THE_NICK