Resructured code, added documentation

pull/1372/head
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 '';
}
/**
* 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
{
if (!empty($parameters)) {
@ -157,6 +164,13 @@ class TumblrOAuth
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
{
try {
@ -169,6 +183,12 @@ class TumblrOAuth
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
{
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)
{
if ($b['name'] != 'notifier_normal') {
@ -388,10 +432,13 @@ function tumblr_send(array &$b)
return;
}
if (tumblr_send_npf($b)) {
return;
if (!tumblr_send_npf($b)) {
tumblr_send_legacy($b);
}
}
function tumblr_send_legacy(array $b)
{
$connection = tumblr_connection($b['uid']);
if (empty($connection)) {
return;
@ -472,27 +519,11 @@ function tumblr_send(array &$b)
if ($result->meta->status < 400) {
Logger::info('Success (legacy)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response]);
return true;
} else {
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
{
$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');
$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'])) {
$parts = explode(':', $uri);
if (($parts[0] != 'tumblr') || empty($parts[2])) {
return [];
}
$post ['id'] = $parts[2];
$post['reblog_key'] = $parts[3] ?? '';
return json_decode($attributes['data-npf'], true);
}
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);
$post['reblog_key'] = str_replace('@t', '', $post['reblog_key']); // Temp
return $post;
}
/**
* Fetch the dashboard (timeline) for the given user
*
* @param integer $uid
* @return void
*/
function tumblr_fetch_dashboard(int $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
{
$contact = tumblr_get_contact($post->blog, $uid);
@ -760,6 +669,13 @@ function tumblr_get_header(stdClass $post, string $uri, int $uid): array
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
{
switch ($post->type) {
@ -846,7 +762,120 @@ function tumblr_get_content(array $item, stdClass $post): array
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];
$contact = Contact::selectFirst([], $condition);
@ -873,6 +902,13 @@ function tumblr_get_contact(stdClass $blog, int $uid)
return Contact::getById($cid);
}
/**
* Create a new contact
*
* @param stdClass $blog
* @param integer $uid
* @return void
*/
function tumblr_insert_contact(stdClass $blog, int $uid)
{
$baseurl = 'https://tumblr.com';
@ -900,6 +936,15 @@ function tumblr_insert_contact(stdClass $blog, int $uid)
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)
{
$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]);
}
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);
}
/**
* Get the default page for posting. Detects the value if not provided or has got a bad value.
*
* @param integer $uid
* @param array $blogs
* @return string
*/
function tumblr_get_page(int $uid, array $blogs = []): string
{
$page = DI::pConfig()->get($uid, 'tumblr', 'page');
@ -985,6 +1021,12 @@ function tumblr_get_page(int $uid, array $blogs = []): string
return '';
}
/**
* Get an array of blogs for the given user
*
* @param integer $uid
* @return array
*/
function tumblr_get_blogs(int $uid): array
{
$connection = tumblr_connection($uid);
@ -1003,4 +1045,26 @@ function tumblr_get_blogs(int $uid): array
$blogs[$blog->uuid] = $blog->name;
}
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);
}