]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - scripts/importtwitteratom.php
Make attachment fit better in notice: drop text and link
[quix0rs-gnu-social.git] / scripts / importtwitteratom.php
1 #!/usr/bin/env php
2 <?php
3 /*
4  * StatusNet - the distributed open-source microblogging tool
5  * Copyright (C) 2010 StatusNet, Inc.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Affero General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Affero General Public License for more details.
16  *
17  * You should have received a copy of the GNU Affero General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 define('INSTALLDIR', dirname(__DIR__));
22 define('PUBLICDIR', INSTALLDIR . DIRECTORY_SEPARATOR . 'public');
23
24 $shortoptions = 'i:n:f:';
25 $longoptions = array('id=', 'nickname=', 'file=');
26
27 $helptext = <<<END_OF_IMPORTTWITTERATOM_HELP
28 importtwitteratom.php [options]
29 import an Atom feed from Twitter as notices by a user
30
31   -i --id       ID of user to update
32   -n --nickname nickname of the user to update
33   -f --file     file to import (Atom-only for now)
34
35 END_OF_IMPORTTWITTERATOM_HELP;
36
37 require_once INSTALLDIR.'/scripts/commandline.inc';
38
39 function getAtomFeedDocument()
40 {
41     $filename = get_option_value('f', 'file');
42
43     if (empty($filename)) {
44         show_help();
45         exit(1);
46     }
47
48     if (!file_exists($filename)) {
49         throw new Exception("No such file '$filename'.");
50     }
51
52     if (!is_file($filename)) {
53         throw new Exception("Not a regular file: '$filename'.");
54     }
55
56     if (!is_readable($filename)) {
57         throw new Exception("File '$filename' not readable.");
58     }
59
60     $xml = file_get_contents($filename);
61
62     $dom = DOMDocument::loadXML($xml);
63
64     if ($dom->documentElement->namespaceURI != Activity::ATOM ||
65         $dom->documentElement->localName != 'feed') {
66         throw new Exception("'$filename' is not an Atom feed.");
67     }
68
69     return $dom;
70 }
71
72 function importActivityStream($user, $doc)
73 {
74     $feed = $doc->documentElement;
75
76     $entries = $feed->getElementsByTagNameNS(Activity::ATOM, 'entry');
77
78     for ($i = $entries->length - 1; $i >= 0; $i--) {
79         $entry = $entries->item($i);
80         $activity = new Activity($entry, $feed);
81         $object = $activity->objects[0];
82         if (!have_option('q', 'quiet')) {
83             print $activity->content . "\n";
84         }
85         $html = common_purify(getTweetHtml($object->link));
86
87         $content = html_entity_decode(strip_tags($html), ENT_QUOTES, 'UTF-8');
88
89         $notice = Notice::saveNew($user->id,
90                                   $content,
91                                   'importtwitter',
92                                   array('uri' => $object->id,
93                                         'url' => $object->link,
94                                         'rendered' => $html,
95                                         'created' => common_sql_date($activity->time),
96                                         'replies' => array(),
97                                         'groups' => array()));
98     }
99 }
100
101 function getTweetHtml($url)
102 {
103     try {
104         $client = new HTTPClient();
105         $response = $client->get($url);
106     } catch (Exception $e) {
107         print "ERROR: HTTP response " . $e->getMessage() . "\n";
108         return false;
109     }
110
111     if (!$response->isOk()) {
112         print "ERROR: HTTP response " . $response->getCode() . "\n";
113         return false;
114     }
115
116     $body = $response->getBody();
117
118     return tweetHtmlFromBody($body);
119 }
120
121 function tweetHtmlFromBody($body)
122 {
123     $doc = DOMDocument::loadHTML($body);
124     $xpath = new DOMXPath($doc);
125
126     $spans = $xpath->query('//span[@class="entry-content"]');
127
128     if ($spans->length == 0) {
129         print "ERROR: No content in tweet page.\n";
130         return '';
131     }
132
133     $span = $spans->item(0);
134
135     $children = $span->childNodes;
136
137     $text = '';
138
139     for ($i = 0; $i < $children->length; $i++) {
140         $child = $children->item($i);
141         if ($child instanceof DOMElement &&
142             $child->tagName == 'a' &&
143             !preg_match('#^https?://#', $child->getAttribute('href'))) {
144             $child->setAttribute('href', 'http://twitter.com' . $child->getAttribute('href'));
145         }
146         $text .= $doc->saveXML($child);
147     }
148
149     return $text;
150 }
151
152 try {
153
154     $doc = getAtomFeedDocument();
155     $user = getUser();
156
157     importActivityStream($user, $doc);
158
159 } catch (Exception $e) {
160     print $e->getMessage()."\n";
161     exit(1);
162 }
163