forked from friendica/friendica-addons
Compare commits
1 commit
| Author | SHA1 | Date | |
|---|---|---|---|
| 153b6b7775 |
2 changed files with 734 additions and 8 deletions
741
pnut/pnut.php
741
pnut/pnut.php
|
|
@ -2,7 +2,7 @@
|
|||
/**
|
||||
* Name: Pnut Connector
|
||||
* Description: Post to pnut.io
|
||||
* Version: 0.1.2
|
||||
* Version: 0.2.0
|
||||
* Author: Morgan McMillian <https://social.clacks.network/profile/spacenerdmo>
|
||||
* Status: In Development
|
||||
*/
|
||||
|
|
@ -11,14 +11,19 @@ require_once 'addon/pnut/lib/phpnut.php';
|
|||
require_once 'addon/pnut/lib/phpnutException.php';
|
||||
|
||||
use Friendica\Content\Text\BBCode;
|
||||
use Friendica\Content\Text\HTML;
|
||||
use Friendica\Content\Text\Plaintext;
|
||||
use Friendica\Core\Config\Util\ConfigFileManager;
|
||||
use Friendica\Content\Text\Markdown;
|
||||
use Friendica\Core\Hook;
|
||||
use Friendica\Core\Renderer;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\DI;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Model\Circle;
|
||||
use Friendica\Util\Strings;
|
||||
use Friendica\Model\Item;
|
||||
use Friendica\Model\Photo;
|
||||
use Friendica\Core\Protocol;
|
||||
use phpnut\phpnutException;
|
||||
|
||||
const PNUT_LIMIT = 256;
|
||||
|
|
@ -32,6 +37,9 @@ function pnut_install()
|
|||
Hook::register('jot_networks', __FILE__, 'pnut_jot_nets');
|
||||
Hook::register('connector_settings', __FILE__, 'pnut_settings');
|
||||
Hook::register('connector_settings_post', __FILE__, 'pnut_settings_post');
|
||||
Hook::register('cron', __FILE__, 'pnut_cron');
|
||||
Hook::register('prepare_body', __FILE__, 'pnut_prepare_body');
|
||||
Hook::register('check_item_notification', __FILE__, 'pnut_check_item_notification');
|
||||
}
|
||||
|
||||
function pnut_module() {}
|
||||
|
|
@ -78,6 +86,10 @@ function pnut_connect()
|
|||
DI::logger()->debug('Got Token', [$token]);
|
||||
$o = DI::l10n()->t('You are now authenticated with pnut.io.');
|
||||
DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'pnut', 'access_token', $token);
|
||||
|
||||
// Get user info and set ownid
|
||||
$userdata = $nut->getUser();
|
||||
DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'pnut', 'ownid', $userdata['id']);
|
||||
} catch (phpnutException $e) {
|
||||
$o = DI::l10n()->t('Error fetching token. Please try again.', ['code' => $e->getCode(), 'message' => $e->getMessage()]);
|
||||
}
|
||||
|
|
@ -87,9 +99,15 @@ function pnut_connect()
|
|||
return $o;
|
||||
}
|
||||
|
||||
function pnut_load_config(ConfigFileManager $loader)
|
||||
function pnut_check_item_notification($a, &$notification_data)
|
||||
{
|
||||
DI::appHelper()->getConfigCache()->load($loader->loadAddonConfig('pnut'), \Friendica\Core\Config\ValueObject\Cache::SOURCE_STATIC);
|
||||
$own_id = DI::pConfig()->get($notification_data["uid"], 'pnut', 'ownid');
|
||||
|
||||
$own_user = DI::dba()->p("SELECT `url` FROM `contact` WHERE `uid` = ? AND `alias` = ?", $notification_data["uid"], "pnut::" . $own_id);
|
||||
|
||||
if ($own_user) {
|
||||
$notification_data["profiles"][] = $own_user[0]["url"];
|
||||
}
|
||||
}
|
||||
|
||||
function pnut_addon_admin(string &$o)
|
||||
|
|
@ -123,9 +141,11 @@ function pnut_settings(array &$data)
|
|||
|
||||
$enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'post') ?? false;
|
||||
$def_enabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'post_by_default') ?? false;
|
||||
$importenabled = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'import') ?? false;
|
||||
$client_id = DI::config()->get('pnut', 'client_id');
|
||||
$client_secret = DI::config()->get('pnut', 'client_secret');
|
||||
$token = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'access_token');
|
||||
$ownid = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'ownid');
|
||||
|
||||
$user_client = empty($client_id) || empty($client_secret);
|
||||
if ($user_client) {
|
||||
|
|
@ -133,6 +153,8 @@ function pnut_settings(array &$data)
|
|||
$client_secret = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'pnut', 'client_secret');
|
||||
}
|
||||
|
||||
$o = '';
|
||||
|
||||
if (!empty($client_id) && !empty($client_secret) && empty($token)) {
|
||||
$nut = new phpnut\phpnut($client_id, $client_secret);
|
||||
$authorize_url = $nut->getAuthUrl($redirectUri, $scope);
|
||||
|
|
@ -140,14 +162,22 @@ function pnut_settings(array &$data)
|
|||
}
|
||||
|
||||
if (!empty($token)) {
|
||||
$disconn_btn = DI::l10n()->t('Disconnect');
|
||||
$nut = new phpnut\phpnut($token);
|
||||
try {
|
||||
$userdata = $nut->getUser();
|
||||
if ($ownid != $userdata["id"]) {
|
||||
DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'pnut', 'ownid', $userdata["id"]);
|
||||
}
|
||||
$o .= '<div id="pnut-info" ><img id="pnut-avatar" src="' . $userdata["avatar_image"]["url"] . '" /><p id="pnut-info-block">' . DI::l10n()->t('Currently connected to: ') . '<a href="' . $userdata["canonical_url"] . '" target="_pnut">' . $userdata["username"] . '</a><br /><em>' . $userdata["description"]["text"] . '</em></p></div>';
|
||||
} catch (phpnutException $e) {
|
||||
$o .= DI::l10n()->t("<p>Error fetching user profile. Please clear the configuration and try again.</p>");
|
||||
}
|
||||
}
|
||||
|
||||
$t = Renderer::getMarkupTemplate('connector_settings.tpl', 'addon/pnut/');
|
||||
$html = Renderer::replaceMacros($t, [
|
||||
'$enable' => ['pnut', DI::l10n()->t('Enable Pnut Post Addon'), $enabled],
|
||||
'$bydefault' => ['pnut_bydefault', DI::l10n()->t('Post to Pnut by default'), $def_enabled],
|
||||
'$client_id' => ['pnut_client_id', DI::l10n()->t('Client ID'), $client_id],
|
||||
'$bydefault' => ['pnut_bydefault', DI::l10n()->t('Post to Pnut by default'), $def_enabled], '$import' => ['pnut_import', DI::l10n()->t('Import the remote timeline'), $importenabled], '$client_id' => ['pnut_client_id', DI::l10n()->t('Client ID'), $client_id],
|
||||
'$client_secret' => ['pnut_client_secret', DI::l10n()->t('Client Secret'), $client_secret],
|
||||
'$access_token' => ['pnut_access_token', DI::l10n()->t('Access Token'), $token, '', '', 'readonly'],
|
||||
'$authorize_url' => $authorize_url ?? '',
|
||||
|
|
@ -174,12 +204,14 @@ function pnut_settings_post(array &$b)
|
|||
if (!empty($_POST['pnut-disconnect'])) {
|
||||
DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'pnut', 'post');
|
||||
DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'pnut', 'post_by_default');
|
||||
DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'pnut', 'import');
|
||||
DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'pnut', 'client_id');
|
||||
DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'pnut', 'client_secret');
|
||||
DI::pConfig()->delete(DI::userSession()->getLocalUserId(), 'pnut', 'access_token');
|
||||
} else {
|
||||
DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'pnut', 'post', intval($_POST['pnut']));
|
||||
DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'pnut', 'post_by_default', intval($_POST['pnut_bydefault']));
|
||||
DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'pnut', 'import', intval($_POST['pnut_import']));
|
||||
if (!empty($_POST['pnut_client_id'])) {
|
||||
DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'pnut', 'client_id', $_POST['pnut_client_id']);
|
||||
}
|
||||
|
|
@ -275,6 +307,59 @@ function pnut_post_hook(array &$b)
|
|||
$token = DI::pConfig()->get($b['uid'], 'pnut', 'access_token');
|
||||
$nut = new phpnut\phpnut($token);
|
||||
|
||||
$iscomment = false;
|
||||
$islike = false;
|
||||
|
||||
if ($b['parent'] != $b['id']) {
|
||||
// Looking if its a reply to a pnut post
|
||||
if ((substr($b["parent-uri"], 0, 6) != "pnut::") && (substr($b["extid"], 0, 6) != "pnut::") && (substr($b["thr-parent"], 0, 6) != "pnut::")) {
|
||||
DI::logger()->debug("PNUT post: no pnut post " . $b["parent"]);
|
||||
return;
|
||||
}
|
||||
|
||||
$r = DI::dba()->p("SELECT * FROM item WHERE item.uri = ? AND item.uid = ? LIMIT 1", $b["thr-parent"], intval($b["uid"]));
|
||||
|
||||
if (!count($r)) {
|
||||
DI::logger()->debug("PNUT post: no parent found " . $b["thr-parent"]);
|
||||
return;
|
||||
} else {
|
||||
$iscomment = true;
|
||||
$orig_post = $r[0];
|
||||
}
|
||||
|
||||
$nicknameplain = preg_replace("=https?://pnut.io/(.*)=ism", "$1", $orig_post["author-link"]);
|
||||
$nickname = "@[url=" . $orig_post["author-link"] . "]" . $nicknameplain . "[/url]";
|
||||
$nicknameplain = "@" . $nicknameplain;
|
||||
|
||||
DI::logger()->debug('PNUT post: comparing ' . $nickname . ' and ' . $nicknameplain . ' with ' . $b["body"]);
|
||||
if ((strpos($b["body"], $nickname) === false) && (strpos($b["body"], $nicknameplain) === false)) {
|
||||
$b["body"] = $nickname . " " . $b["body"];
|
||||
}
|
||||
|
||||
DI::logger()->debug('PNUT post: parent found ' . print_r($orig_post, true));
|
||||
} elseif ($b['verb'] == 'http://activitystrea.ms/schema/1.0/like') {
|
||||
DI::logger()->debug('PNUT post: like detected');
|
||||
$islike = true;
|
||||
}
|
||||
|
||||
if (($b['verb'] == 'http://activitystrea.ms/schema/1.0/post') && $b['deleted']) {
|
||||
pnut_action($b["uid"], substr($orig_post["uri"], 6), "delete");
|
||||
return;
|
||||
}
|
||||
|
||||
if ($b['verb'] == 'http://activitystrea.ms/schema/1.0/like') {
|
||||
if ($b['deleted']) {
|
||||
pnut_action($b["uid"], substr($b["thr-parent"], 6), "unlike");
|
||||
} else {
|
||||
pnut_action($b["uid"], substr($b["thr-parent"], 6), "like");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ($b['deleted'] || ($b['created'] !== $b['edited'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$msgarr = Plaintext::getPost($b, PNUT_LIMIT, true, BBCode::EXTERNAL);
|
||||
$text = $msgarr['text'];
|
||||
$raw = [];
|
||||
|
|
@ -319,7 +404,647 @@ function pnut_post_hook(array &$b)
|
|||
}
|
||||
|
||||
$raw['io.pnut.core.crosspost'][] = ['canonical_url' => $b['plink']];
|
||||
$nut->createPost($text, ['raw' => $raw]);
|
||||
|
||||
$data = ['raw' => $raw];
|
||||
if ($iscomment) {
|
||||
$data['reply_to'] = substr($orig_post["uri"], 6);
|
||||
}
|
||||
|
||||
$nut->createPost($text, $data);
|
||||
|
||||
DI::logger()->debug('PNUT post complete', ['id' => $b['id'], 'text' => $text, 'raw' => $raw]);
|
||||
}
|
||||
|
||||
function pnut_cron($a, $b)
|
||||
{
|
||||
$last = DI::config()->get('pnut', 'last_poll');
|
||||
|
||||
$poll_interval = intval(DI::config()->get('pnut', 'poll_interval'));
|
||||
if (!$poll_interval) {
|
||||
$poll_interval = 5; // default 5 minutes
|
||||
}
|
||||
|
||||
if ($last) {
|
||||
$next = $last + ($poll_interval * 60);
|
||||
if ($next > time()) {
|
||||
DI::logger()->debug('PNUT cron: poll interval not reached');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DI::logger()->debug('PNUT cron: cron_start');
|
||||
|
||||
$abandon_days = intval(DI::config()->get('system', 'account_abandon_days', 0));
|
||||
if ($abandon_days < 1) {
|
||||
$abandon_days = 0;
|
||||
}
|
||||
|
||||
$abandon_limit = date("Y-m-d H:i:s", time() - $abandon_days * 86400);
|
||||
|
||||
$r = DI::dba()->p("SELECT * FROM `pconfig` WHERE `cat` = 'pnut' AND `k` = 'import' AND `v` = '1' ORDER BY RAND()");
|
||||
if (count($r)) {
|
||||
foreach ($r as $rr) {
|
||||
if ($abandon_days != 0) {
|
||||
$user = DI::dba()->p("SELECT `login_date` FROM `user` WHERE uid = ? AND `login_date` >= ?", $rr['uid'], $abandon_limit);
|
||||
if (!count($user)) {
|
||||
DI::logger()->debug('abandoned account: timeline from user ' . $rr['uid'] . ' will not be imported');
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
DI::logger()->debug('PNUT cron: importing timeline from user ' . $rr['uid']);
|
||||
pnut_fetchstream($rr["uid"]);
|
||||
}
|
||||
}
|
||||
|
||||
DI::logger()->debug('PNUT cron: cron_end');
|
||||
|
||||
DI::config()->set('pnut', 'last_poll', time());
|
||||
}
|
||||
|
||||
function pnut_fetchstream($uid)
|
||||
{
|
||||
$token = DI::pConfig()->get($uid, 'pnut', 'access_token');
|
||||
$nut = new phpnut\phpnut($token);
|
||||
|
||||
$r = DI::dba()->p("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = ? LIMIT 1", intval($uid));
|
||||
|
||||
if (count($r)) {
|
||||
$me = $r[0];
|
||||
} else {
|
||||
DI::logger()->debug("PNUT fetchstream: Own contact not found for user " . $uid);
|
||||
return;
|
||||
}
|
||||
|
||||
$user = DI::dba()->p("SELECT * FROM `user` WHERE `uid` = ? AND `account_expired` = 0 LIMIT 1", intval($uid));
|
||||
|
||||
if (count($user)) {
|
||||
$user = $user[0];
|
||||
} else {
|
||||
DI::logger()->debug("PNUT fetchstream: Own user not found for user " . $uid);
|
||||
return;
|
||||
}
|
||||
|
||||
$ownid = DI::pConfig()->get($uid, 'pnut', 'ownid');
|
||||
|
||||
// Fetch stream
|
||||
$param = array("count" => 200, "include_deleted" => false, "include_directed_posts" => true,
|
||||
"include_html" => false, "include_post_annotations" => true);
|
||||
|
||||
$lastid = DI::pConfig()->get($uid, 'pnut', 'laststreamid');
|
||||
|
||||
if ($lastid <> "") {
|
||||
$param["since_id"] = $lastid;
|
||||
}
|
||||
|
||||
try {
|
||||
$stream = $nut->getUserStream($param);
|
||||
} catch (phpnutException $e) {
|
||||
DI::logger()->debug("PNUT fetchstream: Error fetching stream for user " . $uid . " " . $e->getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_array($stream)) {
|
||||
$stream = array();
|
||||
}
|
||||
|
||||
$stream = array_reverse($stream);
|
||||
foreach ($stream as $post) {
|
||||
$postarray = pnut_createpost($uid, $post, $me, $user, $ownid, true);
|
||||
|
||||
$item = Item::insert($postarray);
|
||||
$postarray["id"] = $item;
|
||||
|
||||
DI::logger()->debug('PNUT fetchstream: User ' . $uid . ' posted stream item ' . $item);
|
||||
|
||||
$lastid = $post["id"];
|
||||
}
|
||||
|
||||
DI::pConfig()->set($uid, 'pnut', 'laststreamid', $lastid);
|
||||
|
||||
// Fetch mentions
|
||||
$param = array("count" => 200, "include_deleted" => false, "include_directed_posts" => true,
|
||||
"include_html" => false, "include_post_annotations" => true);
|
||||
|
||||
$lastid = DI::pConfig()->get($uid, 'pnut', 'lastmentionid');
|
||||
|
||||
if ($lastid <> "") {
|
||||
$param["since_id"] = $lastid;
|
||||
}
|
||||
|
||||
try {
|
||||
$mentions = $nut->getUserMentions("me", $param);
|
||||
} catch (phpnutException $e) {
|
||||
DI::logger()->debug("PNUT fetchstream: Error fetching mentions for user " . $uid . " " . $e->getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_array($mentions)) {
|
||||
$mentions = array();
|
||||
}
|
||||
|
||||
$mentions = array_reverse($mentions);
|
||||
foreach ($mentions as $post) {
|
||||
$postarray = pnut_createpost($uid, $post, $me, $user, $ownid, false);
|
||||
|
||||
if (isset($postarray["id"])) {
|
||||
$item = $postarray["id"];
|
||||
$parent_id = $postarray['parent'];
|
||||
} elseif (isset($postarray["body"])) {
|
||||
$item = Item::insert($postarray);
|
||||
$postarray["id"] = $item;
|
||||
|
||||
$parent_id = 0;
|
||||
DI::logger()->debug('PNUT fetchstream: User ' . $uid . ' posted mention item ' . $item);
|
||||
} else {
|
||||
$item = 0;
|
||||
$parent_id = 0;
|
||||
}
|
||||
|
||||
// Fetch the parent and id
|
||||
if (($parent_id == 0) && ($postarray['uri'] != "")) {
|
||||
$r = DI::dba()->p("SELECT `id`, `parent` FROM `item` WHERE `uri` = ? AND `uid` = ? LIMIT 1", $postarray['uri'], intval($uid));
|
||||
|
||||
if (count($r)) {
|
||||
$item = $r[0]['id'];
|
||||
$parent_id = $r[0]['parent'];
|
||||
}
|
||||
}
|
||||
|
||||
$lastid = $post["id"];
|
||||
}
|
||||
|
||||
DI::pConfig()->set($uid, 'pnut', 'lastmentionid', $lastid);
|
||||
}
|
||||
|
||||
function pnut_createpost($uid, $post, $me, $user, $ownid, $createuser, $threadcompletion = true, $nodupcheck = false)
|
||||
{
|
||||
if ($post["machine_only"]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($post["is_deleted"]) {
|
||||
return;
|
||||
}
|
||||
|
||||
$postarray = array();
|
||||
$postarray['gravity'] = 0;
|
||||
$postarray['uid'] = $uid;
|
||||
$postarray['wall'] = 0;
|
||||
$postarray['verb'] = 'http://activitystrea.ms/schema/1.0/post';
|
||||
$postarray['network'] = Protocol::PNUT; // Assuming Protocol::PNUT is defined, else use a string
|
||||
if (is_array($post["repost_of"])) {
|
||||
// You can't reply to reposts. So use the original id and thread-id
|
||||
$postarray['uri'] = "pnut::" . $post["repost_of"]["id"];
|
||||
$postarray['parent-uri'] = "pnut::" . $post["repost_of"]["thread_id"];
|
||||
} else {
|
||||
$postarray['uri'] = "pnut::" . $post["id"];
|
||||
$postarray['parent-uri'] = "pnut::" . $post["thread_id"];
|
||||
}
|
||||
|
||||
if (!$nodupcheck) {
|
||||
$r = DI::dba()->p("SELECT * FROM `item` WHERE `uri` = ? AND `uid` = ? LIMIT 1", $postarray['uri'], intval($uid));
|
||||
|
||||
if (count($r)) {
|
||||
return $r[0];
|
||||
}
|
||||
|
||||
$r = DI::dba()->p("SELECT * FROM `item` WHERE `extid` = ? AND `uid` = ? LIMIT 1", $postarray['uri'], intval($uid));
|
||||
|
||||
if (count($r)) {
|
||||
return $r[0];
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($post["reply_to"]) && ($post["reply_to"] != "")) {
|
||||
$postarray['thr-parent'] = "pnut::" . $post["reply_to"];
|
||||
|
||||
// Complete the thread (if the parent doesn't exists)
|
||||
if ($threadcompletion) {
|
||||
DI::logger()->debug("PNUT createpost: completing thread " . $post["thread_id"] . " for user " . $uid);
|
||||
|
||||
$token = DI::pConfig()->get($uid, 'pnut', 'access_token');
|
||||
$nut = new phpnut\phpnut($token);
|
||||
|
||||
$param = array("count" => 200, "include_deleted" => false, "include_directed_posts" => true,
|
||||
"include_html" => false, "include_post_annotations" => true);
|
||||
try {
|
||||
$thread = [];
|
||||
} catch (phpnutException $e) {
|
||||
DI::logger()->debug("PNUT createpost: Error fetching thread for user " . $uid . " " . $e->getMessage());
|
||||
}
|
||||
$thread = array_reverse($thread);
|
||||
|
||||
DI::logger()->debug("PNUT createpost: fetched " . count($thread) . " items for thread " . $post["thread_id"] . " for user " . $uid);
|
||||
|
||||
foreach ($thread as $tpost) {
|
||||
$threadpost = pnut_createpost($uid, $tpost, $me, $user, $ownid, false, false);
|
||||
$item = Item::insert($threadpost);
|
||||
$threadpost["id"] = $item;
|
||||
|
||||
DI::logger()->debug("PNUT createpost: stored post " . $post["id"] . " thread " . $post["thread_id"] . " in item " . $item);
|
||||
}
|
||||
}
|
||||
// Don't create accounts of people who just comment something
|
||||
$createuser = false;
|
||||
|
||||
$postarray['object-type'] = 'http://activitystrea.ms/schema/1.0/comment';
|
||||
} else {
|
||||
$postarray['thr-parent'] = $postarray['uri'];
|
||||
$postarray['object-type'] = 'http://activitystrea.ms/schema/1.0/note';
|
||||
}
|
||||
|
||||
if (($post["user"]["id"] != $ownid) || ($postarray['thr-parent'] == $postarray['uri'])) {
|
||||
$postarray['owner-name'] = $post["user"]["name"];
|
||||
$postarray['owner-link'] = $post["user"]["canonical_url"];
|
||||
$postarray['owner-avatar'] = $post["user"]["avatar_image"]["url"];
|
||||
$postarray['contact-id'] = pnut_fetchcontact($uid, $post["user"], $me, $createuser);
|
||||
} else {
|
||||
$postarray['owner-name'] = $me["name"];
|
||||
$postarray['owner-link'] = $me["url"];
|
||||
$postarray['owner-avatar'] = $me["thumb"];
|
||||
$postarray['contact-id'] = $me["id"];
|
||||
}
|
||||
|
||||
if (is_array($post["repost_of"])) {
|
||||
$postarray['author-name'] = $post["repost_of"]["user"]["name"];
|
||||
$postarray['author-link'] = $post["repost_of"]["user"]["canonical_url"];
|
||||
$postarray['author-avatar'] = $post["repost_of"]["user"]["avatar_image"]["url"];
|
||||
|
||||
$content = $post["repost_of"];
|
||||
} else {
|
||||
$postarray['author-name'] = $postarray['owner-name'];
|
||||
$postarray['author-link'] = $postarray['owner-link'];
|
||||
$postarray['author-avatar'] = $postarray['owner-avatar'];
|
||||
|
||||
$content = $post;
|
||||
}
|
||||
|
||||
$postarray['plink'] = $content["canonical_url"];
|
||||
|
||||
if (is_array($content["entities"])) {
|
||||
$converted = pnut_expand_entities($content["text"], $content["entities"]);
|
||||
$postarray['body'] = $converted["body"];
|
||||
$postarray['tag'] = $converted["tags"];
|
||||
} else {
|
||||
$postarray['body'] = $content["text"];
|
||||
}
|
||||
|
||||
if (sizeof($content["entities"]["links"])) {
|
||||
foreach ($content["entities"]["links"] as $link) {
|
||||
$url = Strings::normaliseLink($link["url"]);
|
||||
$links[$url] = $link["url"];
|
||||
}
|
||||
}
|
||||
|
||||
$page_info = "";
|
||||
|
||||
if (is_array($content["annotations"])) {
|
||||
$photo = pnut_expand_annotations($content["annotations"]);
|
||||
if (($photo["large"] != "") && ($photo["url"] != "")) {
|
||||
$page_info = "\n[url=" . $photo["url"] . "][img]" . $photo["large"] . "[/img][/url]";
|
||||
} elseif ($photo["url"] != "") {
|
||||
$page_info = "\n[img]" . $photo["url"] . "[/img]";
|
||||
}
|
||||
|
||||
if ($photo["url"] != "") {
|
||||
$postarray['object-type'] = 'http://activitystrea.ms/schema/1.0/image';
|
||||
}
|
||||
} else {
|
||||
$photo = array("url" => "", "large" => "");
|
||||
}
|
||||
|
||||
if (sizeof($links)) {
|
||||
$link = array_pop($links);
|
||||
$url = str_replace(array('/', '.'), array('\/', '\.'), $link);
|
||||
|
||||
$page_info = "";
|
||||
|
||||
if (trim($page_info) != "") {
|
||||
$removedlink = preg_replace("/\[url\=" . $url . "\](.*?)\[\/url\]/ism", '', $postarray['body']);
|
||||
if (($removedlink == "") || strstr($postarray['body'], $removedlink)) {
|
||||
$postarray['body'] = $removedlink;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$postarray['body'] .= $page_info;
|
||||
|
||||
$postarray['created'] = (new DateTime($post["created_at"]))->format(DateTime::ATOM);
|
||||
$postarray['edited'] = (new DateTime($post["created_at"]))->format(DateTime::ATOM);
|
||||
|
||||
$postarray['app'] = $post["source"]["name"];
|
||||
|
||||
return $postarray;
|
||||
}
|
||||
|
||||
function pnut_expand_entities($body, $entities)
|
||||
{
|
||||
if (!function_exists('substr_unicode')) {
|
||||
function substr_unicode($str, $s, $l = null) {
|
||||
return join("", array_slice(
|
||||
preg_split("//u", $str, -1, PREG_SPLIT_NO_EMPTY), $s, $l));
|
||||
}
|
||||
}
|
||||
|
||||
$tags_arr = array();
|
||||
$replace = array();
|
||||
|
||||
foreach ($entities["mentions"] as $mention) {
|
||||
$url = "@[url=https://pnut.io/" . rawurlencode($mention["name"]) . "]" . $mention["name"] . "[/url]";
|
||||
$tags_arr["@" . $mention["name"]] = $url;
|
||||
$replace[$mention["pos"]] = array("pos" => $mention["pos"], "len" => $mention["len"], "replace" => $url);
|
||||
}
|
||||
|
||||
foreach ($entities["hashtags"] as $hashtag) {
|
||||
$url = "#[url=" . DI::baseUrl() . "/search?tag=" . rawurlencode($hashtag["name"]) . "]" . $hashtag["name"] . "[/url]";
|
||||
$tags_arr["#" . $hashtag["name"]] = $url;
|
||||
$replace[$hashtag["pos"]] = array("pos" => $hashtag["pos"], "len" => $hashtag["len"], "replace" => $url);
|
||||
}
|
||||
|
||||
foreach ($entities["links"] as $links) {
|
||||
$url = "[url=" . $links["url"] . "]" . $links["text"] . "[/url]";
|
||||
if (isset($links["amended_len"]) && ($links["amended_len"] > $links["len"])) {
|
||||
$replace[$links["pos"]] = array("pos" => $links["pos"], "len" => $links["amended_len"], "replace" => $url);
|
||||
} else {
|
||||
$replace[$links["pos"]] = array("pos" => $links["pos"], "len" => $links["len"], "replace" => $url);
|
||||
}
|
||||
}
|
||||
|
||||
if (sizeof($replace)) {
|
||||
krsort($replace);
|
||||
foreach ($replace as $entity) {
|
||||
$pre = substr_unicode($body, 0, $entity["pos"]);
|
||||
$post = substr_unicode($body, $entity["pos"] + $entity["len"]);
|
||||
$body = $pre . $entity["replace"] . $post;
|
||||
}
|
||||
}
|
||||
|
||||
return array("body" => $body, "tags" => implode(",", $tags_arr));
|
||||
}
|
||||
|
||||
function pnut_expand_annotations($annotations)
|
||||
{
|
||||
$photo = array("url" => "", "large" => "");
|
||||
foreach ($annotations as $annotation) {
|
||||
if (($annotation["type"] == "io.pnut.core.oembed") &&
|
||||
($annotation["value"]["type"] == "photo")) {
|
||||
if ($annotation["value"]["url"] != "") {
|
||||
$photo["url"] = $annotation["value"]["url"];
|
||||
}
|
||||
|
||||
if ($annotation["value"]["thumbnail_large_url"] != "") {
|
||||
$photo["large"] = $annotation["value"]["thumbnail_large_url"];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $photo;
|
||||
}
|
||||
|
||||
function pnut_action($uid, $post_id, $action)
|
||||
{
|
||||
// TODO: Implement pnut action API call
|
||||
DI::logger()->info('PNUT action', ['uid' => $uid, 'post_id' => $post_id, 'action' => $action]);
|
||||
}
|
||||
|
||||
function pnut_fetchcontact($uid, $contact, $me, $create_user)
|
||||
{
|
||||
$r = DI::dba()->p("SELECT * FROM `contact` WHERE `uid` = ? AND `alias` = ? LIMIT 1", intval($uid), "pnut::" . $contact["id"]);
|
||||
|
||||
if (!count($r) && !$create_user) {
|
||||
return $me["id"];
|
||||
}
|
||||
|
||||
if ($contact["canonical_url"] == "") {
|
||||
return $me["id"];
|
||||
}
|
||||
|
||||
if (count($r) && ($r[0]["readonly"] || $r[0]["blocked"])) {
|
||||
DI::logger()->debug("PNUT fetchcontact: Contact '" . $r[0]["nick"] . "' is blocked or readonly.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!count($r)) {
|
||||
|
||||
if ($contact["name"] == "") {
|
||||
$contact["name"] = $contact["username"];
|
||||
}
|
||||
|
||||
if ($contact["username"] == "") {
|
||||
$contact["username"] = $contact["name"];
|
||||
}
|
||||
|
||||
// create contact record
|
||||
DI::dba()->p("INSERT INTO `contact` (`uid`, `created`, `url`, `nurl`, `addr`, `alias`, `notify`, `poll`,
|
||||
`name`, `nick`, `photo`, `network`, `rel`, `priority`,
|
||||
`about`, `writable`, `blocked`, `readonly`, `pending` )
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, 0, 0 )",
|
||||
intval($uid),
|
||||
new DateTime('now', new DateTimeZone('UTC')),
|
||||
$contact["canonical_url"],
|
||||
Strings::normaliseLink($contact["canonical_url"]),
|
||||
$contact["username"] . "@pnut.io",
|
||||
"pnut::" . $contact["id"],
|
||||
'',
|
||||
"pnut::" . $contact["id"],
|
||||
$contact["name"],
|
||||
$contact["username"],
|
||||
$contact["avatar_image"]["url"],
|
||||
Protocol::PNUT,
|
||||
intval(Contact::SHARING),
|
||||
intval(1),
|
||||
$contact["description"]["text"],
|
||||
intval(1)
|
||||
);
|
||||
|
||||
$r = DI::dba()->p("SELECT * FROM `contact` WHERE `alias` = ? AND `uid` = ? LIMIT 1",
|
||||
"pnut::" . $contact["id"], intval($uid));
|
||||
|
||||
if (!count($r)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$contact_id = $r[0]['id'];
|
||||
|
||||
$g = DI::dba()->p("SELECT def_gid FROM user WHERE uid = ? LIMIT 1", intval($uid));
|
||||
|
||||
if ($g && intval($g[0]['def_gid'])) {
|
||||
require_once('include/group.php');
|
||||
Circle::addMember($uid, '', $contact_id, $g[0]['def_gid']);
|
||||
}
|
||||
|
||||
$photos = Photo::importProfilePhoto($contact["avatar_image"]["url"], $uid, $contact_id);
|
||||
|
||||
DI::dba()->p("UPDATE `contact` SET `photo` = ?, `thumb` = ?, `micro` = ?,
|
||||
`name-date` = ?, `uri-date` = ?, `avatar-date` = ? WHERE `id` = ?",
|
||||
$photos[0],
|
||||
$photos[1],
|
||||
$photos[2],
|
||||
new DateTime('now', new DateTimeZone('UTC')),
|
||||
new DateTime('now', new DateTimeZone('UTC')),
|
||||
new DateTime('now', new DateTimeZone('UTC')),
|
||||
intval($contact_id)
|
||||
);
|
||||
} else {
|
||||
// update profile photos once every two weeks as we have no notification of when they change.
|
||||
|
||||
$update_photo = ($r[0]['avatar-date'] < (new DateTime('now', new DateTimeZone('UTC')))->modify('-12 hours'));
|
||||
|
||||
// check that we have all the photos, this has been known to fail on occasion
|
||||
|
||||
if ((!$r[0]['photo']) || (!$r[0]['thumb']) || (!$r[0]['micro']) || ($update_photo)) {
|
||||
|
||||
DI::logger()->debug("PNUT fetchcontact: Updating contact " . $contact["username"]);
|
||||
|
||||
$photos = Photo::importProfilePhoto($contact["avatar_image"]["url"], $uid, $r[0]['id']);
|
||||
|
||||
DI::dba()->p("UPDATE `contact` SET `photo` = ?, `thumb` = ?, `micro` = ?,
|
||||
`name-date` = ?, `uri-date` = ?, `avatar-date` = ?,
|
||||
`url` = ?, `nurl` = ?, `addr` = ?, `name` = ?, `nick` = ?, `about` = ? WHERE `id` = ?",
|
||||
$photos[0],
|
||||
$photos[1],
|
||||
$photos[2],
|
||||
new DateTime('now', new DateTimeZone('UTC')),
|
||||
new DateTime('now', new DateTimeZone('UTC')),
|
||||
new DateTime('now', new DateTimeZone('UTC')),
|
||||
$contact["canonical_url"],
|
||||
Strings::normaliseLink($contact["canonical_url"]),
|
||||
$contact["username"] . "@pnut.io",
|
||||
$contact["name"],
|
||||
$contact["username"],
|
||||
$contact["description"]["text"],
|
||||
intval($r[0]['id'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $r[0]["id"];
|
||||
}
|
||||
|
||||
function pnut_prepare_body($a, &$b)
|
||||
{
|
||||
if ($b["item"]["network"] != Protocol::PNUT) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($b["preview"]) {
|
||||
$max_char = 256;
|
||||
require_once("include/plaintext.php");
|
||||
$item = $b["item"];
|
||||
$item["plink"] = DI::baseUrl() . "/display/" . $a->user["nickname"] . "/" . $item["parent"];
|
||||
|
||||
$r = DI::dba()->p("SELECT `author-link` FROM item WHERE item.uri = ? AND item.uid = ? LIMIT 1",
|
||||
$item["thr-parent"], intval(DI::userSession()->getLocalUserId()));
|
||||
|
||||
if (count($r)) {
|
||||
$orig_post = $r[0];
|
||||
|
||||
$nicknameplain = preg_replace("=https?://pnut.io/(.*)=ism", "$1", $orig_post["author-link"]);
|
||||
$nickname = "@[url=" . $orig_post["author-link"] . "]" . $nicknameplain . "[/url]";
|
||||
$nicknameplain = "@" . $nicknameplain;
|
||||
|
||||
if ((strpos($item["body"], $nickname) === false) && (strpos($item["body"], $nicknameplain) === false)) {
|
||||
$item["body"] = $nickname . " " . $item["body"];
|
||||
}
|
||||
}
|
||||
|
||||
$msgarr = Plaintext::getPost($a, $item, $max_char, true);
|
||||
$msg = pnut_create_entities($a, $item, $msgarr);
|
||||
|
||||
$msg = Markdown::convert($msg);
|
||||
|
||||
$b['html'] = $msg;
|
||||
}
|
||||
}
|
||||
|
||||
function pnut_create_entities($a, $b, $postdata)
|
||||
{
|
||||
require_once("include/bbcode.php");
|
||||
require_once("include/plaintext.php");
|
||||
|
||||
$bbcode = $b["body"];
|
||||
$bbcode = BBCode::removeShareInformation($bbcode, false, true);
|
||||
|
||||
// Change pure links in text to bbcode uris
|
||||
$bbcode = preg_replace("/([^\]\='".'"'."]|^)(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,]+)/ism", '$1[url=$2]$2[/url]', $bbcode);
|
||||
|
||||
$URLSearchString = "^\[\]";
|
||||
|
||||
$bbcode = preg_replace("/#\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism",'#$2',$bbcode);
|
||||
$bbcode = preg_replace("/@\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism",'@$2',$bbcode);
|
||||
$bbcode = preg_replace("/\[bookmark\=([$URLSearchString]*)\](.*?)\[\/bookmark\]/ism",'[url=$1]$2[/url]',$bbcode);
|
||||
$bbcode = preg_replace("/\[video\](.*?)\[\/video\]/ism",'[url=$1]$1[/url]',$bbcode);
|
||||
$bbcode = preg_replace("/\[youtube\]https?:\/\/(.*?)\[\/youtube\]/ism",'[url=https://$1]https://$1[/url]',$bbcode);
|
||||
$bbcode = preg_replace("/\[youtube\]([A-Za-z0-9\-_=]+)(.*?)\[\/youtube\]/ism",
|
||||
'[url=https://www.youtube.com/watch?v=$1]https://www.youtube.com/watch?v=$1[/url]', $bbcode);
|
||||
$bbcode = preg_replace("/\[vimeo\]https?:\/\/(.*?)\[\/vimeo\]/ism",'[url=https://$1]https://$1[/url]',$bbcode);
|
||||
$bbcode = preg_replace("/\[vimeo\]([0-9]+)(.*?)\[\/vimeo\]/ism",
|
||||
'[url=https://vimeo.com/$1]https://vimeo.com/$1[/url]', $bbcode);
|
||||
$bbcode = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '[img]$3[/img]', $bbcode);
|
||||
|
||||
preg_match_all("/\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", $bbcode, $urls, PREG_SET_ORDER);
|
||||
|
||||
$bbcode = preg_replace("/\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism",'$1',$bbcode);
|
||||
|
||||
$b["body"] = $bbcode;
|
||||
|
||||
$plaintext = Plaintext::getPost($a, $b, 0, false, 6);
|
||||
|
||||
$text = $plaintext["text"];
|
||||
|
||||
$start = 0;
|
||||
$entities = array();
|
||||
|
||||
foreach ($urls as $url) {
|
||||
$lenurl = iconv_strlen($url[1], "UTF-8");
|
||||
$len = iconv_strlen($url[2], "UTF-8");
|
||||
$pos = iconv_strpos($text, $url[1], $start, "UTF-8");
|
||||
$pre = iconv_substr($text, 0, $pos, "UTF-8");
|
||||
$post = iconv_substr($text, $pos + $lenurl, 1000000, "UTF-8");
|
||||
|
||||
$mid = $url[2];
|
||||
$html = BBCode::convert($mid, false, false, 6);
|
||||
$mid = HTML::toPlaintext($html, 0, true);
|
||||
|
||||
$mid = trim(html_entity_decode($mid, ENT_QUOTES, 'UTF-8'));
|
||||
|
||||
$text = $pre . $mid . $post;
|
||||
|
||||
if ($mid != "") {
|
||||
$entities[] = array("pos" => $pos, "len" => $len, "url" => $url[1], "text" => $mid);
|
||||
}
|
||||
|
||||
$start = $pos + 1;
|
||||
}
|
||||
|
||||
if (isset($postdata["url"]) && isset($postdata["title"]) && ($postdata["type"] != "photo")) {
|
||||
$postdata["title"] = Plaintext::shorten($postdata["title"], 90);
|
||||
$max = 256 - strlen($postdata["title"]);
|
||||
$text = Plaintext::shorten($text, $max);
|
||||
$text .= "\n[" . $postdata["title"] . "](" . $postdata["url"] . ")";
|
||||
} elseif (isset($postdata["url"]) && ($postdata["type"] != "photo")) {
|
||||
$postdata["url"] = Strings::normaliseLink($postdata["url"]);
|
||||
$max = 240;
|
||||
$text = Plaintext::shorten($text, $max);
|
||||
$text .= " [" . $postdata["url"] . "](" . $postdata["url"] . ")";
|
||||
} else {
|
||||
$max = 256;
|
||||
$text = Plaintext::shorten($text, $max);
|
||||
}
|
||||
|
||||
if (iconv_strlen($text, "UTF-8") < $max) {
|
||||
$max = iconv_strlen($text, "UTF-8");
|
||||
}
|
||||
|
||||
krsort($entities);
|
||||
foreach ($entities as $entity) {
|
||||
if (($entity["pos"] + $entity["len"]) <= $max) {
|
||||
$pre = iconv_substr($text, 0, $entity["pos"], "UTF-8");
|
||||
$post = iconv_substr($text, $entity["pos"] + $entity["len"], 1000000, "UTF-8");
|
||||
|
||||
$text = $pre . "[" . $entity["text"] . "](" . $entity["url"] . ")" . $post;
|
||||
}
|
||||
}
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<p>{{$status}}</p>
|
||||
{{include file="field_checkbox.tpl" field=$enable}}
|
||||
{{include file="field_checkbox.tpl" field=$bydefault}}
|
||||
{{include file="field_checkbox.tpl" field=$import}}
|
||||
{{if $user_client}}
|
||||
{{include file="field_input.tpl" field=$client_id}}
|
||||
{{include file="field_input.tpl" field=$client_secret}}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue