Add Cristian Greco as uploader
[debian/pino.git] / src / rest_api_abstract.vala
index aba3963..67dd551 100644 (file)
@@ -32,6 +32,7 @@ public class Status : Object {
        public string id;
        public string text;
        public Time created_at = Time();
+       public string created_at_s = "";
        public string user_name;
        public string user_screen_name;
        public string user_avatar;
@@ -45,6 +46,9 @@ public class Status : Object {
        public string to_status_id = "";
        
        public bool is_retweet = false;
+       public bool is_favorite = false;
+       
+       public bool tmp = false;
 }
 
 public class FullStatus : Status {
@@ -61,9 +65,9 @@ public class FullStatus : Status {
 }
 
 public struct AuthData {
-       public string login = "";
-       public string password = "";
-       public string service = "";
+       public string login;
+       public string password;
+       public string service;
 } 
 
 public static enum ServiceType {
@@ -84,7 +88,8 @@ errordomain ParseError {
 public static enum TimelineType {
        HOME,
        MENTIONS,
-       USER
+       USER,
+       FAVORITES
 }
 
 public abstract class RestAPIAbstract : Object {
@@ -92,9 +97,29 @@ public abstract class RestAPIAbstract : Object {
        protected RestUrls urls;
        public Account? account;
        
+       private SessionAsync session_async;
+       private SessionSync session_sync;
+       
        public RestAPIAbstract(Account? _account) {
                urls = new RestUrls(ServiceType.UNKNOWN);
                set_auth(_account);
+
+               session_async = new SessionAsync();
+               session_sync = new SessionSync();
+
+               session_async.timeout = 30; //seconds
+               session_sync.timeout = 30; //seconds
+
+               //Basic HTTP authorization
+        session_async.authenticate.connect(http_auth);
+        session_sync.authenticate.connect(http_auth);
+       }
+
+       private void http_auth(Message msg, Soup.Auth auth, bool retrying) {
+               if(retrying)
+                               return;
+
+               auth.authenticate(account.login, account.password);
        }
        
        private void select_urls() {
@@ -131,7 +156,7 @@ public abstract class RestAPIAbstract : Object {
        public signal void request(string req);
        
        public virtual ArrayList<Status>? get_timeline(int count = 0, FullStatus? fstatus = null,
-               string since_id = "", string max_id = "") throws RestError, ParseError {
+               string since_id = "", string max_id = "", bool sync = true) throws RestError, ParseError {
                
                return null;
        }
@@ -140,6 +165,9 @@ public abstract class RestAPIAbstract : Object {
                return new Status();
        }
        
+       public virtual void favorite_create(string id) throws RestError {}
+       public virtual void favorite_destroy(string id) throws RestError {}
+       
        public virtual void follow_create(string screen_name) throws RestError {}
        public virtual void follow_destroy(string screen_name) throws RestError {}
        
@@ -150,6 +178,12 @@ public abstract class RestAPIAbstract : Object {
                        case 2:
                                throw new RestError.CODE("Connection problems: can't connect to the server.");
                        
+                       case 4:
+                               throw new RestError.CODE("Connection problems: timeout.");
+                       
+                       case 400:
+                               throw new RestError.CODE("%d Rate limiting: you have reached the limit requests.".printf(status_code));
+                       
                        case 401:
                                throw new RestError.CODE("%d Unauthorized: the request requires user authentication.".printf(status_code));
                        
@@ -172,100 +206,77 @@ public abstract class RestAPIAbstract : Object {
        }
        
        public string make_request(owned string req_url, string method,
-               HashTable<string, string> params = new HashTable<string, string>(null, null),
+               HashTable<string, string> params = new HashTable<string, string>(str_hash, str_equal),
                bool async = true, int retry = 3) throws RestError {
                
                if(account == null)
                        no_account();
                
-               if(method == "GET") { //set get-parameters
-                       string query = "";
-               
-                       if(params.size() > 0) {
-                               query = "?";
-                               
-                               //Very dirty. HashTable.loockup() doesn't work. Bug?
-                               int tmp_iter = 0;
-                               foreach(string key in params.get_keys()) {
-                                       int tmp_iter2 = 0;
-                                       foreach(string val in params.get_values()) {
-                                               if(tmp_iter2 == tmp_iter) {
-                                                       query += Soup.form_encode(key, val);
-                                                       if(tmp_iter < params.size() - 1)
-                                                               query += "&";
-                                                       break;
-                                               }
-                                               tmp_iter2++;
-                                       }
-                                       tmp_iter++;
-                               }
-                       }
-                       req_url += query;
-               }
-               
                //send signal about all requests
         request("%s: %s".printf(method, req_url));
         
         Session session;
         
                if(async)
-                       session = new SessionAsync();
+                       session = session_async;
                else
-                       session = new SessionSync();
+                       session = session_sync;
                
-        Message message = new Message(method, req_url);
-        message.set_http_version (HTTPVersion.1_1);
-        
-        MessageHeaders headers = new MessageHeaders(MessageHeadersType.MULTIPART);
-        headers.append("User-Agent", "%s/%s".printf(Config.APPNAME, Config.APP_VERSION));
-        
-        message.request_headers = headers;
-        
-        if(method != "GET") { //set post/delete-parameters
-               string body = form_encode_hash(params);
-                       message.set_request("application/x-www-form-urlencoded",
-                               MemoryUse.COPY, body, (int)body.size());
-               }
-               
-               //Basic HTTP authorization
-        session.authenticate += (sess, msg, auth, retrying) => {
-                       if (retrying) return;
-                       auth.authenticate(account.login, account.password);
-               };
+               Message message = form_request_new_from_hash(method, req_url, params);
+               message.request_headers.append("User-Agent", "%s/%s".printf(Config.APPNAME, Config.APP_VERSION));
                
+               debug("and one more");
                int status_code = 0;
                for(int i = 0; i < retry; i++) {
-                       status_code = (int)session.send_message(message);
-                       if(status_code == 200 || status_code == 401)
+                       debug("go into loop");
+                       try {
+                               status_code = (int)session.send_message(message);
+                       } catch(GLib.Error e) {
+                               debug("we got some error: %s", e.message);
+                               break;
+                       }
+                       debug("something recieve %d", status_code);
+                       if(status_code == 200 || status_code == 401 || status_code == 4)
                                break;
                }
-               
+               debug("...");
                if(status_code != 200)
                        reply_tracking(status_code);
+
+               debug("end of make_request");
                
-               return (string)message.response_body.flatten().data;
+               return (string)message.response_body.data;
        }
        
        /* check user for DM availability */
        public bool check_friendship(string screen_name,
-               bool just_friend_check = false) throws RestError {
+               bool just_friend_check = false) throws RestError, ParseError {
                
                string req_url = urls.friendship();
                
-               HashTable map = new HashTable<string, string>(null, null);
+               var map = new HashTable<string, string>(str_hash, str_equal);
                map.insert("source_screen_name", account.login);
                map.insert("target_screen_name", screen_name);
-               warning(req_url);
+               debug(req_url);
                string data = make_request(req_url, "GET", map);
-               
-               return parse_friendship(data, just_friend_check);
+
+               Parser.init();
+               bool result = parse_friendship(data, just_friend_check);
+               Parser.cleanup();
+
+               return result;
        }
        
-       private bool parse_friendship(string data, bool just_friend_check = false) {
+       private bool parse_friendship(string data,
+               bool just_friend_check = false) throws ParseError {
+
                bool followed_by = false;
                bool following = false;
                
                Xml.Doc* xmlDoc = Xml.Parser.parse_memory(data, (int)data.size());
+               if(xmlDoc == null)
+                       throw new ParseError.CODE("Invalid XML data");
+               
                Xml.Node* rootNode = xmlDoc->get_root_element();
                
                Xml.Node* iter;