mirror of
https://github.com/ChronosX88/psyced.git
synced 2025-01-08 09:11:46 +00:00
Merge commit 'origin'
This commit is contained in:
commit
a13cddb2d4
34
CHANGESTODO
34
CHANGESTODO
@ -6,6 +6,9 @@ Essentially: whenever you fix something, move that line to the end of file.
|
|||||||
________________________________________________________________________
|
________________________________________________________________________
|
||||||
== NEXT RELEASE ========================================================
|
== NEXT RELEASE ========================================================
|
||||||
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||||
|
- autorefetch twitter isnt working
|
||||||
|
http/fetch is too complicated. throw out the queue and callback logic. kiss!
|
||||||
|
|
||||||
? support tls multiplexing on all suitable ports
|
? support tls multiplexing on all suitable ports
|
||||||
|
|
||||||
? bugs in psyced install procedure
|
? bugs in psyced install procedure
|
||||||
@ -35,6 +38,28 @@ ________________________________________________________________________
|
|||||||
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
|
||||||
|
.
|
||||||
|
|
||||||
|
- the linking blues...
|
||||||
|
tgX sagt: on reconnect i didn't get any _echo_place_enter_login's from this room, then no response for _request_do_enter, and after a _request_do_leave i get replies for enter/leave but instead of _echo_place_enter/leave i get _notice_place_enter/leave
|
||||||
|
|
||||||
|
? should /load inform that errors go to the console?
|
||||||
________________________________________________________________________
|
________________________________________________________________________
|
||||||
== psyced 1.0 ==========================================================
|
== psyced 1.0 ==========================================================
|
||||||
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||||
@ -3895,3 +3920,12 @@ spyc/* psyc/*
|
|||||||
install.sh
|
install.sh
|
||||||
+ don't leave _host_IP uncommented
|
+ don't leave _host_IP uncommented
|
||||||
+ mkdir data/* log/*
|
+ mkdir data/* log/*
|
||||||
|
=== 200904 ============================================================
|
||||||
|
net/twitter
|
||||||
|
+ polly: periodically fetch updates from a twitter account and distribute to
|
||||||
|
hundreds of newsfeed contexts
|
||||||
|
+ listing: provide a listing of subscribed feeds
|
||||||
|
http/fetch
|
||||||
|
- minor api cleanups to serve a more generic job
|
||||||
|
library/dns
|
||||||
|
+ honor #define _flag_disable_trust_localhost
|
||||||
|
@ -489,6 +489,10 @@ fi
|
|||||||
|
|
||||||
if test "\$1" = "-m"
|
if test "\$1" = "-m"
|
||||||
then
|
then
|
||||||
|
# git is seriously unsuited for this job. we need to "check in" the changes
|
||||||
|
# to file permissions etc or otherwise we can't update things at all...
|
||||||
|
(cd $base && git commit -a -m 'automatic by psyced -m')
|
||||||
|
# merging will of course fail.. sigh
|
||||||
(cd $base && git merge -s resolve origin)
|
(cd $base && git merge -s resolve origin)
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
@ -1423,6 +1423,24 @@ _HTML_examine_friend_new
|
|||||||
_HTML_examine_button_call
|
_HTML_examine_button_call
|
||||||
| <a id="Pebf" href="javascript:cmd('CALL [_nick]')">{_TEXT_button_call}</a>
|
| <a id="Pebf" href="javascript:cmd('CALL [_nick]')">{_TEXT_button_call}</a>
|
||||||
|
|
||||||
|
_HTML_listing_head_twitter
|
||||||
|
|<title>twitter polly listing of available feeds</title>
|
||||||
|
|<link href="/static/twitter/listing.css" rel="stylesheet" type="text/css" />
|
||||||
|
|<body><div id="content">
|
||||||
|
|<ol class="listing" id="twitterlist">
|
||||||
|
|
||||||
|
_HTML_listing_tail_twitter
|
||||||
|
|</ol></div></body>
|
||||||
|
|
||||||
|
_HTML_listing_item_twitter
|
||||||
|
|<li>
|
||||||
|
|<span class="_photo"><a href="http://twitter.com/[_nick]" rel="nofollow"><img src="[_uniform_photo]" /></a></span>
|
||||||
|
|## <span class="_nick"><a href="http://twitter.com/[_nick]" rel="nofollow">[_nick]</a></span>
|
||||||
|
|<span class="_name"><a href="[_page]" rel="nofollow">[_name]</a></span><br/>
|
||||||
|
|<span class="_description">[_description]</span><br/>
|
||||||
|
|<span class="_uniform"><a href="[_uniform_context]">[_uniform_context]</a></span><br/>
|
||||||
|
|</li>
|
||||||
|
|
||||||
_HTML_call
|
_HTML_call
|
||||||
|<object width="[_amount_width_object]" height="[_amount_height_object]">
|
|<object width="[_amount_width_object]" height="[_amount_height_object]">
|
||||||
|<param name="movie" value="[_path_object_local]"></param>
|
|<param name="movie" value="[_path_object_local]"></param>
|
||||||
|
@ -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)
|
||||||
|
@ -23,6 +23,7 @@ protected int block() { destruct(ME); return 0; }
|
|||||||
|
|
||||||
protected connect_failure(mc, text) {
|
protected connect_failure(mc, text) {
|
||||||
is_connecting = 0;
|
is_connecting = 0;
|
||||||
|
P1(("connect failure %O in %O, %O.\n", mc, ME, text))
|
||||||
monitor_report("_failure_network_connect"+ mc,
|
monitor_report("_failure_network_connect"+ mc,
|
||||||
object_name(ME) +" · "+ text);
|
object_name(ME) +" · "+ text);
|
||||||
}
|
}
|
||||||
@ -42,7 +43,7 @@ protected int logon(int failure) {
|
|||||||
}
|
}
|
||||||
is_connecting = 0;
|
is_connecting = 0;
|
||||||
if (failure == -1 || !interactive(ME)) {
|
if (failure == -1 || !interactive(ME)) {
|
||||||
PT(("Warning: Failed connect attempt in %O\n", ME))
|
P3(("Warning: Failed connect attempt in %O\n", ME))
|
||||||
#if __EFUN_DEFINED__(errno)
|
#if __EFUN_DEFINED__(errno)
|
||||||
connect_failure("_attempt", sprintf("connect failed: errno %s",
|
connect_failure("_attempt", sprintf("connect failed: errno %s",
|
||||||
errno()));
|
errno()));
|
||||||
|
@ -2,8 +2,13 @@
|
|||||||
//
|
//
|
||||||
// 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! ;)
|
||||||
//
|
|
||||||
|
#ifdef Dfetch
|
||||||
|
# undef DEBUG
|
||||||
|
# define DEBUG Dfetch
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <ht/http.h>
|
#include <ht/http.h>
|
||||||
#include <net.h>
|
#include <net.h>
|
||||||
#include <uniform.h>
|
#include <uniform.h>
|
||||||
@ -24,7 +29,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 +38,28 @@ 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 != murl) {
|
||||||
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;
|
||||||
|
// resource may need to be re-parsed (other params)
|
||||||
|
resource = 0;
|
||||||
|
// re-parse the hostname?
|
||||||
|
//thehost = port = 0;
|
||||||
|
}
|
||||||
|
P3(("%O: fetch(%O)\n", ME, url))
|
||||||
|
unless (fetching) 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 +76,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))
|
P4(("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;
|
||||||
@ -73,18 +84,18 @@ void connect() {
|
|||||||
::connect(thehost, port);
|
::connect(thehost, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
varargs int real_logon(int arg) {
|
varargs int real_logon(int failure) {
|
||||||
string scheme;
|
string scheme;
|
||||||
|
|
||||||
headers = ([ ]);
|
headers = ([ ]);
|
||||||
http_status = 500;
|
http_status = 500;
|
||||||
http_message = "(failure)"; // used by debug only
|
http_message = "(failure)"; // used by debug only
|
||||||
|
|
||||||
unless(::logon(arg)) return -1;
|
unless(::logon(failure)) return -1;
|
||||||
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";
|
||||||
@ -92,7 +103,8 @@ varargs int real_logon(int arg) {
|
|||||||
// emit("If-None-Match: " + etag + "\r\n");
|
// emit("If-None-Match: " + etag + "\r\n");
|
||||||
// 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))
|
P1(("%O fetching /%s from %O\n", ME, resource, host))
|
||||||
|
P4(("%O using %O\n", ME, buffer))
|
||||||
emit("GET /"+ resource +" HTTP/1.0\r\n"
|
emit("GET /"+ resource +" HTTP/1.0\r\n"
|
||||||
"Host: "+ host +"\r\n"
|
"Host: "+ host +"\r\n"
|
||||||
+ buffer +
|
+ buffer +
|
||||||
@ -103,7 +115,7 @@ varargs int real_logon(int arg) {
|
|||||||
return 0; // duh.
|
return 0; // duh.
|
||||||
}
|
}
|
||||||
|
|
||||||
varargs int logon(int arg, int sub) {
|
varargs int logon(int failure, int sub) {
|
||||||
// net/connect disables telnet for all robots and circuits
|
// net/connect disables telnet for all robots and circuits
|
||||||
#if 0 //__EFUN_DEFINED__(enable_telnet)
|
#if 0 //__EFUN_DEFINED__(enable_telnet)
|
||||||
// when fetching the spiegel rss feed, telnet_neg() occasionally
|
// when fetching the spiegel rss feed, telnet_neg() occasionally
|
||||||
@ -112,9 +124,9 @@ varargs int logon(int arg, int sub) {
|
|||||||
enable_telnet(0);
|
enable_telnet(0);
|
||||||
#endif
|
#endif
|
||||||
// when called from xmlrpc.c we can't do TLS anyway
|
// when called from xmlrpc.c we can't do TLS anyway
|
||||||
if (sub) return ::logon(arg);
|
if (sub) return ::logon(failure);
|
||||||
if (ssl) tls_init_connection(ME, #'real_logon);
|
if (ssl) tls_init_connection(ME, #'real_logon);
|
||||||
else real_logon(arg);
|
else real_logon(failure);
|
||||||
return 0; // duh.
|
return 0; // duh.
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,8 +136,9 @@ int parse_status(string all) {
|
|||||||
|
|
||||||
sscanf(all, "%s%t%s", prot, state);
|
sscanf(all, "%s%t%s", prot, state);
|
||||||
sscanf(state, "%d%t%s", http_status, http_message);
|
sscanf(state, "%d%t%s", http_status, http_message);
|
||||||
P3(("%O got %O %O from %O\n", ME, http_status, http_message, host));
|
|
||||||
if (http_status != R_OK) {
|
if (http_status != R_OK) {
|
||||||
|
P1(("%O got %O %O from %O\n", ME,
|
||||||
|
http_status, http_message, host));
|
||||||
monitor_report("_failure_unsupported_code_HTTP",
|
monitor_report("_failure_unsupported_code_HTTP",
|
||||||
S("http/fetch'ing %O returned %O %O", url || ME,
|
S("http/fetch'ing %O returned %O %O", url || ME,
|
||||||
http_status, http_message));
|
http_status, http_message));
|
||||||
@ -136,9 +149,9 @@ int parse_status(string all) {
|
|||||||
|
|
||||||
int parse_header(string all) {
|
int parse_header(string all) {
|
||||||
string key, val;
|
string key, val;
|
||||||
D2(D("htroom::parse is: " + all + "\n");)
|
|
||||||
// TODO: parse status code
|
// TODO: parse status code
|
||||||
if (all != "") {
|
if (all != "") {
|
||||||
|
P2(("http/fetch::parse_header %O\n", all))
|
||||||
if (sscanf(all, "%s:%1.0t%s", key, val) == 2) {
|
if (sscanf(all, "%s:%1.0t%s", key, val) == 2) {
|
||||||
headers[lower_case(key)] = val;
|
headers[lower_case(key)] = val;
|
||||||
// P2(("ht head: %O = %O\n", key, val))
|
// P2(("ht head: %O = %O\n", key, val))
|
||||||
@ -147,6 +160,7 @@ int parse_header(string all) {
|
|||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
// das wollen wir nur bei status 200
|
// das wollen wir nur bei status 200
|
||||||
|
P2(("%O now waiting for http body\n", ME))
|
||||||
next_input_to(#'buffer_content);
|
next_input_to(#'buffer_content);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -154,70 +168,72 @@ int parse_header(string all) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int buffer_content(string all) {
|
int buffer_content(string all) {
|
||||||
|
P2(("%O body %O\n", ME, all))
|
||||||
buffer += all + "\n";
|
buffer += all + "\n";
|
||||||
next_input_to(#'buffer_content);
|
next_input_to(#'buffer_content);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnected(remainder) {
|
disconnected(remainder) {
|
||||||
headers["_fetchtime"] = isotime(ctime(time()), 1);
|
P2(("%O got disconnected.. %O\n", ME, remainder))
|
||||||
if (headers["last-modified"])
|
headers["_fetchtime"] = isotime(ctime(time()), 1);
|
||||||
|
if (headers["last-modified"])
|
||||||
modificationtime = headers["last-modified"];
|
modificationtime = headers["last-modified"];
|
||||||
if (headers["etag"])
|
if (headers["etag"])
|
||||||
etag = headers["etag"]; // heise does not work with etag
|
etag = headers["etag"]; // heise does not work with etag
|
||||||
|
|
||||||
fetched = buffer;
|
fetched = buffer;
|
||||||
if (remainder) fetched += remainder;
|
if (remainder) fetched += remainder;
|
||||||
fheaders = headers;
|
fheaders = headers;
|
||||||
buffer = headers = 0;
|
buffer = headers = 0;
|
||||||
switch (http_status) {
|
switch (http_status) {
|
||||||
case R_OK:
|
case R_OK:
|
||||||
mixed *waiter;
|
mixed *waiter;
|
||||||
while (qSize(ME)) {
|
while (qSize(ME)) {
|
||||||
waiter = shift(ME);
|
waiter = shift(ME);
|
||||||
funcall(waiter[0], fetched, waiter[1] ? fheaders : copy(fheaders));
|
P2(("%O calls back.. body is %O\n", ME, fetched))
|
||||||
|
funcall(waiter[0], fetched, waiter[1] ? fheaders : copy(fheaders));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// doesn't seem to get here when HTTP returns 301 or 302. strange.
|
||||||
|
// fall thru
|
||||||
|
case R_NOTMODIFIED:
|
||||||
|
qDel(ME);
|
||||||
|
qInit(ME, 150, 5);
|
||||||
}
|
}
|
||||||
break;
|
fetching = 0;
|
||||||
default:
|
return 1; // presume this disc was expected
|
||||||
// doesn't seem to get here when HTTP returns 301 or 302. strange.
|
|
||||||
// fall thru
|
|
||||||
case R_NOTMODIFIED:
|
|
||||||
qDel(ME);
|
|
||||||
qInit(ME, 150, 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
fetching = 0;
|
|
||||||
return 1; // presume this disc was expected
|
|
||||||
}
|
}
|
||||||
|
|
||||||
varargs string content(closure cb, int force, int willbehave) {
|
varargs string content(closure cb, int force, int willbehave) {
|
||||||
if (cb) {
|
if (cb) {
|
||||||
if (fetched) {
|
if (fetched) {
|
||||||
if (force) {
|
if (force) {
|
||||||
funcall(cb, fetched, willbehave ? fheaders : copy(fheaders));
|
funcall(cb, fetched, willbehave ? fheaders : copy(fheaders));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
enqueue(ME, ({ cb, willbehave }));
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
enqueue(ME, ({ cb, willbehave }));
|
|
||||||
}
|
}
|
||||||
}
|
return fetched;
|
||||||
return fetched;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
varargs mapping headers(int willbehave) {
|
varargs mapping headers(int willbehave) {
|
||||||
return willbehave ? fheaders : copy(fheaders);
|
return willbehave ? fheaders : copy(fheaders);
|
||||||
}
|
}
|
||||||
|
|
||||||
string qHeader(mixed key) {
|
string qHeader(mixed key) {
|
||||||
if (mappingp(fheaders)) return fheaders[key];
|
if (mappingp(fheaders)) return fheaders[key];
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
varargs void refetch(closure cb, int willbehave) {
|
varargs void refetch(closure cb, int willbehave) {
|
||||||
enqueue(ME, ({ cb, willbehave }));
|
enqueue(ME, ({ cb, willbehave }));
|
||||||
unless (fetching) connect();
|
unless (fetching) connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected create() {
|
protected create() {
|
||||||
qCreate();
|
qCreate();
|
||||||
qInit(ME, 150, 5);
|
qInit(ME, 150, 5);
|
||||||
}
|
}
|
||||||
|
@ -189,6 +189,7 @@ mixed unMarshal(XMLNode parsed) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// why is this almost the same code as in http/fetch?
|
||||||
int disconnected(string remainder) {
|
int disconnected(string remainder) {
|
||||||
mixed *args;
|
mixed *args;
|
||||||
|
|
||||||
|
@ -414,12 +414,20 @@ w(string mc, string data, mapping vars, mixed source) {
|
|||||||
# ifdef ALIASES
|
# ifdef ALIASES
|
||||||
if (raliases[source]) {
|
if (raliases[source]) {
|
||||||
nick2 = raliases[source];
|
nick2 = raliases[source];
|
||||||
|
# if 0
|
||||||
vars["_INTERNAL_source_IRC"] = nick2 +"!"+
|
vars["_INTERNAL_source_IRC"] = nick2 +"!"+
|
||||||
u[UNick]? u[UNick] +"@"+ u[UHost]
|
u[UNick]? u[UNick] +"@"+ u[UHost]
|
||||||
: (vars["_nick_long"]
|
: (vars["_nick_long"]
|
||||||
|| vars["_INTERNAL_nick_plain"]
|
|| vars["_INTERNAL_nick_plain"]
|
||||||
|| vars["_nick"])
|
|| vars["_nick"])
|
||||||
+"@alias.undefined";
|
+"@alias.undefined";
|
||||||
|
# else
|
||||||
|
vars["_INTERNAL_source_IRC"] = nick2 +"!"+
|
||||||
|
(u[UNick]? u[UNick] +"@"+ u[UHost]
|
||||||
|
: (vars["_nick_long"]
|
||||||
|
|| vars["_INTERNAL_nick_plain"]
|
||||||
|
|| vars["_nick"]));
|
||||||
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
unless (nick2) {
|
unless (nick2) {
|
||||||
|
@ -107,7 +107,7 @@ int legal_host(string ip, int port, string scheme, int udpflag) { // proto.h!
|
|||||||
// we sincerely hope our kernel will drop udp packets that
|
// we sincerely hope our kernel will drop udp packets that
|
||||||
// spoof they are coming from localhost.. would be ridiculous if not
|
// spoof they are coming from localhost.. would be ridiculous if not
|
||||||
// if (ip == "127.0.0.1" || ip == "127.1" || ip == "0") return 9;
|
// if (ip == "127.0.0.1" || ip == "127.1" || ip == "0") return 9;
|
||||||
#ifndef DONT_TRUST_LOCALHOST
|
#ifndef _flag_disable_trust_localhost
|
||||||
if (localhosts[ip]) return 9;
|
if (localhosts[ip]) return 9;
|
||||||
if (ip == myIP || !ip) return 8;
|
if (ip == myIP || !ip) return 8;
|
||||||
#endif
|
#endif
|
||||||
@ -123,7 +123,7 @@ int legal_domain(string host, int port, string scheme, int udpflag) {
|
|||||||
// spoof they are coming from localhost.. would be ridiculous if not
|
// spoof they are coming from localhost.. would be ridiculous if not
|
||||||
//
|
//
|
||||||
// TODO: use is_localhost here?
|
// TODO: use is_localhost here?
|
||||||
#ifndef DONT_TRUST_LOCALHOST
|
#ifndef _flag_disable_trust_localhost
|
||||||
if (host == "localhost" || host == SERVER_HOST) return 9;
|
if (host == "localhost" || host == SERVER_HOST) return 9;
|
||||||
#endif
|
#endif
|
||||||
// if (host == myLowerCaseHost) return 8;
|
// if (host == myLowerCaseHost) return 8;
|
||||||
|
@ -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
|
||||||
@ -1372,24 +1376,33 @@ case "_request_execute":
|
|||||||
// our places
|
// our places
|
||||||
if (places[t]) {
|
if (places[t]) {
|
||||||
vSet("place", place = t);
|
vSet("place", place = t);
|
||||||
|
PT(("REQ-EX place %O\n", t))
|
||||||
} else {
|
} else {
|
||||||
// see if it is a local object
|
// see if it is a local object
|
||||||
object o = psyc_object(t);
|
object o = psyc_object(t);
|
||||||
|
if (o) {
|
||||||
// object one of our places?
|
// object one of our places?
|
||||||
if (o && places[o]) {
|
if (places[o]) {
|
||||||
place = o;
|
place = o;
|
||||||
vSet("place", o->qName());
|
vSet("place", o->qName());
|
||||||
|
PT(("REQ-EX o'place %O\n", o))
|
||||||
|
} else {
|
||||||
|
PT(("REQ-EX object %O not found in %s's places %O\n", o, MYNICK, places))
|
||||||
|
}
|
||||||
} else unless (t2) {
|
} else unless (t2) {
|
||||||
// must be a person then
|
// must be a person then
|
||||||
// ME->parsecmd(data, t);
|
// ME->parsecmd(data, t);
|
||||||
parsecmd(data, t);
|
PT(("REQ-EX person %O vs %O\n", t, o))
|
||||||
// should be able to put o||t
|
// should be able to put o||t
|
||||||
// here.. TODO
|
// here.. TODO
|
||||||
|
parsecmd(data, t);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
PT(("REQ-EX non-string %O\n", t))
|
||||||
|
}
|
||||||
// ME->parsecmd(data);
|
// ME->parsecmd(data);
|
||||||
if (t2) {
|
if (t2) {
|
||||||
unless (request(source, t2, vars, data)) {
|
unless (request(source, t2, vars, data)) {
|
||||||
@ -1632,8 +1645,12 @@ case "_notice_invitation":
|
|||||||
vars["_nick_place"] : vars["_place"]);
|
vars["_nick_place"] : vars["_place"]);
|
||||||
|
|
||||||
// same filtering code as couple lines further below
|
// same filtering code as couple lines further below
|
||||||
if (( IS_NEWBIE || !itsme && FILTERED(source)) &&
|
if ((
|
||||||
(!profile || profile[PPL_NOTIFY] <= PPL_NOTIFY_PENDING)) {
|
#ifndef _flag_enable_unauthenticated_message_private
|
||||||
|
IS_NEWBIE ||
|
||||||
|
#endif
|
||||||
|
(!itsme && FILTERED(source)) &&
|
||||||
|
(!profile || profile[PPL_NOTIFY] <= PPL_NOTIFY_PENDING))) {
|
||||||
sendmsg(source, "_failure_filter_strangers", 0,
|
sendmsg(source, "_failure_filter_strangers", 0,
|
||||||
([ "_nick" : MYNICK ]) );
|
([ "_nick" : MYNICK ]) );
|
||||||
unless (boss(source))
|
unless (boss(source))
|
||||||
|
@ -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"])) {
|
||||||
@ -1789,6 +1790,7 @@ cmd(a, args, b, source, vars) {
|
|||||||
return 1;
|
return 1;
|
||||||
# endif
|
# endif
|
||||||
case "hc":
|
case "hc":
|
||||||
|
case "histclean": // in case you don't remember exactly.. it's ok
|
||||||
case "histclear": // wieso um alles in der welt soll das jeder dürfen?
|
case "histclear": // wieso um alles in der welt soll das jeder dürfen?
|
||||||
// liest denn keiner die cvs kommentare? da stands
|
// liest denn keiner die cvs kommentare? da stands
|
||||||
// drin.. ok wir sind realistisch und schreiben es
|
// drin.. ok wir sind realistisch und schreiben es
|
||||||
|
@ -177,8 +177,8 @@ static varargs string psyc_render(mixed source, string mc, mixed data,
|
|||||||
data = data? to_string(data): "";
|
data = data? to_string(data): "";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (data == S_GLYPH_PACKET_DELIMITER ||
|
else if (data == S_GLYPH_PACKET_DELIMITER || (strlen(data) > 1 &&
|
||||||
(data[0] == C_GLYPH_PACKET_DELIMITER && data[1] == '\n')
|
data[0] == C_GLYPH_PACKET_DELIMITER && data[1] == '\n')
|
||||||
|| strstr(data, "\n" S_GLYPH_PACKET_DELIMITER "\n") != -1) {
|
|| strstr(data, "\n" S_GLYPH_PACKET_DELIMITER "\n") != -1) {
|
||||||
// this check shouldn't be necessary here: we should check what
|
// this check shouldn't be necessary here: we should check what
|
||||||
// people are typing in usercmd
|
// people are typing in usercmd
|
||||||
|
@ -414,7 +414,8 @@ vamixed parse(string a) {
|
|||||||
#ifndef __PIKE__
|
#ifndef __PIKE__
|
||||||
if (peerip && pongtime + 120 < time()) {
|
if (peerip && pongtime + 120 < time()) {
|
||||||
if (same_host(SERVER_HOST, peerip)) {
|
if (same_host(SERVER_HOST, peerip)) {
|
||||||
P1(("why am i talking psyc to myself?\n"))
|
P1(("Another PSYC node on my IP? Or am I talking to myself? %O\n", ME))
|
||||||
|
// not ponging to ping then...
|
||||||
} else {
|
} else {
|
||||||
#ifdef PSYC_TCP
|
#ifdef PSYC_TCP
|
||||||
P2(("%O sending TCP PONG to %O=%O\n",
|
P2(("%O sending TCP PONG to %O=%O\n",
|
||||||
|
126
world/net/twitter/listing.c
Normal file
126
world/net/twitter/listing.c
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
// vim:foldmethod=marker:syntax=lpc:noexpandtab
|
||||||
|
//
|
||||||
|
// http://localhost:33333/net/twitter/listing shows a list of friends
|
||||||
|
|
||||||
|
#include <net.h>
|
||||||
|
#include <ht/http.h>
|
||||||
|
#include <text.h>
|
||||||
|
|
||||||
|
volatile object fetcha;
|
||||||
|
volatile mixed wurst;
|
||||||
|
|
||||||
|
parse(string body) {
|
||||||
|
if (!body || body == "") {
|
||||||
|
P1(("%O failed to get its listing.\n", ME))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//#if DEBUG > 0
|
||||||
|
rm(DATA_PATH "twitter/friends.json");
|
||||||
|
write_file(DATA_PATH "twitter/friends.json", body);
|
||||||
|
P4((body))
|
||||||
|
//#endif
|
||||||
|
unless (pointerp(wurst = parse_json(body))) {
|
||||||
|
P1(("%O failed to parse its listing.\n", ME))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#ifdef DEVELOPMENT
|
||||||
|
write_file(DATA_PATH "twitter/friends.parsed", sprintf("%O\n", wurst));
|
||||||
|
#endif
|
||||||
|
P1(("%O sorting %O subscription names ", ME, sizeof(wurst)))
|
||||||
|
wurst = sort_array(wurst, (:
|
||||||
|
unless (mappingp($1)) return 0;
|
||||||
|
unless (mappingp($2)) return 1;
|
||||||
|
// PT(("%O got %O vs %O\n", ME, $1, $2))
|
||||||
|
P1(("."))
|
||||||
|
return lower_case($2["screen_name"] || "") >
|
||||||
|
lower_case($1["screen_name"] || "");
|
||||||
|
:) );
|
||||||
|
P1((" done!\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
htget(prot, query, headers, qs, data, noprocess) {
|
||||||
|
string nick;
|
||||||
|
mapping d; //, s;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
//sTextPath(query["layout"] || "twitter", query["lang"], "html");
|
||||||
|
localize(query["lang"], "html");
|
||||||
|
|
||||||
|
unless (pointerp(wurst)) {
|
||||||
|
hterror(R_TEMPOVERL,
|
||||||
|
"Haven't successfully retrieved data yet.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
htok(prot); // outputs utf-8 header, but..
|
||||||
|
w("_HTML_listing_head_twitter");
|
||||||
|
for (i=sizeof(wurst)-1; i>=0; i--) {
|
||||||
|
d = wurst[i];
|
||||||
|
unless (mappingp(d)) {
|
||||||
|
P1(("%O got a broken entry: %O.\n", ME, d))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// user "foebud" has no updates ;)
|
||||||
|
//
|
||||||
|
// s = d["status"];
|
||||||
|
// unless (mappingp(s)) {
|
||||||
|
// P1(("%O got a statusless entry: %O.\n", ME, d))
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
unless (nick = d["screen_name"]) {
|
||||||
|
P1(("%O got a nickless tweeter.\n", ME))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
w("_HTML_listing_item_twitter", 0, ([
|
||||||
|
// should i send text as _action?
|
||||||
|
"_nick": nick,
|
||||||
|
"_amount_updates": d["statuses_count"],
|
||||||
|
// _count_subscribers seems to be better for this
|
||||||
|
// or should it be _recipients? _targets?
|
||||||
|
"_amount_followers": d["followers_count"],
|
||||||
|
"_amount_sources": d["friends_count"],
|
||||||
|
// shows how old listing is.. hmm
|
||||||
|
//"_description_update": s["text"] || "",
|
||||||
|
"_color": "#"+ d["profile_sidebar_fill_color"],
|
||||||
|
"_description": d["description"] || "",
|
||||||
|
"_uniform_context": SERVER_UNIFORM +"@"+ nick,
|
||||||
|
"_page": d["url"] || "",
|
||||||
|
"_name": d["name"] || "",
|
||||||
|
// "_contact_twitter": d["id"],
|
||||||
|
"_reference_reply": d["in_reply_to_screen_name"],
|
||||||
|
// "_twit": d["id"],
|
||||||
|
"_uniform_photo": d["profile_image_url"] || "",
|
||||||
|
"_uniform_photo_background":
|
||||||
|
d["profile_background_image_url"] || ""
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
w("_HTML_listing_tail_twitter");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch() {
|
||||||
|
fetcha -> content( #'parse, 0, 1 );
|
||||||
|
fetcha -> fetch("http://twitter.com/statuses/friends.json?count=200");
|
||||||
|
}
|
||||||
|
|
||||||
|
create() {
|
||||||
|
mapping config;
|
||||||
|
object o = find_object(CONFIG_PATH "config");
|
||||||
|
|
||||||
|
if (o) config = o->qConfig();
|
||||||
|
if (!config) {
|
||||||
|
P1(("\nNo configuration for twitter gateway found in %O.\n", o))
|
||||||
|
//destruct(ME);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
string body = read_file(DATA_PATH "twitter/friends.json");
|
||||||
|
if (body) return parse(body);
|
||||||
|
|
||||||
|
// we could even choose to inherit this instead...
|
||||||
|
fetcha = clone_object(NET_PATH "http/fetch");
|
||||||
|
//fetcha -> sAgent(SERVER_VERSION " builtin Twitter to PSYC gateway");
|
||||||
|
fetcha -> sAuth(config["nickname"], config["password"]);
|
||||||
|
call_out( #'fetch, 14 );
|
||||||
|
}
|
||||||
|
|
117
world/net/twitter/polly.c
Normal file
117
world/net/twitter/polly.c
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
// 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, mapping headers) {
|
||||||
|
mixed wurst;
|
||||||
|
string nick;
|
||||||
|
object o;
|
||||||
|
mapping d, p;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!body || body == "") {
|
||||||
|
P1(("%O failed to get its timeline from %O.\n", ME,
|
||||||
|
previous_object()))
|
||||||
|
PT(("Got headers: %O\n", headers))
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
unless (sizeof(wurst)) {
|
||||||
|
P1(("%O received an empty structure.\n", ME))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (wurst[0]["id"] <= lastid) {
|
||||||
|
P1(("%O received %d old updates.\n", ME, sizeof(wurst)))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lastid = wurst[0]["id"];
|
||||||
|
save_object(DATA_PATH "twitter");
|
||||||
|
for (i=sizeof(wurst)-1; 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;
|
||||||
|
}
|
||||||
|
P4((" %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_updates": p["statuses_count"],
|
||||||
|
"_amount_followers": p["followers_count"],
|
||||||
|
"_amount_sources": p["friends_count"],
|
||||||
|
"_color": "#"+ p["profile_sidebar_fill_color"],
|
||||||
|
"_description": p["description"] || "",
|
||||||
|
"_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"],
|
||||||
|
"_uniform_photo": p["profile_image_url"] || "",
|
||||||
|
"_uniform_photo_background":
|
||||||
|
p["profile_background_image_url"] || ""
|
||||||
|
]), "/"); // 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() {
|
||||||
|
P1(("%O going to fetch from %O since %O\n", ME, feed, lastid))
|
||||||
|
call_out( #'fetch, 4 * 59 ); // odd is better
|
||||||
|
feed -> content( #'parse, 1, 1 );
|
||||||
|
// twitter ignores since_id if count is present. stupid.
|
||||||
|
feed -> fetch("http://twitter.com/statuses/friends_timeline.json?"
|
||||||
|
// +( lastid? ("since_id="+ lastid) : "count=23"));
|
||||||
|
"count="+( lastid? ("23&since_id="+ lastid) : "23"));
|
||||||
|
}
|
||||||
|
|
||||||
|
create() {
|
||||||
|
mapping config;
|
||||||
|
object o = find_object(CONFIG_PATH "config");
|
||||||
|
|
||||||
|
if (o) config = o->qConfig();
|
||||||
|
if (!config) {
|
||||||
|
P1(("\nNo 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(NET_PATH "http/fetch");
|
||||||
|
//feed -> sAgent(SERVER_VERSION " builtin Twitter to PSYC gateway");
|
||||||
|
feed -> sAuth(config["nickname"], config["password"]);
|
||||||
|
call_out( #'fetch, 14 );
|
||||||
|
}
|
||||||
|
|
@ -615,6 +615,9 @@ case "_jabber_iq_set":
|
|||||||
case "_jabber":
|
case "_jabber":
|
||||||
P1(("%O got %O", ME, mc))
|
P1(("%O got %O", ME, mc))
|
||||||
break;
|
break;
|
||||||
|
case "_notice_composing_media":
|
||||||
|
if (v("scheme") != "psyc") return 1;
|
||||||
|
break;
|
||||||
case "_message_video":
|
case "_message_video":
|
||||||
case "_message_audio":
|
case "_message_audio":
|
||||||
// not being displayed to users other than psyc clients
|
// not being displayed to users other than psyc clients
|
||||||
@ -753,6 +756,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
|
||||||
|
31
world/static/twitter/listing.css
Normal file
31
world/static/twitter/listing.css
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
* {
|
||||||
|
margin:0;padding:0;border-width:0;border-color:transparent;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
text-decoration:none;
|
||||||
|
color:#06a;
|
||||||
|
}
|
||||||
|
a:hover {
|
||||||
|
text-decoration:overline;
|
||||||
|
}
|
||||||
|
body{
|
||||||
|
font-family: 'Lucida Grande',helvetica,sans-serif;
|
||||||
|
color:#333;
|
||||||
|
background-color:#cc6;
|
||||||
|
margin:44px;
|
||||||
|
}
|
||||||
|
.listing {
|
||||||
|
background-color:#ddd;
|
||||||
|
border-left: 2px solid black;
|
||||||
|
border-right: 2px solid black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.listing li:first-child{ border-top:1px dashed black; }
|
||||||
|
.listing li{position:relative;padding:7;border-bottom:1px dashed black;line-height:1.1em;}
|
||||||
|
.listing li:hover,ol.listing li.hover{background-color:white;}
|
||||||
|
|
||||||
|
._photo{display:block;width:50px;height:50px;position:absolute;right:7;margin:0 0 0 0;}
|
||||||
|
._photo img{width:48px;height:48px;}
|
||||||
|
._description{font-size:70%;}
|
||||||
|
._uniform{font-size:80%;}
|
||||||
|
._uniform a{color:#c30}
|
Loading…
Reference in New Issue
Block a user