~ubuntu-branches/ubuntu/natty/newsbeuter/natty

« back to all changes in this revision

Viewing changes to src/google_api.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Nico Golde
  • Date: 2010-03-23 19:09:18 UTC
  • mfrom: (4.1.10 sid)
  • Revision ID: james.westby@ubuntu.com-20100323190918-o3mwdwl3v4li449s
Tags: 2.2-2
Do not cleanup deleted items uppon quitting so they will be
reloaded and marked as new next time (Closes: #574665).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <vector>
 
2
#include <cstring>
 
3
 
 
4
#include <google_api.h>
 
5
#include <config.h>
 
6
#include <utils.h>
 
7
 
 
8
#include <curl/curl.h>
 
9
 
 
10
#define GREADER_LOGIN                                   "https://www.google.com/accounts/ClientLogin"
 
11
#define GREADER_API_PREFIX                              "http://www.google.com/reader/api/0/"
 
12
#define GREADER_FEED_PREFIX                             "http://www.google.com/reader/atom/"
 
13
 
 
14
#define GREADER_SUBSCRIPTION_LIST               GREADER_API_PREFIX "subscription/list"
 
15
#define GREADER_API_MARK_ALL_READ_URL   GREADER_API_PREFIX "mark-all-as-read"
 
16
#define GREADER_API_EDIT_TAG_URL                GREADER_API_PREFIX "edit-tag"
 
17
#define GREADER_API_TOKEN_URL                   GREADER_API_PREFIX "token"
 
18
 
 
19
// for reference, see http://code.google.com/p/pyrfeed/wiki/GoogleReaderAPI
 
20
 
 
21
namespace newsbeuter {
 
22
 
 
23
googlereader_api::googlereader_api(configcontainer * c) : remote_api(c) {
 
24
        // TODO
 
25
}
 
26
 
 
27
googlereader_api::~googlereader_api() {
 
28
        // TODO
 
29
}
 
30
 
 
31
bool googlereader_api::authenticate() {
 
32
        sid = retrieve_sid();
 
33
        LOG(LOG_DEBUG, "googlereader_api::authenticate: SID = %s", sid.c_str());
 
34
        return sid != "";
 
35
}
 
36
 
 
37
static size_t my_write_data(void *buffer, size_t size, size_t nmemb, void *userp) {
 
38
        std::string * pbuf = static_cast<std::string *>(userp);
 
39
        pbuf->append(static_cast<const char *>(buffer), size * nmemb);
 
40
        return size * nmemb;
 
41
}
 
42
 
 
43
std::string googlereader_api::retrieve_sid() {
 
44
        CURL * handle = curl_easy_init();
 
45
        std::string postcontent = utils::strprintf("service=reader&Email=%s&Passwd=%s&source=%s/%s&continue=http://www.google.com/", 
 
46
                cfg->get_configvalue("googlereader-login").c_str(), cfg->get_configvalue("googlereader-password").c_str(), PROGRAM_NAME, PROGRAM_VERSION);
 
47
        std::string result;
 
48
        
 
49
        utils::set_common_curl_options(handle, cfg);
 
50
        curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, my_write_data);
 
51
        curl_easy_setopt(handle, CURLOPT_WRITEDATA, &result);
 
52
        curl_easy_setopt(handle, CURLOPT_POSTFIELDS, postcontent.c_str());
 
53
        curl_easy_setopt(handle, CURLOPT_URL, GREADER_LOGIN);
 
54
        curl_easy_perform(handle);
 
55
        curl_easy_cleanup(handle);
 
56
 
 
57
        std::vector<std::string> lines = utils::tokenize(result);
 
58
        for (std::vector<std::string>::iterator it=lines.begin();it!=lines.end();it++) {
 
59
                LOG(LOG_DEBUG, "googlereader_api::retrieve_sid: line = %s", it->c_str());
 
60
                if (it->substr(0,4)=="SID=") {
 
61
                        std::string sid = it->substr(4, it->length()-4);
 
62
                        return sid;
 
63
                }
 
64
        }
 
65
 
 
66
        return "";
 
67
}
 
68
 
 
69
std::vector<tagged_feedurl> googlereader_api::get_subscribed_urls() {
 
70
        std::vector<tagged_feedurl> urls;
 
71
 
 
72
        CURL * handle = curl_easy_init();
 
73
        std::string result;
 
74
        std::string cookie = utils::strprintf("SID=%s;", sid.c_str());
 
75
        
 
76
        utils::set_common_curl_options(handle, cfg);
 
77
        curl_easy_setopt(handle, CURLOPT_COOKIE, cookie.c_str());
 
78
        curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, my_write_data);
 
79
        curl_easy_setopt(handle, CURLOPT_WRITEDATA, &result);
 
80
        curl_easy_setopt(handle, CURLOPT_URL, GREADER_SUBSCRIPTION_LIST);
 
81
        curl_easy_perform(handle);
 
82
        curl_easy_cleanup(handle);
 
83
 
 
84
        LOG(LOG_DEBUG, "googlereader_api::get_subscribed_urls: document = %s", result.c_str());
 
85
 
 
86
        xmlDoc * doc = xmlParseMemory(result.c_str(), result.length());
 
87
 
 
88
        if (!doc) {
 
89
                LOG(LOG_ERROR, "googlreader_api::get_subscribed_urls: failed to parse subscription list");
 
90
                return urls;
 
91
        }
 
92
 
 
93
        xmlNode * root = xmlDocGetRootElement(doc);
 
94
 
 
95
        LOG(LOG_DEBUG, "googlereader_api::get_subscribed_urls: root = %p", root);
 
96
 
 
97
        if (root) {
 
98
                for (xmlNode * node = root->children; node != NULL; node = node->next) {
 
99
                        if (strcmp((const char *)node->name, "list")==0 && utils::get_prop(node, "name") == "subscriptions") {
 
100
                                LOG(LOG_DEBUG, "found subscriptions list");
 
101
                                for (xmlNode * objectnode = node->children; objectnode != NULL; objectnode = objectnode->next) {
 
102
                                        if (strcmp((const char *)objectnode->name, "object")==0) {
 
103
                                                LOG(LOG_DEBUG, "found object");
 
104
                                                std::string id;
 
105
                                                std::string title;
 
106
                                                std::vector<std::string> tags;
 
107
                                                for (xmlNode * elem = objectnode->children; elem != NULL; elem = elem->next) {
 
108
                                                        if (strcmp((const char *)elem->name, "string")==0 && utils::get_prop(elem,"name")=="id") {
 
109
                                                                LOG(LOG_DEBUG, "found id");
 
110
                                                                id = utils::get_content(elem);
 
111
                                                        } else if (strcmp((const char *)elem->name, "string")==0 && utils::get_prop(elem,"name")=="title") {
 
112
                                                                title = utils::get_content(elem);
 
113
                                                        } else if (strcmp((const char *)elem->name, "list")==0 && utils::get_prop(elem,"name")=="categories") {
 
114
                                                                LOG(LOG_DEBUG, "found tag");
 
115
                                                                tags = get_tags(elem);
 
116
                                                        }
 
117
                                                }
 
118
                                                if (id != "") {
 
119
                                                        if (title != "") {
 
120
                                                                tags.push_back(utils::strprintf("~%s", title.c_str()));
 
121
                                                        }
 
122
                                                        urls.push_back(tagged_feedurl(utils::strprintf("%s%s", GREADER_FEED_PREFIX, utils::escape_url(id).c_str()), tags));
 
123
                                                }
 
124
                                        }
 
125
                                }
 
126
                        }
 
127
                }
 
128
        }
 
129
 
 
130
        xmlFreeDoc(doc);
 
131
 
 
132
        return urls;
 
133
}
 
