| 1 | #include <v8.h>
|
|---|
| 2 | #include <cstring>
|
|---|
| 3 | #include <cstdio>
|
|---|
| 4 | #include <cstdlib>
|
|---|
| 5 | #include <curl/curl.h>
|
|---|
| 6 | #include "twitter.h"
|
|---|
| 7 |
|
|---|
| 8 | #define SERVICE_UPDATE_URL "http://twitter.com/statuses/update.json"
|
|---|
| 9 | #define SERVICE_FRIENDS_TIMELINE_URL "http://twitter.com/statuses/friends_timeline.json"
|
|---|
| 10 | #define SERVICE_USER_TIMELINE_URL "http://twitter.com/statuses/user_timeline/"
|
|---|
| 11 | #define SERVICE_PUBLIC_TIMELINE_URL "http://twitter.com/statuses/public_timeline.json"
|
|---|
| 12 |
|
|---|
| 13 | static char* response_data = NULL; /* response data from server. */
|
|---|
| 14 | static size_t response_size = 0; /* response size of data */
|
|---|
| 15 | static size_t handle_returned_data(char* ptr, size_t size, size_t nmemb, void* stream) {
|
|---|
| 16 | if (!response_data) {
|
|---|
| 17 | response_data = new char[size*nmemb];
|
|---|
| 18 | } else {
|
|---|
| 19 | char* response_tmp = new char[response_size+size*nmemb];
|
|---|
| 20 | memset(response_tmp, 0, response_size+size*nmemb);
|
|---|
| 21 | memcpy(response_tmp, response_data, response_size);
|
|---|
| 22 | delete[] response_data;
|
|---|
| 23 | response_data = response_tmp;
|
|---|
| 24 | }
|
|---|
| 25 | if (response_data) {
|
|---|
| 26 | memcpy(response_data+response_size, ptr, size*nmemb);
|
|---|
| 27 | response_size += size*nmemb;
|
|---|
| 28 | }
|
|---|
| 29 | return size*nmemb;
|
|---|
| 30 | }
|
|---|
| 31 |
|
|---|
| 32 | v8::Handle<v8::Value> TwitterUpdateStatus(const v8::Arguments& args) {
|
|---|
| 33 | v8::HandleScope handle_scope;
|
|---|
| 34 | v8::TryCatch try_catch;
|
|---|
| 35 |
|
|---|
| 36 | if (args.Length() != 1) return v8::ThrowException(v8::String::New("Error: usage is updateStatus(message)"));
|
|---|
| 37 |
|
|---|
| 38 | v8::Handle<v8::Value> ret = v8::Undefined();
|
|---|
| 39 | v8::Local<v8::Object> This = args.This();
|
|---|
| 40 |
|
|---|
| 41 | v8::String::AsciiValue username(This->Get(v8::String::New("username")));
|
|---|
| 42 | v8::String::AsciiValue password(This->Get(v8::String::New("password")));
|
|---|
| 43 |
|
|---|
| 44 | v8::Handle<v8::Object> global = v8::Context::GetCurrent()->Global();
|
|---|
| 45 | v8::Local<v8::Function> func = v8::Function::Cast(*global->Get(v8::String::New("encodeURIComponent")));
|
|---|
| 46 | v8::Local<v8::Value> funcargs[1];
|
|---|
| 47 | funcargs[0] = args[0]->ToString();
|
|---|
| 48 | v8::Local<v8::Value> result_val = func->Call(global, 1, funcargs);
|
|---|
| 49 | v8::String::AsciiValue escaped(result_val->ToString());
|
|---|
| 50 | char *status = *escaped;
|
|---|
| 51 |
|
|---|
| 52 | CURL* curl = NULL;
|
|---|
| 53 | CURLcode res = CURLE_OK;
|
|---|
| 54 | char *auth;
|
|---|
| 55 | char *url;
|
|---|
| 56 |
|
|---|
| 57 | response_data = NULL;
|
|---|
| 58 | response_size = 0;
|
|---|
| 59 | curl = curl_easy_init();
|
|---|
| 60 | if (!curl) return v8::ThrowException(v8::String::New("Error: unknown"));
|
|---|
| 61 |
|
|---|
| 62 | int n_url = strlen(SERVICE_UPDATE_URL) + 8 + strlen(status) + 1;
|
|---|
| 63 | url = new char[n_url];
|
|---|
| 64 | memset(url, 0, n_url);
|
|---|
| 65 | strcpy(url, SERVICE_UPDATE_URL);
|
|---|
| 66 | strcat(url, "?status=");
|
|---|
| 67 | strcat(url, status);
|
|---|
| 68 |
|
|---|
| 69 | int n_auth = strlen(*username) + 1 + strlen(*password) + 1;
|
|---|
| 70 | auth = new char[n_auth];
|
|---|
| 71 | memset(auth, 0, n_auth);
|
|---|
| 72 | strcpy(auth, *username);
|
|---|
| 73 | strcat(auth, ":");
|
|---|
| 74 | strcat(auth, *password);
|
|---|
| 75 |
|
|---|
| 76 | curl_easy_setopt(curl, CURLOPT_URL, url);
|
|---|
| 77 | curl_easy_setopt(curl, CURLOPT_USERPWD, auth);
|
|---|
| 78 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, handle_returned_data);
|
|---|
| 79 | curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
|
|---|
| 80 | curl_easy_setopt(curl, CURLOPT_POST, 1);
|
|---|
| 81 | curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "");
|
|---|
| 82 | res = curl_easy_perform(curl);
|
|---|
| 83 | int stat = 0;
|
|---|
| 84 | res == CURLE_OK ? curl_easy_getinfo(curl, CURLINFO_HTTP_CODE, &stat) : res;
|
|---|
| 85 | curl_easy_cleanup(curl);
|
|---|
| 86 |
|
|---|
| 87 | delete[] auth;
|
|---|
| 88 | delete[] url;
|
|---|
| 89 |
|
|---|
| 90 | if (res != CURLE_OK) {
|
|---|
| 91 | ret = v8::ThrowException(v8::String::New("Error: unknown"));
|
|---|
| 92 | }
|
|---|
| 93 | if (response_data) {
|
|---|
| 94 | delete[] response_data;
|
|---|
| 95 | response_data = NULL;
|
|---|
| 96 | }
|
|---|
| 97 | return ret;
|
|---|
| 98 | }
|
|---|
| 99 |
|
|---|
| 100 | v8::Handle<v8::Value> TwitterTimeline(const char* url, const char* username, const char* password) {
|
|---|
| 101 | v8::Handle<v8::Value> ret = v8::Undefined();
|
|---|
| 102 |
|
|---|
| 103 | CURL* curl = NULL;
|
|---|
| 104 | CURLcode res = CURLE_OK;
|
|---|
| 105 | char *auth;
|
|---|
| 106 |
|
|---|
| 107 | response_data = NULL;
|
|---|
| 108 | response_size = 0;
|
|---|
| 109 | curl = curl_easy_init();
|
|---|
| 110 | if (!curl) return v8::ThrowException(v8::String::New("Error: unknown"));
|
|---|
| 111 |
|
|---|
| 112 | int n_auth = strlen(username) + 1 + strlen(password) + 1;
|
|---|
| 113 | auth = new char[n_auth];
|
|---|
| 114 | memset(auth, 0, n_auth);
|
|---|
| 115 | strcpy(auth, username);
|
|---|
| 116 | strcat(auth, ":");
|
|---|
| 117 | strcat(auth, password);
|
|---|
| 118 |
|
|---|
| 119 | curl_easy_setopt(curl, CURLOPT_URL, url);
|
|---|
| 120 |
|
|---|
| 121 | curl_easy_setopt(curl, CURLOPT_USERPWD, auth);
|
|---|
| 122 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, handle_returned_data);
|
|---|
| 123 | curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
|
|---|
| 124 | res = curl_easy_perform(curl);
|
|---|
| 125 | int stat = 0;
|
|---|
| 126 | res == CURLE_OK ? curl_easy_getinfo(curl, CURLINFO_HTTP_CODE, &stat) : res;
|
|---|
| 127 | curl_easy_cleanup(curl);
|
|---|
| 128 |
|
|---|
| 129 | delete[] auth;
|
|---|
| 130 |
|
|---|
| 131 | if (res == CURLE_OK) {
|
|---|
| 132 | char* json = new char[response_size+1];
|
|---|
| 133 | memset(json, 0, response_size+1);
|
|---|
| 134 | memcpy(json, (char*) response_data, response_size);
|
|---|
| 135 | v8::Handle<v8::String> source = v8::String::New(json);
|
|---|
| 136 | delete[] json;
|
|---|
| 137 |
|
|---|
| 138 | v8::Handle<v8::Script> script = v8::Script::Compile(source);
|
|---|
| 139 | if (script.IsEmpty()) {
|
|---|
| 140 | ret = v8::ThrowException(v8::String::New("Error: unknown"));
|
|---|
| 141 | goto leave;
|
|---|
| 142 | }
|
|---|
| 143 | v8::Handle<v8::Value> result = script->Run();
|
|---|
| 144 | if (script.IsEmpty()) {
|
|---|
| 145 | ret = v8::ThrowException(v8::String::New("Error: unknown"));
|
|---|
| 146 | goto leave;
|
|---|
| 147 | }
|
|---|
| 148 | if (!result->IsArray()) {
|
|---|
| 149 | ret = v8::ThrowException(v8::String::New("Error: unknown"));
|
|---|
| 150 | goto leave;
|
|---|
| 151 | }
|
|---|
| 152 | ret = result;
|
|---|
| 153 | }
|
|---|
| 154 |
|
|---|
| 155 | leave:
|
|---|
| 156 | if (response_data) {
|
|---|
| 157 | delete[] response_data;
|
|---|
| 158 | response_data = NULL;
|
|---|
| 159 | }
|
|---|
| 160 | return ret;
|
|---|
| 161 | }
|
|---|
| 162 |
|
|---|
| 163 | v8::Handle<v8::Value> TwitterFriendsTimeline(const v8::Arguments& args) {
|
|---|
| 164 | v8::HandleScope handle_scope;
|
|---|
| 165 | v8::TryCatch try_catch;
|
|---|
| 166 |
|
|---|
| 167 | if (args.Length() != 0) return v8::ThrowException(v8::String::New("Error: usage is friendsTimeline()"));
|
|---|
| 168 |
|
|---|
| 169 | v8::Handle<v8::Value> ret = v8::Undefined();
|
|---|
| 170 | v8::Handle<v8::Object> This = args.This();
|
|---|
| 171 |
|
|---|
| 172 | v8::String::AsciiValue username(This->Get(v8::String::New("username")));
|
|---|
| 173 | v8::String::AsciiValue password(This->Get(v8::String::New("password")));
|
|---|
| 174 |
|
|---|
| 175 | return TwitterTimeline(SERVICE_FRIENDS_TIMELINE_URL, *username, *password);
|
|---|
| 176 | }
|
|---|
| 177 |
|
|---|
| 178 | v8::Handle<v8::Value> TwitterUserTimeline(const v8::Arguments& args) {
|
|---|
| 179 | v8::HandleScope handle_scope;
|
|---|
| 180 | v8::TryCatch try_catch;
|
|---|
| 181 |
|
|---|
| 182 | if (args.Length() != 1) return v8::ThrowException(v8::String::New("Error: usage is userTimeline(username)"));
|
|---|
| 183 |
|
|---|
| 184 | v8::Handle<v8::Value> ret = v8::Undefined();
|
|---|
| 185 | v8::Handle<v8::Object> This = args.This();
|
|---|
| 186 |
|
|---|
| 187 | v8::String::AsciiValue target(args[0]);
|
|---|
| 188 | v8::String::AsciiValue username(This->Get(v8::String::New("username")));
|
|---|
| 189 | v8::String::AsciiValue password(This->Get(v8::String::New("password")));
|
|---|
| 190 |
|
|---|
| 191 | int n_targeturl = strlen(SERVICE_USER_TIMELINE_URL) + strlen(*target) + 5 + 1;
|
|---|
| 192 | char* targeturl = new char[n_targeturl];
|
|---|
| 193 | memset(targeturl, 0, n_targeturl);
|
|---|
| 194 | strcpy(targeturl , SERVICE_USER_TIMELINE_URL);
|
|---|
| 195 | strcat(targeturl , *target);
|
|---|
| 196 | strcat(targeturl , ".json");
|
|---|
| 197 | ret = TwitterTimeline(targeturl, *username, *password);
|
|---|
| 198 | delete[] targeturl;
|
|---|
| 199 |
|
|---|
| 200 | return ret;
|
|---|
| 201 | }
|
|---|
| 202 |
|
|---|
| 203 | v8::Handle<v8::Value> TwitterPublicTimeline(const v8::Arguments& args) {
|
|---|
| 204 | v8::HandleScope handle_scope;
|
|---|
| 205 | v8::TryCatch try_catch;
|
|---|
| 206 |
|
|---|
| 207 | if (args.Length() != 0) return v8::ThrowException(v8::String::New("Error: usage is publicTimeline()"));
|
|---|
| 208 |
|
|---|
| 209 | v8::Handle<v8::Value> ret = v8::Undefined();
|
|---|
| 210 | v8::Handle<v8::Object> This = args.This();
|
|---|
| 211 |
|
|---|
| 212 | v8::String::AsciiValue username(This->Get(v8::String::New("username")));
|
|---|
| 213 | v8::String::AsciiValue password(This->Get(v8::String::New("password")));
|
|---|
| 214 | return TwitterTimeline(SERVICE_PUBLIC_TIMELINE_URL, *username, *password);
|
|---|
| 215 | }
|
|---|