]>
Commit | Line | Data |
---|---|---|
493c2f88 | 1 | <?php |
93e79595 | 2 | class GoogleReaderImport extends Plugin { |
493c2f88 AD |
3 | private $host; |
4 | ||
5 | function about() { | |
6 | return array(1.0, | |
7c93962d | 7 | "Import starred/shared items from Google Reader takeout", |
493c2f88 AD |
8 | "fox", |
9 | false, | |
10 | ""); | |
11 | } | |
12 | ||
13 | function init($host) { | |
493c2f88 AD |
14 | $this->host = $host; |
15 | ||
4cf0f9a9 AD |
16 | $host->add_command("greader-import", |
17 | "import data in Google Reader JSON format", | |
18 | $this, ":", "FILE"); | |
19 | ||
493c2f88 AD |
20 | $host->add_hook($host::HOOK_PREFS_TAB, $this); |
21 | } | |
22 | ||
4cf0f9a9 AD |
23 | function greader_import($args) { |
24 | $file = $args['greader_import']; | |
25 | ||
26 | if (!file_exists($file)) { | |
27 | _debug("file not found: $file"); | |
28 | return; | |
29 | } | |
30 | ||
31 | _debug("please enter your username:"); | |
32 | ||
a42c55f0 | 33 | $username = db_escape_string(trim(read_stdin())); |
4cf0f9a9 AD |
34 | |
35 | _debug("looking up user: $username..."); | |
36 | ||
a42c55f0 | 37 | $result = db_query("SELECT id FROM ttrss_users |
4cf0f9a9 AD |
38 | WHERE login = '$username'"); |
39 | ||
40 | if (db_num_rows($result) == 0) { | |
41 | _debug("user not found."); | |
42 | return; | |
43 | } | |
44 | ||
45 | $owner_uid = db_fetch_result($result, 0, "id"); | |
46 | ||
47 | _debug("processing: $file (owner_uid: $owner_uid)"); | |
48 | ||
49 | $this->import($file, $owner_uid); | |
50 | } | |
51 | ||
493c2f88 AD |
52 | function get_prefs_js() { |
53 | return file_get_contents(dirname(__FILE__) . "/init.js"); | |
54 | } | |
55 | ||
4cf0f9a9 | 56 | function import($file = false, $owner_uid = 0) { |
493c2f88 | 57 | |
6322ac79 | 58 | purge_orphans(); |
749da11b | 59 | |
4cf0f9a9 AD |
60 | if (!$file) { |
61 | header("Content-Type: text/html"); | |
493c2f88 | 62 | |
93e79595 AD |
63 | $owner_uid = $_SESSION["uid"]; |
64 | ||
3306daec AD |
65 | if ($_FILES['starred_file']['error'] != 0) { |
66 | print_error(T_sprintf("Upload failed with error code %d", | |
67 | $_FILES['starred_file']['error'])); | |
68 | return; | |
69 | } | |
70 | ||
71 | $tmp_file = false; | |
72 | ||
73 | if (is_uploaded_file($_FILES['starred_file']['tmp_name'])) { | |
74 | $tmp_file = tempnam(CACHE_DIR . '/upload', 'starred'); | |
75 | ||
76 | $result = move_uploaded_file($_FILES['starred_file']['tmp_name'], | |
77 | $tmp_file); | |
78 | ||
79 | if (!$result) { | |
80 | print_error(__("Unable to move uploaded file.")); | |
81 | return; | |
82 | } | |
83 | } else { | |
84 | print_error(__('Error: please upload OPML file.')); | |
85 | return; | |
86 | } | |
87 | ||
88 | if (is_file($tmp_file)) { | |
89 | $doc = json_decode(file_get_contents($tmp_file), true); | |
90 | unlink($tmp_file); | |
4cf0f9a9 AD |
91 | } else { |
92 | print_error(__('No file uploaded.')); | |
93 | return; | |
94 | } | |
493c2f88 | 95 | } else { |
4cf0f9a9 | 96 | $doc = json_decode(file_get_contents($file), true); |
493c2f88 AD |
97 | } |
98 | ||
4cf0f9a9 AD |
99 | if ($file) { |
100 | $sql_set_marked = strtolower(basename($file)) == 'starred.json' ? 'true' : 'false'; | |
101 | _debug("will set articles as starred: $sql_set_marked"); | |
102 | ||
103 | } else { | |
104 | $sql_set_marked = strtolower($_FILES['starred_file']['name']) == 'starred.json' ? 'true' : 'false'; | |
105 | } | |
4c92878f | 106 | |
493c2f88 AD |
107 | if ($doc) { |
108 | if (isset($doc['items'])) { | |
109 | $processed = 0; | |
110 | ||
111 | foreach ($doc['items'] as $item) { | |
112 | // print_r($item); | |
113 | ||
a42c55f0 AD |
114 | $guid = db_escape_string(mb_substr($item['id'], 0, 250)); |
115 | $title = db_escape_string($item['title']); | |
493c2f88 | 116 | $updated = date('Y-m-d h:i:s', $item['updated']); |
af26179d | 117 | $last_marked = date('Y-m-d h:i:s', mb_substr($item['crawlTimeMsec'], 0, 10)); |
493c2f88 AD |
118 | $link = ''; |
119 | $content = ''; | |
a42c55f0 | 120 | $author = db_escape_string($item['author']); |
4188225c | 121 | $tags = array(); |
749da11b | 122 | $orig_feed_data = array(); |
493c2f88 AD |
123 | |
124 | if (is_array($item['alternate'])) { | |
125 | foreach ($item['alternate'] as $alt) { | |
126 | if (isset($alt['type']) && $alt['type'] == 'text/html') { | |
a42c55f0 | 127 | $link = db_escape_string($alt['href']); |
493c2f88 AD |
128 | } |
129 | } | |
130 | } | |
131 | ||
b87bd8ed | 132 | if (is_array($item['summary'])) { |
6322ac79 | 133 | $content = db_escape_string( |
b87bd8ed AD |
134 | $item['summary']['content'], false); |
135 | } | |
136 | ||
493c2f88 | 137 | if (is_array($item['content'])) { |
6322ac79 | 138 | $content = db_escape_string( |
493c2f88 AD |
139 | $item['content']['content'], false); |
140 | } | |
141 | ||
4188225c AD |
142 | if (is_array($item['categories'])) { |
143 | foreach ($item['categories'] as $cat) { | |
144 | if (strstr($cat, "com.google/") === FALSE) { | |
145 | array_push($tags, sanitize_tag($cat)); | |
146 | } | |
147 | } | |
148 | } | |
149 | ||
749da11b AD |
150 | if (is_array($item['origin'])) { |
151 | if (strpos($item['origin']['streamId'], 'feed/') === 0) { | |
152 | ||
6322ac79 | 153 | $orig_feed_data['feed_url'] = db_escape_string( |
61096207 AD |
154 | mb_substr(preg_replace("/^feed\//", |
155 | "", $item['origin']['streamId']), 0, 200)); | |
749da11b | 156 | |
6322ac79 | 157 | $orig_feed_data['title'] = db_escape_string( |
61096207 | 158 | mb_substr($item['origin']['title'], 0, 200)); |
749da11b | 159 | |
6322ac79 | 160 | $orig_feed_data['site_url'] = db_escape_string( |
61096207 | 161 | mb_substr($item['origin']['htmlUrl'], 0, 200)); |
749da11b AD |
162 | } |
163 | } | |
164 | ||
493c2f88 AD |
165 | $processed++; |
166 | ||
4cf0f9a9 | 167 | $imported += (int) $this->create_article($owner_uid, $guid, $title, |
c6c968b0 | 168 | $link, $updated, $content, $author, $sql_set_marked, $tags, |
af26179d | 169 | $orig_feed_data, $last_marked); |
b9fc62a7 AD |
170 | |
171 | if ($file && $processed % 25 == 0) { | |
172 | _debug("processed $processed articles..."); | |
173 | } | |
493c2f88 AD |
174 | } |
175 | ||
4cf0f9a9 AD |
176 | if ($file) { |
177 | _debug(sprintf("All done. %d of %d articles imported.", $imported, $processed)); | |
178 | } else { | |
179 | print "<p style='text-align : center'>" . T_sprintf("All done. %d out of %d articles imported.", $imported, $processed) . "</p>"; | |
180 | } | |
493c2f88 AD |
181 | |
182 | } else { | |
183 | print_error(__('The document has incorrect format.')); | |
184 | } | |
185 | ||
186 | } else { | |
187 | print_error(__('Error while parsing document.')); | |
188 | } | |
189 | ||
4cf0f9a9 AD |
190 | if (!$file) { |
191 | print "<div align='center'>"; | |
192 | print "<button dojoType=\"dijit.form.Button\" | |
193 | onclick=\"dijit.byId('starredImportDlg').execute()\">". | |
194 | __('Close this window')."</button>"; | |
195 | print "</div>"; | |
196 | } | |
493c2f88 AD |
197 | } |
198 | ||
199 | // expects ESCAPED data | |
af26179d | 200 | private function create_article($owner_uid, $guid, $title, $link, $updated, $content, $author, $marked, $tags, $orig_feed_data, $last_marked) { |
493c2f88 AD |
201 | |
202 | if (!$guid) $guid = sha1($link); | |
203 | ||
b9fc62a7 | 204 | $create_archived_feeds = true; |
fc5cd158 | 205 | |
493c2f88 AD |
206 | $guid = "$owner_uid,$guid"; |
207 | ||
208 | $content_hash = sha1($content); | |
209 | ||
a42c55f0 | 210 | if (filter_var(FILTER_VALIDATE_URL) === FALSE) return false; |
493c2f88 | 211 | |
a42c55f0 | 212 | db_query("BEGIN"); |
493c2f88 | 213 | |
749da11b AD |
214 | $feed_id = 'NULL'; |
215 | ||
216 | // let's check for archived feed entry | |
217 | ||
218 | $feed_inserted = false; | |
219 | ||
220 | // before dealing with archived feeds we must check ttrss_feeds to maintain id consistency | |
221 | ||
fc5cd158 | 222 | if ($orig_feed_data['feed_url'] && $create_archived_feeds) { |
6322ac79 | 223 | $result = db_query( |
749da11b AD |
224 | "SELECT id FROM ttrss_feeds WHERE feed_url = '".$orig_feed_data['feed_url']."' |
225 | AND owner_uid = $owner_uid"); | |
226 | ||
227 | if (db_num_rows($result) != 0) { | |
228 | $feed_id = db_fetch_result($result, 0, "id"); | |
229 | } else { | |
230 | // let's insert it | |
231 | ||
232 | if (!$orig_feed_data['title']) $orig_feed_data['title'] = '[Unknown]'; | |
233 | ||
6322ac79 | 234 | $result = db_query( |
749da11b AD |
235 | "INSERT INTO ttrss_feeds |
236 | (owner_uid,feed_url,site_url,title,cat_id,auth_login,auth_pass,update_method) | |
237 | VALUES ($owner_uid, | |
238 | '".$orig_feed_data['feed_url']."', | |
239 | '".$orig_feed_data['site_url']."', | |
240 | '".$orig_feed_data['title']."', | |
241 | NULL, '', '', 0)"); | |
242 | ||
6322ac79 | 243 | $result = db_query( |
749da11b AD |
244 | "SELECT id FROM ttrss_feeds WHERE feed_url = '".$orig_feed_data['feed_url']."' |
245 | AND owner_uid = $owner_uid"); | |
246 | ||
247 | if (db_num_rows($result) != 0) { | |
248 | $feed_id = db_fetch_result($result, 0, "id"); | |
249 | $feed_inserted = true; | |
250 | } | |
251 | } | |
252 | } | |
253 | ||
61096207 | 254 | if ($feed_id && $feed_id != 'NULL') { |
749da11b AD |
255 | // locate archived entry to file entries in, we don't want to file them in actual feeds because of purging |
256 | // maybe file marked in real feeds because eh | |
257 | ||
a42c55f0 | 258 | $result = db_query("SELECT id FROM ttrss_archived_feeds WHERE |
749da11b AD |
259 | feed_url = '".$orig_feed_data['feed_url']."' AND owner_uid = $owner_uid"); |
260 | ||
261 | if (db_num_rows($result) != 0) { | |
262 | $orig_feed_id = db_fetch_result($result, 0, "id"); | |
263 | } else { | |
a42c55f0 | 264 | db_query("INSERT INTO ttrss_archived_feeds |
749da11b AD |
265 | (id, owner_uid, title, feed_url, site_url) |
266 | SELECT id, owner_uid, title, feed_url, site_url from ttrss_feeds | |
267 | WHERE id = '$feed_id'"); | |
268 | ||
a42c55f0 | 269 | $result = db_query("SELECT id FROM ttrss_archived_feeds WHERE |
749da11b AD |
270 | feed_url = '".$orig_feed_data['feed_url']."' AND owner_uid = $owner_uid"); |
271 | ||
272 | if (db_num_rows($result) != 0) { | |
273 | $orig_feed_id = db_fetch_result($result, 0, "id"); | |
749da11b AD |
274 | } |
275 | } | |
276 | } | |
277 | ||
b9fc62a7 AD |
278 | // delete temporarily inserted feed |
279 | if ($feed_id && $feed_inserted) { | |
a42c55f0 | 280 | db_query("DELETE FROM ttrss_feeds WHERE id = $feed_id"); |
b9fc62a7 AD |
281 | } |
282 | ||
61096207 AD |
283 | if (!$orig_feed_id) $orig_feed_id = 'NULL'; |
284 | ||
a42c55f0 | 285 | $result = db_query("SELECT id FROM ttrss_entries, ttrss_user_entries WHERE |
493c2f88 AD |
286 | guid = '$guid' AND ref_id = id AND owner_uid = '$owner_uid' LIMIT 1"); |
287 | ||
288 | if (db_num_rows($result) == 0) { | |
a42c55f0 | 289 | $result = db_query("INSERT INTO ttrss_entries |
493c2f88 AD |
290 | (title, guid, link, updated, content, content_hash, date_entered, date_updated, author) |
291 | VALUES | |
292 | ('$title', '$guid', '$link', '$updated', '$content', '$content_hash', NOW(), NOW(), '$author')"); | |
293 | ||
a42c55f0 | 294 | $result = db_query("SELECT id FROM ttrss_entries WHERE guid = '$guid'"); |
493c2f88 AD |
295 | |
296 | if (db_num_rows($result) != 0) { | |
297 | $ref_id = db_fetch_result($result, 0, "id"); | |
298 | ||
a42c55f0 | 299 | db_query("INSERT INTO ttrss_user_entries |
493c2f88 AD |
300 | (ref_id, uuid, feed_id, orig_feed_id, owner_uid, marked, tag_cache, label_cache, |
301 | last_read, note, unread, last_marked) | |
302 | VALUES | |
af26179d | 303 | ('$ref_id', '', NULL, $orig_feed_id, $owner_uid, $marked, '', '', '$last_marked', '', false, '$last_marked')"); |
493c2f88 | 304 | |
a42c55f0 | 305 | $result = db_query("SELECT int_id FROM ttrss_user_entries, ttrss_entries |
4188225c AD |
306 | WHERE owner_uid = $owner_uid AND ref_id = id AND ref_id = $ref_id"); |
307 | ||
308 | if (db_num_rows($result) != 0 && is_array($tags)) { | |
309 | ||
310 | $entry_int_id = db_fetch_result($result, 0, "int_id"); | |
311 | $tags_to_cache = array(); | |
312 | ||
313 | foreach ($tags as $tag) { | |
314 | ||
a42c55f0 | 315 | $tag = db_escape_string(sanitize_tag($tag)); |
4188225c AD |
316 | |
317 | if (!tag_is_valid($tag)) continue; | |
318 | ||
a42c55f0 | 319 | $result = db_query("SELECT id FROM ttrss_tags |
4188225c AD |
320 | WHERE tag_name = '$tag' AND post_int_id = '$entry_int_id' AND |
321 | owner_uid = '$owner_uid' LIMIT 1"); | |
322 | ||
323 | if ($result && db_num_rows($result) == 0) { | |
a42c55f0 | 324 | db_query("INSERT INTO ttrss_tags |
4188225c AD |
325 | (owner_uid,tag_name,post_int_id) |
326 | VALUES ('$owner_uid','$tag', '$entry_int_id')"); | |
327 | } | |
328 | ||
329 | array_push($tags_to_cache, $tag); | |
493c2f88 | 330 | } |
4188225c AD |
331 | |
332 | /* update the cache */ | |
333 | ||
334 | $tags_to_cache = array_unique($tags_to_cache); | |
a42c55f0 | 335 | $tags_str = db_escape_string(join(",", $tags_to_cache)); |
4188225c | 336 | |
a42c55f0 | 337 | db_query("UPDATE ttrss_user_entries |
4188225c AD |
338 | SET tag_cache = '$tags_str' WHERE ref_id = '$ref_id' |
339 | AND owner_uid = $owner_uid"); | |
493c2f88 AD |
340 | } |
341 | ||
342 | $rc = true; | |
343 | } | |
344 | } | |
345 | ||
a42c55f0 | 346 | db_query("COMMIT"); |
493c2f88 AD |
347 | |
348 | return $rc; | |
349 | } | |
350 | ||
351 | function hook_prefs_tab($args) { | |
352 | if ($args != "prefFeeds") return; | |
353 | ||
4c92878f | 354 | print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"".__("Import starred or shared items from Google Reader")."\">"; |
493c2f88 | 355 | |
4c92878f | 356 | print_notice("Your imported articles will appear in Starred (in file is named starred.json) and Archived feeds."); |
493c2f88 | 357 | |
4c92878f | 358 | print "<p>".__("Paste your starred.json or shared.json into the form below."). "</p>"; |
493c2f88 AD |
359 | |
360 | print "<iframe id=\"starred_upload_iframe\" | |
361 | name=\"starred_upload_iframe\" onload=\"starredImportComplete(this)\" | |
362 | style=\"width: 400px; height: 100px; display: none;\"></iframe>"; | |
363 | ||
364 | print "<form name=\"starred_form\" style='display : block' target=\"starred_upload_iframe\" | |
365 | enctype=\"multipart/form-data\" method=\"POST\" | |
366 | action=\"backend.php\"> | |
367 | <input id=\"starred_file\" name=\"starred_file\" type=\"file\"> | |
368 | <input type=\"hidden\" name=\"op\" value=\"pluginhandler\"> | |
369 | <input type=\"hidden\" name=\"method\" value=\"import\"> | |
93e79595 | 370 | <input type=\"hidden\" name=\"plugin\" value=\"googlereaderimport\"> |
493c2f88 AD |
371 | <button dojoType=\"dijit.form.Button\" onclick=\"return starredImport();\" type=\"submit\">" . |
372 | __('Import my Starred items') . "</button>"; | |
373 | ||
b229a184 | 374 | print "</form>"; |
493c2f88 AD |
375 | |
376 | print "</div>"; #pane | |
377 | } | |
106a3de9 AD |
378 | |
379 | function api_version() { | |
380 | return 2; | |
381 | } | |
382 | ||
493c2f88 AD |
383 | } |
384 | ?> |