134
 
 
135
std::vector<std::string> googlereader_api::get_tags(xmlNode * node) {
 
136
        std::vector<std::string> tags;
 
137
 
 
138
        if (node && strcmp((const char *)node->name, "list")==0 && utils::get_prop(node, "name")=="categories") {
 
139
                LOG(LOG_DEBUG, "found tag list");
 
140
                for (xmlNode * objnode = node->children; objnode != NULL; objnode = objnode->next) {
 
141
                        if (strcmp((const char *)objnode->name, "object")==0) {
 
142
                                LOG(LOG_DEBUG, "found tag list object");
 
143
                                for (xmlNode * str = objnode->children; str != NULL; str = str->next) {
 
144
                                        if (strcmp((const char *)str->name, "string")==0 && utils::get_prop(str, "name")=="label") {
 
145
                                                LOG(LOG_DEBUG, "found tag list label");
 
146
                                                tags.push_back(utils::get_content(str));
 
147
                                        }
 
148
                                }
 
149
                        }
 
150
                }
 
151
        }
 
152
        return tags;
 
153
}
 
154
 
 
155
void googlereader_api::configure_handle(CURL * handle) {
 
156
        std::string cookie = utils::strprintf("SID=%s;", sid.c_str());
 
157
        curl_easy_setopt(handle, CURLOPT_COOKIE, cookie.c_str());
 
158
}
 
