Files
friendica-addons/pumpio/pumpio.php
T
Philipp Holzer a555820111 Rename namespace
2019-10-24 09:06:21 +02:00

1622 lines
51 KiB
PHP

<?php
/**
* Name: pump.io Post Connector
* Description: Bidirectional (posting, relaying and reading) connector for pump.io.
* Version: 0.2
* Author: Michael Vogel <http://pirati.ca/profile/heluecht>
*/
use Friendica\App;
use Friendica\Content\Text\BBCode;
use Friendica\Content\Text\HTML;
use Friendica\Core\Config;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\Logger;
use Friendica\Core\PConfig;
use Friendica\Core\Protocol;
use Friendica\Core\Worker;
use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Model\Group;
use Friendica\Model\Item;
use Friendica\Model\User;
use Friendica\Protocol\Activity;
use Friendica\Util\ConfigFileLoader;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Network;
use Friendica\Util\Strings;
use Friendica\Util\XML;
require 'addon/pumpio/oauth/http.php';
require 'addon/pumpio/oauth/oauth_client.php';
require_once "mod/share.php";
define('PUMPIO_DEFAULT_POLL_INTERVAL', 5); // given in minutes
function pumpio_install()
{
Hook::register('load_config', 'addon/pumpio/pumpio.php', 'pumpio_load_config');
Hook::register('hook_fork', 'addon/pumpio/pumpio.php', 'hook_fork');
Hook::register('post_local', 'addon/pumpio/pumpio.php', 'pumpio_post_local');
Hook::register('notifier_normal', 'addon/pumpio/pumpio.php', 'pumpio_send');
Hook::register('jot_networks', 'addon/pumpio/pumpio.php', 'pumpio_jot_nets');
Hook::register('connector_settings', 'addon/pumpio/pumpio.php', 'pumpio_settings');
Hook::register('connector_settings_post', 'addon/pumpio/pumpio.php', 'pumpio_settings_post');
Hook::register('cron', 'addon/pumpio/pumpio.php', 'pumpio_cron');
Hook::register('check_item_notification', 'addon/pumpio/pumpio.php', 'pumpio_check_item_notification');
}
function pumpio_uninstall()
{
Hook::unregister('load_config', 'addon/pumpio/pumpio.php', 'pumpio_load_config');
Hook::unregister('hook_fork', 'addon/pumpio/pumpio.php', 'pumpio_hook_fork');
Hook::unregister('post_local', 'addon/pumpio/pumpio.php', 'pumpio_post_local');
Hook::unregister('notifier_normal', 'addon/pumpio/pumpio.php', 'pumpio_send');
Hook::unregister('jot_networks', 'addon/pumpio/pumpio.php', 'pumpio_jot_nets');
Hook::unregister('connector_settings', 'addon/pumpio/pumpio.php', 'pumpio_settings');
Hook::unregister('connector_settings_post', 'addon/pumpio/pumpio.php', 'pumpio_settings_post');
Hook::unregister('cron', 'addon/pumpio/pumpio.php', 'pumpio_cron');
Hook::unregister('check_item_notification', 'addon/pumpio/pumpio.php', 'pumpio_check_item_notification');
}
function pumpio_module() {}
function pumpio_content(App $a)
{
if (!local_user()) {
notice(L10n::t('Permission denied.') . EOL);
return '';
}
require_once("mod/settings.php");
settings_init($a);
if (isset($a->argv[1])) {
switch ($a->argv[1]) {
case "connect":
$o = pumpio_connect($a);
break;
default:
$o = print_r($a->argv, true);
break;
}
} else {
$o = pumpio_connect($a);
}
return $o;
}
function pumpio_check_item_notification($a, &$notification_data)
{
$hostname = PConfig::get($notification_data["uid"], 'pumpio', 'host');
$username = PConfig::get($notification_data["uid"], "pumpio", "user");
$notification_data["profiles"][] = "https://".$hostname."/".$username;
}
function pumpio_registerclient(App $a, $host)
{
$url = "https://".$host."/api/client/register";
$params = [];
$application_name = Config::get('pumpio', 'application_name');
if ($application_name == "") {
$application_name = $a->getHostName();
}
$adminlist = explode(",", str_replace(" ", "", Config::get('config', 'admin_email')));
$params["type"] = "client_associate";
$params["contacts"] = $adminlist[0];
$params["application_type"] = "native";
$params["application_name"] = $application_name;
$params["logo_url"] = $a->getBaseURL()."/images/friendica-256.png";
$params["redirect_uris"] = $a->getBaseURL()."/pumpio/connect";
Logger::log("pumpio_registerclient: ".$url." parameters ".print_r($params, true), Logger::DEBUG);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
curl_setopt($ch, CURLOPT_USERAGENT, "Friendica");
$s = curl_exec($ch);
$curl_info = curl_getinfo($ch);
if ($curl_info["http_code"] == "200") {
$values = json_decode($s);
Logger::log("pumpio_registerclient: success ".print_r($values, true), Logger::DEBUG);
return $values;
}
Logger::log("pumpio_registerclient: failed: ".print_r($curl_info, true), Logger::DEBUG);
return false;
}
function pumpio_connect(App $a)
{
// Define the needed keys
$consumer_key = PConfig::get(local_user(), 'pumpio', 'consumer_key');
$consumer_secret = PConfig::get(local_user(), 'pumpio', 'consumer_secret');
$hostname = PConfig::get(local_user(), 'pumpio', 'host');
if ((($consumer_key == "") || ($consumer_secret == "")) && ($hostname != "")) {
Logger::log("pumpio_connect: register client");
$clientdata = pumpio_registerclient($a, $hostname);
PConfig::set(local_user(), 'pumpio', 'consumer_key', $clientdata->client_id);
PConfig::set(local_user(), 'pumpio', 'consumer_secret', $clientdata->client_secret);
$consumer_key = PConfig::get(local_user(), 'pumpio', 'consumer_key');
$consumer_secret = PConfig::get(local_user(), 'pumpio', 'consumer_secret');
Logger::log("pumpio_connect: ckey: ".$consumer_key." csecrect: ".$consumer_secret, Logger::DEBUG);
}
if (($consumer_key == "") || ($consumer_secret == "")) {
Logger::log("pumpio_connect: ".sprintf("Unable to register the client at the pump.io server '%s'.", $hostname));
$o .= L10n::t("Unable to register the client at the pump.io server '%s'.", $hostname);
return $o;
}
// The callback URL is the script that gets called after the user authenticates with pumpio
$callback_url = $a->getBaseURL()."/pumpio/connect";
// Let's begin. First we need a Request Token. The request token is required to send the user
// to pumpio's login page.
// Create a new instance of the oauth_client_class library. For this step, all we need to give the library is our
// Consumer Key and Consumer Secret
$client = new oauth_client_class;
$client->debug = 0;
$client->server = '';
$client->oauth_version = '1.0a';
$client->request_token_url = 'https://'.$hostname.'/oauth/request_token';
$client->dialog_url = 'https://'.$hostname.'/oauth/authorize';
$client->access_token_url = 'https://'.$hostname.'/oauth/access_token';
$client->url_parameters = false;
$client->authorization_header = true;
$client->redirect_uri = $callback_url;
$client->client_id = $consumer_key;
$client->client_secret = $consumer_secret;
if (($success = $client->Initialize())) {
if (($success = $client->Process())) {
if (strlen($client->access_token)) {
Logger::log("pumpio_connect: otoken: ".$client->access_token." osecrect: ".$client->access_token_secret, Logger::DEBUG);
PConfig::set(local_user(), "pumpio", "oauth_token", $client->access_token);
PConfig::set(local_user(), "pumpio", "oauth_token_secret", $client->access_token_secret);
}
}
$success = $client->Finalize($success);
}
if ($client->exit) {
$o = 'Could not connect to pumpio. Refresh the page or try again later.';
}
if ($success) {
Logger::log("pumpio_connect: authenticated");
$o = L10n::t("You are now authenticated to pumpio.");
$o .= '<br /><a href="'.$a->getBaseURL().'/settings/connectors">'.L10n::t("return to the connector page").'</a>';
} else {
Logger::log("pumpio_connect: could not connect");
$o = 'Could not connect to pumpio. Refresh the page or try again later.';
}
return $o;
}
function pumpio_jot_nets(App $a, array &$jotnets_fields)
{
if (! local_user()) {
return;
}
if (PConfig::get(local_user(), 'pumpio', 'post')) {
$jotnets_fields[] = [
'type' => 'checkbox',
'field' => [
'pumpio_enable',
L10n::t('Post to pumpio'),
PConfig::get(local_user(), 'pumpio', 'post_by_default')
]
];
}
}
function pumpio_settings(App $a, &$s)
{
if (!local_user()) {
return;
}
/* Add our stylesheet to the page so we can make our settings look nice */
$a->page['htmlhead'] .= '<link rel="stylesheet" type="text/css" href="' . $a->getBaseURL() . '/addon/pumpio/pumpio.css' . '" media="all" />' . "\r\n";
/* Get the current state of our config variables */
$import_enabled = PConfig::get(local_user(), 'pumpio', 'import');
$import_checked = (($import_enabled) ? ' checked="checked" ' : '');
$enabled = PConfig::get(local_user(), 'pumpio', 'post');
$checked = (($enabled) ? ' checked="checked" ' : '');
$css = (($enabled) ? '' : '-disabled');
$def_enabled = PConfig::get(local_user(), 'pumpio', 'post_by_default');
$def_checked = (($def_enabled) ? ' checked="checked" ' : '');
$public_enabled = PConfig::get(local_user(), 'pumpio', 'public');
$public_checked = (($public_enabled) ? ' checked="checked" ' : '');
$mirror_enabled = PConfig::get(local_user(), 'pumpio', 'mirror');
$mirror_checked = (($mirror_enabled) ? ' checked="checked" ' : '');
$servername = PConfig::get(local_user(), "pumpio", "host");
$username = PConfig::get(local_user(), "pumpio", "user");
/* Add some HTML to the existing form */
$s .= '<span id="settings_pumpio_inflated" class="settings-block fakelink" style="display: block;" onclick="openClose(\'settings_pumpio_expanded\'); openClose(\'settings_pumpio_inflated\');">';
$s .= '<img class="connector'.$css.'" src="images/pumpio.png" /><h3 class="connector">'. L10n::t('Pump.io Import/Export/Mirror').'</h3>';
$s .= '</span>';
$s .= '<div id="settings_pumpio_expanded" class="settings-block" style="display: none;">';
$s .= '<span class="fakelink" onclick="openClose(\'settings_pumpio_expanded\'); openClose(\'settings_pumpio_inflated\');">';
$s .= '<img class="connector'.$css.'" src="images/pumpio.png" /><h3 class="connector">'. L10n::t('Pump.io Import/Export/Mirror').'</h3>';
$s .= '</span>';
$s .= '<div id="pumpio-username-wrapper">';
$s .= '<label id="pumpio-username-label" for="pumpio-username">'.L10n::t('pump.io username (without the servername)').'</label>';
$s .= '<input id="pumpio-username" type="text" name="pumpio_user" value="'.$username.'" />';
$s .= '</div><div class="clear"></div>';
$s .= '<div id="pumpio-servername-wrapper">';
$s .= '<label id="pumpio-servername-label" for="pumpio-servername">'.L10n::t('pump.io servername (without "http://" or "https://" )').'</label>';
$s .= '<input id="pumpio-servername" type="text" name="pumpio_host" value="'.$servername.'" />';
$s .= '</div><div class="clear"></div>';
if (($username != '') && ($servername != '')) {
$oauth_token = PConfig::get(local_user(), "pumpio", "oauth_token");
$oauth_token_secret = PConfig::get(local_user(), "pumpio", "oauth_token_secret");
$s .= '<div id="pumpio-password-wrapper">';
if (($oauth_token == "") || ($oauth_token_secret == "")) {
$s .= '<div id="pumpio-authenticate-wrapper">';
$s .= '<a href="'.$a->getBaseURL().'/pumpio/connect">'.L10n::t("Authenticate your pump.io connection").'</a>';
$s .= '</div><div class="clear"></div>';
} else {
$s .= '<div id="pumpio-import-wrapper">';
$s .= '<label id="pumpio-import-label" for="pumpio-import">' . L10n::t('Import the remote timeline') . '</label>';
$s .= '<input id="pumpio-import" type="checkbox" name="pumpio_import" value="1" ' . $import_checked . '/>';
$s .= '</div><div class="clear"></div>';
$s .= '<div id="pumpio-enable-wrapper">';
$s .= '<label id="pumpio-enable-label" for="pumpio-checkbox">' . L10n::t('Enable pump.io Post Addon') . '</label>';
$s .= '<input id="pumpio-checkbox" type="checkbox" name="pumpio" value="1" ' . $checked . '/>';
$s .= '</div><div class="clear"></div>';
$s .= '<div id="pumpio-bydefault-wrapper">';
$s .= '<label id="pumpio-bydefault-label" for="pumpio-bydefault">' . L10n::t('Post to pump.io by default') . '</label>';
$s .= '<input id="pumpio-bydefault" type="checkbox" name="pumpio_bydefault" value="1" ' . $def_checked . '/>';
$s .= '</div><div class="clear"></div>';
$s .= '<div id="pumpio-public-wrapper">';
$s .= '<label id="pumpio-public-label" for="pumpio-public">' . L10n::t('Should posts be public?') . '</label>';
$s .= '<input id="pumpio-public" type="checkbox" name="pumpio_public" value="1" ' . $public_checked . '/>';
$s .= '</div><div class="clear"></div>';
$s .= '<div id="pumpio-mirror-wrapper">';
$s .= '<label id="pumpio-mirror-label" for="pumpio-mirror">' . L10n::t('Mirror all public posts') . '</label>';
$s .= '<input id="pumpio-mirror" type="checkbox" name="pumpio_mirror" value="1" ' . $mirror_checked . '/>';
$s .= '</div><div class="clear"></div>';
$s .= '<div id="pumpio-delete-wrapper">';
$s .= '<label id="pumpio-delete-label" for="pumpio-delete">' . L10n::t('Check to delete this preset') . '</label>';
$s .= '<input id="pumpio-delete" type="checkbox" name="pumpio_delete" value="1" />';
$s .= '</div><div class="clear"></div>';
}
$s .= '</div><div class="clear"></div>';
}
/* provide a submit button */
$s .= '<div class="settings-submit-wrapper" ><input type="submit" id="pumpio-submit" name="pumpio-submit" class="settings-submit" value="' . L10n::t('Save Settings') . '" /></div></div>';
}
function pumpio_settings_post(App $a, array &$b)
{
if (!empty($_POST['pumpio-submit'])) {
if (!empty($_POST['pumpio_delete'])) {
PConfig::set(local_user(), 'pumpio', 'consumer_key' , '');
PConfig::set(local_user(), 'pumpio', 'consumer_secret' , '');
PConfig::set(local_user(), 'pumpio', 'oauth_token' , '');
PConfig::set(local_user(), 'pumpio', 'oauth_token_secret', '');
PConfig::set(local_user(), 'pumpio', 'post' , false);
PConfig::set(local_user(), 'pumpio', 'import' , false);
PConfig::set(local_user(), 'pumpio', 'host' , '');
PConfig::set(local_user(), 'pumpio', 'user' , '');
PConfig::set(local_user(), 'pumpio', 'public' , false);
PConfig::set(local_user(), 'pumpio', 'mirror' , false);
PConfig::set(local_user(), 'pumpio', 'post_by_default' , false);
PConfig::set(local_user(), 'pumpio', 'lastdate' , 0);
PConfig::set(local_user(), 'pumpio', 'last_id' , '');
} else {
// filtering the username if it is filled wrong
$user = $_POST['pumpio_user'];
if (strstr($user, "@")) {
$pos = strpos($user, "@");
if ($pos > 0) {
$user = substr($user, 0, $pos);
}
}
// Filtering the hostname if someone is entering it with "http"
$host = $_POST['pumpio_host'];
$host = trim($host);
$host = str_replace(["https://", "http://"], ["", ""], $host);
PConfig::set(local_user(), 'pumpio', 'post' , $_POST['pumpio'] ?? false);
PConfig::set(local_user(), 'pumpio', 'import' , $_POST['pumpio_import'] ?? false);
PConfig::set(local_user(), 'pumpio', 'host' , $host);
PConfig::set(local_user(), 'pumpio', 'user' , $user);
PConfig::set(local_user(), 'pumpio', 'public' , $_POST['pumpio_public'] ?? false);
PConfig::set(local_user(), 'pumpio', 'mirror' , $_POST['pumpio_mirror'] ?? false);
PConfig::set(local_user(), 'pumpio', 'post_by_default', $_POST['pumpio_bydefault'] ?? false);
if (!empty($_POST['pumpio_mirror'])) {
PConfig::delete(local_user(), 'pumpio', 'lastdate');
}
}
}
}
function pumpio_load_config(App $a, ConfigFileLoader $loader)
{
$a->getConfigCache()->load($loader->loadAddonConfig('pumpio'));
}
function pumpio_hook_fork(App $a, array &$b)
{
if ($b['name'] != 'notifier_normal') {
return;
}
$post = $b['data'];
// Deleting and editing is not supported by the addon (deleting could, but isn't by now)
if ($post['deleted'] || ($post['created'] !== $post['edited'])) {
$b['execute'] = false;
return;
}
// if post comes from pump.io don't send it back
if ($post['app'] == "pump.io") {
$b['execute'] = false;
return;
}
if (PConfig::get($post['uid'], 'pumpio', 'import')) {
// Don't fork if it isn't a reply to a pump.io post
if (($post['parent'] != $post['id']) && !Item::exists(['id' => $post['parent'], 'network' => Protocol::PUMPIO])) {
Logger::log('No pump.io parent found for item ' . $post['id']);
$b['execute'] = false;
return;
}
} else {
// Comments are never exported when we don't import the pumpio timeline
if (!strstr($post['postopts'], 'pumpio') || ($post['parent'] != $post['id']) || $post['private']) {
$b['execute'] = false;
return;
}
}
}