From 42314b667063d2dca23376d138ef7cb27874c3ce Mon Sep 17 00:00:00 2001 From: Matthew Exon Date: Mon, 30 Sep 2019 20:52:05 +0200 Subject: [PATCH] Add phototrack and publicise --- phototrack/database.sql | 23 ++ phototrack/phototrack.php | 258 ++++++++++++++++++++ publicise/publicise.php | 431 ++++++++++++++++++++++++++++++++++ publicise/templates/admin.tpl | 39 +++ 4 files changed, 751 insertions(+) create mode 100644 phototrack/database.sql create mode 100644 phototrack/phototrack.php create mode 100644 publicise/publicise.php create mode 100644 publicise/templates/admin.tpl diff --git a/phototrack/database.sql b/phototrack/database.sql new file mode 100644 index 00000000..f1b58f6b --- /dev/null +++ b/phototrack/database.sql @@ -0,0 +1,23 @@ +CREATE TABLE IF NOT EXISTS `phototrack_photo_use` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `resource-id` char(64) NOT NULL, + `table` char(64) NOT NULL, + `field` char(64) NOT NULL, + `row-id` int(11) NOT NULL, + `checked` timestamp NOT NULL DEFAULT now(), + PRIMARY KEY (`id`), + INDEX `resource-id` (`resource-id`), + INDEX `row` (`table`,`field`,`row-id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + +CREATE TABLE IF NOT EXISTS `phototrack_row_check` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `table` char(64) NOT NULL, + `row-id` int(11) NOT NULL, + `checked` timestamp NOT NULL DEFAULT now(), + PRIMARY KEY (`id`), + INDEX `row` (`table`,`row-id`), + INDEX `checked` (`checked`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + +SELECT TRUE diff --git a/phototrack/phototrack.php b/phototrack/phototrack.php new file mode 100644 index 00000000..8b909f5d --- /dev/null +++ b/phototrack/phototrack.php @@ -0,0 +1,258 @@ + + */ + +/* + * List of tables and the fields that are checked: + * + * contact: photo thumb micro about + * fcontact: photo + * fsuggest: photo + * gcontact: photo about + * item: body + * item-content: body + * mail: from-photo + * notify: photo + * profile: photo thumb about + */ + +use Friendica\Core\Addon; +use Friendica\Core\Config; +use Friendica\Core\Logger; +use Friendica\Object\Image; +use Friendica\Database\DBA; + +if (!defined('PHOTOTRACK_DEFAULT_BATCH_SIZE')) { + define('PHOTOTRACK_DEFAULT_BATCH_SIZE', 1000); +} +// Time in *minutes* between searching for photo uses +if (!defined('PHOTOTRACK_DEFAULT_SEARCH_INTERVAL')) { + define('PHOTOTRACK_DEFAULT_SEARCH_INTERVAL', 10); +} + +function phototrack_install() { + global $db; + + Addon::registerHook('post_local_end', 'addon/phototrack/phototrack.php', 'phototrack_post_local_end'); + Addon::registerHook('post_remote_end', 'addon/phototrack/phototrack.php', 'phototrack_post_remote_end'); + Addon::registerHook('notifier_end', 'addon/phototrack/phototrack.php', 'phototrack_notifier_end'); + Addon::registerHook('cron', 'addon/phototrack/phototrack.php', 'phototrack_cron'); + + if (Config::get('phototrack', 'dbversion') != '0.1') { + $schema = file_get_contents(dirname(__file__).'/database.sql'); + $arr = explode(';', $schema); + foreach ($arr as $a) { + if (!DBA::e($a)) { + Logger::warning('Unable to create database table: ' . DBA::errorMessage()); + return; + } + } + Config::set('phototrack', 'dbversion', '0.1'); + } +} + +function phototrack_uninstall() { + Addon::unregisterHook('post_local_end', 'addon/phototrack/phototrack.php', 'phototrack_post_local_end'); + Addon::unregisterHook('post_remote_end', 'addon/phototrack/phototrack.php', 'phototrack_post_remote_end'); + Addon::unregisterHook('notifier_end', 'addon/phototrack/phototrack.php', 'phototrack_notifier_end'); + Addon::unregisterHook('cron', 'addon/phototrack/phototrack.php', 'phototrack_cron'); +} + +function phototrack_module() {} + +function phototrack_finished_row($table, $id) { + $existing = DBA::selectFirst('phototrack_row_check', ['id'], ['table' => $table, 'row-id' => $id]); + if (!is_bool($existing)) { + q("UPDATE phototrack_row_check SET checked = NOW() WHERE `table` = '$table' AND `row-id` = '$id'"); + } + else { + q("INSERT INTO phototrack_row_check (`table`, `row-id`, `checked`) VALUES ('$table', '$id', NOW())"); + } +} + +function phototrack_photo_use($photo, $table, $field, $id) { + Logger::debug('@@@ phototrack_photo_use ' . $photo); + foreach (Image::supportedTypes() as $m => $e) { + $photo = str_replace(".$e", '', $photo); + } + if (substr($photo, -2, 1) == '-') { + $resolution = intval(substr($photo,-1,1)); + $photo = substr($photo,0,-2); + } + if (strlen($photo) != 32) { + return; + } + $r = q("SELECT `resource-id` FROM `photo` WHERE `resource-id` = '%s' LIMIT 1", DBA::escape($photo)); + if (!count($r)) { + return; + } + $rid = $r[0]['resource-id']; + $existing = q("SELECT id FROM phototrack_photo_use WHERE `resource-id` = '$rid' AND `table` = '$table' AND `field` = '$field' AND `row-id` = '$id'"); + if (count($existing)) { + q("UPDATE phototrack_photo_use SET checked = NOW() WHERE `resource-id` = '$rid' AND `table` = '$table' AND `field` = '$field' AND `row-id` = '$id'"); + } + else { + q("INSERT INTO phototrack_photo_use (`resource-id`, `table`, `field`, `row-id`, `checked`) VALUES ('$rid', '$table', '$field', '$id', NOW())"); + } +} + +function phototrack_check_field_url($a, $table, $field, $id, $url) { + Logger::info('@@@ phototrack_check_field_url table ' . $table . ' field ' . $field . ' id ' . $id . ' url ' . $url); + $baseurl = $a->getBaseURL(); + if (strpos($url, $baseurl) !== FALSE) { + $url = substr($url, strlen($baseurl)); + Logger::info('@@@ phototrack_check_field_url funny url stuff ' . $url . ' base ' . $baseurl); + } + if (strpos($url, '/photo/') !== FALSE) { + $rid = substr($url, strlen('/photo/')); + Logger::info('@@@ phototrack_check_field_url rid ' . $rid); + phototrack_photo_use($rid, $table, $field, $id); + } +} + +function phototrack_check_field_bbcode($a, $table, $field, $id, $value) { + $baseurl = $a->getBaseURL(); + $matches = array(); + preg_match_all("/\[img(\=([0-9]*)x([0-9]*))?\](.*?)\[\/img\]/ism", $value, $matches); + foreach ($matches[4] as $url) { + phototrack_check_field_url($a, $table, $field, $id, $url); + } +} + +function phototrack_post_local_end(&$a, &$item) { + phototrack_check_row($a, 'item', $item); + phototrack_check_row($a, 'item-content', $item); +} + +function phototrack_post_remote_end(&$a, &$item) { + phototrack_check_row($a, 'item', $item); + phototrack_check_row($a, 'item-content', $item); +} + +function phototrack_notifier_end($item) { + $a = get_app(); +} + +function phototrack_check_row($a, $table, $row) { + switch ($table) { + case 'item': + $fields = array( + 'body' => 'bbcode'); + break; + case 'item-content': + $fields = array( + 'body' => 'bbcode'); + break; + case 'contact': + $fields = array( + 'photo' => 'url', + 'thumb' => 'url', + 'micro' => 'url', + 'about' => 'bbcode'); + break; + case 'fcontact': + $fields = array( + 'photo' => 'url'); + break; + case 'fsuggest': + $fields = array( + 'photo' => 'url'); + break; + case 'gcontact': + $fields = array( + 'photo' => 'url', + 'about' => 'bbcode'); + break; + default: $fields = array(); break; + } + foreach ($fields as $field => $type) { + switch ($type) { + case 'bbcode': phototrack_check_field_bbcode($a, $table, $field, $row['id'], $row[$field]); break; + case 'url': phototrack_check_field_url($a, $table, $field, $row['id'], $row[$field]); break; + } + } + phototrack_finished_row($table, $row['id']); +} + +function phototrack_batch_size() { + $batch_size = Config::get('phototrack', 'batch_size'); + if ($batch_size > 0) { + return $batch_size; + } + return PHOTOTRACK_DEFAULT_BATCH_SIZE; +} + +function phototrack_search_table($a, $table) { + $batch_size = phototrack_batch_size(); + $rows = q("SELECT `$table`.* FROM `$table` LEFT OUTER JOIN phototrack_row_check ON ( phototrack_row_check.`table` = '$table' AND phototrack_row_check.`row-id` = `$table`.id ) WHERE ( ( phototrack_row_check.checked IS NULL ) OR ( phototrack_row_check.checked < DATE_SUB(NOW(), INTERVAL 1 MONTH) ) ) ORDER BY phototrack_row_check.checked LIMIT $batch_size"); + foreach ($rows as $row) { + phototrack_check_row($a, $table, $row); + } + $r = q("SELECT COUNT(*) FROM `$table` LEFT OUTER JOIN phototrack_row_check ON ( phototrack_row_check.`table` = '$table' AND phototrack_row_check.`row-id` = `$table`.id ) WHERE ( ( phototrack_row_check.checked IS NULL ) OR ( phototrack_row_check.checked < DATE_SUB(NOW(), INTERVAL 1 MONTH) ) )"); + $remaining = $r[0]['COUNT(*)']; + Logger::info('phototrack: searched ' . count($rows) . ' rows in table ' . $table . ', ' . $remaining . ' still remaining to search'); + return $remaining; +} + +function phototrack_cron_time() { + $prev_remaining = Config::get('phototrack', 'remaining_items'); + if ($prev_remaining > 10 * phototrack_batch_size()) { + Logger::debug('phototrack: more than ' . (10 * phototrack_batch_size()) . ' items remaining'); + return true; + } + $last = Config::get('phototrack', 'last_search'); + $search_interval = intval(Config::get('phototrack', 'search_interval')); + if (!$search_interval) { + $search_interval = PHOTOTRACK_DEFAULT_SEARCH_INTERVAL; + } + if ($last) { + $next = $last + ($search_interval * 60); + if ($next > time()) { + Logger::debug('phototrack: search interval not reached'); + return false; + } + } + return true; +} + +function phototrack_cron($a, $b) { + if (!phototrack_cron_time()) { + return; + } + Config::set('phototrack', 'last_search', time()); + + $remaining = 0; + $remaining += phototrack_search_table($a, 'item'); + $remaining += phototrack_search_table($a, 'item-content'); + $remaining += phototrack_search_table($a, 'contact'); + $remaining += phototrack_search_table($a, 'fcontact'); + $remaining += phototrack_search_table($a, 'fsuggest'); + $remaining += phototrack_search_table($a, 'gcontact'); + + Config::set('phototrack', 'remaining_items', $remaining); + if ($remaining === 0) { + phototrack_tidy(); + } +} + +function phototrack_tidy() { + $batch_size = phototrack_batch_size(); + q('CREATE TABLE IF NOT EXISTS `phototrack-temp` (`resource-id` char(255) not null)'); + q('INSERT INTO `phototrack-temp` SELECT DISTINCT(`resource-id`) FROM photo WHERE photo.`created` < DATE_SUB(NOW(), INTERVAL 2 MONTH)'); + $rows = q('SELECT `phototrack-temp`.`resource-id` FROM `phototrack-temp` LEFT OUTER JOIN phototrack_photo_use ON (`phototrack-temp`.`resource-id` = phototrack_photo_use.`resource-id`) WHERE phototrack_photo_use.id IS NULL limit ' . /*$batch_size*/1000); + foreach ($rows as $row) { + Logger::debug('phototrack: remove photo ' . $row['resource-id']); + q('DELETE FROM photo WHERE `resource-id` = "' . $row['resource-id'] . '"'); + } + q('DROP TABLE `phototrack-temp`'); + Logger::info('phototrack_tidy: deleted ' . count($rows) . ' photos'); + $rows = q('SELECT id FROM phototrack_photo_use WHERE checked < DATE_SUB(NOW(), INTERVAL 14 DAY)'); + foreach ($rows as $row) { + q('DELETE FROM phototrack_photo_use WHERE id = ' . $row['id']); + } + Logger::info('phototrack_tidy: deleted ' . count($rows) . ' phototrack_photo_use rows'); +} diff --git a/publicise/publicise.php b/publicise/publicise.php new file mode 100644 index 00000000..d27eefd4 --- /dev/null +++ b/publicise/publicise.php @@ -0,0 +1,431 @@ + + */ + +use Friendica\Core\Addon; +use Friendica\Core\Logger; +use Friendica\Core\Renderer; +use Friendica\Core\L10n; +use Friendica\Database\DBA; + +function publicise_install() { + Addon::registerHook('post_remote', 'addon/publicise/publicise.php', 'publicise_post_remote_hook'); +} + +function publicise_uninstall() { + Addon::unregisterHook('post_remote', 'addon/publicise/publicise.php', 'publicise_post_remote_hook'); + Addon::unregisterHook('post_remote_end', 'addon/publicise/publicise.php', 'publicise_post_remote_end_hook'); +} + +function publicise_get_contacts() { + $query = <<$v) { + $enabled = ($v['reason'] === 'publicise') ? 1 : NULL; + $expire = 30; + $comments = 1; + $url = $v['url']; + if ($enabled) { + $r = q('SELECT * FROM `user` WHERE `uid` = %d', intval($v['uid'])); + $expire = $r[0]['expire']; + $url = $a->get_baseurl() . '/profile/' . $v['nick']; + if ($r[0]['page-flags'] == PAGE_SOAPBOX) { + $comments = NULL; + } + if ($r[0]['account_expired']) { + $enabled = NULL; + } + } + $contacts[$k]['enabled'] = array('publicise-enabled-' . $v['id'], NULL, $enabled); + $contacts[$k]['comments'] = array('publicise-comments-' . $v['id'], NULL, $comments); + $contacts[$k]['expire'] = $expire; + $contacts[$k]['url'] = $url; + } + $template = Renderer::getMarkupTemplate('admin.tpl', 'addon/publicise/'); + $o .= Renderer::replaceMacros($template, array( + '$feeds' => $contacts, + '$feed_t' => L10n::t('Feed'), + '$publicised_t' => L10n::t('Publicised'), + '$comments_t' => L10n::t('Allow Comments/Likes'), + '$expire_t' => L10n::t('Expire Articles After (Days)'), + '$submit_t' => L10n::t('Submit'))); +} + +function publicise_make_string($in) { + return "'" . DBA::escape($in) . "'"; +} + +function publicise_make_int($in) { + return intval($in) ? $in : 0; +} + +function publicise_create_user($owner, $contact) { + + $nick = $contact['nick']; + if (!$nick) { + notice(sprintf(t("Can't publicise feed \"%s\" because it doesn't have a nickname"), $contact['name']) . EOL); + return; + } + Logger::info('Publicise: create user, beginning key generation...'); + $res=openssl_pkey_new(array( + 'digest_alg' => 'sha1', + 'private_key_bits' => 4096, + 'encrypt_key' => false )); + $prvkey = ''; + openssl_pkey_export($res, $prvkey); + $pkey = openssl_pkey_get_details($res); + $pubkey = $pkey["key"]; + $sres=openssl_pkey_new(array( + 'digest_alg' => 'sha1', + 'private_key_bits' => 512, + 'encrypt_key' => false )); + $sprvkey = ''; + openssl_pkey_export($sres, $sprvkey); + $spkey = openssl_pkey_get_details($sres); + $spubkey = $spkey["key"]; + $guid = generate_user_guid(); + + $newuser = array( + 'guid' => publicise_make_string($guid), + 'username' => publicise_make_string($contact['name']), + 'password' => publicise_make_string($owner['password']), + 'nickname' => publicise_make_string($contact['nick']), + 'email' => publicise_make_string($owner['email']), + 'openid' => publicise_make_string($owner['openid']), + 'timezone' => publicise_make_string($owner['timezone']), + 'language' => publicise_make_string($owner['language']), + 'register_date' => publicise_make_string(datetime_convert()), + 'default-location' => publicise_make_string($owner['default-location']), + 'allow_location' => publicise_make_string($owner['allow_location']), + 'theme' => publicise_make_string($owner['theme']), + 'pubkey' => publicise_make_string($pubkey), + 'prvkey' => publicise_make_string($prvkey), + 'spubkey' => publicise_make_string($spubkey), + 'sprvkey' => publicise_make_string($sprvkey), + 'verified' => publicise_make_int($owner['verified']), + 'blocked' => publicise_make_int(0), + 'blockwall' => publicise_make_int(1), + 'hidewall' => publicise_make_int(0), + 'blocktags' => publicise_make_int(0), + 'notify-flags' => publicise_make_int($owner['notifyflags']), + 'page-flags' => publicise_make_int($comments ? PAGE_COMMUNITY : PAGE_SOAPBOX), + 'expire' => publicise_make_int($expire), + ); + Logger::debug('Publicise: creating user ' . print_r($newuser, true)); + $r = q("INSERT INTO `user` (`" + . implode("`, `", array_keys($newuser)) + . "`) VALUES (" + . implode(", ", array_values($newuser)) + . ")" ); + if (!$r) { + Logger::warning('Publicise: create user failed'); + return; + } + $r = q('SELECT * FROM `user` WHERE `guid` = "%s"', DBA::escape($guid)); + if (count($r) != 1) { + Logger::warning('Publicise: unexpected number of uids returned'); + return; + } + Logger::debug('Publicise: created user ID ' . $r[0]); + return $r[0]; +} + +function publicise_create_self_contact($a, $contact, $uid) { + $newcontact = array( + 'uid' => $uid, + 'created' => publicise_make_string(datetime_convert()), + 'self' => publicise_make_int(1), + 'name' => publicise_make_string($contact['name']), + 'nick' => publicise_make_string($contact['nick']), + 'photo' => publicise_make_string($contact['photo']), + 'thumb' => publicise_make_string($contact['thumb']), + 'micro' => publicise_make_string($contact['micro']), + 'blocked' => publicise_make_int(0), + 'pending' => publicise_make_int(0), + 'url' => publicise_make_string($a->get_baseurl() . '/profile/' . $contact['nick']), + 'nurl' => publicise_make_string($a->get_baseurl() . '/profile/' . $contact['nick']), + 'request' => publicise_make_string($a->get_baseurl() . '/dfrn_request/' . $contact['nick']), + 'notify' => publicise_make_string($a->get_baseurl() . '/dfrn_notify/' . $contact['nick']), + 'poll' => publicise_make_string($a->get_baseurl() . '/dfrn_poll/' . $contact['nick']), + 'confirm' => publicise_make_string($a->get_baseurl() . '/dfrn_confirm/' . $contact['nick']), + 'poco' => publicise_make_string($a->get_baseurl() . '/poco/' . $contact['nick']), + 'uri-date' => publicise_make_string(datetime_convert()), + 'avatar-date' => publicise_make_string(datetime_convert()), + 'closeness' => publicise_make_int(0), + ); + $existing = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 1", intval($uid)); + if (count($existing)) { + $newcontact = $existing[0]; + Logger::debug('Publicise: self contact already exists for user ' . $uid . ' id ' . $newcontact['id']); + } else { + Logger::debug('Publicise: create contact ' . print_r($newcontact, true)); + q("INSERT INTO `contact` (`" + . implode("`, `", array_keys($newcontact)) + . "`) VALUES (" + . implode(", ", array_values($newcontact)) + . ")" ); + $results = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `self` = 1", intval($uid)); + if (count($results) != 1) { + Logger::warning('Publicise: create self contact failed, will delete uid ' . $uid); + $r = q("DELETE FROM `user` WHERE `uid` = %d", intval($uid)); + return; + } + $newcontact = $results[0]; + Logger::debug('Publicise: created self contact for user ' . $uid . ' id ' . $newcontact['id']); + } + Logger::debug('Publicise: self contact for ' . $uid . ' nick ' . $contact['nick'] . ' is ' . $newcontact['id']); + return $newcontact['id']; +} + +function publicise_create_profile($contact, $uid) { + $newprofile = array( + 'uid' => $uid, + 'profile-name' => publicise_make_string('default'), + 'is-default' => publicise_make_int(1), + 'name' => publicise_make_string($contact['name']), + 'photo' => publicise_make_string($contact['photo']), + 'thumb' => publicise_make_string($contact['thumb']), + 'homepage' => publicise_make_string($contact['url']), + 'publish' => publicise_make_int(1), + 'net-publish' => publicise_make_int(1), + ); + Logger::debug('Publicise: create profile ' . print_r($newprofile, true)); + $r = q("INSERT INTO `profile` (`" + . implode("`, `", array_keys($newprofile)) + . "`) VALUES (" + . implode(", ", array_values($newprofile)) + . ")" ); + if (!$r) { + Logger::warning('Publicise: create profile failed'); + } + $newprofile = q('SELECT `id` FROM `profile` WHERE `uid` = %d AND `is-default` = 1', intval($uid)); + if (count($newprofile) != 1) { + Logger::warning('Publicise: create profile produced unexpected number of results'); + return; + } + Logger::debug('Publicise: created profile ' . $newprofile[0]['id']); + return $newprofile[0]['id']; +} + +function publicise_set_up_user($a, $contact, $owner) { + $user = publicise_create_user($owner, $contact); + if (!$user) { + notice(sprintf(t("Failed to create user for feed \"%s\""), $contact['name']) . EOL); + return; + } + $self_contact = publicise_create_self_contact($a, $contact, $user['uid']); + if (!$self_contact) { + notice(sprintf(t("Failed to create self contact for user \"%s\""), $contact['name']) . EOL); + Logger::warning("Publicise: unable to create self contact, deleting user " . $user['uid']); + q('DELETE FROM `user` WHERE `uid` = %d', intval($user['uid'])); + return; + } + $profile = publicise_create_profile($contact, $user['uid']); + if (!$profile) { + notice(sprintf(t("Failed to create profile for user \"%s\""), $contact['name']) . EOL); + Logger::warning("Publicise: unable to create profile, deleting user $uid contact $self_contact"); + q('DELETE FROM `user` WHERE `uid` = %d', intval($user['uid'])); + q('DELETE FROM `contact` WHERE `id` = %d', intval($self_contact)); + return; + } + return $user; +} + +function publicise($a, &$contact, &$owner) { + Logger::info('@@@ Publicise: publicise'); + if (!is_site_admin()) { + notice(t("Only admin users can publicise feeds")); + Logger::warning('Publicise: non-admin tried to publicise'); + return; + } + + // Check if we're changing our mind about a feed we earlier depublicised + Logger::info('@@@ Publicise: ' . 'SELECT * FROM `user` WHERE `account_expires_on` != "0000-00-00 00:00:00" AND `nickname` = "' . $contact['nick'] . '" AND `email` = "' . $owner['email'] . '" AND `page-flags` in (' . intval(PAGE_COMMUNITY) . ', ' . intval(PAGE_SOAPBOX) . ')'); + $existing = q('SELECT * FROM `user` WHERE `account_expires_on` != "0000-00-00 00:00:00" AND `nickname` = "%s" AND `email` = "%s" AND `page-flags` in (%d, %d)', + DBA::escape($contact['nick']), DBA::escape($owner['email']), intval(PAGE_COMMUNITY), intval(PAGE_SOAPBOX)); + if (count($existing) == 1) { + Logger::info('@@@ Publicise: there is existing'); + $owner = $existing[0]; + q('UPDATE `user` SET `account_expires_on` = "0000-00-00 00:00:00", `account_removed` = 0, `account_expired` = 0 WHERE `uid` = %d', intval($owner['uid'])); + q('UPDATE `profile` SET `publish` = 1, `net-publish` = 1 WHERE `uid` = %d AND `is-default` = 1', intval($owner['uid'])); + Logger::debug('Publicise: recycled previous user ' . $owner['uid']); + } + else { + Logger::info('@@@ Publicise: there is not existing'); + $owner = publicise_set_up_user($a, $contact, $owner); + if (!$owner) { + return; + } + Logger::debug("Publicise: created new user " . $owner['uid']); + } + Logger::info('Publicise: new contact user is ' . $owner['uid']); + + $r = q("UPDATE `contact` SET `uid` = %d, `reason` = 'publicise', `hidden` = 1 WHERE id = %d", intval($owner['uid']), intval($contact['id'])); + if (!$r) { + Logger::warning('Publicise: update contact failed, user is probably in a bad state ' . $user['uid']); + } + $contact['uid'] = $owner['uid']; + $contact['reason'] = 'publicise'; + $contact['hidden'] = 1; + $r = q("UPDATE `item` SET `uid` = %d, type = 'wall', wall = 1, private = 0 WHERE `contact-id` = %d", + intval($owner['uid']), intval($contact['id'])); + Logger::debug('Publicise: moved items from contact ' . $contact['id'] . ' to uid ' . $owner['uid']); + + // Update the retriever config + $r = q("UPDATE `retriever_rule` SET `uid` = %d WHERE `contact-id` = %d", + intval($owner['uid']), intval($contact['id'])); + + info(sprintf(t("Moved feed \"%s\" to dedicated account"), $contact['name']) . EOL); + return true; +} + +function publicise_self_contact($uid) { + $r = q('SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 1', intval($uid)); + if (count($r) != 1) { + Logger::warning('Publicise: unexpected number of self contacts for user ' . $uid); + return; + } + return $r[0]; +} + +function depublicise($a, $contact, $user) { + require_once('include/Contact.php'); + + if (!is_site_admin()) { + notice("Only admin users can depublicise feeds"); + Logger::warning('Publicise: non-admin tried to depublicise'); + return; + } + + Logger::debug('Publicise: about to depublicise contact ' . $contact['id'] . ' user ' . $user['uid']); + + $self_contact = publicise_self_contact($user['uid']); + + // If the local_user() is subscribed to the feed, take ownership + // of the feed and all its items and photos. Otherwise they will + // be deleted when the account expires. + $r = q('SELECT * FROM `contact` WHERE `uid` = %d AND `url` = "%s"', + intval(local_user()), DBA::escape($self_contact['url'])); + if (count($r)) { + // Delete the contact to the feed user and any + // copies of its items. These will be replaced by the originals, + // which will be brought back into the local_user's feed along + // with the feed contact itself. + foreach ($r as $my_contact) { + q('DELETE FROM `item` WHERE `contact-id` = %d', intval($my_contact['id'])); + q('DELETE FROM `contact` WHERE `id` = %d', intval($my_contact['id'])); + } + + // Move the feed contact to local_user. Existing items stay + // attached to the original feed contact, but must have their uid + // updated. Also update the fields we scribbled over in + // publicise_post_remote_hook. + q('UPDATE `contact` SET `uid` = %d, `reason` = "", hidden = 0 WHERE id = %d', + intval(local_user()), intval($contact['id'])); + q('UPDATE `item` SET `uid` = %d, `wall` = 0, `type` = "remote", `private` = 2 WHERE `contact-id` = %d', + intval(local_user()), intval($contact['id'])); + + // Take ownership of any photos created by the feed user + q('UPDATE `photo` SET `uid` = %d WHERE `uid` = %d', + intval(local_user()), intval($user['uid'])); + + // Update the retriever config + $r = q("UPDATE `retriever_rule` SET `uid` = %d WHERE `contact-id` = %d", + intval($owner['uid']), intval($contact['id'])); + } + + // Set the account to removed and expired right now. It will be cleaned up by cron after 3 days, giving a chance to change your mind + q('UPDATE `user` SET `account_removed` = 1, `account_expired` = 1, `account_expires_on` = UTC_TIMESTAMP() WHERE `uid` = %d', + intval($user['uid'])); + q('UPDATE `profile` SET `publish` = 0, `net-publish` = 0 WHERE `uid` = %d AND `is-default` = 1', intval($user['uid'])); + + info(sprintf(t("Removed dedicated account for feed \"%s\""), $contact['name']) . EOL); +} + +function publicise_addon_admin_post ($a) { + Logger::info('@@@ publicise_addon_admin_post'); + if (!is_site_admin()) { + Logger::warning('Publicise: non-admin tried to do admin post'); + return; + } + + foreach (publicise_get_contacts() as $contact) { + Logger::info('@@@ publicise_addon_admin_post contact ' . $contact['id'] . ' ' . $contact['name']); + $user = publicise_get_user($contact['uid']); + if (!$_POST['publicise-enabled-' . $contact['id']]) { + if ($contact['reason'] === 'publicise') { + Logger::info('@@@ depublicise'); + depublicise($a, $contact, $user); + } + } + else { + if ($contact['reason'] !== 'publicise') { + Logger::info('@@@ publicise'); + if (!publicise($a, $contact, $user)) { + Logger::warning('Publicise: failed to publicise contact ' . $contact['id']); + continue; + } + } + if ($_POST['publicise-expire-' . $contact['id']] != $user['expire']) { + q('UPDATE `user` SET `expire` = %d WHERE `uid` = %d', + intval($_POST['publicise-expire-' . $contact['id']]), intval($user['uid'])); + } + if ($_POST['publicise-comments-' . $contact['id']]) { + if ($user['page-flags'] != PAGE_COMMUNITY) { + q('UPDATE `user` SET `page-flags` = %d WHERE `uid` = %d', + intval(PAGE_COMMUNITY), intval($user['uid'])); + q('UPDATE `contact` SET `rel` = %d WHERE `uid` = %d AND `network` = "dfrn"', + intval(CONTACT_IS_SHARING), intval($user['uid'])); + } + } + else { + if ($user['page-flags'] != PAGE_SOAPBOX) { + q('UPDATE `user` SET `page-flags` = %d WHERE `uid` = %d', + intval(PAGE_SOAPBOX), intval($user['uid'])); + q('UPDATE `contact` SET `rel` = %d WHERE `uid` = %d AND `network` = "dfrn"', + intval(CONTACT_IS_FOLLOWER), intval($user['uid'])); + } + } + } + } +} + +function publicise_post_remote_hook(&$a, &$item) { + $r1 = q("SELECT `uid` FROM `contact` WHERE `id` = %d AND `reason` = 'publicise'", intval($item['contact-id'])); + if (!$r1) { + return; + } + + Logger::debug('Publicise: moving to wall: ' . $item['uid'] . ' ' . $item['contact-id'] . ' ' . $item['uri']); + $item['type'] = 'wall'; + $item['wall'] = 1; + $item['private'] = 0; +} + diff --git a/publicise/templates/admin.tpl b/publicise/templates/admin.tpl new file mode 100644 index 00000000..b10c3546 --- /dev/null +++ b/publicise/templates/admin.tpl @@ -0,0 +1,39 @@ +{{* + * AUTOMATICALLY GENERATED TEMPLATE + * DO NOT EDIT THIS FILE, CHANGES WILL BE OVERWRITTEN + * + *}} +
+ + + + + + + + + + +{{foreach $feeds as $f}} + + + + + + +{{/foreach}} + +
{{$feed_t}}{{$publicised_t}}{{$comments_t}}{{$expire_t}}
+ + + {{$f.name}} + + +{{include file="field_yesno.tpl" field=$f.enabled}} + +{{include file="field_yesno.tpl" field=$f.comments}} + + +
+ +