159
 
 
160
bool googlereader_api::mark_all_read(const std::string& feedurl) {
 
161
        std::string real_feedurl = feedurl.substr(strlen(GREADER_FEED_PREFIX), feedurl.length() - strlen(GREADER_FEED_PREFIX));
 
162
        std::vector<std::string> elems = utils::tokenize(real_feedurl, "?");
 
163
        real_feedurl = utils::unescape_url(elems[0]);
 
164
        std::string token = get_new_token();
 
165
 
 
166
        std::string postcontent = utils::strprintf("s=%s&T=%s", real_feedurl.c_str(), token.c_str());
 
167
        
 
168
        std::string result = post_content(GREADER_API_MARK_ALL_READ_URL, postcontent);
 
169
 
 
170
        return result == "OK";
 
171
}
 
172
 
 
173
bool googlereader_api::mark_article_read(const std::string& guid, bool read) {
 
174
        std::string token = get_new_token();
 
175
        std::string postcontent;
 
176
 
 
177
        if (read) {
 
178
                postcontent = utils::strprintf("i=%s&a=user/-/state/com.google/read&r=user/-/state/com.google/kept-unread&ac=edit&T=%s", guid.c_str(), token.c_str());
 
179
        } else {
 
180
                postcontent = utils::strprintf("i=%s&r=user/-/state/com.google/read&a=user/-/state/com.google/kept-unread&a=user/-/state/com.google/tracking-kept-unread&ac=edit&T=%s", guid.c_str(), token.c_str());
 
181
        }
 
182
 
 
183
        std::string result = post_content(GREADER_API_EDIT_TAG_URL, postcontent);
 
184
 
 
185
        LOG(LOG_DEBUG, "googlereader_api::mark_article_read: postcontent = %s result = %s", postcontent.c_str(), result.c_str());
 
186
 
 
187
        return result == "OK";
 
188
}
 
189
 
 
190
std::string googlereader_api::get_new_token() {
 
191
        CURL * handle = curl_easy_init();
 
192
        std::string result;
 
193
        
 
194
        utils::set_common_curl_options(handle, cfg);
 
195
        configure_handle(handle);
 
196
        curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, my_write_data);
 
197
        curl_easy_setopt(handle, CURLOPT_WRITEDATA, &result);
 
198
        curl_easy_setopt(handle, CURLOPT_URL, GREADER_API_TOKEN_URL);
 
199
        curl_easy_perform(handle);
 
200
        curl_easy_cleanup(handle);
 
201
 
 
202
        LOG(LOG_DEBUG, "googlereader_api::get_new_token: token = %s", result.c_str());
 
203
        
 
204
        return result;
 
