* (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..'));
$helptext = <<<ENDOFHELP
USAGE: initialize_notice_to_status.php

Initializes the notice_to_status table with existing Twitter synch
data. Only necessary if you've had the Twitter bridge enabled before
version 0.9.5.

ENDOFHELP;
require_once INSTALLDIR . '/scripts/commandline.inc';
// We update any notices that may have come in from
// Twitter that we don't have a status_id for. Note that
// this won't catch notices that originated at this StatusNet site.
$n = new Notice();
$n->query('SELECT notice.id, notice.uri ' . 'FROM notice LEFT JOIN notice_to_status ' . 'ON notice.id = notice_to_status.notice_id ' . 'WHERE notice.source = "twitter"' . 'AND notice_to_status.status_id IS NULL');
while ($n->fetch()) {
    if (preg_match('#^http://twitter.com/[\\w_.]+/status/(\\d+)$#', $n->uri, $match)) {
        $status_id = $match[1];
        Notice_to_status::saveNew($n->id, $status_id);
    }
}
 /**
  * If a notice gets deleted, remove the Notice_to_status mapping and
  * delete the status on Twitter.
  *
  * @param User   $user   The user doing the deleting
  * @param Notice $notice The notice getting deleted
  *
  * @return boolean hook value
  */
 function onStartDeleteOwnNotice(User $user, Notice $notice)
 {
     $n2s = Notice_to_status::getKV('notice_id', $notice->id);
     if (!empty($n2s)) {
         $flink = Foreign_link::getByUserID($notice->profile_id, TWITTER_SERVICE);
         // twitter service
         if (empty($flink)) {
             return true;
         }
         if (!TwitterOAuthClient::isPackedToken($flink->credentials)) {
             $this->log(LOG_INFO, "Skipping deleting notice for {$notice->id} since link is not OAuth.");
             return true;
         }
         try {
             $token = TwitterOAuthClient::unpackToken($flink->credentials);
             $client = new TwitterOAuthClient($token->key, $token->secret);
             $client->statusesDestroy($n2s->status_id);
         } catch (Exception $e) {
             common_log(LOG_ERR, "Error attempting to delete bridged notice from Twitter: " . $e->getMessage());
         }
         $n2s->delete();
     }
     return true;
 }
 function saveStatus($status)
 {
     $profile = $this->ensureProfile($status->user);
     if (empty($profile)) {
         common_log(LOG_ERR, $this->name() . ' - Problem saving notice. No associated Profile.');
         return null;
     }
     $statusId = twitter_id($status);
     $statusUri = $this->makeStatusURI($status->user->screen_name, $statusId);
     // check to see if we've already imported the status
     $n2s = Notice_to_status::staticGet('status_id', $statusId);
     if (!empty($n2s)) {
         common_log(LOG_INFO, $this->name() . " - Ignoring duplicate import: {$statusId}");
         return Notice::staticGet('id', $n2s->notice_id);
     }
     // If it's a retweet, save it as a repeat!
     if (!empty($status->retweeted_status)) {
         common_log(LOG_INFO, "Status {$statusId} is a retweet of " . twitter_id($status->retweeted_status) . ".");
         $original = $this->saveStatus($status->retweeted_status);
         if (empty($original)) {
             return null;
         } else {
             $author = $original->getProfile();
             // TRANS: Message used to repeat a notice. RT is the abbreviation of 'retweet'.
             // TRANS: %1$s is the repeated user's name, %2$s is the repeated notice.
             $content = sprintf(_m('RT @%1$s %2$s'), $author->nickname, $original->content);
             if (Notice::contentTooLong($content)) {
                 $contentlimit = Notice::maxContent();
                 $content = mb_substr($content, 0, $contentlimit - 4) . ' ...';
             }
             $repeat = Notice::saveNew($profile->id, $content, 'twitter', array('repeat_of' => $original->id, 'uri' => $statusUri, 'is_local' => Notice::GATEWAY));
             common_log(LOG_INFO, "Saved {$repeat->id} as a repeat of {$original->id}");
             Notice_to_status::saveNew($repeat->id, $statusId);
             return $repeat;
         }
     }
     $notice = new Notice();
     $notice->profile_id = $profile->id;
     $notice->uri = $statusUri;
     $notice->url = $statusUri;
     $notice->created = strftime('%Y-%m-%d %H:%M:%S', strtotime($status->created_at));
     $notice->source = 'twitter';
     $notice->reply_to = null;
     $replyTo = twitter_id($status, 'in_reply_to_status_id');
     if (!empty($replyTo)) {
         common_log(LOG_INFO, "Status {$statusId} is a reply to status {$replyTo}");
         $n2s = Notice_to_status::staticGet('status_id', $replyTo);
         if (empty($n2s)) {
             common_log(LOG_INFO, "Couldn't find local notice for status {$replyTo}");
         } else {
             $reply = Notice::staticGet('id', $n2s->notice_id);
             if (empty($reply)) {
                 common_log(LOG_INFO, "Couldn't find local notice for status {$replyTo}");
             } else {
                 common_log(LOG_INFO, "Found local notice {$reply->id} for status {$replyTo}");
                 $notice->reply_to = $reply->id;
                 $notice->conversation = $reply->conversation;
             }
         }
     }
     if (empty($notice->conversation)) {
         $conv = Conversation::create();
         $notice->conversation = $conv->id;
         common_log(LOG_INFO, "No known conversation for status {$statusId} so making a new one {$conv->id}.");
     }
     $notice->is_local = Notice::GATEWAY;
     $notice->content = html_entity_decode($status->text, ENT_QUOTES, 'UTF-8');
     $notice->rendered = $this->linkify($status);
     if (Event::handle('StartNoticeSave', array(&$notice))) {
         $id = $notice->insert();
         if (!$id) {
             common_log_db_error($notice, 'INSERT', __FILE__);
             common_log(LOG_ERR, $this->name() . ' - Problem saving notice.');
         }
         Event::handle('EndNoticeSave', array($notice));
     }
     Notice_to_status::saveNew($notice->id, $statusId);
     $this->saveStatusMentions($notice, $status);
     $this->saveStatusAttachments($notice, $status);
     $notice->blowOnInsert();
     return $notice;
 }
 /**
  * If a notice gets deleted, remove the Notice_to_status mapping and
  * delete the status on Twitter.
  *
  * @param User   $user   The user doing the deleting
  * @param Notice $notice The notice getting deleted
  *
  * @return boolean hook value
  */
 function onStartDeleteOwnNotice(User $user, Notice $notice)
 {
     $n2s = Notice_to_status::staticGet('notice_id', $notice->id);
     if (!empty($n2s)) {
         $flink = Foreign_link::getByUserID($notice->profile_id, TWITTER_SERVICE);
         // twitter service
         if (empty($flink)) {
             return true;
         }
         if (!TwitterOAuthClient::isPackedToken($flink->credentials)) {
             $this->log(LOG_INFO, "Skipping deleting notice for {$notice->id} since link is not OAuth.");
             return true;
         }
         $token = TwitterOAuthClient::unpackToken($flink->credentials);
         $client = new TwitterOAuthClient($token->key, $token->secret);
         $client->statusesDestroy($n2s->status_id);
         $n2s->delete();
     }
     return true;
 }
 /**
  * Save a mapping between a notice and a status
  * Warning: status_id values may not fit in 32-bit integers.
  *
  * @param integer $notice_id ID of the notice in StatusNet
  * @param integer $status_id ID of the status in Twitter
  *
  * @return Notice_to_status new object for this value
  */
 static function saveNew($notice_id, $status_id)
 {
     if (empty($notice_id)) {
         throw new Exception("Invalid notice_id {$notice_id}");
     }
     $n2s = Notice_to_status::staticGet('notice_id', $notice_id);
     if (!empty($n2s)) {
         return $n2s;
     }
     if (empty($status_id)) {
         throw new Exception("Invalid status_id {$status_id}");
     }
     $n2s = Notice_to_status::staticGet('status_id', $status_id);
     if (!empty($n2s)) {
         return $n2s;
     }
     common_debug("Mapping notice {$notice_id} to Twitter status {$status_id}");
     $n2s = new Notice_to_status();
     $n2s->notice_id = $notice_id;
     $n2s->status_id = $status_id;
     $n2s->created = common_sql_now();
     $n2s->insert();
     return $n2s;
 }
Exemple #6
0
function broadcast_oauth($notice, $flink)
{
    $user = $flink->getUser();
    $statustxt = format_status($notice);
    $params = twitter_update_params($notice);
    $token = TwitterOAuthClient::unpackToken($flink->credentials);
    $client = new TwitterOAuthClient($token->key, $token->secret);
    $status = null;
    try {
        $status = $client->statusesUpdate($statustxt, $params);
        if (!empty($status)) {
            Notice_to_status::saveNew($notice->id, twitter_id($status));
        }
    } catch (OAuthClientException $e) {
        return process_error($e, $flink, $notice);
    }
    if (empty($status)) {
        // This could represent a failure posting,
        // or the Twitter API might just be behaving flakey.
        $errmsg = sprintf('Twitter bridge - No data returned by Twitter API when ' . 'trying to post notice %d for User %s (user id %d).', $notice->id, $user->nickname, $user->id);
        common_log(LOG_WARNING, $errmsg);
        return false;
    }
    // Notice crossed the great divide
    $msg = sprintf('Twitter bridge - posted notice %d to Twitter using ' . 'OAuth for User %s (user id %d).', $notice->id, $user->nickname, $user->id);
    common_log(LOG_INFO, $msg);
    return true;
}