Resructured code, added documentation

This commit is contained in:
Michael 2023-04-23 10:26:19 +00:00
parent 9e7f06ed44
commit da65314df5
2 changed files with 263 additions and 179 deletions

View File

@ -141,6 +141,13 @@ class TumblrOAuth
return ''; return '';
} }
/**
* OAuth get from a given url with given parameters
*
* @param string $url
* @param array $parameters
* @return stdClass
*/
public function get(string $url, array $parameters = []): stdClass public function get(string $url, array $parameters = []): stdClass
{ {
if (!empty($parameters)) { if (!empty($parameters)) {
@ -157,6 +164,13 @@ class TumblrOAuth
return $this->formatResponse($response); return $this->formatResponse($response);
} }
/**
* OAuth Post to a given url with given parameters
*
* @param string $url
* @param array $parameter
* @return stdClass
*/
public function post(string $url, array $parameter): stdClass public function post(string $url, array $parameter): stdClass
{ {
try { try {
@ -169,6 +183,12 @@ class TumblrOAuth
return $this->formatResponse($response); return $this->formatResponse($response);
} }
/**
* Convert the body in the given response to a class
*
* @param ResponseInterface|null $response
* @return stdClass
*/
private function formatResponse(ResponseInterface $response = null): stdClass private function formatResponse(ResponseInterface $response = null): stdClass
{ {
if (!is_null($response)) { if (!is_null($response)) {

View File

@ -264,6 +264,50 @@ function tumblr_settings_post(array &$b)
} }
} }
function tumblr_cron()
{
$last = DI::keyValue()->get('tumblr_last_poll');
$poll_interval = intval(DI::config()->get('tumblr', 'poll_interval'));
if (!$poll_interval) {
$poll_interval = TUMBLR_DEFAULT_POLL_INTERVAL;
}
if ($last) {
$next = $last + ($poll_interval * 60);
if ($next > time()) {
Logger::notice('poll intervall not reached');
return;
}
}
Logger::notice('cron_start');
$abandon_days = intval(DI::config()->get('system', 'account_abandon_days'));
if ($abandon_days < 1) {
$abandon_days = 0;
}
$abandon_limit = date(DateTimeFormat::MYSQL, time() - $abandon_days * 86400);
$pconfigs = DBA::selectToArray('pconfig', [], ['cat' => 'tumblr', 'k' => 'import', 'v' => true]);
foreach ($pconfigs as $pconfig) {
if ($abandon_days != 0) {
if (!DBA::exists('user', ["`uid` = ? AND `login_date` >= ?", $pconfig['uid'], $abandon_limit])) {
Logger::notice('abandoned account: timeline from user will not be imported', ['user' => $pconfig['uid']]);
continue;
}
}
Logger::notice('importing timeline - start', ['user' => $pconfig['uid']]);
tumblr_fetch_dashboard($pconfig['uid']);
Logger::notice('importing timeline - done', ['user' => $pconfig['uid']]);
}
Logger::notice('cron_end');
DI::keyValue()->set('tumblr_last_poll', time());
}
function tumblr_hook_fork(array &$b) function tumblr_hook_fork(array &$b)
{ {
if ($b['name'] != 'notifier_normal') { if ($b['name'] != 'notifier_normal') {
@ -388,10 +432,13 @@ function tumblr_send(array &$b)
return; return;
} }
if (tumblr_send_npf($b)) { if (!tumblr_send_npf($b)) {
return; tumblr_send_legacy($b);
} }
}
function tumblr_send_legacy(array $b)
{
$connection = tumblr_connection($b['uid']); $connection = tumblr_connection($b['uid']);
if (empty($connection)) { if (empty($connection)) {
return; return;
@ -472,27 +519,11 @@ function tumblr_send(array &$b)
if ($result->meta->status < 400) { if ($result->meta->status < 400) {
Logger::info('Success (legacy)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response]); Logger::info('Success (legacy)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response]);
return true;
} else { } else {
Logger::notice('Error posting blog (legacy)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'params' => $params]); Logger::notice('Error posting blog (legacy)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response, 'errors' => $result->errors, 'params' => $params]);
return false;
} }
} }
function tumblr_get_post_from_uri(string $uri): array
{
$parts = explode(':', $uri);
if (($parts[0] != 'tumblr') || empty($parts[2])) {
return [];
}
$post ['id'] = $parts[2];
$post['reblog_key'] = $parts[3] ?? '';
$post['reblog_key'] = str_replace('@t', '', $post['reblog_key']); // Temp
return $post;
}
function tumblr_send_npf(array $post): bool function tumblr_send_npf(array $post): bool
{ {
$page = tumblr_get_page($post['uid']); $page = tumblr_get_page($post['uid']);
@ -529,156 +560,26 @@ function tumblr_send_npf(array $post): bool
} }
} }
function tumblr_cron() function tumblr_get_post_from_uri(string $uri): array
{ {
$last = DI::keyValue()->get('tumblr_last_poll'); $parts = explode(':', $uri);
if (($parts[0] != 'tumblr') || empty($parts[2])) {
$poll_interval = intval(DI::config()->get('tumblr', 'poll_interval'));
if (!$poll_interval) {
$poll_interval = TUMBLR_DEFAULT_POLL_INTERVAL;
}
if ($last) {
$next = $last + ($poll_interval * 60);
if ($next > time()) {
Logger::notice('poll intervall not reached');
return;
}
}
Logger::notice('cron_start');
$abandon_days = intval(DI::config()->get('system', 'account_abandon_days'));
if ($abandon_days < 1) {
$abandon_days = 0;
}
$abandon_limit = date(DateTimeFormat::MYSQL, time() - $abandon_days * 86400);
$pconfigs = DBA::selectToArray('pconfig', [], ['cat' => 'tumblr', 'k' => 'import', 'v' => true]);
foreach ($pconfigs as $pconfig) {
if ($abandon_days != 0) {
if (!DBA::exists('user', ["`uid` = ? AND `login_date` >= ?", $pconfig['uid'], $abandon_limit])) {
Logger::notice('abandoned account: timeline from user will not be imported', ['user' => $pconfig['uid']]);
continue;
}
}
Logger::notice('importing timeline - start', ['user' => $pconfig['uid']]);
tumblr_fetch_dashboard($pconfig['uid']);
Logger::notice('importing timeline - done', ['user' => $pconfig['uid']]);
}
Logger::notice('cron_end');
DI::keyValue()->set('tumblr_last_poll', time());
}
function tumblr_add_npf_data(string $html, string $plink): string
{
$doc = new DOMDocument();
$doc->formatOutput = true;
@$doc->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
$xpath = new DomXPath($doc);
$list = $xpath->query('//p[@class="npf_link"]');
foreach ($list as $node) {
$data = tumblr_get_npf_data($node);
if (empty($data)) {
continue;
}
tumblr_replace_with_npf($doc, $node, tumblr_get_type_replacement($data, $plink));
}
$list = $xpath->query('//div[@data-npf]');
foreach ($list as $node) {
$data = tumblr_get_npf_data($node);
if (empty($data)) {
continue;
}
tumblr_replace_with_npf($doc, $node, tumblr_get_type_replacement($data, $plink));
}
$list = $xpath->query('//figure[@data-provider="youtube"]');
foreach ($list as $node) {
$attributes = tumblr_get_attributes($node);
if (empty($attributes['data-url'])) {
continue;
}
tumblr_replace_with_npf($doc, $node, '[youtube]' . $attributes['data-url'] . '[/youtube]');
}
$list = $xpath->query('//figure[@data-npf]');
foreach ($list as $node) {
$data = tumblr_get_npf_data($node);
if (empty($data)) {
continue;
}
tumblr_replace_with_npf($doc, $node, tumblr_get_type_replacement($data, $plink));
}
return $doc->saveHTML();
}
function tumblr_get_type_replacement(array $data, string $plink): string
{
switch ($data['type']) {
case 'poll':
$body = '[p][url=' . $plink. ']'. $data['question'] . '[/url][/p][ul]';
foreach ($data['answers'] as $answer) {
$body .= '[li]' . $answer['answer_text'] . '[/li]';
}
$body .= '[/ul]';
break;
case 'link':
$body = PageInfo::getFooterFromUrl(str_replace('https://href.li/?', '', $data['url']));
break;
case 'video':
if (!empty($data['url']) && ($data['provider'] == 'tumblr')) {
$body = '[video]' . $data['url'] . '[/video]';
break;
}
default:
Logger::notice('Unknown type', ['type' => $data['type'], 'data' => $data, 'plink' => $plink]);
$body = '';
}
return $body;
}
function tumblr_get_attributes($node): array
{
$attributes = [];
foreach ($node->attributes as $key => $attribute) {
$attributes[$key] = trim($attribute->value);
}
return $attributes;
}
function tumblr_get_npf_data(DOMNode $node): array
{
$attributes = tumblr_get_attributes($node);
if (empty($attributes['data-npf'])) {
return []; return [];
} }
$post ['id'] = $parts[2];
$post['reblog_key'] = $parts[3] ?? '';
return json_decode($attributes['data-npf'], true); $post['reblog_key'] = str_replace('@t', '', $post['reblog_key']); // Temp
} return $post;
function tumblr_replace_with_npf(DOMDocument $doc, DOMNode $node, string $replacement)
{
if (empty($replacement)) {
return;
}
$replace = $doc->createTextNode($replacement);
$node->parentNode->insertBefore($replace, $node);
$node->parentNode->removeChild($node);
} }
/**
* Fetch the dashboard (timeline) for the given user
*
* @param integer $uid
* @return void
*/
function tumblr_fetch_dashboard(int $uid) function tumblr_fetch_dashboard(int $uid)
{ {
$page = tumblr_get_page($uid); $page = tumblr_get_page($uid);
@ -735,6 +636,14 @@ function tumblr_fetch_dashboard(int $uid)
} }
} }
/**
* Sets the initial data for the item array
*
* @param stdClass $post
* @param string $uri
* @param integer $uid
* @return array
*/
function tumblr_get_header(stdClass $post, string $uri, int $uid): array function tumblr_get_header(stdClass $post, string $uri, int $uid): array
{ {
$contact = tumblr_get_contact($post->blog, $uid); $contact = tumblr_get_contact($post->blog, $uid);
@ -760,6 +669,13 @@ function tumblr_get_header(stdClass $post, string $uri, int $uid): array
return $item; return $item;
} }
/**
* Set the body according the given content type
*
* @param array $item
* @param stdClass $post
* @return array
*/
function tumblr_get_content(array $item, stdClass $post): array function tumblr_get_content(array $item, stdClass $post): array
{ {
switch ($post->type) { switch ($post->type) {
@ -846,7 +762,120 @@ function tumblr_get_content(array $item, stdClass $post): array
return $item; return $item;
} }
function tumblr_get_contact(stdClass $blog, int $uid) function tumblr_add_npf_data(string $html, string $plink): string
{
$doc = new DOMDocument();
$doc->formatOutput = true;
@$doc->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
$xpath = new DomXPath($doc);
$list = $xpath->query('//p[@class="npf_link"]');
foreach ($list as $node) {
$data = tumblr_get_npf_data($node);
if (empty($data)) {
continue;
}
tumblr_replace_with_npf($doc, $node, tumblr_get_type_replacement($data, $plink));
}
$list = $xpath->query('//div[@data-npf]');
foreach ($list as $node) {
$data = tumblr_get_npf_data($node);
if (empty($data)) {
continue;
}
tumblr_replace_with_npf($doc, $node, tumblr_get_type_replacement($data, $plink));
}
$list = $xpath->query('//figure[@data-provider="youtube"]');
foreach ($list as $node) {
$attributes = tumblr_get_attributes($node);
if (empty($attributes['data-url'])) {
continue;
}
tumblr_replace_with_npf($doc, $node, '[youtube]' . $attributes['data-url'] . '[/youtube]');
}
$list = $xpath->query('//figure[@data-npf]');
foreach ($list as $node) {
$data = tumblr_get_npf_data($node);
if (empty($data)) {
continue;
}
tumblr_replace_with_npf($doc, $node, tumblr_get_type_replacement($data, $plink));
}
return $doc->saveHTML();
}
function tumblr_replace_with_npf(DOMDocument $doc, DOMNode $node, string $replacement)
{
if (empty($replacement)) {
return;
}
$replace = $doc->createTextNode($replacement);
$node->parentNode->insertBefore($replace, $node);
$node->parentNode->removeChild($node);
}
function tumblr_get_npf_data(DOMNode $node): array
{
$attributes = tumblr_get_attributes($node);
if (empty($attributes['data-npf'])) {
return [];
}
return json_decode($attributes['data-npf'], true);
}
function tumblr_get_attributes($node): array
{
$attributes = [];
foreach ($node->attributes as $key => $attribute) {
$attributes[$key] = trim($attribute->value);
}
return $attributes;
}
function tumblr_get_type_replacement(array $data, string $plink): string
{
switch ($data['type']) {
case 'poll':
$body = '[p][url=' . $plink. ']'. $data['question'] . '[/url][/p][ul]';
foreach ($data['answers'] as $answer) {
$body .= '[li]' . $answer['answer_text'] . '[/li]';
}
$body .= '[/ul]';
break;
case 'link':
$body = PageInfo::getFooterFromUrl(str_replace('https://href.li/?', '', $data['url']));
break;
case 'video':
if (!empty($data['url']) && ($data['provider'] == 'tumblr')) {
$body = '[video]' . $data['url'] . '[/video]';
break;
}
default:
Logger::notice('Unknown type', ['type' => $data['type'], 'data' => $data, 'plink' => $plink]);
$body = '';
}
return $body;
}
/**
* Get a contact array for the given blog
*
* @param stdClass $blog
* @param integer $uid
* @return array
*/
function tumblr_get_contact(stdClass $blog, int $uid): array
{ {
$condition = ['network' => Protocol::TUMBLR, 'uid' => $uid, 'poll' => 'tumblr::' . $blog->uuid]; $condition = ['network' => Protocol::TUMBLR, 'uid' => $uid, 'poll' => 'tumblr::' . $blog->uuid];
$contact = Contact::selectFirst([], $condition); $contact = Contact::selectFirst([], $condition);
@ -873,6 +902,13 @@ function tumblr_get_contact(stdClass $blog, int $uid)
return Contact::getById($cid); return Contact::getById($cid);
} }
/**
* Create a new contact
*
* @param stdClass $blog
* @param integer $uid
* @return void
*/
function tumblr_insert_contact(stdClass $blog, int $uid) function tumblr_insert_contact(stdClass $blog, int $uid)
{ {
$baseurl = 'https://tumblr.com'; $baseurl = 'https://tumblr.com';
@ -900,6 +936,15 @@ function tumblr_insert_contact(stdClass $blog, int $uid)
return Contact::insert($fields); return Contact::insert($fields);
} }
/**
* Updates the given contact for the given user and proviced contact ids
*
* @param stdClass $blog
* @param integer $uid
* @param integer $cid
* @param integer $pcid
* @return void
*/
function tumblr_update_contact(stdClass $blog, int $uid, int $cid, int $pcid) function tumblr_update_contact(stdClass $blog, int $uid, int $cid, int $pcid)
{ {
$connection = tumblr_connection($uid); $connection = tumblr_connection($uid);
@ -948,22 +993,13 @@ function tumblr_update_contact(stdClass $blog, int $uid, int $cid, int $pcid)
Contact::update($fields, ['id' => $pcid]); Contact::update($fields, ['id' => $pcid]);
} }
function tumblr_connection(int $uid): ?TumblrOAuth /**
{ * Get the default page for posting. Detects the value if not provided or has got a bad value.
$oauth_token = DI::pConfig()->get($uid, 'tumblr', 'oauth_token'); *
$oauth_token_secret = DI::pConfig()->get($uid, 'tumblr', 'oauth_token_secret'); * @param integer $uid
* @param array $blogs
$consumer_key = DI::config()->get('tumblr', 'consumer_key'); * @return string
$consumer_secret = DI::config()->get('tumblr', 'consumer_secret'); */
if (!$consumer_key || !$consumer_secret || !$oauth_token || !$oauth_token_secret) {
Logger::notice('Missing data, connection is not established', ['uid' => $uid]);
return null;
}
return new TumblrOAuth($consumer_key, $consumer_secret, $oauth_token, $oauth_token_secret);
}
function tumblr_get_page(int $uid, array $blogs = []): string function tumblr_get_page(int $uid, array $blogs = []): string
{ {
$page = DI::pConfig()->get($uid, 'tumblr', 'page'); $page = DI::pConfig()->get($uid, 'tumblr', 'page');
@ -985,6 +1021,12 @@ function tumblr_get_page(int $uid, array $blogs = []): string
return ''; return '';
} }
/**
* Get an array of blogs for the given user
*
* @param integer $uid
* @return array
*/
function tumblr_get_blogs(int $uid): array function tumblr_get_blogs(int $uid): array
{ {
$connection = tumblr_connection($uid); $connection = tumblr_connection($uid);
@ -1003,4 +1045,26 @@ function tumblr_get_blogs(int $uid): array
$blogs[$blog->uuid] = $blog->name; $blogs[$blog->uuid] = $blog->name;
} }
return $blogs; return $blogs;
}
/**
* Creates a OAuth connection for the given user
*
* @param integer $uid
* @return TumblrOAuth|null
*/
function tumblr_connection(int $uid): ?TumblrOAuth
{
$oauth_token = DI::pConfig()->get($uid, 'tumblr', 'oauth_token');
$oauth_token_secret = DI::pConfig()->get($uid, 'tumblr', 'oauth_token_secret');
$consumer_key = DI::config()->get('tumblr', 'consumer_key');
$consumer_secret = DI::config()->get('tumblr', 'consumer_secret');
if (!$consumer_key || !$consumer_secret || !$oauth_token || !$oauth_token_secret) {
Logger::notice('Missing data, connection is not established', ['uid' => $uid]);
return null;
}
return new TumblrOAuth($consumer_key, $consumer_secret, $oauth_token, $oauth_token_secret);
} }