205
}
 
206
 
 
207
bool googlereader_api::update_article_flags(const std::string& oldflags, const std::string& newflags, const std::string& guid) {
 
208
        std::string star_flag = cfg->get_configvalue("googlereader-flag-star");
 
209
        std::string share_flag = cfg->get_configvalue("googlereader-flag-share");
 
210
        bool success = true;
 
211
 
 
212
        if (star_flag.length() > 0) {
 
213
                if (strchr(oldflags.c_str(), star_flag[0])==NULL && strchr(newflags.c_str(), star_flag[0])!=NULL) {
 
214
                        success = star_article(guid, true);
 
215
                } else if (strchr(oldflags.c_str(), star_flag[0])!=NULL && strchr(newflags.c_str(), star_flag[0])==NULL) {
 
216
                        success = star_article(guid, false);
 
217
                }
 
218
        }
 
219
 
 
220
        if (share_flag.length() > 0) {
 
221
                if (strchr(oldflags.c_str(), share_flag[0])==NULL && strchr(newflags.c_str(), share_flag[0])!=NULL) {
 
222
                        success = share_article(guid, true);
 
223
                } else if (strchr(oldflags.c_str(), share_flag[0])!=NULL && strchr(newflags.c_str(), share_flag[0])==NULL) {
 
224
                        success = share_article(guid, false);
 
225
                }
 
226
        }
 
227
 
 
228
        return success;
 
229
}
 
230
 
 
231
bool googlereader_api::star_article(const std::string& guid, bool star) {
 
232
        std::string token = get_new_token();
 
233
        std::string postcontent;
 
234
 
 
235
        if (star) {
 
236
                postcontent = utils::strprintf("i=%s&a=user/-/state/com.google/starred&ac=edit&T=%s", guid.c_str(), token.c_str());
 
237
        } else {
 
238
                postcontent = utils::strprintf("i=%s&r=user/-/state/com.google/starred&ac=edit&T=%s", guid.c_str(), token.c_str());
 
239
        }
 
240
 
 
241
        std::string result = post_content(GREADER_API_EDIT_TAG_URL, postcontent);
 
242
 
 
243
        return result == "OK";
 
244
}
 
245
 
 
246
bool googlereader_api::share_article(const std::string& guid, bool share) {
 
247
        std::string token = get_new_token();
 
248
        std::string postcontent;
 
249
 
 
250
        if (share) {
 
251
                postcontent = utils::strprintf("i=%s&a=user/-/state/com.google/broadcast&ac=edit&T=%s", guid.c_str(), token.c_str());
 
252
        } else {
 
253
                postcontent = utils::strprintf("i=%s&r=user/-/state/com.google/broadcast&ac=edit&T=%s", guid.c_str(), token.c_str());
 
254
        }
 
255
 
 
256
        std::string result = post_content(GREADER_API_EDIT_TAG_URL, postcontent);
 
257
 
 
258
        return result == "OK";
 
259
}
 
260
 
 
261
std::string googlereader_api::post_content(const std::string& url, const std::string& postdata) {
 
262
        std::string result;
 
263
 
 
264
        CURL * handle = curl_easy_init();
 
265
        utils::set_common_curl_options(handle, cfg);
 
266
        configure_handle(handle);
 
267
        curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, my_write_data);
 
268
        curl_easy_setopt(handle, CURLOPT_WRITEDATA, &result);
 
269
        curl_easy_setopt(handle, CURLOPT_POSTFIELDS, postdata.c_str());
 
270
        curl_easy_setopt(handle, CURLOPT_URL, url.c_str());
 
271
        curl_easy_perform(handle);
 
272
        curl_easy_cleanup(handle);
 
273
 
 
274
        LOG(LOG_DEBUG, "googlereader_api::post_content: url = %s postdata = %s result = %s", url.c_str(), postdata.c_str(), result.c_str());
 
275
 
 
276
        return result;
 
277
}
 
278
 
 
279
}