mirror of
git://git.psyced.org/git/psyced
synced 2024-08-15 03:25:10 +00:00
http/oauth fixes, http/fetch POST support, place/threads signatures, place/userthreads: twitter submit
This commit is contained in:
parent
b48557c67a
commit
2ecaf00c24
8 changed files with 237 additions and 183 deletions
|
@ -30,6 +30,7 @@ volatile mapping rheaders = (["User-Agent": SERVER_VERSION]);
|
||||||
volatile string http_message;
|
volatile string http_message;
|
||||||
volatile int http_status, port, fetching, ssl;
|
volatile int http_status, port, fetching, ssl;
|
||||||
volatile string buffer, thehost, url, fetched, host, resource, method;
|
volatile string buffer, thehost, url, fetched, host, resource, method;
|
||||||
|
volatile mixed rbody;
|
||||||
|
|
||||||
int parse_status(string all);
|
int parse_status(string all);
|
||||||
int parse_header(string all);
|
int parse_header(string all);
|
||||||
|
@ -37,8 +38,9 @@ int buffer_content(string all);
|
||||||
|
|
||||||
string qHost() { return thehost; }
|
string qHost() { return thehost; }
|
||||||
|
|
||||||
varargs void fetch(string murl, string meth, mapping hdrs) {
|
varargs void fetch(string murl, string meth, mixed body, mapping hdrs) {
|
||||||
method = meth || "GET";
|
method = meth || "GET";
|
||||||
|
rbody = body;
|
||||||
if (hdrs) rheaders += hdrs;
|
if (hdrs) rheaders += hdrs;
|
||||||
if (url != murl) {
|
if (url != murl) {
|
||||||
// accept.c does this for us:
|
// accept.c does this for us:
|
||||||
|
@ -96,18 +98,28 @@ varargs int real_logon(int failure) {
|
||||||
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);
|
||||||
|
|
||||||
|
string body = "";
|
||||||
|
if (stringp(rbody)) {
|
||||||
|
body = rbody;
|
||||||
|
} else if (mappingp(rbody) && sizeof(rbody)) {
|
||||||
|
body = make_query_string(rbody);
|
||||||
|
unless (rheaders["Content-Type"])
|
||||||
|
rheaders["Content-Type"] = "application/x-www-form-urlencoded";
|
||||||
|
}
|
||||||
|
if (strlen(body)) rheaders["Content-Length"] = strlen(body);
|
||||||
|
|
||||||
buffer = "";
|
buffer = "";
|
||||||
foreach (string key, string value : rheaders) {
|
foreach (string key, string value : rheaders) {
|
||||||
buffer += key + ": " + value + "\r\n";
|
buffer += key + ": " + value + "\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");
|
||||||
P2(("%O fetching /%s from %O\n", ME, resource, host))
|
P2(("%O fetching /%s from %O\n", ME, resource, host))
|
||||||
P4(("%O using %O\n", ME, buffer))
|
P4(("%O using %O\n", ME, buffer))
|
||||||
emit(method + " /"+ resource +" HTTP/1.0\r\n"
|
emit(method + " /"+ resource +" HTTP/1.0\r\n"
|
||||||
"Host: "+ host +"\r\n"
|
"Host: "+ host +"\r\n"
|
||||||
+ buffer +
|
+ buffer + "\r\n" + body);
|
||||||
"\r\n");
|
|
||||||
|
|
||||||
buffer = "";
|
buffer = "";
|
||||||
next_input_to(#'parse_status);
|
next_input_to(#'parse_status);
|
||||||
|
|
|
@ -192,7 +192,7 @@ default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_query(query, qs) {
|
mapping parse_query(mapping query, string qs) {
|
||||||
foreach (string pair : explode(qs, "&")) {
|
foreach (string pair : explode(qs, "&")) {
|
||||||
string key, val;
|
string key, val;
|
||||||
|
|
||||||
|
@ -207,3 +207,14 @@ parse_query(query, qs) {
|
||||||
}
|
}
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
varargs string make_query_string(mapping params, int sort) {
|
||||||
|
string q = "";
|
||||||
|
array(mixed) keys = m_indices(params);
|
||||||
|
if (sort) keys = sort_array(keys, #'>);
|
||||||
|
|
||||||
|
foreach(string key : keys) {
|
||||||
|
q += (strlen(q) ? "&" : "") + urlencode(to_string(key)) + "=" + urlencode(to_string(params[key]));
|
||||||
|
}
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
|
@ -13,52 +13,49 @@
|
||||||
string consumer_key;
|
string consumer_key;
|
||||||
string consumer_secret;
|
string consumer_secret;
|
||||||
string request_token_url;
|
string request_token_url;
|
||||||
string request_token;
|
mapping request_params = ([ ]);
|
||||||
string request_secret;
|
mapping access_params = ([ ]);
|
||||||
string access_token_url;
|
string access_token_url;
|
||||||
string access_token;
|
|
||||||
string access_secret;
|
|
||||||
string authorize_url;
|
string authorize_url;
|
||||||
string callback_url = "http://" + my_lower_case_host() + ":" + HTTP_PORT + "/oauth"; //TODO: https?
|
string callback_url = "http://" + my_lower_case_host() + ":" + HTTP_PORT + "/oauth"; //TODO: https?
|
||||||
mapping oauth = ([]);
|
|
||||||
object user;
|
object user;
|
||||||
|
|
||||||
varargs void fetch(object ua, string url, string method, mapping oauth) {
|
varargs void fetch(object ua, string url, string method, mapping get, mapping post, mapping oauth) {
|
||||||
P3((">> oauth:fetch(%O, %O, %O)\n", url, method, oauth))
|
P3((">> oauth:fetch(%O, %O, %O)\n", url, method, oauth))
|
||||||
unless (method) method = "GET";
|
unless (method) method = "GET";
|
||||||
|
unless (get) get = ([]);
|
||||||
|
unless (post) post = ([]);
|
||||||
unless (oauth) oauth = ([]);
|
unless (oauth) oauth = ([]);
|
||||||
|
|
||||||
oauth["consumer_key"] = consumer_key;
|
oauth["oauth_consumer_key"] = consumer_key;
|
||||||
if (access_token || request_token) oauth["token"] = access_token || request_token;
|
string token;
|
||||||
string token_secret = access_token ? access_secret : request_token ? request_secret : "";
|
if (token = access_params["oauth_token"] || request_params["oauth_token"])
|
||||||
oauth["timestamp"] = time();
|
oauth["oauth_token"] = token;
|
||||||
oauth["nonce"] = sprintf("%x", random(oauth["timestamp"] ^ 98987));
|
string token_secret = access_params["oauth_token_secret"] || request_params["oauth_token_secret"] || "";
|
||||||
oauth["signature_method"] = "HMAC-SHA1";
|
oauth["oauth_timestamp"] = time();
|
||||||
oauth["version"] = "1.0";
|
oauth["oauth_nonce"] = sprintf("%x", random(oauth["oauth_timestamp"] ^ 98987));
|
||||||
|
oauth["oauth_signature_method"] = "HMAC-SHA1";
|
||||||
|
oauth["oauth_version"] = "1.0";
|
||||||
|
|
||||||
array(string) params = ({});
|
P3(("token: %O, token_secret: %O, access: %O, request: %O\n", token, token_secret, access_params, request_params))
|
||||||
foreach (string key : sort_array(m_indices(oauth), #'>)) //'))
|
string base_str = method + "&" + urlencode(url) + "&" + urlencode(make_query_string(get + post + oauth, 1));
|
||||||
params += ({"oauth_" + key + "=" + urlencode(to_string(oauth[key]))});
|
oauth["oauth_signature"] = hmac_base64(TLS_HASH_SHA1, urlencode(consumer_secret) + "&" + urlencode(token_secret), base_str);
|
||||||
string base_str = method + "&" + urlencode(url) + "&" + urlencode(implode(params, "&"));
|
|
||||||
oauth["signature"] = hmac_base64(TLS_HASH_SHA1, urlencode(consumer_secret) + "&" + urlencode(token_secret), base_str);
|
|
||||||
|
|
||||||
params = ({});
|
string p = "";
|
||||||
foreach (string key, string value : oauth)
|
foreach (string key, string value : oauth)
|
||||||
params += ({"oauth_" + key + "=\"" + urlencode(to_string(value)) + "\""});
|
p += (strlen(p) ? "," : "") + key + "=\"" + urlencode(to_string(value)) + "\"";
|
||||||
|
|
||||||
ua->fetch(url, method, (["Authorization": "OAuth " + implode(params, ",")]));
|
ua->fetch(url, method, post, (["Authorization": "OAuth " + p]));
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_request_token(string body, mapping headers) {
|
void parse_request_token(string body, mapping headers) {
|
||||||
P3((">> oauth:parse_request_token(%O, %O)\n", body, headers))
|
P3((">> oauth:parse_request_token(%O, %O)\n", body, headers))
|
||||||
mapping params = ([]);
|
request_params = ([]);
|
||||||
parse_query(params, body);
|
parse_query(request_params, body);
|
||||||
request_token = params["oauth_token"];
|
if (strlen(request_params["oauth_token"]) && strlen(request_params["oauth_token_secret"])) {
|
||||||
request_secret = params["oauth_token_secret"];
|
shared_memory("oauth_request_tokens")[request_params["oauth_token"]] = ME;
|
||||||
if (strlen(request_token) && strlen(request_secret)) {
|
|
||||||
shared_memory("oauth_request_tokens")[request_token] = ME;
|
|
||||||
sendmsg(user, "_notice_oauth_authorize_url", "Open [_url] to perform authorization.",
|
sendmsg(user, "_notice_oauth_authorize_url", "Open [_url] to perform authorization.",
|
||||||
(["_url": authorize_url + "?oauth_token=" + request_token]));
|
(["_url": authorize_url + "?oauth_token=" + request_params["oauth_token"]]));
|
||||||
} else {
|
} else {
|
||||||
sendmsg(user, "_error_oauth_token_request", "OAuth failed: could not get a request token.");
|
sendmsg(user, "_error_oauth_token_request", "OAuth failed: could not get a request token.");
|
||||||
}
|
}
|
||||||
|
@ -66,11 +63,9 @@ void parse_request_token(string body, mapping headers) {
|
||||||
|
|
||||||
void parse_access_token(string body, mapping headers) {
|
void parse_access_token(string body, mapping headers) {
|
||||||
P3((">> oauth:parse_access_token(%O, %O)\n", body, headers))
|
P3((">> oauth:parse_access_token(%O, %O)\n", body, headers))
|
||||||
mapping params = ([]);
|
access_params = ([]);
|
||||||
parse_query(params, body);
|
parse_query(access_params, body);
|
||||||
access_token = params["oauth_token"];
|
if (strlen(access_params["oauth_token"]) && strlen(access_params["oauth_token_secret"])) {
|
||||||
access_secret = params["oauth_token_secret"];
|
|
||||||
if (strlen(access_token) && strlen(access_secret)) {
|
|
||||||
sendmsg(user, "_notice_oauth_success", "OAuth successful.");
|
sendmsg(user, "_notice_oauth_success", "OAuth successful.");
|
||||||
} else {
|
} else {
|
||||||
sendmsg(user, "_error_oauth_token_access", "OAuth failed: could not get an access token.");
|
sendmsg(user, "_error_oauth_token_access", "OAuth failed: could not get an access token.");
|
||||||
|
@ -81,7 +76,7 @@ void verified(string verifier) {
|
||||||
P3((">> oauth:verified(%O)\n", verifier))
|
P3((">> oauth:verified(%O)\n", verifier))
|
||||||
object ua = clone_object(NET_PATH "http/fetch");
|
object ua = clone_object(NET_PATH "http/fetch");
|
||||||
ua->content(#'parse_access_token, 1, 1); //');
|
ua->content(#'parse_access_token, 1, 1); //');
|
||||||
fetch(ua, access_token_url, "POST", (["verifier": verifier]));
|
fetch(ua, access_token_url, "POST", 0, 0, (["oauth_verifier": verifier]));
|
||||||
}
|
}
|
||||||
|
|
||||||
object load(object usr, string key, string secret, string request, string access, string authorize) {
|
object load(object usr, string key, string secret, string request, string access, string authorize) {
|
||||||
|
@ -95,7 +90,7 @@ object load(object usr, string key, string secret, string request, string access
|
||||||
if (request_token_url && user) {
|
if (request_token_url && user) {
|
||||||
object ua = clone_object(NET_PATH "http/fetch");
|
object ua = clone_object(NET_PATH "http/fetch");
|
||||||
ua->content(#'parse_request_token, 1, 1); //');
|
ua->content(#'parse_request_token, 1, 1); //');
|
||||||
fetch(ua, request_token_url, "POST", (["callback": callback_url]));
|
fetch(ua, request_token_url, "POST", 0, 0, (["oauth_callback": callback_url]));
|
||||||
}
|
}
|
||||||
return ME;
|
return ME;
|
||||||
}
|
}
|
||||||
|
|
|
@ -184,7 +184,7 @@ case "/oauth":
|
||||||
//PT((">>> oauth: %O\n", oauth))
|
//PT((">>> oauth: %O\n", oauth))
|
||||||
oauth->verified(query["oauth_verifier"]);
|
oauth->verified(query["oauth_verifier"]);
|
||||||
m_delete(shared_memory("oauth_request_tokens"), query["oauth_token"]);
|
m_delete(shared_memory("oauth_request_tokens"), query["oauth_token"]);
|
||||||
write("OAuth succeeded");
|
write("OAuth succeeded, you can now return to your client.");
|
||||||
} else {
|
} else {
|
||||||
write("OAuth failed: token not found");
|
write("OAuth failed: token not found");
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,17 @@ private volatile mapping _sigs = ([
|
||||||
"_request_ni": ({ "_request_nick_local", 0, "_nick_local", "_INTERNAL_stuss" }),
|
"_request_ni": ({ "_request_nick_local", 0, "_nick_local", "_INTERNAL_stuss" }),
|
||||||
"_request_public": ({ "_request_public", 0, "_flag_public" }),
|
"_request_public": ({ "_request_public", 0, "_flag_public" }),
|
||||||
"_request_pub": ({ "_request_public", 0, "_flag_public" }),
|
"_request_pub": ({ "_request_public", 0, "_flag_public" }),
|
||||||
|
|
||||||
|
"_request_entries": ({ "_request_entries", 0, "_num" }),
|
||||||
|
"_request_entry": ({ "_request_entry", 0, "_id" }),
|
||||||
|
"_request_comment": ({ "_request_comment", 0, "_id", "_text" }),
|
||||||
|
"_request_thread": ({ "_request_thread", 0, "_id", "_title" }),
|
||||||
|
"_request_addentry": ({ "_request_addentry", 0, "_text" }),
|
||||||
|
"_request_submit": ({ "_request_addentry", 0, "_text" }),
|
||||||
|
"_request_blog": ({ "_request_addentry", 0, "_text" }),
|
||||||
|
"_request_delentry": ({ "_request_delentry", 0, "_id" }),
|
||||||
|
"_request_unsubmit": ({ "_request_delentry", 0, "_id" }),
|
||||||
|
"_request_unblog": ({ "_request_delentry", 0, "_id" }),
|
||||||
#ifdef _flag_enable_module_microblogging
|
#ifdef _flag_enable_module_microblogging
|
||||||
"_request_add": ({ "_request_add", 0, "_person" }),
|
"_request_add": ({ "_request_add", 0, "_person" }),
|
||||||
"_request_remove": ({ "_request_remove", 0, "_person" }),
|
"_request_remove": ({ "_request_remove", 0, "_person" }),
|
||||||
|
|
|
@ -40,146 +40,152 @@ create() {
|
||||||
unless (pointerp(_thread)) _thread = ({ });
|
unless (pointerp(_thread)) _thread = ({ });
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd(a, args, b, source, vars) {
|
_request_entries(source, mc, data, vars, b) {
|
||||||
P3((">> threads:cmd(%O, %O, %O, %O, %O)", a, args, b, source, vars))
|
int num = to_int(vars["_num"]) || DEFAULT_BACKLOG;
|
||||||
// TODO: multiline-sachen irgendwie
|
array(mapping) entries = ({ });
|
||||||
mapping entry;
|
mapping entry;
|
||||||
array(mapping) entries;
|
|
||||||
int i = 0;
|
|
||||||
int id;
|
|
||||||
int num_entries;
|
|
||||||
//unless (source) source = previous_object();
|
|
||||||
switch (a) {
|
|
||||||
case "entries":
|
|
||||||
num_entries = sizeof(args) >= 2 ? to_int(args[1]) : DEFAULT_BACKLOG;
|
|
||||||
// _thread[<5..]
|
|
||||||
//foreach( entry : _thread[<num_entries..] ) {
|
|
||||||
entries = ({ });
|
|
||||||
for (i = sizeof(_thread) - 1; i >= 0; i--) {
|
|
||||||
unless (entry = _thread[i]) continue;
|
|
||||||
entries =
|
|
||||||
({ ([
|
|
||||||
"_sep" : strlen(entry["thread"]) ? " - " : "",
|
|
||||||
"_thread" : entry["thread"],
|
|
||||||
"_text" : entry["text"],
|
|
||||||
"_author" : entry["author"],
|
|
||||||
"_date" : entry["date"],
|
|
||||||
"_comments": sizeof(entry["comments"]),
|
|
||||||
"_id" : i,
|
|
||||||
"_nick_place" : MYNICK,
|
|
||||||
]) }) + entries;
|
|
||||||
if (sizeof(entries) == num_entries) break;
|
|
||||||
}
|
|
||||||
foreach(entry : entries)
|
|
||||||
sendmsg(source, "_list_thread_entry",
|
|
||||||
"#[_id] - [_author][_sep][_thread]: [_text] ([_comments])",
|
|
||||||
entry);
|
|
||||||
return 1;
|
|
||||||
case "entry":
|
|
||||||
unless (sizeof(args) > 1){
|
|
||||||
sendmsg(source, "_warning_usage_entry",
|
|
||||||
"Usage: /entry <threadid>", ([ ]));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
id = to_int(args[1]);
|
|
||||||
if (id >= 0 && id < sizeof(_thread))
|
|
||||||
entry = _thread[id];
|
|
||||||
|
|
||||||
unless (entry) {
|
for (int i = sizeof(_thread) - 1; i >= 0; i--) {
|
||||||
sendmsg(source, "_error_thread_invalid_entry",
|
unless (entry = _thread[i]) continue;
|
||||||
"#[_id]: no such entry", (["_id": id]));
|
entries =
|
||||||
return 1;
|
({ ([
|
||||||
}
|
"_sep" : strlen(entry["thread"]) ? " - " : "",
|
||||||
|
"_thread" : entry["thread"],
|
||||||
sendmsg(source, "_list_thread_entry",
|
"_text" : entry["text"],
|
||||||
"#[_id] [_author][_sep][_thread]: [_text] ([_comments])",
|
"_author" : entry["author"],
|
||||||
([
|
"_date" : entry["date"],
|
||||||
"_sep" : strlen(entry["thread"]) ? " - " : "",
|
"_comments": sizeof(entry["comments"]),
|
||||||
"_thread" : entry["thread"],
|
"_id" : i,
|
||||||
"_text" : entry["text"],
|
"_nick_place" : MYNICK,
|
||||||
"_author" : entry["author"],
|
]) }) + entries;
|
||||||
"_date" : entry["date"],
|
if (sizeof(entries) == num) break;
|
||||||
"_comments": sizeof(entry["comments"]),
|
}
|
||||||
"_id" : id,
|
foreach(entry : entries)
|
||||||
"_nick_place" : MYNICK ]) );
|
sendmsg(source, "_list_thread_entry",
|
||||||
|
"#[_id] - [_author][_sep][_thread]: [_text] ([_comments])",
|
||||||
if (entry["comments"]) {
|
entry);
|
||||||
foreach(mapping item : entry["comments"]) {
|
return 1;
|
||||||
sendmsg(source, "_list_thread_comment",
|
|
||||||
"> [_nick]: [_text]",
|
|
||||||
([
|
|
||||||
"_nick" : item["nick"],
|
|
||||||
"_text" : item["text"],
|
|
||||||
"_date": item["date"],
|
|
||||||
"_nick_place" : MYNICK ]) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
case "thread":
|
|
||||||
unless (sizeof(args) > 2){
|
|
||||||
sendmsg(source, "_warning_usage_thread",
|
|
||||||
"Usage: /thread <threadid> <title>", ([ ]));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
id = to_int(args[1]);
|
|
||||||
unless (setSubject(id, ARGS(2)))
|
|
||||||
sendmsg(source, "_error_thread_invalid_entry",
|
|
||||||
"#[_id]: no such entry", (["_id": id]));
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
case "comment":
|
|
||||||
unless (sizeof(args) >= 2) {
|
|
||||||
sendmsg(source, "_warning_usage_reply",
|
|
||||||
"Usage: /comment <threadid> <text>", ([ ]));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
id = to_int(args[1]);
|
|
||||||
unless (addComment(ARGS(2), SNICKER, id))
|
|
||||||
sendmsg(source, "_error_thread_invalid_entry",
|
|
||||||
"#[_id]: no such entry", (["_id": id]));
|
|
||||||
return 1;
|
|
||||||
case "blog":
|
|
||||||
case "submit":
|
|
||||||
case "addentry":
|
|
||||||
unless (canPost(SNICKER)) return 0;
|
|
||||||
unless (sizeof(args) >= 1) {
|
|
||||||
sendmsg(source, "_warning_usage_submit",
|
|
||||||
"Usage: /submit <text>", ([ ]));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
addEntry(ARGS(1), SNICKER);
|
|
||||||
return 1;
|
|
||||||
// TODO: append fuer multiline-sachen
|
|
||||||
#if 0
|
|
||||||
case "iterator":
|
|
||||||
unless (canPost(SNICKER)) return 0;
|
|
||||||
sendmsg(source, "_notice_thread_iterator",
|
|
||||||
"[_iterator] blog entries have been requested "
|
|
||||||
"since creation.", ([
|
|
||||||
// i suppose this wasn't intentionally using
|
|
||||||
// MMP _count so i rename it to _iterator
|
|
||||||
"_iterator" : v("iterator")
|
|
||||||
]) );
|
|
||||||
return 1;
|
|
||||||
#endif
|
|
||||||
case "unblog":
|
|
||||||
case "deblog":
|
|
||||||
case "delentry":
|
|
||||||
unless (canPost(SNICKER)) return 0;
|
|
||||||
id = to_int(args[1]);
|
|
||||||
if (delEntry(id, source, vars)) {
|
|
||||||
sendmsg(source, "_notice_thread_entry_removed",
|
|
||||||
"Entry #[_id] has been removed.",
|
|
||||||
([ "_id" : id ]) );
|
|
||||||
} else {
|
|
||||||
sendmsg(source, "_error_thread_invalid_entry",
|
|
||||||
"#[_id]: no such entry", (["_id": id]));
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return ::cmd(a, args, b, source, vars);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_request_entry(source, mc, data, vars, b) {
|
||||||
|
unless (vars["_id"] && strlen(vars["_id"])) {
|
||||||
|
sendmsg(source, "_warning_usage_entry",
|
||||||
|
"Usage: /entry <id>", ([ ]));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mapping entry;
|
||||||
|
int id = to_int(vars["_id"]);
|
||||||
|
|
||||||
|
if (id >= 0 && id < sizeof(_thread))
|
||||||
|
entry = _thread[id];
|
||||||
|
|
||||||
|
unless (entry) {
|
||||||
|
sendmsg(source, "_error_thread_invalid_entry",
|
||||||
|
"#[_id]: no such entry", (["_id": id]));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendmsg(source, "_list_thread_entry",
|
||||||
|
"#[_id] [_author][_sep][_thread]: [_text] ([_comments])",
|
||||||
|
([
|
||||||
|
"_sep" : strlen(entry["thread"]) ? " - " : "",
|
||||||
|
"_thread" : entry["thread"],
|
||||||
|
"_text" : entry["text"],
|
||||||
|
"_author" : entry["author"],
|
||||||
|
"_date" : entry["date"],
|
||||||
|
"_comments": sizeof(entry["comments"]),
|
||||||
|
"_id" : id,
|
||||||
|
"_nick_place" : MYNICK ]) );
|
||||||
|
|
||||||
|
if (entry["comments"]) {
|
||||||
|
foreach(mapping item : entry["comments"]) {
|
||||||
|
sendmsg(source, "_list_thread_comment",
|
||||||
|
"> [_nick]: [_text]",
|
||||||
|
([
|
||||||
|
"_nick" : item["nick"],
|
||||||
|
"_text" : item["text"],
|
||||||
|
"_date": item["date"],
|
||||||
|
"_nick_place" : MYNICK ]) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
_request_thread(source, mc, data, vars, b) {
|
||||||
|
unless (vars["_id"] && strlen(vars["_id"])) {
|
||||||
|
sendmsg(source, "_warning_usage_thread",
|
||||||
|
"Usage: /thread <id> <title>", ([ ]));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int id = to_int(vars["_id"]);
|
||||||
|
unless (setSubject(id, vars["_title"]))
|
||||||
|
sendmsg(source, "_error_thread_invalid_entry",
|
||||||
|
"#[_id]: no such entry", (["_id": id]));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
_request_comment(source, mc, data, vars, b) {
|
||||||
|
unless (vars["_id"] && strlen(vars["_id"]) &&
|
||||||
|
vars["_text"] && strlen(vars["_text"])) {
|
||||||
|
sendmsg(source, "_warning_usage_reply",
|
||||||
|
"Usage: /comment <id> <text>", ([ ]));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int id = to_int(vars["_id"]);
|
||||||
|
unless (addComment(vars["_text"], SNICKER, id))
|
||||||
|
sendmsg(source, "_error_thread_invalid_entry",
|
||||||
|
"#[_id]: no such entry", (["_id": id]));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
_request_addentry(source, mc, data, vars, b) {
|
||||||
|
unless (canPost(SNICKER)) return 0;
|
||||||
|
unless (vars["_text"] && strlen(vars["_text"])) {
|
||||||
|
sendmsg(source, "_warning_usage_addentry",
|
||||||
|
"Usage: /addentry <text>", ([ ]));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
addEntry(vars["_text"], SNICKER);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
_request_delentry(source, mc, data, vars, b) {
|
||||||
|
unless (canPost(SNICKER)) return 0;
|
||||||
|
unless (vars["_id"] && strlen(vars["_id"])) {
|
||||||
|
sendmsg(source, "_warning_usage_delentry",
|
||||||
|
"Usage: /delentry <id>", ([ ]));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
int id = to_int(vars["_id"]);
|
||||||
|
if (delEntry(id, source, vars)) {
|
||||||
|
sendmsg(source, "_notice_thread_entry_removed",
|
||||||
|
"Entry #[_id] has been removed.",
|
||||||
|
([ "_id" : id ]) );
|
||||||
|
} else {
|
||||||
|
sendmsg(source, "_error_thread_invalid_entry",
|
||||||
|
"#[_id]: no such entry", (["_id": id]));
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
_request_iterator(source, mc, data, vars, b) {
|
||||||
|
unless (canPost(SNICKER)) return 0;
|
||||||
|
sendmsg(source, "_notice_thread_iterator",
|
||||||
|
"[_iterator] blog entries have been requested "
|
||||||
|
"since creation.", ([
|
||||||
|
// i suppose this wasn't intentionally using
|
||||||
|
// MMP _count so i rename it to _iterator
|
||||||
|
"_iterator" : v("iterator")
|
||||||
|
]) );
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
msg(source, mc, data, vars){
|
msg(source, mc, data, vars){
|
||||||
P3(("thread:msg(%O, %O, %O, %O)", source, mc, data, vars))
|
P3(("thread:msg(%O, %O, %O, %O)", source, mc, data, vars))
|
||||||
// TODO: die source muss hierbei uebereinstimmen mit dem autor
|
// TODO: die source muss hierbei uebereinstimmen mit dem autor
|
||||||
|
|
|
@ -139,12 +139,16 @@ _request_twitter(source, mc, data, vars, b) {
|
||||||
vSet("twitter", 0);
|
vSet("twitter", 0);
|
||||||
save();
|
save();
|
||||||
}
|
}
|
||||||
DT(else if (sw == "test") twitter->home();)
|
|
||||||
|
|
||||||
sendmsg(source, "_status_twitter", "Twitter submission is [_status].", (["_status": v("twitter") ? "enabled" : "disabled"]));
|
sendmsg(source, "_status_twitter", "Twitter submission is [_status].", (["_status": v("twitter") ? "enabled" : "disabled"]));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addEntry(text, unick, thread) {
|
||||||
|
if (::addEntry(text, unick, thread) && v("twitter") && twitter)
|
||||||
|
twitter->status_update(text);
|
||||||
|
}
|
||||||
|
|
||||||
htMain(int last) {
|
htMain(int last) {
|
||||||
return htmlEntries(_thread, last, 1, channel);
|
return htmlEntries(_thread, last, 1, channel);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,10 @@
|
||||||
*
|
*
|
||||||
* - register @ http://twitter.com/apps
|
* - register @ http://twitter.com/apps
|
||||||
* - settings:
|
* - settings:
|
||||||
* - name: e.g. psyc://your.host/
|
* - app name: e.g. psyc://your.host/
|
||||||
* - app type: browser
|
* - app type: browser
|
||||||
* - callback url: http://your.host/oauth
|
* - callback url: http://your.host/oauth
|
||||||
|
* (actually the url psyced sends will be used but you have to type in something)
|
||||||
* - access type: read/write
|
* - access type: read/write
|
||||||
* - then in local.h #define TWITTER_KEY & TWITTER_SECRET
|
* - then in local.h #define TWITTER_KEY & TWITTER_SECRET
|
||||||
*/
|
*/
|
||||||
|
@ -22,12 +23,26 @@ object load(object usr, string key, string secret, string request, string access
|
||||||
return ::load(usr, key, secret, request, access, authorize);
|
return ::load(usr, key, secret, request, access, authorize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_home(string body, string headers) {
|
void parse_status_update(string body, string headers) {
|
||||||
P3(("twitter/client:parse_home(%O, %O)\n", body, headers))
|
P3(("twitter/client:parse_status_update(%O, %O)\n", body, headers))
|
||||||
}
|
}
|
||||||
|
|
||||||
void home() {
|
void status_update(string text) {
|
||||||
|
P3(("twitter/client:status_update()\n"))
|
||||||
|
if (strlen(text) > 140) text = text[0..136] + "...";
|
||||||
|
|
||||||
object ua = clone_object(NET_PATH "http/fetch");
|
object ua = clone_object(NET_PATH "http/fetch");
|
||||||
ua->content(#'parse_home, 1, 1); //');
|
ua->content(#'parse_status_update, 1, 1); //');
|
||||||
|
fetch(ua, "http://api.twitter.com/1/statuses/update.json", "POST", 0, (["status": text]));
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_home_timeline(string body, string headers) {
|
||||||
|
P3(("twitter/client:parse_home_timeline(%O, %O)\n", body, headers))
|
||||||
|
}
|
||||||
|
|
||||||
|
void home_timeline() {
|
||||||
|
P3(("twitter/client:home_timeline()\n"))
|
||||||
|
object ua = clone_object(NET_PATH "http/fetch");
|
||||||
|
ua->content(#'parse_home_timeline, 1, 1); //');
|
||||||
fetch(ua, "http://api.twitter.com/1/statuses/home_timeline.json");
|
fetch(ua, "http://api.twitter.com/1/statuses/home_timeline.json");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue