Compare commits
52 commits
2024.06-rc
...
2024.09-rc
Author | SHA1 | Date | |
---|---|---|---|
Tobias Diekershoff | fca2d609c9 | ||
Michael | 8b694fbb4c | ||
Tobias Diekershoff | 5a9dafec70 | ||
Michael | 586ebe9699 | ||
Tobias Diekershoff | 10bd219bd1 | ||
Michael | 08c17c9dd4 | ||
Tobias Diekershoff | feb7722f72 | ||
Michael | f8f63532f4 | ||
Tobias Diekershoff | ef37aa60e3 | ||
Michael | 6f3ba10466 | ||
Tobias Diekershoff | 778b9e3f61 | ||
loma-one | 10521115c4 | ||
Tobias Diekershoff | 956233ff1d | ||
Michael | 14e1c96775 | ||
Tobias Diekershoff | 7a7dbb579d | ||
loma-one | 712edf4236 | ||
Tobias Diekershoff | 5c0cddfc1d | ||
loma-one | 3dc77b2102 | ||
Tobias Diekershoff | 6c43a14198 | ||
Michael | 0dfb345f85 | ||
Tobias Diekershoff | ab837dfec5 | ||
Michael | 2f9076bffd | ||
Tobias Diekershoff | 454e9834bf | ||
Michael | 50930c301d | ||
Philipp Holzer | 3457ab2f3f | ||
Philipp Holzer | 276c27678f | ||
Tobias Diekershoff | cd95ca1a0a | ||
Tobias Diekershoff | 5c04e7136f | ||
heluecht | 179382d8a9 | ||
Tobias Diekershoff | a55f80cb39 | ||
Tobias Diekershoff | 4ad7d61893 | ||
Michael | 4bfdb45e81 | ||
Tobias Diekershoff | 4414471100 | ||
46a55f13f7 | |||
Tobias Diekershoff | a97cccb6b2 | ||
Michael | c0535db742 | ||
Tobias Diekershoff | 0c04b086cb | ||
589cf712cc | |||
heluecht | ce53e48cb2 | ||
f3db763c59 | |||
heluecht | 4e5998c73d | ||
5f27f72b0d | |||
Tobias Diekershoff | b0a95ca2d2 | ||
Hannes Heute | b2108c7a4c | ||
Hypolite Petovan | abca07b29d | ||
Hypolite Petovan | d3dcd5428c | ||
18e512cc8b | |||
7d5446a778 | |||
Hypolite Petovan | 38ea90104d | ||
08b46e5536 | |||
Hypolite Petovan | 010261c1dc | ||
Philipp Holzer | 3f26f9785e |
|
@ -4,6 +4,9 @@ pipeline:
|
|||
clone_friendica_base:
|
||||
image: alpine/git
|
||||
commands:
|
||||
- git config --global user.email "no-reply@friendi.ca"
|
||||
- git config --global user.name "Friendica"
|
||||
- git config --global --add safe.directory $CI_WORKSPACE
|
||||
- git clone https://github.com/friendica/friendica.git .
|
||||
- git checkout $CI_COMMIT_BRANCH
|
||||
when:
|
||||
|
|
|
@ -9,6 +9,9 @@ pipeline:
|
|||
clone_friendica_base:
|
||||
image: alpine/git
|
||||
commands:
|
||||
- git config --global user.email "no-reply@friendi.ca"
|
||||
- git config --global user.name "Friendica"
|
||||
- git config --global --add safe.directory $CI_WORKSPACE
|
||||
- git clone https://github.com/friendica/friendica.git .
|
||||
- git checkout $CI_COMMIT_BRANCH
|
||||
when:
|
||||
|
|
|
@ -4,6 +4,9 @@ pipeline:
|
|||
clone_friendica_base:
|
||||
image: alpine/git
|
||||
commands:
|
||||
- git config --global user.email "no-reply@friendi.ca"
|
||||
- git config --global user.name "Friendica"
|
||||
- git config --global --add safe.directory $CI_WORKSPACE
|
||||
- git clone https://github.com/friendica/friendica.git .
|
||||
- git checkout $CI_COMMIT_BRANCH
|
||||
when:
|
||||
|
|
|
@ -21,6 +21,9 @@ pipeline:
|
|||
clone_friendica_base:
|
||||
image: alpine/git
|
||||
commands:
|
||||
- git config --global user.email "no-reply@friendi.ca"
|
||||
- git config --global user.name "Friendica"
|
||||
- git config --global --add safe.directory $CI_WORKSPACE
|
||||
- git clone https://github.com/friendica/friendica.git .
|
||||
- git checkout $CI_COMMIT_BRANCH
|
||||
clone_friendica_addon:
|
||||
|
|
|
@ -9,6 +9,9 @@ pipeline:
|
|||
clone_friendica_base:
|
||||
image: alpine/git
|
||||
commands:
|
||||
- git config --global user.email "no-reply@friendi.ca"
|
||||
- git config --global user.name "Friendica"
|
||||
- git config --global --add safe.directory $CI_WORKSPACE
|
||||
- git clone https://github.com/friendica/friendica.git .
|
||||
- git checkout $CI_COMMIT_BRANCH
|
||||
when:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
/**
|
||||
* Name: Bluesky Connector
|
||||
* Description: Post to Bluesky
|
||||
* Description: Post to Bluesky, import timelines and feeds
|
||||
* Version: 1.1
|
||||
* Author: Michael Vogel <https://pirati.ca/profile/heluecht>
|
||||
*
|
||||
|
@ -10,6 +10,8 @@
|
|||
* - Outgoing mentions
|
||||
*
|
||||
* At some point in time:
|
||||
* - post videos
|
||||
* - direct messages
|
||||
* - Sending Quote shares https://atproto.com/lexicons/app-bsky-embed#appbskyembedrecord and https://atproto.com/lexicons/app-bsky-embed#appbskyembedrecordwithmedia
|
||||
*
|
||||
* Possibly not possible:
|
||||
|
@ -45,10 +47,12 @@ use Friendica\Model\Tag;
|
|||
use Friendica\Model\User;
|
||||
use Friendica\Network\HTTPClient\Client\HttpClientAccept;
|
||||
use Friendica\Network\HTTPClient\Client\HttpClientOptions;
|
||||
use Friendica\Network\HTTPClient\Client\HttpClientRequest;
|
||||
use Friendica\Object\Image;
|
||||
use Friendica\Protocol\Activity;
|
||||
use Friendica\Protocol\Relay;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
use Friendica\Util\Network;
|
||||
use Friendica\Util\Strings;
|
||||
|
||||
const BLUESKY_DEFAULT_POLL_INTERVAL = 10; // given in minutes
|
||||
|
@ -129,8 +133,13 @@ function bluesky_probe_detect(array &$hookData)
|
|||
|
||||
if (parse_url($hookData['uri'], PHP_URL_SCHEME) == 'did') {
|
||||
$did = $hookData['uri'];
|
||||
} elseif (preg_match('#^' . BLUESKY_WEB . '/profile/(.+)#', $hookData['uri'], $matches)) {
|
||||
$did = bluesky_get_did($matches[1]);
|
||||
} elseif (parse_url($hookData['uri'], PHP_URL_PATH) == $hookData['uri'] && strpos($hookData['uri'], '@') === false) {
|
||||
$did = bluesky_get_did($hookData['uri'], $pconfig['uid']);
|
||||
if (empty($did)) {
|
||||
return;
|
||||
}
|
||||
} elseif (Network::isValidHttpUrl($hookData['uri'])) {
|
||||
$did = bluesky_get_did_by_profile($hookData['uri'], $pconfig['uid']);
|
||||
if (empty($did)) {
|
||||
return;
|
||||
}
|
||||
|
@ -144,23 +153,18 @@ function bluesky_probe_detect(array &$hookData)
|
|||
}
|
||||
|
||||
$data = bluesky_xrpc_get($pconfig['uid'], 'app.bsky.actor.getProfile', ['actor' => $did]);
|
||||
if (empty($data)) {
|
||||
if (empty($data) || empty($data->did)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$hookData['result'] = bluesky_get_contact_fields($data, 0, $pconfig['uid'], false);
|
||||
|
||||
$hookData['result']['baseurl'] = bluesky_get_pds($did);
|
||||
$hookData['result'] = bluesky_get_contact_fields($data, 0, $pconfig['uid'], true);
|
||||
|
||||
// Preparing probe data. This differs slightly from the contact array
|
||||
$hookData['result']['about'] = HTML::toBBCode($data->description ?? '');
|
||||
$hookData['result']['photo'] = $data->avatar ?? '';
|
||||
$hookData['result']['header'] = $data->banner ?? '';
|
||||
$hookData['result']['batch'] = '';
|
||||
$hookData['result']['notify'] = '';
|
||||
$hookData['result']['poll'] = '';
|
||||
$hookData['result']['poco'] = '';
|
||||
$hookData['result']['pubkey'] = '';
|
||||
$hookData['result']['priority'] = 0;
|
||||
$hookData['result']['guid'] = '';
|
||||
}
|
||||
|
@ -177,21 +181,21 @@ function bluesky_item_by_link(array &$hookData)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!preg_match('#^' . BLUESKY_WEB . '/profile/(.+)/post/(.+)#', $hookData['uri'], $matches)) {
|
||||
if (!preg_match('#/profile/(.+)/post/(.+)#', $hookData['uri'], $matches)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$did = bluesky_get_did($matches[1]);
|
||||
$did = bluesky_get_did($matches[1], $hookData['uid']);
|
||||
if (empty($did)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Logger::debug('Found bluesky post', ['url' => $hookData['uri'], 'handle' => $matches[1], 'did' => $did, 'cid' => $matches[2]]);
|
||||
Logger::debug('Found bluesky post', ['url' => $hookData['uri'], 'did' => $did, 'cid' => $matches[2]]);
|
||||
|
||||
$uri = 'at://' . $did . '/app.bsky.feed.post/' . $matches[2];
|
||||
|
||||
$uri = bluesky_fetch_missing_post($uri, $hookData['uid'], $hookData['uid'], Item::PR_FETCHED, 0, 0, 0);
|
||||
Logger::debug('Got post', ['profile' => $matches[1], 'cid' => $matches[2], 'result' => $uri]);
|
||||
Logger::debug('Got post', ['did' => $did, 'cid' => $matches[2], 'result' => $uri]);
|
||||
if (!empty($uri)) {
|
||||
$item = Post::selectFirst(['id'], ['uri' => $uri, 'uid' => $hookData['uid']]);
|
||||
if (!empty($item['id'])) {
|
||||
|
@ -274,14 +278,12 @@ function bluesky_block(array &$hook_data)
|
|||
return;
|
||||
}
|
||||
|
||||
Logger::debug('Check if contact is bluesky', ['data' => $hook_data]);
|
||||
$contact = DBA::selectFirst('contact', [], ['network' => Protocol::BLUESKY, 'url' => $hook_data['url'], 'uid' => [0, $hook_data['uid']]]);
|
||||
if (empty($contact)) {
|
||||
if ($hook_data['contact']['network'] != Protocol::BLUESKY) {
|
||||
return;
|
||||
}
|
||||
|
||||
$record = [
|
||||
'subject' => $contact['url'],
|
||||
'subject' => $hook_data['contact']['url'],
|
||||
'createdAt' => DateTimeFormat::utcNow(DateTimeFormat::ATOM),
|
||||
'$type' => 'app.bsky.graph.block'
|
||||
];
|
||||
|
@ -294,9 +296,9 @@ function bluesky_block(array &$hook_data)
|
|||
|
||||
$activity = bluesky_xrpc_post($hook_data['uid'], 'com.atproto.repo.createRecord', $post);
|
||||
if (!empty($activity->uri)) {
|
||||
$cdata = Contact::getPublicAndUserContactID($hook_data['contact']['id'], $hook_data['uid']);
|
||||
if (!empty($cdata['user'])) {
|
||||
Contact::remove($cdata['user']);
|
||||
$ucid = Contact::getUserContactId($hook_data['contact']['id'], $hook_data['uid']);
|
||||
if ($ucid) {
|
||||
Contact::remove($ucid);
|
||||
}
|
||||
Logger::debug('Successfully blocked contact', ['url' => $hook_data['contact']['url'], 'uri' => $activity->uri]);
|
||||
}
|
||||
|
@ -352,6 +354,7 @@ function bluesky_settings(array &$data)
|
|||
$token = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'access_token');
|
||||
$import = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'import') ?? false;
|
||||
$import_feeds = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'import_feeds') ?? false;
|
||||
$complete_threads = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'complete_threads') ?? false;
|
||||
$custom_handle = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'bluesky', 'friendica_handle') ?? false;
|
||||
|
||||
if (DI::config()->get('bluesky', 'friendica_handles')) {
|
||||
|
@ -371,6 +374,7 @@ function bluesky_settings(array &$data)
|
|||
'$bydefault' => ['bluesky_bydefault', DI::l10n()->t('Post to Bluesky by default'), $def_enabled],
|
||||
'$import' => ['bluesky_import', DI::l10n()->t('Import the remote timeline'), $import],
|
||||
'$import_feeds' => ['bluesky_import_feeds', DI::l10n()->t('Import the pinned feeds'), $import_feeds, DI::l10n()->t('When activated, Posts will be imported from all the feeds that you pinned in Bluesky.')],
|
||||
'$complete_threads' => ['bluesky_complete_threads', DI::l10n()->t('Complete the threads'), $complete_threads, DI::l10n()->t('When activated, the system fetches additional replies for the posts in the timeline. This leads to more complete threads.')],
|
||||
'$custom_handle' => $friendica_handle,
|
||||
'$pds' => ['bluesky_pds', DI::l10n()->t('Personal Data Server'), $pds, DI::l10n()->t('The personal data server (PDS) is the system that hosts your profile.'), '', 'readonly'],
|
||||
'$handle' => ['bluesky_handle', DI::l10n()->t('Bluesky handle'), $handle, '', '', $custom_handle ? 'readonly' : ''],
|
||||
|
@ -444,6 +448,7 @@ function bluesky_settings_post(array &$b)
|
|||
DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'handle', $handle);
|
||||
DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'import', intval($_POST['bluesky_import']));
|
||||
DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'import_feeds', intval($_POST['bluesky_import_feeds']));
|
||||
DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'complete_threads', intval($_POST['bluesky_complete_threads']));
|
||||
DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'bluesky', 'friendica_handle', intval($_POST['bluesky_friendica_handle'] ?? false));
|
||||
|
||||
if (!empty($handle)) {
|
||||
|
@ -532,15 +537,15 @@ function bluesky_cron()
|
|||
Logger::debug('Refresh the token', ['uid' => $pconfig['uid']]);
|
||||
bluesky_get_token($pconfig['uid']);
|
||||
|
||||
Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_notifications.php', $pconfig['uid'], $last);
|
||||
Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_notifications.php', $pconfig['uid']);
|
||||
if (DI::pConfig()->get($pconfig['uid'], 'bluesky', 'import')) {
|
||||
Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_timeline.php', $pconfig['uid'], $last);
|
||||
Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_timeline.php', $pconfig['uid']);
|
||||
}
|
||||
if (DI::pConfig()->get($pconfig['uid'], 'bluesky', 'import_feeds')) {
|
||||
Logger::debug('Fetch feeds for user', ['uid' => $pconfig['uid']]);
|
||||
$feeds = bluesky_get_feeds($pconfig['uid']);
|
||||
foreach ($feeds as $feed) {
|
||||
Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_feed.php', $pconfig['uid'], $feed, $last);
|
||||
Worker::add(['priority' => Worker::PRIORITY_MEDIUM, 'force_priority' => true], 'addon/bluesky/bluesky_feed.php', $pconfig['uid'], $feed);
|
||||
}
|
||||
}
|
||||
Logger::debug('Polling done for user', ['uid' => $pconfig['uid']]);
|
||||
|
@ -708,7 +713,7 @@ function bluesky_create_activity(array $item, stdClass $parent = null)
|
|||
}
|
||||
|
||||
$activity = bluesky_xrpc_post($uid, 'com.atproto.repo.createRecord', $post);
|
||||
if (empty($activity)) {
|
||||
if (empty($activity->uri)) {
|
||||
return;
|
||||
}
|
||||
Logger::debug('Activity done', ['return' => $activity]);
|
||||
|
@ -792,7 +797,7 @@ function bluesky_create_post(array $item, stdClass $root = null, stdClass $paren
|
|||
];
|
||||
|
||||
$parent = bluesky_xrpc_post($uid, 'com.atproto.repo.createRecord', $post);
|
||||
if (empty($parent)) {
|
||||
if (empty($parent->uri)) {
|
||||
if ($part == 0) {
|
||||
Worker::defer();
|
||||
}
|
||||
|
@ -970,11 +975,12 @@ function bluesky_upload_blob(int $uid, array $photo): ?stdClass
|
|||
Logger::info('Uploading', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]);
|
||||
|
||||
$data = bluesky_post($uid, '/xrpc/com.atproto.repo.uploadBlob', $content, ['Content-type' => $photo['type'], 'Authorization' => ['Bearer ' . bluesky_get_token($uid)]]);
|
||||
if (empty($data)) {
|
||||
if (empty($data) || empty($data->blob)) {
|
||||
Logger::info('Uploading failed', ['uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]);
|
||||
return null;
|
||||
}
|
||||
|
||||
Item::incrementOutbound(Protocol::BLUESKY);
|
||||
Logger::debug('Uploaded blob', ['return' => $data, 'uid' => $uid, 'retrial' => $retrial, 'height' => $new_height, 'width' => $new_width, 'size' => $new_size, 'orig-height' => $height, 'orig-width' => $width, 'orig-size' => $size]);
|
||||
return $data->blob;
|
||||
}
|
||||
|
@ -990,7 +996,7 @@ function bluesky_delete_post(string $uri, int $uid)
|
|||
Logger::debug('Deleted', ['parts' => $parts]);
|
||||
}
|
||||
|
||||
function bluesky_fetch_timeline(int $uid, int $last_poll)
|
||||
function bluesky_fetch_timeline(int $uid)
|
||||
{
|
||||
$data = bluesky_xrpc_get($uid, 'app.bsky.feed.getTimeline');
|
||||
if (empty($data)) {
|
||||
|
@ -1001,15 +1007,44 @@ function bluesky_fetch_timeline(int $uid, int $last_poll)
|
|||
return;
|
||||
}
|
||||
|
||||
$last_post = DBA::selectFirst('post-thread-user', ['received'], ['network' => Protocol::BLUESKY, 'uid' => $uid], ['order' => ['received' => true]]);
|
||||
$last_poll = !empty($last_post['received']) ? strtotime($last_post['received']) : 0;
|
||||
|
||||
foreach (array_reverse($data->feed) as $entry) {
|
||||
$causer = bluesky_get_contact($entry->post->author, 0, $uid);
|
||||
if (!empty($entry->reply)) {
|
||||
if (!empty($entry->reply->root)) {
|
||||
bluesky_complete_post($entry->reply->root, $uid, Item::PR_COMMENT, $causer['id'], $last_poll);
|
||||
}
|
||||
if (!empty($entry->reply->parent)) {
|
||||
bluesky_complete_post($entry->reply->parent, $uid, Item::PR_COMMENT, $causer['id'], $last_poll);
|
||||
}
|
||||
}
|
||||
bluesky_process_post($entry->post, $uid, $uid, Item::PR_NONE, 0, 0, $last_poll);
|
||||
if (!empty($entry->reason)) {
|
||||
bluesky_process_reason($entry->reason, bluesky_get_uri($entry->post), $uid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @todo Support paging
|
||||
// [cursor] => 1684670516000::bafyreidq3ilwslmlx72jf5vrk367xcc63s6lrhzlyup2bi3zwcvso6w2vi
|
||||
function bluesky_complete_post(stdClass $post, int $uid, int $post_reason, int $causer, int $last_poll): int
|
||||
{
|
||||
$complete = DI::pConfig()->get($uid, 'bluesky', 'complete_threads');
|
||||
$existing_uri = bluesky_fetch_post(bluesky_get_uri($post), $uid);
|
||||
if (!empty($existing_uri)) {
|
||||
$comments = Post::countPosts(['thr-parent' => $existing_uri, 'gravity' => Item::GRAVITY_COMMENT]);
|
||||
if (($post->replyCount <= $comments) || !$complete) {
|
||||
return bluesky_fetch_uri_id($existing_uri, $uid);
|
||||
}
|
||||
}
|
||||
|
||||
if ($complete) {
|
||||
$uri = bluesky_fetch_missing_post($post->uri, $uid, $uid, $post_reason, $causer, 0, $last_poll, '', true);
|
||||
$uri_id = bluesky_fetch_uri_id($uri, $uid);
|
||||
} else {
|
||||
$uri_id = bluesky_process_post($post, $uid, $uid, $post_reason, $causer, 0, $last_poll);
|
||||
}
|
||||
return $uri_id;
|
||||
}
|
||||
|
||||
function bluesky_process_reason(stdClass $reason, string $uri, int $uid)
|
||||
|
@ -1048,17 +1083,21 @@ function bluesky_process_reason(stdClass $reason, string $uri, int $uid)
|
|||
$item['owner-link'] = $item['author-link'];
|
||||
$item['owner-avatar'] = $item['author-avatar'];
|
||||
if (Item::insert($item)) {
|
||||
$cdata = Contact::getPublicAndUserContactID($contact['id'], $uid);
|
||||
Item::update(['post-reason' => Item::PR_ANNOUNCEMENT, 'causer-id' => $cdata['public']], ['uri' => $uri, 'uid' => $uid]);
|
||||
$pcid = Contact::getPublicContactId($contact['id'], $uid);
|
||||
Item::update(['post-reason' => Item::PR_ANNOUNCEMENT, 'causer-id' => $pcid], ['uri' => $uri, 'uid' => $uid]);
|
||||
}
|
||||
}
|
||||
|
||||
function bluesky_fetch_notifications(int $uid, int $last_poll)
|
||||
function bluesky_fetch_notifications(int $uid)
|
||||
{
|
||||
$data = bluesky_xrpc_get($uid, 'app.bsky.notification.listNotifications');
|
||||
if (empty($data->notifications)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$last_post = DBA::selectFirst('post-thread-user', ['received'], ['network' => Protocol::BLUESKY, 'uid' => $uid], ['order' => ['received' => true]]);
|
||||
$last_poll = !empty($last_post['received']) ? strtotime($last_post['received']) : 0;
|
||||
|
||||
foreach ($data->notifications as $notification) {
|
||||
$uri = bluesky_get_uri($notification);
|
||||
if (Post::exists(['uri' => $uri, 'uid' => $uid]) || Post::exists(['extid' => $uri, 'uid' => $uid])) {
|
||||
|
@ -1068,7 +1107,7 @@ function bluesky_fetch_notifications(int $uid, int $last_poll)
|
|||
Logger::debug('Process notification', ['uid' => $uid, 'reason' => $notification->reason, 'uri' => $uri, 'indexedAt' => $notification->indexedAt]);
|
||||
switch ($notification->reason) {
|
||||
case 'like':
|
||||
$item = bluesky_get_header($notification, $uri, $uid, $uid);
|
||||
$item = bluesky_get_header($notification, $uri, $uid, $uid, $last_poll);
|
||||
$item['gravity'] = Item::GRAVITY_ACTIVITY;
|
||||
$item['body'] = $item['verb'] = Activity::LIKE;
|
||||
$item['thr-parent'] = bluesky_get_uri($notification->record->subject);
|
||||
|
@ -1082,7 +1121,7 @@ function bluesky_fetch_notifications(int $uid, int $last_poll)
|
|||
break;
|
||||
|
||||
case 'repost':
|
||||
$item = bluesky_get_header($notification, $uri, $uid, $uid);
|
||||
$item = bluesky_get_header($notification, $uri, $uid, $uid, $last_poll);
|
||||
$item['gravity'] = Item::GRAVITY_ACTIVITY;
|
||||
$item['body'] = $item['verb'] = Activity::ANNOUNCE;
|
||||
$item['thr-parent'] = bluesky_get_uri($notification->record->subject);
|
||||
|
@ -1125,7 +1164,7 @@ function bluesky_fetch_notifications(int $uid, int $last_poll)
|
|||
}
|
||||
}
|
||||
|
||||
function bluesky_fetch_feed(int $uid, string $feed, int $last_poll)
|
||||
function bluesky_fetch_feed(int $uid, string $feed)
|
||||
{
|
||||
$data = bluesky_xrpc_get($uid, 'app.bsky.feed.getFeed', ['feed' => $feed]);
|
||||
if (empty($data)) {
|
||||
|
@ -1136,8 +1175,11 @@ function bluesky_fetch_feed(int $uid, string $feed, int $last_poll)
|
|||
return;
|
||||
}
|
||||
|
||||
$last_post = DBA::selectFirst('post-thread-user', ['received'], ['network' => Protocol::BLUESKY, 'uid' => $uid], ['order' => ['received' => true]]);
|
||||
$last_poll = !empty($last_post['received']) ? strtotime($last_post['received']) : 0;
|
||||
|
||||
$feeddata = bluesky_xrpc_get($uid, 'app.bsky.feed.getFeedGenerator', ['feed' => $feed]);
|
||||
if (!empty($feeddata)) {
|
||||
if (!empty($feeddata) && !empty($feeddata->view)) {
|
||||
$feedurl = $feeddata->view->uri;
|
||||
$feedname = $feeddata->view->displayName;
|
||||
} else {
|
||||
|
@ -1150,10 +1192,11 @@ function bluesky_fetch_feed(int $uid, string $feed, int $last_poll)
|
|||
$languages = $entry->post->record->langs ?? [];
|
||||
|
||||
if (!Relay::isWantedLanguage($entry->post->record->text, 0, $contact['id'] ?? 0, $languages)) {
|
||||
Logger::debug('Unwanted language detected', ['text' => $entry->post->record->text]);
|
||||
Logger::debug('Unwanted language detected', ['languages' => $languages, 'text' => $entry->post->record->text]);
|
||||
continue;
|
||||
}
|
||||
$uri_id = bluesky_process_post($entry->post, $uid, $uid, Item::PR_TAG, 0, 0, $last_poll);
|
||||
$causer = bluesky_get_contact($entry->post->author, 0, $uid);
|
||||
$uri_id = bluesky_complete_post($entry->post, $uid, Item::PR_TAG, $causer['id'], $last_poll);
|
||||
if (!empty($uri_id)) {
|
||||
$stored = Post\Category::storeFileByURIId($uri_id, $uid, Post\Category::SUBCRIPTION, $feedname, $feedurl);
|
||||
Logger::debug('Stored tag subscription for user', ['uri-id' => $uri_id, 'uid' => $uid, 'name' => $feedname, 'url' => $feedurl, 'stored' => $stored]);
|
||||
|
@ -1181,7 +1224,7 @@ function bluesky_process_post(stdClass $post, int $uid, int $fetch_uid, int $pos
|
|||
|
||||
Logger::debug('Importing post', ['uid' => $uid, 'indexedAt' => $post->indexedAt, 'uri' => $post->uri, 'cid' => $post->cid, 'root' => $post->record->reply->root ?? '']);
|
||||
|
||||
$item = bluesky_get_header($post, $uri, $uid, $fetch_uid);
|
||||
$item = bluesky_get_header($post, $uri, $uid, $fetch_uid, $last_poll);
|
||||
$item = bluesky_get_content($item, $post->record, $uri, $uid, $fetch_uid, $level, $last_poll);
|
||||
if (empty($item)) {
|
||||
return 0;
|
||||
|
@ -1205,7 +1248,7 @@ function bluesky_process_post(stdClass $post, int $uid, int $fetch_uid, int $pos
|
|||
return bluesky_fetch_uri_id($uri, $uid);
|
||||
}
|
||||
|
||||
function bluesky_get_header(stdClass $post, string $uri, int $uid, int $fetch_uid): array
|
||||
function bluesky_get_header(stdClass $post, string $uri, int $uid, int $fetch_uid, int $last_poll = 0): array
|
||||
{
|
||||
$parts = bluesky_get_uri_parts($uri);
|
||||
if (empty($post->author) || empty($post->cid) || empty($parts->rkey)) {
|
||||
|
@ -1218,6 +1261,7 @@ function bluesky_get_header(stdClass $post, string $uri, int $uid, int $fetch_ui
|
|||
'wall' => false,
|
||||
'uri' => $uri,
|
||||
'guid' => $post->cid,
|
||||
'received' => DateTimeFormat::utc($post->indexedAt, DateTimeFormat::MYSQL),
|
||||
'private' => Item::UNLISTED,
|
||||
'verb' => Activity::POST,
|
||||
'contact-id' => $contact['id'],
|
||||
|
@ -1228,6 +1272,10 @@ function bluesky_get_header(stdClass $post, string $uri, int $uid, int $fetch_ui
|
|||
'source' => json_encode($post),
|
||||
];
|
||||
|
||||
if (($last_poll != 0) && strtotime($item['received']) < $last_poll) {
|
||||
unset($item['received']);
|
||||
}
|
||||
|
||||
$account = Contact::selectFirstAccountUser(['pid'], ['id' => $contact['id']]);
|
||||
|
||||
$item['author-id'] = $account['pid'];
|
||||
|
@ -1247,6 +1295,7 @@ function bluesky_get_header(stdClass $post, string $uri, int $uid, int $fetch_ui
|
|||
// When "ver" is set to "1" it was flagged by some automated process.
|
||||
if (empty($label->ver)) {
|
||||
$item['sensitive'] = true;
|
||||
$item['content-warning'] = $label->val ?? '';
|
||||
Logger::debug('Sensitive content', ['uri-id' => $item['uri-id'], 'label' => $label]);
|
||||
}
|
||||
}
|
||||
|
@ -1326,10 +1375,6 @@ function bluesky_get_content(array $item, stdClass $record, string $uri, int $ui
|
|||
$item['created'] = DateTimeFormat::utc($record->createdAt, DateTimeFormat::MYSQL);
|
||||
$item['transmitted-languages'] = $record->langs ?? [];
|
||||
|
||||
if (($last_poll != 0) && strtotime($item['created']) > $last_poll) {
|
||||
$item['received'] = $item['created'];
|
||||
}
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
|
@ -1407,6 +1452,19 @@ function bluesky_add_media(stdClass $embed, array $item, int $fetch_uid, int $le
|
|||
}
|
||||
break;
|
||||
|
||||
case 'app.bsky.embed.video#view':
|
||||
$media = [
|
||||
'uri-id' => $item['uri-id'],
|
||||
'type' => Post\Media::HLS,
|
||||
'url' => $embed->playlist,
|
||||
'preview' => $embed->thumbnail,
|
||||
'description' => $embed->alt ?? '',
|
||||
'height' => $embed->aspectRatio->height,
|
||||
'width' => $embed->aspectRatio->width,
|
||||
];
|
||||
Post\Media::insert($media);
|
||||
break;
|
||||
|
||||
case 'app.bsky.embed.external#view':
|
||||
$media = [
|
||||
'uri-id' => $item['uri-id'],
|
||||
|
@ -1506,10 +1564,10 @@ function bluesky_get_uri_parts(string $uri): ?stdClass
|
|||
return $class;
|
||||
}
|
||||
|
||||
function bluesky_fetch_missing_post(string $uri, int $uid, int $fetch_uid, int $post_reason, int $causer, int $level, int $last_poll, string $fallback = ''): string
|
||||
function bluesky_fetch_missing_post(string $uri, int $uid, int $fetch_uid, int $post_reason, int $causer, int $level, int $last_poll, string $fallback = '', bool $always_fetch = false): string
|
||||
{
|
||||
$fetched_uri = bluesky_fetch_post($uri, $uid);
|
||||
if (!empty($fetched_uri)) {
|
||||
if (!$always_fetch && !empty($fetched_uri)) {
|
||||
return $fetched_uri;
|
||||
}
|
||||
|
||||
|
@ -1529,7 +1587,7 @@ function bluesky_fetch_missing_post(string $uri, int $uid, int $fetch_uid, int $
|
|||
|
||||
Logger::debug('Fetch missing post', ['level' => $level, 'uid' => $uid, 'uri' => $uri]);
|
||||
$data = bluesky_xrpc_get($fetch_uid, 'app.bsky.feed.getPostThread', ['uri' => $fetch_uri]);
|
||||
if (empty($data)) {
|
||||
if (empty($data) || empty($data->thread)) {
|
||||
Logger::info('Thread was not fetched', ['level' => $level, 'uid' => $uid, 'uri' => $uri, 'fallback' => $fallback]);
|
||||
return $fallback;
|
||||
}
|
||||
|
@ -1537,13 +1595,34 @@ function bluesky_fetch_missing_post(string $uri, int $uid, int $fetch_uid, int $
|
|||
Logger::debug('Reply count', ['level' => $level, 'uid' => $uid, 'uri' => $uri]);
|
||||
|
||||
if ($causer != 0) {
|
||||
$cdata = Contact::getPublicAndUserContactID($causer, $uid);
|
||||
$causer = $cdata['public'] ?? 0;
|
||||
$causer = Contact::getPublicContactId($causer, $uid);
|
||||
}
|
||||
|
||||
if (!empty($data->thread->parent)) {
|
||||
$parents = bluesky_fetch_parents($data->thread->parent, $uid);
|
||||
|
||||
foreach ($parents as $parent) {
|
||||
$uri_id = bluesky_process_post($parent, $uid, $fetch_uid, Item::PR_FETCHED, $causer, $level, $last_poll);
|
||||
Logger::debug('Parent created', ['uri-id' => $uri_id]);
|
||||
}
|
||||
}
|
||||
|
||||
return bluesky_process_thread($data->thread, $uid, $fetch_uid, $post_reason, $causer, $level, $last_poll);
|
||||
}
|
||||
|
||||
function bluesky_fetch_parents(stdClass $parent, int $uid, array $parents = []): array
|
||||
{
|
||||
if (!empty($parent->parent)) {
|
||||
$parents = bluesky_fetch_parents($parent->parent, $uid, $parents);
|
||||
}
|
||||
|
||||
if (!empty($parent->post) && empty(bluesky_fetch_post(bluesky_get_uri($parent->post), $uid))) {
|
||||
$parents[] = $parent->post;
|
||||
}
|
||||
|
||||
return $parents;
|
||||
}
|
||||
|
||||
function bluesky_fetch_post(string $uri, int $uid): string
|
||||
{
|
||||
if (Post::exists(['uri' => $uri, 'uid' => [$uid, 0]])) {
|
||||
|
@ -1678,11 +1757,15 @@ function bluesky_get_contact_fields(stdClass $author, int $uid, int $fetch_uid,
|
|||
return $fields;
|
||||
}
|
||||
|
||||
$fields['baseurl'] = bluesky_get_pds($author->did);
|
||||
$data = bluesky_get(BLUESKY_DIRECTORY . '/' . $author->did);
|
||||
if (!empty($data)) {
|
||||
$fields['baseurl'] = bluesky_get_pds('', $data);
|
||||
if (!empty($fields['baseurl'])) {
|
||||
GServer::check($fields['baseurl'], Protocol::BLUESKY);
|
||||
$fields['gsid'] = GServer::getID($fields['baseurl'], true);
|
||||
}
|
||||
$fields['pubkey'] = bluesky_get_public_key('', $data);
|
||||
}
|
||||
|
||||
$data = bluesky_xrpc_get($fetch_uid, 'app.bsky.actor.getProfile', ['actor' => $author->did]);
|
||||
if (empty($data)) {
|
||||
|
@ -1748,6 +1831,55 @@ function bluesky_get_preferences(int $uid): ?stdClass
|
|||
return $data;
|
||||
}
|
||||
|
||||
function bluesky_get_did_by_profile(string $url, int $uid): string
|
||||
{
|
||||
if (preg_match('#/profile/(.+)#', $url, $matches)) {
|
||||
$did = bluesky_get_did($matches[1], $uid);
|
||||
if (!empty($did)) {
|
||||
return $did;
|
||||
}
|
||||
}
|
||||
try {
|
||||
$curlResult = DI::httpClient()->get($url, HttpClientAccept::HTML, [HttpClientOptions::REQUEST => HttpClientRequest::CONTACTINFO]);
|
||||
} catch (\Throwable $th) {
|
||||
return '';
|
||||
}
|
||||
if (!$curlResult->isSuccess()) {
|
||||
return '';
|
||||
}
|
||||
$profile = $curlResult->getBodyString();
|
||||
if (empty($profile)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$doc = new DOMDocument();
|
||||
try {
|
||||
@$doc->loadHTML($profile);
|
||||
} catch (\Throwable $th) {
|
||||
return '';
|
||||
}
|
||||
$xpath = new DOMXPath($doc);
|
||||
$list = $xpath->query('//p[@id]');
|
||||
foreach ($list as $node) {
|
||||
foreach ($node->attributes as $attribute) {
|
||||
if ($attribute->name == 'id') {
|
||||
$ids[$attribute->value] = $node->textContent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($ids['bsky_handle']) || empty($ids['bsky_did'])) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!bluesky_valid_did($ids['bsky_did'], $ids['bsky_handle'])) {
|
||||
Logger::notice('Invalid DID', ['handle' => $ids['bsky_handle'], 'did' => $ids['bsky_did']]);
|
||||
return '';
|
||||
}
|
||||
|
||||
return $ids['bsky_did'];
|
||||
}
|
||||
|
||||
function bluesky_get_did_by_wellknown(string $handle): string
|
||||
{
|
||||
$curlResult = DI::httpClient()->get('http://' . $handle . '/.well-known/atproto-did');
|
||||
|
@ -1757,7 +1889,6 @@ function bluesky_get_did_by_wellknown(string $handle): string
|
|||
Logger::notice('Invalid DID', ['handle' => $handle, 'did' => $did]);
|
||||
return '';
|
||||
}
|
||||
Logger::debug('Got DID by wellknown', ['handle' => $handle, 'did' => $did]);
|
||||
return $did;
|
||||
}
|
||||
return '';
|
||||
|
@ -1776,14 +1907,13 @@ function bluesky_get_did_by_dns(string $handle): string
|
|||
Logger::notice('Invalid DID', ['handle' => $handle, 'did' => $did]);
|
||||
return '';
|
||||
}
|
||||
Logger::debug('Got DID by DNS', ['handle' => $handle, 'did' => $did]);
|
||||
return $did;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
function bluesky_get_did(string $handle): string
|
||||
function bluesky_get_did(string $handle, int $uid): string
|
||||
{
|
||||
if ($handle == '') {
|
||||
return '';
|
||||
|
@ -1793,24 +1923,40 @@ function bluesky_get_did(string $handle): string
|
|||
$handle .= '.' . BLUESKY_HOSTNAME;
|
||||
}
|
||||
|
||||
// Deactivated at the moment, since it isn't reliable by now
|
||||
//$did = bluesky_get_did_by_dns($handle);
|
||||
//if ($did != '') {
|
||||
// return $did;
|
||||
//}
|
||||
|
||||
//$did = bluesky_get_did_by_wellknown($handle);
|
||||
//if ($did != '') {
|
||||
// return $did;
|
||||
//}
|
||||
|
||||
$data = bluesky_get(BLUESKY_PDS . '/xrpc/com.atproto.identity.resolveHandle?handle=' . urlencode($handle));
|
||||
if (empty($data) || empty($data->did)) {
|
||||
return '';
|
||||
}
|
||||
Logger::debug('Got DID by PDS call', ['handle' => $handle, 'did' => $data->did]);
|
||||
// At first we use the user PDS. That should cover most cases.
|
||||
$pds = DI::pConfig()->get($uid, 'bluesky', 'pds');
|
||||
if (!empty($pds)) {
|
||||
$data = bluesky_get($pds . '/xrpc/com.atproto.identity.resolveHandle?handle=' . urlencode($handle));
|
||||
if (!empty($data) && !empty($data->did)) {
|
||||
Logger::debug('Got DID by user PDS call', ['handle' => $handle, 'did' => $data->did]);
|
||||
return $data->did;
|
||||
}
|
||||
}
|
||||
|
||||
// Then we query the DNS, which is used for third party handles (DNS should be faster than wellknown)
|
||||
$did = bluesky_get_did_by_dns($handle);
|
||||
if ($did != '') {
|
||||
Logger::debug('Got DID by DNS', ['handle' => $handle, 'did' => $did]);
|
||||
return $did;
|
||||
}
|
||||
|
||||
// Then we query wellknown, which should mostly cover the rest.
|
||||
$did = bluesky_get_did_by_wellknown($handle);
|
||||
if ($did != '') {
|
||||
Logger::debug('Got DID by wellknown', ['handle' => $handle, 'did' => $did]);
|
||||
return $did;
|
||||
}
|
||||
|
||||
// And finally we use the default PDS from Bluesky.
|
||||
$data = bluesky_get(BLUESKY_PDS . '/xrpc/com.atproto.identity.resolveHandle?handle=' . urlencode($handle));
|
||||
if (!empty($data) && !empty($data->did)) {
|
||||
Logger::debug('Got DID by system PDS call', ['handle' => $handle, 'did' => $data->did]);
|
||||
return $data->did;
|
||||
}
|
||||
|
||||
Logger::notice('No DID detected', ['handle' => $handle]);
|
||||
return '';
|
||||
}
|
||||
|
||||
function bluesky_get_user_did(int $uid, bool $refresh = false): ?string
|
||||
{
|
||||
|
@ -1826,7 +1972,7 @@ function bluesky_get_user_did(int $uid, bool $refresh = false): ?string
|
|||
return null;
|
||||
}
|
||||
|
||||
$did = bluesky_get_did($handle);
|
||||
$did = bluesky_get_did($handle, $uid);
|
||||
if (empty($did)) {
|
||||
return null;
|
||||
}
|
||||
|
@ -1857,9 +2003,11 @@ function bluesky_get_user_pds(int $uid): ?string
|
|||
return $pds;
|
||||
}
|
||||
|
||||
function bluesky_get_pds(string $did): ?string
|
||||
function bluesky_get_pds(string $did, stdClass $data = null): ?string
|
||||
{
|
||||
if (empty($data)) {
|
||||
$data = bluesky_get(BLUESKY_DIRECTORY . '/' . $did);
|
||||
}
|
||||
if (empty($data) || empty($data->service)) {
|
||||
return null;
|
||||
}
|
||||
|
@ -1873,6 +2021,22 @@ function bluesky_get_pds(string $did): ?string
|
|||
return null;
|
||||
}
|
||||
|
||||
function bluesky_get_public_key(string $did, stdClass $data = null): ?string
|
||||
{
|
||||
if (empty($data)) {
|
||||
$data = bluesky_get(BLUESKY_DIRECTORY . '/' . $did);
|
||||
}
|
||||
if (empty($data) || empty($data->verificationMethod)) {
|
||||
return null;
|
||||
}
|
||||
foreach ($data->verificationMethod as $method) {
|
||||
if (!empty($method->publicKeyMultibase)) {
|
||||
return $method->publicKeyMultibase;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function bluesky_valid_did(string $did, string $handle): bool
|
||||
{
|
||||
$data = bluesky_get(BLUESKY_DIRECTORY . '/' . $did);
|
||||
|
@ -1902,7 +2066,7 @@ function bluesky_refresh_token(int $uid): string
|
|||
$token = DI::pConfig()->get($uid, 'bluesky', 'refresh_token');
|
||||
|
||||
$data = bluesky_post($uid, '/xrpc/com.atproto.server.refreshSession', '', ['Authorization' => ['Bearer ' . $token]]);
|
||||
if (empty($data)) {
|
||||
if (empty($data) || empty($data->accessJwt)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
@ -1921,7 +2085,7 @@ function bluesky_create_token(int $uid, string $password): string
|
|||
}
|
||||
|
||||
$data = bluesky_post($uid, '/xrpc/com.atproto.server.createSession', json_encode(['identifier' => $did, 'password' => $password]), ['Content-type' => 'application/json']);
|
||||
if (empty($data)) {
|
||||
if (empty($data) || empty($data->accessJwt)) {
|
||||
DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_TOKEN_FAIL);
|
||||
return '';
|
||||
}
|
||||
|
@ -1936,7 +2100,11 @@ function bluesky_create_token(int $uid, string $password): string
|
|||
|
||||
function bluesky_xrpc_post(int $uid, string $url, $parameters): ?stdClass
|
||||
{
|
||||
return bluesky_post($uid, '/xrpc/' . $url, json_encode($parameters), ['Content-type' => 'application/json', 'Authorization' => ['Bearer ' . bluesky_get_token($uid)]]);
|
||||
$data = bluesky_post($uid, '/xrpc/' . $url, json_encode($parameters), ['Content-type' => 'application/json', 'Authorization' => ['Bearer ' . bluesky_get_token($uid)]]);
|
||||
if (!empty($data)) {
|
||||
Item::incrementOutbound(Protocol::BLUESKY);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
function bluesky_post(int $uid, string $url, string $params, array $headers): ?stdClass
|
||||
|
@ -1954,14 +2122,18 @@ function bluesky_post(int $uid, string $url, string $params, array $headers): ?s
|
|||
return null;
|
||||
}
|
||||
|
||||
$data = json_decode($curlResult->getBodyString());
|
||||
if (!$curlResult->isSuccess()) {
|
||||
Logger::notice('API Error', ['error' => json_decode($curlResult->getBodyString()) ?: $curlResult->getBodyString()]);
|
||||
Logger::notice('API Error', ['url' => $url, 'code' => $curlResult->getReturnCode(), 'error' => $data ?: $curlResult->getBodyString()]);
|
||||
if (!$data) {
|
||||
DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_API_FAIL);
|
||||
return null;
|
||||
}
|
||||
$data->code = $curlResult->getReturnCode();
|
||||
}
|
||||
|
||||
DI::pConfig()->set($uid, 'bluesky', 'status', BLUEKSY_STATUS_SUCCESS);
|
||||
return json_decode($curlResult->getBodyString());
|
||||
return $data;
|
||||
}
|
||||
|
||||
function bluesky_xrpc_get(int $uid, string $url, array $parameters = []): ?stdClass
|
||||
|
@ -1975,7 +2147,14 @@ function bluesky_xrpc_get(int $uid, string $url, array $parameters = []): ?stdCl
|
|||
return null;
|
||||
}
|
||||
|
||||
$data = bluesky_get($pds . '/xrpc/' . $url, HttpClientAccept::JSON, [HttpClientOptions::HEADERS => ['Authorization' => ['Bearer ' . bluesky_get_token($uid)]]]);
|
||||
$headers = ['Authorization' => ['Bearer ' . bluesky_get_token($uid)]];
|
||||
|
||||
$languages = User::getWantedLanguages($uid);
|
||||
if (!empty($languages)) {
|
||||
$headers['Accept-Language'] = implode(',', $languages);
|
||||
}
|
||||
|
||||
$data = bluesky_get($pds . '/xrpc/' . $url, HttpClientAccept::JSON, [HttpClientOptions::HEADERS => $headers]);
|
||||
DI::pConfig()->set($uid, 'bluesky', 'status', is_null($data) ? BLUEKSY_STATUS_API_FAIL : BLUEKSY_STATUS_SUCCESS);
|
||||
return $data;
|
||||
}
|
||||
|
@ -1989,10 +2168,15 @@ function bluesky_get(string $url, string $accept_content = HttpClientAccept::DEF
|
|||
return null;
|
||||
}
|
||||
|
||||
$data = json_decode($curlResult->getBodyString());
|
||||
if (!$curlResult->isSuccess()) {
|
||||
Logger::notice('API Error', ['url' => $url, 'error' => json_decode($curlResult->getBodyString()) ?: $curlResult->getBodyString()]);
|
||||
Logger::notice('API Error', ['url' => $url, 'code' => $curlResult->getReturnCode(), 'error' => $data ?: $curlResult->getBodyString()]);
|
||||
if (!$data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return json_decode($curlResult->getBodyString());
|
||||
$data->code = $curlResult->getReturnCode();
|
||||
}
|
||||
|
||||
Item::incrementInbound(Protocol::BLUESKY);
|
||||
return $data;
|
||||
}
|
||||
|
|
|
@ -6,11 +6,11 @@ function bluesky_feed_run($argv, $argc)
|
|||
{
|
||||
require_once 'addon/bluesky/bluesky.php';
|
||||
|
||||
if ($argc != 4) {
|
||||
if ($argc < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
Logger::debug('Importing feed - start', ['user' => $argv[1], 'feed' => $argv[2], 'last_poll' => $argv[3]]);
|
||||
bluesky_fetch_feed($argv[1], $argv[2], $argv[3]);
|
||||
Logger::debug('Importing feed - done', ['user' => $argv[1], 'feed' => $argv[2], 'last_poll' => $argv[3]]);
|
||||
Logger::debug('Importing feed - start', ['user' => $argv[1], 'feed' => $argv[2]]);
|
||||
bluesky_fetch_feed($argv[1], $argv[2]);
|
||||
Logger::debug('Importing feed - done', ['user' => $argv[1], 'feed' => $argv[2]]);
|
||||
}
|
||||
|
|
|
@ -6,11 +6,11 @@ function bluesky_notifications_run($argv, $argc)
|
|||
{
|
||||
require_once 'addon/bluesky/bluesky.php';
|
||||
|
||||
if ($argc != 3) {
|
||||
if ($argc < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
Logger::notice('importing notifications - start', ['user' => $argv[1], 'last_poll' => $argv[2]]);
|
||||
bluesky_fetch_notifications($argv[1], $argv[2]);
|
||||
Logger::notice('importing notifications - done', ['user' => $argv[1], 'last_poll' => $argv[2]]);
|
||||
Logger::notice('importing notifications - start', ['user' => $argv[1]]);
|
||||
bluesky_fetch_notifications($argv[1]);
|
||||
Logger::notice('importing notifications - done', ['user' => $argv[1]]);
|
||||
}
|
||||
|
|
|
@ -6,11 +6,11 @@ function bluesky_timeline_run($argv, $argc)
|
|||
{
|
||||
require_once 'addon/bluesky/bluesky.php';
|
||||
|
||||
if ($argc != 3) {
|
||||
if ($argc < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
Logger::notice('importing timeline - start', ['user' => $argv[1], 'last_poll' => $argv[2]]);
|
||||
bluesky_fetch_timeline($argv[1], $argv[2]);
|
||||
Logger::notice('importing timeline - done', ['user' => $argv[1], 'last_poll' => $argv[2]]);
|
||||
Logger::notice('importing timeline - start', ['user' => $argv[1]]);
|
||||
bluesky_fetch_timeline($argv[1]);
|
||||
Logger::notice('importing timeline - done', ['user' => $argv[1]]);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-03-22 05:31+0000\n"
|
||||
"POT-Creation-Date: 2024-09-29 18:16+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -17,131 +17,117 @@ msgstr ""
|
|||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: bluesky.php:325
|
||||
#: bluesky.php:335
|
||||
msgid "Save Settings"
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:326
|
||||
#: bluesky.php:336
|
||||
msgid "Allow your users to use your hostname for their Bluesky handles"
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:326
|
||||
#: bluesky.php:336
|
||||
#, php-format
|
||||
msgid ""
|
||||
"Before enabling this option, you have to setup a wildcard domain "
|
||||
"configuration and you have to enable wildcard requests in your webserver "
|
||||
"configuration. On Apache this is done by adding \"ServerAlias *.%s\" to your "
|
||||
"HTTP configuration. You don't need to change the HTTPS configuration."
|
||||
msgid "Before enabling this option, you have to setup a wildcard domain configuration and you have to enable wildcard requests in your webserver configuration. On Apache this is done by adding \"ServerAlias *.%s\" to your HTTP configuration. You don't need to change the HTTPS configuration."
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:354
|
||||
#: bluesky.php:365
|
||||
#, php-format
|
||||
msgid "Allow to use %s as your Bluesky handle."
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:354
|
||||
#: bluesky.php:365
|
||||
#, php-format
|
||||
msgid ""
|
||||
"When enabled, you can use %s as your Bluesky handle. After you enabled this "
|
||||
"option, please go to https://bsky.app/settings and select to change your "
|
||||
"handle. Select that you have got your own domain. Then enter %s and select "
|
||||
"\"No DNS Panel\". Then select \"Verify Text File\"."
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:361
|
||||
msgid "Enable Bluesky Post Addon"
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:362
|
||||
msgid "Post to Bluesky by default"
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:363
|
||||
msgid "Import the remote timeline"
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:364
|
||||
msgid "Import the pinned feeds"
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:364
|
||||
msgid ""
|
||||
"When activated, Posts will be imported from all the feeds that you pinned in "
|
||||
"Bluesky."
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:366
|
||||
msgid "Personal Data Server"
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:366
|
||||
msgid "The personal data server (PDS) is the system that hosts your profile."
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:367
|
||||
msgid "Bluesky handle"
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:368
|
||||
msgid "Bluesky DID"
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:368
|
||||
msgid ""
|
||||
"This is the unique identifier. It will be fetched automatically, when the "
|
||||
"handle is entered."
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:369
|
||||
msgid "Bluesky app password"
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:369
|
||||
msgid ""
|
||||
"Please don't add your real password here, but instead create a specific app "
|
||||
"password in the Bluesky settings."
|
||||
msgid "When enabled, you can use %s as your Bluesky handle. After you enabled this option, please go to https://bsky.app/settings and select to change your handle. Select that you have got your own domain. Then enter %s and select \"No DNS Panel\". Then select \"Verify Text File\"."
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:375
|
||||
msgid "Enable Bluesky Post Addon"
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:376
|
||||
msgid "Post to Bluesky by default"
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:377
|
||||
msgid "Import the remote timeline"
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:378
|
||||
msgid "Import the pinned feeds"
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:378
|
||||
msgid "When activated, Posts will be imported from all the feeds that you pinned in Bluesky."
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:379
|
||||
msgid "Complete the threads"
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:379
|
||||
msgid "When activated, the system fetches additional replies for the posts in the timeline. This leads to more complete threads."
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:381
|
||||
msgid "Personal Data Server"
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:381
|
||||
msgid "The personal data server (PDS) is the system that hosts your profile."
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:382
|
||||
msgid "Bluesky handle"
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:383
|
||||
msgid "Bluesky DID"
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:383
|
||||
msgid "This is the unique identifier. It will be fetched automatically, when the handle is entered."
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:384
|
||||
msgid "Bluesky app password"
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:384
|
||||
msgid "Please don't add your real password here, but instead create a specific app password in the Bluesky settings."
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:390
|
||||
msgid "Bluesky Import/Export"
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:385
|
||||
msgid ""
|
||||
"You are not authenticated. Please enter your handle and the app password."
|
||||
#: bluesky.php:400
|
||||
msgid "You are not authenticated. Please enter your handle and the app password."
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:405
|
||||
msgid ""
|
||||
"You are authenticated to Bluesky. For security reasons the password isn't "
|
||||
"stored."
|
||||
#: bluesky.php:420
|
||||
msgid "You are authenticated to Bluesky. For security reasons the password isn't stored."
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:407
|
||||
msgid ""
|
||||
"The communication with the personal data server service (PDS) is established."
|
||||
#: bluesky.php:422
|
||||
msgid "The communication with the personal data server service (PDS) is established."
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:409
|
||||
#: bluesky.php:424
|
||||
msgid "Communication issues with the personal data server service (PDS)."
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:411
|
||||
msgid ""
|
||||
"The DID for the provided handle could not be detected. Please check if you "
|
||||
"entered the correct handle."
|
||||
#: bluesky.php:426
|
||||
msgid "The DID for the provided handle could not be detected. Please check if you entered the correct handle."
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:413
|
||||
#: bluesky.php:428
|
||||
msgid "The personal data server service (PDS) could not be detected."
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:415
|
||||
msgid ""
|
||||
"The authentication with the provided handle and password failed. Please "
|
||||
"check if you entered the correct password."
|
||||
#: bluesky.php:430
|
||||
msgid "The authentication with the provided handle and password failed. Please check if you entered the correct password."
|
||||
msgstr ""
|
||||
|
||||
#: bluesky.php:484
|
||||
#: bluesky.php:492
|
||||
msgid "Post to Bluesky"
|
||||
msgstr ""
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
{{include file="field_checkbox.tpl" field=$bydefault}}
|
||||
{{include file="field_checkbox.tpl" field=$import}}
|
||||
{{include file="field_checkbox.tpl" field=$import_feeds}}
|
||||
{{include file="field_checkbox.tpl" field=$complete_threads}}
|
||||
{{if $custom_handle}}
|
||||
{{include file="field_checkbox.tpl" field=$custom_handle}}
|
||||
{{/if}}
|
||||
|
|
|
@ -152,7 +152,7 @@ function curweather_network_mod_init(string &$body)
|
|||
|
||||
function curweather_addon_settings_post($post)
|
||||
{
|
||||
if (!DI::userSession()->getLocalUserId() || empty($_POST['curweather-settings-submit'])) {
|
||||
if (!DI::userSession()->getLocalUserId() || empty($_POST['curweather-submit'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#
|
||||
# Translators:
|
||||
# bob lebonche <lebonche@tutanota.com>, 2021
|
||||
# cracrayol, 2024
|
||||
# Hypolite Petovan <hypolite@mrpetovan.com>, 2022
|
||||
# Hypolite Petovan <hypolite@mrpetovan.com>, 2016
|
||||
# ea1cd8241cb389ffb6f92bc6891eff5d_dc12308 <70dced5587d47e18d88f9298024d96f8_93383>, 2015
|
||||
|
@ -15,8 +16,8 @@ msgstr ""
|
|||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-11-21 19:14-0500\n"
|
||||
"PO-Revision-Date: 2014-06-22 11:34+0000\n"
|
||||
"Last-Translator: Hypolite Petovan <hypolite@mrpetovan.com>, 2022\n"
|
||||
"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n"
|
||||
"Last-Translator: cracrayol, 2024\n"
|
||||
"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
@ -45,7 +46,7 @@ msgstr "Vent"
|
|||
|
||||
#: curweather.php:140
|
||||
msgid "Last Updated"
|
||||
msgstr "Dernière mise-à-jour"
|
||||
msgstr "Dernière mise à jour"
|
||||
|
||||
#: curweather.php:141
|
||||
msgid "Data by"
|
||||
|
|
|
@ -10,7 +10,7 @@ $a->strings['Current Weather'] = 'Météo actuelle';
|
|||
$a->strings['Relative Humidity'] = 'Humidité relative';
|
||||
$a->strings['Pressure'] = 'Pression';
|
||||
$a->strings['Wind'] = 'Vent';
|
||||
$a->strings['Last Updated'] = 'Dernière mise-à-jour';
|
||||
$a->strings['Last Updated'] = 'Dernière mise à jour';
|
||||
$a->strings['Data by'] = 'Données de';
|
||||
$a->strings['Show on map'] = 'Montrer sur la carte';
|
||||
$a->strings['There was a problem accessing the weather data. But have a look'] = 'Une erreur est survenue lors de l\'accès aux données météo. Vous pouvez quand même jeter un oeil';
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
# Translators:
|
||||
# bob lebonche <lebonche@tutanota.com>, 2021
|
||||
# ButterflyOfFire, 2020
|
||||
# cracrayol, 2024
|
||||
# Hypolite Petovan <hypolite@mrpetovan.com>, 2016
|
||||
msgid ""
|
||||
msgstr ""
|
||||
|
@ -13,8 +14,8 @@ msgstr ""
|
|||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-11-21 19:14-0500\n"
|
||||
"PO-Revision-Date: 2014-06-23 08:27+0000\n"
|
||||
"Last-Translator: bob lebonche <lebonche@tutanota.com>, 2021\n"
|
||||
"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n"
|
||||
"Last-Translator: cracrayol, 2024\n"
|
||||
"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
@ -29,7 +30,7 @@ msgstr "Remplacer les coordonnées par le nom de la localité la plus proche dan
|
|||
|
||||
#: geonames.php:136
|
||||
msgid "Enable Geonames Addon"
|
||||
msgstr "Activer l'application complémentaire Geonames"
|
||||
msgstr "Activer l'extension Geonames"
|
||||
|
||||
#: geonames.php:141
|
||||
msgid "Geonames Settings"
|
||||
|
|
|
@ -6,5 +6,5 @@ function string_plural_select_fr($n){
|
|||
if (($n == 0 || $n == 1)) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; }
|
||||
}}
|
||||
$a->strings['Replace numerical coordinates by the nearest populated location name in your posts.'] = 'Remplacer les coordonnées par le nom de la localité la plus proche dans votre publication.';
|
||||
$a->strings['Enable Geonames Addon'] = 'Activer l\'application complémentaire Geonames';
|
||||
$a->strings['Enable Geonames Addon'] = 'Activer l\'extension Geonames';
|
||||
$a->strings['Geonames Settings'] = 'Paramètres Geonames';
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
# Translators:
|
||||
# bob lebonche <lebonche@tutanota.com>, 2021
|
||||
# ButterflyOfFire, 2020
|
||||
# cracrayol, 2024
|
||||
# Hypolite Petovan <hypolite@mrpetovan.com>, 2016
|
||||
msgid ""
|
||||
msgstr ""
|
||||
|
@ -13,8 +14,8 @@ msgstr ""
|
|||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-11-21 19:14-0500\n"
|
||||
"PO-Revision-Date: 2014-06-23 08:30+0000\n"
|
||||
"Last-Translator: bob lebonche <lebonche@tutanota.com>, 2021\n"
|
||||
"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n"
|
||||
"Last-Translator: cracrayol, 2024\n"
|
||||
"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
@ -29,7 +30,7 @@ msgstr "Permettre le filtrage des notifications de commentaires par courriel sur
|
|||
|
||||
#: gnot.php:64
|
||||
msgid "Enable this addon?"
|
||||
msgstr "Activer cette application complémentaire ?"
|
||||
msgstr "Activer cette extension ?"
|
||||
|
||||
#: gnot.php:69
|
||||
msgid "Gnot Settings"
|
||||
|
|
|
@ -6,6 +6,6 @@ function string_plural_select_fr($n){
|
|||
if (($n == 0 || $n == 1)) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; }
|
||||
}}
|
||||
$a->strings['Allows threading of email comment notifications on Gmail and anonymising the subject line.'] = 'Permettre le filtrage des notifications de commentaires par courriel sur Gmail et l\'anonymisation de l\'objet.';
|
||||
$a->strings['Enable this addon?'] = 'Activer cette application complémentaire ?';
|
||||
$a->strings['Enable this addon?'] = 'Activer cette extension ?';
|
||||
$a->strings['Gnot Settings'] = 'Paramètres Gnot';
|
||||
$a->strings['[Friendica:Notify] Comment to conversation #%d'] = '[Friendica:Notify] Commentaire vers conversation #%d';
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#
|
||||
# Translators:
|
||||
# bob lebonche <lebonche@tutanota.com>, 2021
|
||||
# cracrayol, 2024
|
||||
# Marie Olive <lacellule101@gmail.com>, 2018
|
||||
# ea1cd8241cb389ffb6f92bc6891eff5d_dc12308 <70dced5587d47e18d88f9298024d96f8_93383>, 2015
|
||||
msgid ""
|
||||
|
@ -13,8 +14,8 @@ msgstr ""
|
|||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-02-01 18:15+0100\n"
|
||||
"PO-Revision-Date: 2014-06-23 08:33+0000\n"
|
||||
"Last-Translator: bob lebonche <lebonche@tutanota.com>, 2021\n"
|
||||
"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n"
|
||||
"Last-Translator: cracrayol, 2024\n"
|
||||
"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
@ -50,7 +51,7 @@ msgid ""
|
|||
"Libravatar addon is installed, too. Please disable Libravatar addon or this "
|
||||
"Gravatar addon.<br>The Libravatar addon will fall back to Gravatar if "
|
||||
"nothing was found at Libravatar."
|
||||
msgstr "L'application complémentaire Libravatar est aussi installée. Merci de désactiver l'application complémentaire Libravatar ou cette application complémentaire Gravatar. L'application complémentaire se repliera sur Gravatar si rien n'est trouvé dans Libravatar."
|
||||
msgstr "L'extension Libravatar est aussi installée. Merci de désactiver l'extension Libravatar ou cette extension Gravatar. L'extension se repliera sur Gravatar si rien n'est trouvé dans Libravatar."
|
||||
|
||||
#: gravatar.php:102
|
||||
msgid "Save Settings"
|
||||
|
|
|
@ -11,7 +11,7 @@ $a->strings['monster face'] = 'Face de monstre';
|
|||
$a->strings['computer generated face'] = 'visage généré par ordinateur';
|
||||
$a->strings['retro arcade style face'] = 'Face style retro arcade';
|
||||
$a->strings['Information'] = 'Information';
|
||||
$a->strings['Libravatar addon is installed, too. Please disable Libravatar addon or this Gravatar addon.<br>The Libravatar addon will fall back to Gravatar if nothing was found at Libravatar.'] = 'L\'application complémentaire Libravatar est aussi installée. Merci de désactiver l\'application complémentaire Libravatar ou cette application complémentaire Gravatar. L\'application complémentaire se repliera sur Gravatar si rien n\'est trouvé dans Libravatar.';
|
||||
$a->strings['Libravatar addon is installed, too. Please disable Libravatar addon or this Gravatar addon.<br>The Libravatar addon will fall back to Gravatar if nothing was found at Libravatar.'] = 'L\'extension Libravatar est aussi installée. Merci de désactiver l\'extension Libravatar ou cette extension Gravatar. L\'extension se repliera sur Gravatar si rien n\'est trouvé dans Libravatar.';
|
||||
$a->strings['Save Settings'] = 'Sauvegarder les paramètres.';
|
||||
$a->strings['Default avatar image'] = 'Image par défaut d\'avatar';
|
||||
$a->strings['Select default avatar image if none was found at Gravatar. See README'] = 'Sélectionner l\'avatar par défaut, si aucun n\'est trouvé sur Gravatar. Voir Lisezmoi.';
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#
|
||||
# Translators:
|
||||
# bob lebonche <lebonche@tutanota.com>, 2021
|
||||
# cracrayol, 2024
|
||||
# Hypolite Petovan <hypolite@mrpetovan.com>, 2016
|
||||
msgid ""
|
||||
msgstr ""
|
||||
|
@ -12,8 +13,8 @@ msgstr ""
|
|||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-11-21 19:17-0500\n"
|
||||
"PO-Revision-Date: 2014-06-23 08:37+0000\n"
|
||||
"Last-Translator: bob lebonche <lebonche@tutanota.com>, 2021\n"
|
||||
"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n"
|
||||
"Last-Translator: cracrayol, 2024\n"
|
||||
"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
@ -26,7 +27,7 @@ msgstr "Publier sur Insanejournal"
|
|||
|
||||
#: ijpost.php:61
|
||||
msgid "Enable InsaneJournal Post Addon"
|
||||
msgstr "Activer l'application complémentaire InsaneJournalPost"
|
||||
msgstr "Activer l'extension InsaneJournal"
|
||||
|
||||
#: ijpost.php:62
|
||||
msgid "InsaneJournal username"
|
||||
|
|
|
@ -6,7 +6,7 @@ function string_plural_select_fr($n){
|
|||
if (($n == 0 || $n == 1)) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; }
|
||||
}}
|
||||
$a->strings['Post to Insanejournal'] = 'Publier sur Insanejournal';
|
||||
$a->strings['Enable InsaneJournal Post Addon'] = 'Activer l\'application complémentaire InsaneJournalPost';
|
||||
$a->strings['Enable InsaneJournal Post Addon'] = 'Activer l\'extension InsaneJournal';
|
||||
$a->strings['InsaneJournal username'] = 'Identifiant du InsaneJournal';
|
||||
$a->strings['InsaneJournal password'] = 'Mot de passe du InsaneJournal';
|
||||
$a->strings['Post to InsaneJournal by default'] = 'Publier sur le InsaneJournal par défaut';
|
||||
|
|
|
@ -96,6 +96,8 @@ function invidious_render(array &$b)
|
|||
$b['html'] = preg_replace("~https?://(?:www\.)?youtube\.com/watch\?v=(.*?)~ism", $server . '/watch?v=$1', $b['html']);
|
||||
$b['html'] = preg_replace("~https?://(?:www\.)?youtube\.com/embed/(.*?)~ism", $server . '/embed/$1', $b['html']);
|
||||
$b['html'] = preg_replace("~https?://(?:www\.)?youtube\.com/shorts/(.*?)~ism", $server . '/shorts/$1', $b['html']);
|
||||
$b['html'] = preg_replace ("/https?:\/\/music.youtube.com\/(.*?)/ism", $server . '/watch?v=$1', $b['html']);
|
||||
$b['html'] = preg_replace ("/https?:\/\/m.youtube.com\/(.*?)/ism", $server . '/watch?v=$1', $b['html']);
|
||||
$b['html'] = preg_replace("/https?:\/\/youtu.be\/(.*?)/ism", $server . '/watch?v=$1', $b['html']);
|
||||
|
||||
if ($original != $b['html']) {
|
||||
|
|
|
@ -5,14 +5,15 @@
|
|||
#
|
||||
# Translators:
|
||||
# bob lebonche <lebonche@tutanota.com>, 2021
|
||||
# cracrayol, 2024
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: friendica\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-11-21 19:14-0500\n"
|
||||
"PO-Revision-Date: 2015-07-07 15:14+0000\n"
|
||||
"Last-Translator: bob lebonche <lebonche@tutanota.com>, 2021\n"
|
||||
"Language-Team: French (http://www.transifex.com/Friendica/friendica/language/fr/)\n"
|
||||
"Last-Translator: cracrayol, 2024\n"
|
||||
"Language-Team: French (http://app.transifex.com/Friendica/friendica/language/fr/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
@ -21,7 +22,7 @@ msgstr ""
|
|||
|
||||
#: krynn.php:127
|
||||
msgid "Enable Krynn Addon"
|
||||
msgstr "Activer l'application complémentaire Krynn"
|
||||
msgstr "Activer l'extension Krynn"
|
||||
|
||||
#: krynn.php:132
|
||||
msgid "Krynn Settings"
|
||||
|
|
|
@ -5,5 +5,5 @@ function string_plural_select_fr($n){
|
|||
$n = intval($n);
|
||||
if (($n == 0 || $n == 1)) { return 0; } else if ($n != 0 && $n % 1000000 == 0) { return 1; } else { return 2; }
|
||||
}}
|
||||
$a->strings['Enable Krynn Addon'] = 'Activer l\'application complémentaire Krynn';
|
||||
$a->strings['Enable Krynn Addon'] = 'Activer l\'extension Krynn';
|
||||
$a->strings['Krynn Settings'] = 'Paramètres de Krynn';
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
* Author: Matthew Exon <http://mat.exon.name>
|
||||
*/
|
||||
|
||||
use Friendica\App;
|
||||
use Friendica\Content\Text\BBCode;
|
||||
use Friendica\Core\Hook;
|
||||
use Friendica\Core\Logger;
|
||||
|
@ -16,12 +15,11 @@ use Friendica\Core\Worker;
|
|||
use Friendica\Database\DBA;
|
||||
use Friendica\DI;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Model\Item;
|
||||
use Friendica\Model\Post;
|
||||
use Friendica\Model\User;
|
||||
use Friendica\Network\HTTPClient\Client\HttpClientAccept;
|
||||
use Friendica\Network\HTTPClient\Client\HttpClientOptions;
|
||||
use Friendica\Protocol\Activity;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
|
||||
/**
|
||||
* Sets up the addon hooks and the database table
|
||||
|
@ -34,26 +32,7 @@ function mailstream_install()
|
|||
Hook::register('post_remote_end', 'addon/mailstream/mailstream.php', 'mailstream_post_hook');
|
||||
Hook::register('mailstream_send_hook', 'addon/mailstream/mailstream.php', 'mailstream_send_hook');
|
||||
|
||||
Logger::info("mailstream: installed");
|
||||
}
|
||||
|
||||
/**
|
||||
* Enforces that mailstream_install has set up the current version
|
||||
*/
|
||||
function mailstream_check_version()
|
||||
{
|
||||
if (!is_null(DI::config()->get('mailstream', 'dbversion'))) {
|
||||
DI::config()->delete('mailstream', 'dbversion');
|
||||
Logger::info("mailstream_check_version: old version detected, reinstalling");
|
||||
mailstream_install();
|
||||
Hook::loadHooks();
|
||||
Hook::add(
|
||||
'mailstream_convert_table_entries',
|
||||
'addon/mailstream/mailstream.php',
|
||||
'mailstream_convert_table_entries'
|
||||
);
|
||||
Hook::fork(Worker::PRIORITY_LOW, 'mailstream_convert_table_entries');
|
||||
}
|
||||
Logger::info("installed mailstream");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -72,10 +51,12 @@ function mailstream_addon_admin(string &$o)
|
|||
{
|
||||
$frommail = DI::config()->get('mailstream', 'frommail');
|
||||
$template = Renderer::getMarkupTemplate('admin.tpl', 'addon/mailstream/');
|
||||
$config = ['frommail',
|
||||
$config = [
|
||||
'frommail',
|
||||
DI::l10n()->t('From Address'),
|
||||
$frommail,
|
||||
DI::l10n()->t('Email address that stream items will appear to be from.')];
|
||||
DI::l10n()->t('Email address that stream items will appear to be from.')
|
||||
];
|
||||
$o .= Renderer::replaceMacros($template, [
|
||||
'$frommail' => $config,
|
||||
'$submit' => DI::l10n()->t('Save Settings')
|
||||
|
@ -105,7 +86,7 @@ function mailstream_generate_id(string $uri): string
|
|||
$host = DI::baseUrl()->getHost();
|
||||
$resource = hash('md5', $uri);
|
||||
$message_id = "<" . $resource . "@" . $host . ">";
|
||||
Logger::debug('mailstream: Generated message ID ' . $message_id . ' for URI ' . $uri);
|
||||
Logger::debug('generated message ID', ['id' => $message_id, 'uri' => $uri]);
|
||||
return $message_id;
|
||||
}
|
||||
|
||||
|
@ -114,20 +95,20 @@ function mailstream_send_hook(array $data)
|
|||
$criteria = array('uid' => $data['uid'], 'contact-id' => $data['contact-id'], 'uri' => $data['uri']);
|
||||
$item = Post::selectFirst([], $criteria);
|
||||
if (empty($item)) {
|
||||
Logger::error('mailstream_send_hook could not find item');
|
||||
Logger::error('could not find item');
|
||||
return;
|
||||
}
|
||||
|
||||
$user = User::getById($item['uid']);
|
||||
if (empty($user)) {
|
||||
Logger::error('mailstream_send_hook could not fund user', ['uid' => $item['uid']]);
|
||||
Logger::error('could not find user', ['uid' => $item['uid']]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mailstream_send($data['message_id'], $item, $user)) {
|
||||
Logger::debug('mailstream_send_hook send failed, will retry', $data);
|
||||
Logger::debug('send failed, will retry', $data);
|
||||
if (!Worker::defer()) {
|
||||
Logger::error('mailstream_send_hook failed and could not defer', $data);
|
||||
Logger::error('failed and could not defer', $data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -142,35 +123,33 @@ function mailstream_send_hook(array $data)
|
|||
*/
|
||||
function mailstream_post_hook(array &$item)
|
||||
{
|
||||
mailstream_check_version();
|
||||
|
||||
if ($item['uid'] === 0) {
|
||||
Logger::debug('mailstream: root user, skipping item ' . $item['id']);
|
||||
return;
|
||||
}
|
||||
if (!DI::pConfig()->get($item['uid'], 'mailstream', 'enabled')) {
|
||||
Logger::debug('mailstream: not enabled.', ['item' => $item['id'], ' uid ' => $item['uid']]);
|
||||
return;
|
||||
}
|
||||
if (!$item['uid']) {
|
||||
Logger::debug('mailstream: no uid for item ' . $item['id']);
|
||||
return;
|
||||
}
|
||||
if (!$item['contact-id']) {
|
||||
Logger::debug('mailstream: no contact-id for item ' . $item['id']);
|
||||
Logger::debug('no contact-id', ['item' => $item['id']]);
|
||||
return;
|
||||
}
|
||||
if (!$item['uri']) {
|
||||
Logger::debug('mailstream: no uri for item ' . $item['id']);
|
||||
Logger::debug('no uri', ['item' => $item['id']]);
|
||||
return;
|
||||
}
|
||||
if ($item['verb'] == Activity::ANNOUNCE) {
|
||||
Logger::debug('mailstream: announce item ', ['item' => $item['id']]);
|
||||
Logger::debug('ignoring announce', ['item' => $item['id']]);
|
||||
return;
|
||||
}
|
||||
if (DI::pConfig()->get($item['uid'], 'mailstream', 'nolikes')) {
|
||||
if ($item['verb'] == Activity::LIKE) {
|
||||
Logger::debug('mailstream: like item ' . $item['id']);
|
||||
Logger::debug('ignoring like', ['item' => $item['id']]);
|
||||
return;
|
||||
}
|
||||
if ($item['verb'] == Activity::DISLIKE) {
|
||||
Logger::debug('mailstream: dislike item ' . $item['id']);
|
||||
Logger::debug('ignoring dislike', ['item' => $item['id']]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -219,14 +198,17 @@ function mailstream_do_images(array &$item, array &$attachments)
|
|||
|
||||
$cookiejar = tempnam(System::getTempPath(), 'cookiejar-mailstream-');
|
||||
try {
|
||||
$curlResult = DI::httpClient()->fetchFull($url, HttpClientAccept::DEFAULT, 0, $cookiejar);
|
||||
$curlResult = DI::httpClient()->get($url, HttpClientAccept::DEFAULT, [HttpClientOptions::COOKIEJAR => $cookiejar]);
|
||||
if (!$curlResult->isSuccess()) {
|
||||
Logger::debug('mailstream: fetch image url failed', [
|
||||
'url' => $url, 'item_id' => $item['id'], 'return_code' => $curlResult->getReturnCode()]);
|
||||
'url' => $url,
|
||||
'item_id' => $item['id'],
|
||||
'return_code' => $curlResult->getReturnCode()
|
||||
]);
|
||||
continue;
|
||||
}
|
||||
} catch (InvalidArgumentException $e) {
|
||||
Logger::error('mailstream_do_images exception fetching url', ['url' => $url, 'item_id' => $item['id']]);
|
||||
Logger::error('exception fetching url', ['url' => $url, 'item_id' => $item['id']]);
|
||||
continue;
|
||||
}
|
||||
$attachments[$url] = [
|
||||
|
@ -327,13 +309,12 @@ function mailstream_subject(array $item): string
|
|||
}
|
||||
$contact = Contact::selectFirst([], ['id' => $item['contact-id'], 'uid' => $item['uid']]);
|
||||
if (!DBA::isResult($contact)) {
|
||||
Logger::error(
|
||||
'mailstream_subject no contact for item',
|
||||
['id' => $item['id'],
|
||||
Logger::error('no contact', [
|
||||
'item' => $item['id'],
|
||||
'plink' => $item['plink'],
|
||||
'contact id' => $item['contact-id'],
|
||||
'uid' => $item['uid']]
|
||||
);
|
||||
'uid' => $item['uid']
|
||||
]);
|
||||
return DI::l10n()->t("Friendica post");
|
||||
}
|
||||
if ($contact['network'] === 'dfrn') {
|
||||
|
@ -370,17 +351,16 @@ function mailstream_subject(array $item): string
|
|||
function mailstream_send(string $message_id, array $item, array $user): bool
|
||||
{
|
||||
if (!is_array($item)) {
|
||||
Logger::error('mailstream_send item is empty', ['message_id' => $message_id]);
|
||||
Logger::error('item is empty', ['message_id' => $message_id]);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$item['visible']) {
|
||||
Logger::debug('mailstream_send item not yet visible', ['item uri' => $item['uri']]);
|
||||
Logger::debug('item not yet visible', ['item uri' => $item['uri']]);
|
||||
return false;
|
||||
}
|
||||
if (!$message_id) {
|
||||
Logger::error('mailstream_send no message ID supplied', ['item uri' => $item['uri'],
|
||||
'user email' => $user['email']]);
|
||||
Logger::error('no message ID supplied', ['item uri' => $item['uri'], 'user email' => $user['email']]);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -432,18 +412,21 @@ function mailstream_send(string $message_id, array $item, array $user): bool
|
|||
'$upstream' => DI::l10n()->t('Upstream'),
|
||||
'$uri' => DI::l10n()->t('URI'),
|
||||
'$local' => DI::l10n()->t('Local'),
|
||||
'$item' => $item]);
|
||||
'$item' => $item
|
||||
]);
|
||||
$mail->Body = mailstream_html_wrap($mail->Body);
|
||||
if (!$mail->Send()) {
|
||||
throw new Exception($mail->ErrorInfo);
|
||||
}
|
||||
Logger::debug('mailstream_send sent message', ['message ID' => $mail->MessageID,
|
||||
Logger::debug('sent message', [
|
||||
'message ID' => $mail->MessageID,
|
||||
'subject' => $mail->Subject,
|
||||
'address' => $address]);
|
||||
'address' => $address
|
||||
]);
|
||||
} catch (phpmailerException $e) {
|
||||
Logger::debug('mailstream_send PHPMailer exception sending message ' . $message_id . ': ' . $e->errorMessage());
|
||||
Logger::debug('PHPMailer exception sending message', ['id' => $message_id, 'error' => $e->errorMessage()]);
|
||||
} catch (Exception $e) {
|
||||
Logger::debug('mailstream_send exception sending message ' . $message_id . ': ' . $e->getMessage());
|
||||
Logger::debug('exception sending message', ['id' => $message_id, 'error' => $e->getMessage()]);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -467,29 +450,6 @@ function mailstream_html_wrap(string &$text)
|
|||
return $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert v1 mailstream table entries to v2 workerqueue items
|
||||
*/
|
||||
function mailstream_convert_table_entries()
|
||||
{
|
||||
$ms_item_ids = DBA::selectToArray('mailstream_item', [], ['message-id', 'uri', 'uid', 'contact-id'], ["`mailstream_item`.`completed` IS NULL"]);
|
||||
Logger::debug('mailstream_convert_table_entries processing ' . count($ms_item_ids) . ' items');
|
||||
foreach ($ms_item_ids as $ms_item_id) {
|
||||
$send_hook_data = array('uid' => $ms_item_id['uid'],
|
||||
'contact-id' => $ms_item_id['contact-id'],
|
||||
'uri' => $ms_item_id['uri'],
|
||||
'message_id' => $ms_item_id['message-id'],
|
||||
'tries' => 0);
|
||||
if (!$ms_item_id['message-id'] || !strlen($ms_item_id['message-id'])) {
|
||||
Logger::info('mailstream_convert_table_entries: item has no message-id.', ['item' => $ms_item_id['id'], 'uri' => $ms_item_id['uri']]);
|
||||
continue;
|
||||
}
|
||||
Logger::info('mailstream_convert_table_entries: convert item to workerqueue', $send_hook_data);
|
||||
Hook::fork(Worker::PRIORITY_LOW, 'mailstream_send_hook', $send_hook_data);
|
||||
}
|
||||
DBA::e('DROP TABLE `mailstream_item`');
|
||||
}
|
||||
|
||||
/**
|
||||
* Form for configuring mailstream features for a user
|
||||
*
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Name: Mastodon Custom Emojis
|
||||
* Description: Replace emojis shortcodes in Mastodon posts with their originating server custom emojis images.
|
||||
|
@ -9,7 +8,6 @@
|
|||
* Status: Unsupported
|
||||
*/
|
||||
|
||||
use Friendica\App;
|
||||
use Friendica\Content\Smilies;
|
||||
use Friendica\Core\Cache\Enum\Duration;
|
||||
use Friendica\Core\Hook;
|
||||
|
@ -78,7 +76,7 @@ function mastodoncustomemojis_fetch_custom_emojis_for_url($api_base_url)
|
|||
|
||||
$api_url = $api_base_url . '/api/v1/custom_emojis';
|
||||
|
||||
$fetchResult = DI::httpClient()->fetchFull($api_url);
|
||||
$fetchResult = DI::httpClient()->get($api_url);
|
||||
|
||||
if ($fetchResult->isSuccess()) {
|
||||
$emojis_array = json_decode($fetchResult->getBodyString(), true);
|
||||
|
|
213
ratioed/RatioedPanel.php
Normal file
|
@ -0,0 +1,213 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Addon\ratioed;
|
||||
|
||||
use Friendica\Content\Pager;
|
||||
use Friendica\Core\Logger;
|
||||
use Friendica\Core\Renderer;
|
||||
use Friendica\Database\DBA;
|
||||
use Friendica\DI;
|
||||
use Friendica\Model\User;
|
||||
use Friendica\Module\Moderation\Users\Active;
|
||||
|
||||
/**
|
||||
* This class implements the "Behaviour" panel in Moderation/Users
|
||||
*/
|
||||
class RatioedPanel extends Active
|
||||
{
|
||||
protected function content(array $request = []): string
|
||||
{
|
||||
Active::content();
|
||||
|
||||
if (isset(DI::args()->getArgv()[1]) and DI::args()->getArgv()[1] === 'help') {
|
||||
$template = Renderer::getMarkupTemplate('/help.tpl', 'addon/ratioed/');
|
||||
return Renderer::replaceMacros($template, array('$config' => DI::baseUrl() . '/settings/addon'));
|
||||
}
|
||||
|
||||
$action = $this->parameters['action'] ?? '';
|
||||
$uid = $this->parameters['uid'] ?? 0;
|
||||
|
||||
if ($uid) {
|
||||
$user = User::getById($uid, ['username', 'blocked']);
|
||||
if (!$user) {
|
||||
$this->systemMessages->addNotice($this->t('User not found'));
|
||||
$this->baseUrl->redirect('moderation/users');
|
||||
}
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
case 'delete':
|
||||
if ($this->session->getLocalUserId() != $uid) {
|
||||
self::checkFormSecurityTokenRedirectOnError('moderation/users/active', 'moderation_users_active', 't');
|
||||
// delete user
|
||||
User::remove($uid);
|
||||
|
||||
$this->systemMessages->addNotice($this->t('User "%s" deleted', $user['username']));
|
||||
} else {
|
||||
$this->systemMessages->addNotice($this->t('You can\'t remove yourself'));
|
||||
}
|
||||
|
||||
$this->baseUrl->redirect('moderation/users/active');
|
||||
break;
|
||||
case 'block':
|
||||
self::checkFormSecurityTokenRedirectOnError('moderation/users/active', 'moderation_users_active', 't');
|
||||
User::block($uid);
|
||||
$this->systemMessages->addNotice($this->t('User "%s" blocked', $user['username']));
|
||||
$this->baseUrl->redirect('moderation/users/active');
|
||||
break;
|
||||
}
|
||||
$pager = new Pager($this->l10n, $this->args->getQueryString(), 100);
|
||||
|
||||
$valid_orders = [
|
||||
'name',
|
||||
'email',
|
||||
'register_date',
|
||||
'last-activity',
|
||||
'last-item',
|
||||
'page-flags',
|
||||
];
|
||||
|
||||
$order = 'last-item';
|
||||
$order_direction = '-';
|
||||
if (!empty($request['o'])) {
|
||||
$new_order = $request['o'];
|
||||
if ($new_order[0] === '-') {
|
||||
$order_direction = '-';
|
||||
$new_order = substr($new_order, 1);
|
||||
}
|
||||
|
||||
if (in_array($new_order, $valid_orders)) {
|
||||
$order = $new_order;
|
||||
}
|
||||
}
|
||||
|
||||
$users = User::getList($pager->getStart(), $pager->getItemsPerPage(), 'active', $order, ($order_direction == '-'));
|
||||
|
||||
$users = array_map($this->setupUserCallback(), $users);
|
||||
|
||||
$header_titles = [
|
||||
$this->t('Name'),
|
||||
$this->t('Email'),
|
||||
$this->t('Register date'),
|
||||
$this->t('Last login'),
|
||||
$this->t('Last public item'),
|
||||
$this->t('Type'),
|
||||
$this->t('Blocked by'),
|
||||
$this->t('Comments last 24h'),
|
||||
$this->t('Reactions last 24h'),
|
||||
$this->t('Ratio last 24h'),
|
||||
];
|
||||
$field_names = [
|
||||
'name',
|
||||
'email',
|
||||
'register_date',
|
||||
'login_date',
|
||||
'lastitem_date',
|
||||
'page_flags',
|
||||
'blocked_by',
|
||||
'comments',
|
||||
'reactions',
|
||||
'ratio',
|
||||
];
|
||||
$th_users = array_map(null, $header_titles, $valid_orders, $field_names);
|
||||
|
||||
$count = $this->database->count('user', ["`verified` AND NOT `blocked` AND NOT `account_removed` AND NOT `account_expired` AND `uid` != ?", 0]);
|
||||
|
||||
$t = Renderer::getMarkupTemplate('ratioed.tpl', 'addon/ratioed');
|
||||
return self::getTabsHTML('ratioed') . Renderer::replaceMacros($t, [
|
||||
// strings //
|
||||
'$title' => $this->t('Moderation'),
|
||||
'$help_url' => $this->baseUrl . '/ratioed/help',
|
||||
'$page' => $this->t('Behaviour'),
|
||||
'$select_all' => $this->t('select all'),
|
||||
'$delete' => $this->t('Delete'),
|
||||
'$block' => $this->t('Block'),
|
||||
'$blocked' => $this->t('User blocked'),
|
||||
'$siteadmin' => $this->t('Site admin'),
|
||||
'$accountexpired' => $this->t('Account expired'),
|
||||
'$h_newuser' => $this->t('Create a new user'),
|
||||
|
||||
'$th_users' => $th_users,
|
||||
'$order_users' => $order,
|
||||
'$order_direction_users' => $order_direction,
|
||||
|
||||
'$confirm_delete_multi' => $this->t('Selected users will be deleted!\n\nEverything these users had posted on this site will be permanently deleted!\n\nAre you sure?'),
|
||||
'$confirm_delete' => $this->t('The user {0} will be deleted!\n\nEverything this user has posted on this site will be permanently deleted!\n\nAre you sure?'),
|
||||
|
||||
'$form_security_token' => self::getFormSecurityToken('moderation_users_active'),
|
||||
|
||||
// values //
|
||||
'$baseurl' => $this->baseUrl,
|
||||
'$query_string' => $this->args->getQueryString(),
|
||||
|
||||
'$users' => $users,
|
||||
'$count' => $count,
|
||||
'$pager' => $pager->renderFull($count),
|
||||
]);
|
||||
}
|
||||
|
||||
protected function setupUserCallback(): \Closure
|
||||
{
|
||||
Logger::debug("ratioed: setupUserCallback");
|
||||
$parentCallback = parent::setupUserCallback();
|
||||
return function ($user) use ($parentCallback) {
|
||||
$blocked_count = DBA::count('user-contact', ['uid' => $user['uid'], 'is-blocked' => 1]);
|
||||
$user['blocked_by'] = $blocked_count;
|
||||
|
||||
$self_contact_result = DBA::p('SELECT admin_contact.id AS user_contact_uid FROM contact AS admin_contact JOIN contact AS user_contact ON admin_contact.`uri-id` = user_contact.`uri-id` AND admin_contact.self = 0 AND user_contact.self = 1 WHERE user_contact.uid = ?', $user['uid']);
|
||||
if (DBA::isResult($self_contact_result)) {
|
||||
$self_contact_result_row = DBA::fetch($self_contact_result);
|
||||
$user['user_contact_uid'] = $self_contact_result_row['user_contact_uid'];
|
||||
}
|
||||
else {
|
||||
$user['user_contact_uid'] = NULL;
|
||||
}
|
||||
|
||||
if ($user['user_contact_uid']) {
|
||||
$post_engagement_result = DBA::p('SELECT SUM(`comments`) AS `comment_count`, SUM(`activities`) AS `activities_count` FROM `post-engagement` WHERE `post-engagement`.created > DATE_SUB(now(), INTERVAL 1 DAY) AND `post-engagement`.`owner-id` = ?', $user['user_contact_uid']);
|
||||
if (DBA::isResult($post_engagement_result)) {
|
||||
$post_engagement_result_row = DBA::fetch($post_engagement_result);
|
||||
$user['comments'] = $post_engagement_result_row['comment_count'];
|
||||
$user['reactions'] = $post_engagement_result_row['activities_count'];
|
||||
if ($user['reactions'] > 0) {
|
||||
$user['ratio'] = number_format($user['comments'] / $user['reactions'], 1, '.', '');
|
||||
$user['ratioed'] = (float)($user['ratio']) >= 2.0;
|
||||
}
|
||||
else {
|
||||
if ($user['comments'] == 0) {
|
||||
$user['ratio'] = '0';
|
||||
$user['ratioed'] = false;
|
||||
}
|
||||
else {
|
||||
$user['ratio'] = '∞';
|
||||
$user['ratioed'] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$user['comments'] = 'error';
|
||||
$user['reactions'] = 'error';
|
||||
$user['ratio'] = 'error';
|
||||
$user['ratioed'] = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$user['comments'] = 'error';
|
||||
$user['reactions'] = 'error';
|
||||
$user['ratio'] = 'error';
|
||||
$user['ratioed'] = false;
|
||||
}
|
||||
|
||||
$user = $parentCallback($user);
|
||||
Logger::debug("ratioed: setupUserCallback", [
|
||||
'uid' => $user['uid'],
|
||||
'blocked_by' => $user['blocked_by'],
|
||||
'comments' => $user['comments'],
|
||||
'reactions' => $user['reactions'],
|
||||
'ratio' => $user['ratio'],
|
||||
'ratioed' => $user['ratioed'],
|
||||
]);
|
||||
return $user;
|
||||
};
|
||||
}
|
||||
}
|
58
ratioed/ratioed.php
Normal file
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
/**
|
||||
* Name: Ratioed
|
||||
* Description: Additional moderation user table with statistics about user behaviour
|
||||
* Version: 0.1
|
||||
* Author: Matthew Exon <http://mat.exon.name>
|
||||
*/
|
||||
|
||||
use Friendica\Addon\ratioed\RatioedPanel;
|
||||
use Friendica\Core\Hook;
|
||||
use Friendica\Core\Logger;
|
||||
use Friendica\DI;
|
||||
|
||||
/**
|
||||
* Sets up the addon hooks and updates data in the database if needed
|
||||
*/
|
||||
function ratioed_install()
|
||||
{
|
||||
Hook::register('moderation_users_tabs', 'addon/ratioed/ratioed.php', 'ratioed_users_tabs');
|
||||
|
||||
Logger::info("ratioed: installed");
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a statement rather than an actual function definition. The simple
|
||||
* existence of this method is checked to figure out if the addon offers a
|
||||
* module.
|
||||
*/
|
||||
function ratioed_module() {}
|
||||
|
||||
/**
|
||||
* @brief Adds additional users tab to the moderation panel
|
||||
*
|
||||
* @param array $arr Parameters, including "tabs" which is the list to modify, and "selectedTab", which is the currently selected tab ID
|
||||
*/
|
||||
function ratioed_users_tabs(array &$arr) {
|
||||
Logger::debug("ratioed: users tabs");
|
||||
|
||||
array_push($arr['tabs'], [
|
||||
'label' => DI::l10n()->t('Behaviour'),
|
||||
'url' => 'ratioed',
|
||||
'sel' => $arr['selectedTab'] == 'ratioed' ? 'active' : '',
|
||||
'title' => DI::l10n()->t('Statistics about users behaviour'),
|
||||
'id' => 'admin-users-ratioed',
|
||||
'accesskey' => 'r',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Displays the ratioed tab in the moderation panel
|
||||
*/
|
||||
function ratioed_content() {
|
||||
Logger::debug("ratioed: content");
|
||||
|
||||
$ratioed = DI::getDice()->create(RatioedPanel::class, [$_SERVER]);
|
||||
$httpException = DI::getDice()->create(Friendica\Module\Special\HTTPException::class);
|
||||
$ratioed->run($httpException);
|
||||
}
|
92
ratioed/templates/help.tpl
Normal file
|
@ -0,0 +1,92 @@
|
|||
<div class="panel 'help-content-wrapper">
|
||||
<div class="panel-body">
|
||||
<h2>Ratioed Plugin Help</h2>
|
||||
<p>
|
||||
This plugin provides administrators with additional statistics about
|
||||
the behaviour of users. These may be useful as early warning signs
|
||||
that warrant more carefully watching the behaviour of a user. They
|
||||
are <em>not</em> suitable as a trigger for instantly blocking,
|
||||
muting, or reporting a user, since they lack context.
|
||||
</p>
|
||||
<p>
|
||||
The name of the plugin comes
|
||||
from <a href="https://knowyourmeme.com/editorials/guides/what-is-the-ratio-and-what-does-it-mean-to-get-ratioed-twitters-1-rule-explained">"The
|
||||
Ratio"</a>, a well-known quick rule of thumb:
|
||||
</p>
|
||||
<blockquote>
|
||||
If the Replies:RT ratio is greater than 2:1, you done messed up.
|
||||
</blockquote>
|
||||
<p>
|
||||
To "get ratioed" is to receive a large number of comments in a short
|
||||
space of time, with relatively few likes or boosts. If commenters
|
||||
were enthusiastic about the posts, they would also have liked or
|
||||
boosted them. Receiving many comments without such likes or boosts
|
||||
indicates the comments were probably angry. This anger may or may
|
||||
not be justified, but either way this is probably something
|
||||
moderators should be aware of.
|
||||
</p>
|
||||
<p>
|
||||
This plugin allows viewing of an actual ratio, calculated over the
|
||||
last 24 hours. This is a useful timeframe for sudden dogpiling
|
||||
events that administrators might not otherwise notice. The plugin
|
||||
also calculates other statistics.
|
||||
</p>
|
||||
<h3>Explanation of Statistics</h3>
|
||||
<h4>Blocked by</h4>
|
||||
<p>
|
||||
This summarises the number of users on remote servers that have
|
||||
blocked this user.
|
||||
</p>
|
||||
<p>
|
||||
Note that the ActivityPub spec expressly says that
|
||||
implementations "SHOULD NOT" forward such block messages to
|
||||
remote servers. Nevertheless some implementations do this
|
||||
anyway, notably Mastodon. This statistic can only count block
|
||||
messages from servers that do this, as well as blocks from local
|
||||
users. As such, it is usually an undercount.
|
||||
</p>
|
||||
<p>
|
||||
The reason the spec recommends against forwarding these messages
|
||||
is that they can lead to retaliation. For this reason, this
|
||||
plugin deliberately does not provide any way to investigate
|
||||
exactly who blocked the user.
|
||||
</p>
|
||||
<h4>Comments last 24h</h4>
|
||||
<p>
|
||||
This gives the number of comments made on the top-level posts that
|
||||
this user made within the last 24 hours.
|
||||
</p>
|
||||
<h4>Reactions last 24h</h4>
|
||||
<p>
|
||||
This collects the number of likes, boosts, or other "one-click"
|
||||
interactions made on the user's top-level posts within the last 24
|
||||
hours.
|
||||
</p>
|
||||
<h4>Ratio last 24h</h4>
|
||||
<p>
|
||||
This is the ratio between "Comments last 24h" and "Reactions last
|
||||
24h". It is intended to approximate the traditional ratio as
|
||||
understood on Twitter.
|
||||
</p>
|
||||
<h3>Performance</h3>
|
||||
<p>
|
||||
The statistics are computed from scratch each time the page loads.
|
||||
It's possible that this might put a heavy load on the database. and
|
||||
the page may take a long time to load.
|
||||
</p>
|
||||
<h3>Extending</h3>
|
||||
<p>
|
||||
Suggestions for additional statistics are welcome, especially from
|
||||
moderators. This plugin should be considered a sandbox for
|
||||
experimentation, so it is not necessary to prove that any statistic
|
||||
is correlated with unwanted behaviour.
|
||||
</p>
|
||||
<p>
|
||||
However, this plugin does deal with potentially sensitive
|
||||
information. Even if moderators do in principle have access to all
|
||||
information, it should not necessarily be highlighted. Statistics
|
||||
should be kept anonymous and neutral. Also, they should be
|
||||
presented only to moderators, not to the users themselves.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
164
ratioed/templates/ratioed.tpl
Normal file
|
@ -0,0 +1,164 @@
|
|||
<script type="text/javascript" src="view/theme/frio/js/mod_admin.js?v={{constant('\Friendica\App::VERSION')}}"></script>
|
||||
<link rel="stylesheet" href="view/theme/frio/css/mod_admin.css?v={{constant('\Friendica\App::VERSION')}}" type="text/css" media="screen"/>
|
||||
|
||||
<div id="admin-users" class="adminpage generic-page-wrapper">
|
||||
<h1>{{$title}} - {{$page}} ({{$count}})</h1>
|
||||
<p>
|
||||
<a href="{{$base_url}}/moderation/users/create" class="btn btn-primary"><i class="fa fa-user-plus"></i> {{$h_newuser}}</a>
|
||||
</p>
|
||||
<form action="{{$baseurl}}/{{$query_string}}" method="post">
|
||||
<input type="hidden" name="form_security_token" value="{{$form_security_token}}">
|
||||
<table id="users" class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<div class="checkbox">
|
||||
<input type="checkbox" id="admin-settings-users-select" class="selecttoggle" data-select-class="users_ckbx"/>
|
||||
<label for="admin-settings-users-select"></label>
|
||||
</div>
|
||||
</th>
|
||||
<th></th>
|
||||
{{foreach $th_users as $k=>$th}}
|
||||
{{if $k < 2 || $order_users == $th.1 || ($k==5 && !in_array($order_users,[$th_users.2.1, $th_users.3.1, $th_users.4.1])) }}
|
||||
<th class="th-{{$k}}">
|
||||
<a href="{{$baseurl}}/moderation/users/active?o={{if $order_direction_users == "+"}}-{{/if}}{{$th.1}}" class="table-order">
|
||||
{{if $order_users == $th.1}}
|
||||
{{if $order_direction_users == "+"}}
|
||||
↓
|
||||
{{else}}
|
||||
↑
|
||||
{{/if}}
|
||||
{{else}}
|
||||
↕
|
||||
{{/if}}
|
||||
{{$th.0}}
|
||||
</a>
|
||||
</th>
|
||||
{{/if}}
|
||||
{{/foreach}}
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{foreach $users as $u}}
|
||||
<tr id="user-{{$u.uid}}" class="{{if $u.ratioed}}blocked{{/if}}">
|
||||
<td>
|
||||
{{if $u.is_deletable}}
|
||||
<div class="checkbox">
|
||||
<input type="checkbox" class="users_ckbx" id="id_user_{{$u.uid}}" name="user[]" value="{{$u.uid}}"/>
|
||||
<label for="id_user_{{$u.uid}}"></label>
|
||||
</div>
|
||||
{{else}}
|
||||
|
||||
{{/if}}
|
||||
</td>
|
||||
<td><img class="avatar-nano" src="{{$u.micro}}" title="{{$u.nickname}}"></td>
|
||||
<td><a href="{{$u.url}}" title="{{$u.nickname}}"> {{$u.name}}</a></td>
|
||||
<td>{{$u.email}}</td>
|
||||
{{if $order_users == $th_users.2.1}}
|
||||
<td>{{$u.register_date}}</td>
|
||||
{{/if}}
|
||||
|
||||
{{if $order_users == $th_users.3.1}}
|
||||
<td>{{$u.login_date}}</td>
|
||||
{{/if}}
|
||||
|
||||
{{if $order_users == $th_users.4.1}}
|
||||
<td>{{$u.lastitem_date}}</td>
|
||||
{{/if}}
|
||||
|
||||
{{if !in_array($order_users,[$th_users.2.1, $th_users.3.1, $th_users.4.1]) }}
|
||||
<td>
|
||||
<i class="fa
|
||||
{{if $u.page_flags_raw==0}}fa-user{{/if}} {{* PAGE_NORMAL *}}
|
||||
{{if $u.page_flags_raw==1}}fa-bullhorn{{/if}} {{* PAGE_SOAPBOX *}}
|
||||
{{if $u.page_flags_raw==2}}fa-users{{/if}} {{* PAGE_COMMUNITY *}}
|
||||
{{if $u.page_flags_raw==3}}fa-heart{{/if}} {{* PAGE_FREELOVE *}}
|
||||
{{if $u.page_flags_raw==4}}fa-rss{{/if}} {{* PAGE_BLOG *}}
|
||||
{{if $u.page_flags_raw==5}}fa-user-secret{{/if}} {{* PAGE_PRVGROUP *}}
|
||||
" title="{{$u.page_flags}}">
|
||||
</i>
|
||||
{{if $u.page_flags_raw==0 && $u.account_type_raw > 0}}
|
||||
<i class="fa
|
||||
{{if $u.account_type_raw==1}}fa-sitemap{{/if}} {{* ACCOUNT_TYPE_ORGANISATION *}}
|
||||
{{if $u.account_type_raw==2}}fa-newspaper-o{{/if}} {{* ACCOUNT_TYPE_NEWS *}}
|
||||
{{if $u.account_type_raw==3}}fa-comments{{/if}} {{* ACCOUNT_TYPE_COMMUNITY *}}
|
||||
" title="{{$u.account_type}}">
|
||||
</i>
|
||||
{{/if}}
|
||||
{{if $u.is_admin}}<i class="fa fa-user-secret text-primary" title="{{$siteadmin}}"></i>{{/if}}
|
||||
{{if $u.account_expired}}<i class="fa fa-clock-o text-warning" title="{{$accountexpired}}"></i>{{/if}}
|
||||
</td>
|
||||
{{/if}}
|
||||
|
||||
<td class="text-right">
|
||||
<button type="button" class="btn-link admin-settings-action-link" onclick="return details({{$u.uid}})"><span class="caret"></span></button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="user-{{$u.uid}}-detail" class=" details hidden {{if $u.blocked != 0}}blocked{{/if}}">
|
||||
<td> </td>
|
||||
<td colspan="4">
|
||||
{{if $order_users != $th_users.2.1}}
|
||||
<p>
|
||||
<a href="{{$baseurl}}/ratioed?o={{if $order_direction_users == "+"}}-{{/if}}{{$th_users.2.1}}" class="btn-link table-order">
|
||||
↕ {{$th_users.2.0}}</a> : {{$u.register_date}}
|
||||
</p>
|
||||
{{/if}}
|
||||
|
||||
{{if $order_users != $th_users.3.1}}
|
||||
<p>
|
||||
<a href="{{$baseurl}}/ratioed?o={{if $order_direction_users == "+"}}-{{/if}}{{$th_users.3.1}}" class="btn-link table-order">
|
||||
↕ {{$th_users.3.0}}</a> : {{$u.login_date}}
|
||||
</p>
|
||||
{{/if}}
|
||||
|
||||
{{if $order_users != $th_users.4.1}}
|
||||
<p>
|
||||
<a href="{{$baseurl}}/ratioed?o={{if $order_direction_users == "+"}}-{{/if}}{{$th_users.4.1}}" class="btn-link table-order">
|
||||
↕ {{$th_users.4.0}}</a> : {{$u.lastitem_date}}
|
||||
</p>
|
||||
{{/if}}
|
||||
|
||||
{{if in_array($order_users,[$th_users.2.1, $th_users.3.1, $th_users.4.1]) }}
|
||||
<p>
|
||||
<a href="{{$baseurl}}/ratioed?o={{if $order_direction_users == "+"}}-{{/if}}{{$th_users.5.1}}" class="btn-link table-order">
|
||||
↕ {{$th_users.5.0}}</a> : {{$u.page_flags}}{{if $u.page_flags_raw==0 && $u.account_type_raw > 0}}, {{$u.account_type}}{{/if}} {{if $u.is_admin}}({{$siteadmin}}){{/if}} {{if $u.account_expired}}({{$accountexpired}}){{/if}}
|
||||
</p>
|
||||
{{/if}}
|
||||
|
||||
{{foreach $th_users as $k=>$th}}
|
||||
{{if $order_users != $th.1 && $k > 5}}
|
||||
<p>
|
||||
{{$th.0}} : {{$u[$th.2]}}
|
||||
</p>
|
||||
{{/if}}
|
||||
{{/foreach}}
|
||||
|
||||
</td>
|
||||
<td class="text-right">
|
||||
{{if $u.is_deletable}}
|
||||
<a href="{{$baseurl}}/moderation/users/active/block/{{$u.uid}}?t={{$form_security_token}}" class="admin-settings-action-link" title="{{$block}}">
|
||||
<i class="fa fa-ban" aria-hidden="true"></i>
|
||||
</a>
|
||||
<a href="{{$baseurl}}/moderation/users/active/delete/{{$u.uid}}?t={{$form_security_token}}" class="admin-settings-action-link" title="{{$delete}}" onclick="return confirm_delete('{{$confirm_delete}}','{{$u.name}}')">
|
||||
<i class="fa fa-trash" aria-hidden="true"></i>
|
||||
</a>
|
||||
{{else}}
|
||||
|
||||
{{/if}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/foreach}}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="panel-footer">
|
||||
<button type="submit" name="page_users_block" value="1" class="btn btn-warning">
|
||||
<i class="fa fa-ban" aria-hidden="true"></i> {{$block}}
|
||||
</button>
|
||||
<button type="submit" name="page_users_delete" value="1" class="btn btn-danger" onclick="return confirm_delete('{{$confirm_delete_multi}}')">
|
||||
<i class="fa fa-trash" aria-hidden="true"></i> {{$delete}}
|
||||
</button>
|
||||
</div>
|
||||
{{$pager nofilter}}
|
||||
</form>
|
||||
</div>
|
BIN
smiley_pack/icons/commercial/facebook.gif
Normal file
After Width: | Height: | Size: 269 B |
BIN
smiley_pack/icons/commercial/github.png
Normal file
After Width: | Height: | Size: 4.6 KiB |
BIN
smiley_pack/icons/commercial/google.gif
Normal file
After Width: | Height: | Size: 270 B |
BIN
smiley_pack/icons/commercial/instagram.gif
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
smiley_pack/icons/commercial/signal.gif
Normal file
After Width: | Height: | Size: 339 B |
BIN
smiley_pack/icons/commercial/telegram.gif
Normal file
After Width: | Height: | Size: 627 B |
BIN
smiley_pack/icons/commercial/threads.png
Normal file
After Width: | Height: | Size: 1 KiB |
BIN
smiley_pack/icons/commercial/threema.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
smiley_pack/icons/commercial/tiktok.gif
Normal file
After Width: | Height: | Size: 257 B |
BIN
smiley_pack/icons/commercial/whatsapp.gif
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
smiley_pack/icons/commercial/windows.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 79 B After Width: | Height: | Size: 1.1 KiB |
BIN
smiley_pack/icons/fediverse/diaspora.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
smiley_pack/icons/fediverse/fediverse.gif
Normal file
After Width: | Height: | Size: 444 B |
BIN
smiley_pack/icons/fediverse/friendica.png
Normal file
After Width: | Height: | Size: 4.6 KiB |
BIN
smiley_pack/icons/fediverse/funkwhale.gif
Normal file
After Width: | Height: | Size: 471 B |
BIN
smiley_pack/icons/fediverse/gnusocial.gif
Normal file
After Width: | Height: | Size: 135 B |
BIN
smiley_pack/icons/fediverse/hubzilla.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
smiley_pack/icons/fediverse/lemmy.gif
Normal file
After Width: | Height: | Size: 418 B |
Before Width: | Height: | Size: 405 B After Width: | Height: | Size: 1.1 KiB |
BIN
smiley_pack/icons/fediverse/peertube.gif
Normal file
After Width: | Height: | Size: 137 B |
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 100 B After Width: | Height: | Size: 180 B |
BIN
smiley_pack/icons/fediverse/plume.gif
Normal file
After Width: | Height: | Size: 410 B |
BIN
smiley_pack/icons/fediverse/writefreely.gif
Normal file
After Width: | Height: | Size: 112 B |
BIN
smiley_pack/icons/noncommercial/bluesky.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
smiley_pack/icons/noncommercial/invidious.gif
Normal file
After Width: | Height: | Size: 908 B |
BIN
smiley_pack/icons/noncommercial/vivaldi.png
Normal file
After Width: | Height: | Size: 4.8 KiB |
BIN
smiley_pack/icons/opensource/archlinux.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
smiley_pack/icons/opensource/debian.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
BIN
smiley_pack/icons/opensource/fdroid.png
Normal file
After Width: | Height: | Size: 7.7 KiB |
BIN
smiley_pack/icons/opensource/fedora.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
smiley_pack/icons/opensource/firefox.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
smiley_pack/icons/opensource/firefoxnightly.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
smiley_pack/icons/opensource/foss.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
smiley_pack/icons/opensource/jabber.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
smiley_pack/icons/opensource/kde.png
Normal file
After Width: | Height: | Size: 4.6 KiB |
BIN
smiley_pack/icons/opensource/linux.png
Normal file
After Width: | Height: | Size: 5 KiB |
BIN
smiley_pack/icons/opensource/matrix.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
smiley_pack/icons/opensource/mint.png
Normal file
After Width: | Height: | Size: 8.5 KiB |
BIN
smiley_pack/icons/opensource/opensuse.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
smiley_pack/icons/opensource/raspi.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
smiley_pack/icons/opensource/thunderbird.png
Normal file
After Width: | Height: | Size: 4.6 KiB |
BIN
smiley_pack/icons/opensource/tutanota.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
smiley_pack/icons/opensource/ubuntu.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
smiley_pack/icons/opensource/xmpp.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
smiley_pack/icons/respect/cc.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
smiley_pack/icons/respect/cc0.png
Normal file
After Width: | Height: | Size: 4.6 KiB |
BIN
smiley_pack/icons/respect/ccby.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
smiley_pack/icons/respect/ccsa.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
|
@ -2,17 +2,17 @@
|
|||
/*
|
||||
* Name: Smiley Pack
|
||||
* Description: Pack of smileys that make master too AOLish.
|
||||
* Version: 1.05
|
||||
* Version: 1.06
|
||||
* Author: Thomas Willingham (based on Mike Macgirvin's Adult Smile template)
|
||||
* Author: Matthias Ebers <https://loma.ml/profile/one>
|
||||
* All smileys from sites offering them as Public Domain
|
||||
*/
|
||||
|
||||
use Friendica\App;
|
||||
use Friendica\Core\Hook;
|
||||
use Friendica\DI;
|
||||
|
||||
function smiley_pack_install() {
|
||||
function smiley_pack_install()
|
||||
{
|
||||
Hook::register('smilie', 'addon/smiley_pack/smiley_pack.php', 'smiley_pack_smilies');
|
||||
}
|
||||
|
||||
|
@ -23,8 +23,6 @@ function smiley_pack_smilies(array &$b)
|
|||
#Be careful with invocation strings. If you have a smiley called foo, and another called foobar, typing :foobar will call foo. Avoid this with clever naming, using ~ instead of :
|
||||
#when all else fails.
|
||||
|
||||
|
||||
|
||||
#Animal smileys.
|
||||
|
||||
$b['texts'][] = ':bunnyflowers:';
|
||||
|
@ -99,8 +97,6 @@ function smiley_pack_smilies(array &$b)
|
|||
$b['texts'][] = ':pig:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/animals/pig.gif' . '" alt="' . ':pig:' . '" />';
|
||||
|
||||
|
||||
|
||||
#Baby Smileys
|
||||
|
||||
$b['texts'][] = ':baby:';
|
||||
|
@ -109,14 +105,12 @@ function smiley_pack_smilies(array &$b)
|
|||
$b['texts'][] = ':babycot:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/babies/babycot.gif' . '" alt="' . ':babycot:' . '" />';
|
||||
|
||||
|
||||
$b['texts'][] = ':pregnant:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/babies/pregnant.gif' . '" alt="' . ':pregnant:' . '" />';
|
||||
|
||||
$b['texts'][] = ':stork:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/babies/stork.gif' . '" alt="' . ':stork:' . '" />';
|
||||
|
||||
|
||||
#Confused Smileys
|
||||
$b['texts'][] = ':confused:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/confused/confused.gif' . '" alt="' . ':confused:' . '" />';
|
||||
|
@ -130,7 +124,6 @@ function smiley_pack_smilies(array &$b)
|
|||
$b['texts'][] = ':dazed:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/confused/dazed.gif' . '" alt="' . ':dazed:' . '" />';
|
||||
|
||||
|
||||
#Cool Smileys
|
||||
|
||||
$b['texts'][] = ':affro:';
|
||||
|
@ -390,6 +383,18 @@ function smiley_pack_smilies(array &$b)
|
|||
$b['texts'][] = ':number1:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/respect/number1.gif' . '" alt="' . ':number1:' . '" />';
|
||||
|
||||
$b['texts'][] = ':cc_cc:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/respect/cc.png' . '" alt="' . ':cc_cc:' . '" />';
|
||||
|
||||
$b['texts'][] = ':cc_by:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/respect/ccby.png' . '" alt="' . ':cc_by:' . '" />';
|
||||
|
||||
$b['texts'][] = ':cc_sa:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/respect/ccsa.png' . '" alt="' . ':cc_sa:' . '" />';
|
||||
|
||||
$b['texts'][] = ':cc_0:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/respect/cc0.png' . '" alt="' . ':cc_0:' . '" />';
|
||||
|
||||
#Laugh smileys
|
||||
|
||||
$b['texts'][] = ':hahaha:';
|
||||
|
@ -406,7 +411,6 @@ function smiley_pack_smilies(array &$b)
|
|||
$b['texts'][] = ':drums:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/music/drums.gif' . '" alt="' . ':drums:' . '" />';
|
||||
|
||||
|
||||
$b['texts'][] = ':guitar:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/music/guitar.gif' . '" alt="' . ':guitar:' . '" />';
|
||||
|
||||
|
@ -480,11 +484,9 @@ function smiley_pack_smilies(array &$b)
|
|||
$b['texts'][] = ':gangs:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/fight/gangs.gif' . '" alt="' . ':gangs:' . '" />';
|
||||
|
||||
|
||||
$b['texts'][] = ':dj:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/music/dj.gif' . '" alt="' . ':dj:' . '" />';
|
||||
|
||||
|
||||
$b['texts'][] = ':elvis:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/music/elvis.gif' . '" alt="' . ':elivs:' . '" />';
|
||||
|
||||
|
@ -495,7 +497,10 @@ function smiley_pack_smilies(array &$b)
|
|||
# Fediverse
|
||||
|
||||
$b['texts'][] = ':friendica:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/fediverse/friendica.gif' . '" alt="' . ':friendica:' . '" />';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/fediverse/friendica.png' . '" alt="' . ':friendica:' . '" />';
|
||||
|
||||
$b['texts'][] = ':fediverse:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/fediverse/fediverse.gif' . '" alt="' . ':fediverse:' . '" />';
|
||||
|
||||
$b['texts'][] = ':mastodon:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/fediverse/mastodon.gif' . '" alt="' . ':mastodon:' . '" />';
|
||||
|
@ -507,10 +512,10 @@ function smiley_pack_smilies(array &$b)
|
|||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/fediverse/misskey.gif' . '" alt="' . ':misskey:' . '" />';
|
||||
|
||||
$b['texts'][] = ':diaspora:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/fediverse/diaspora.gif' . '" alt="' . ':diaspora:' . '" />';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/fediverse/diaspora.png' . '" alt="' . ':diaspora:' . '" />';
|
||||
|
||||
$b['texts'][] = ':hubzilla:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/fediverse/hubzilla.gif' . '" alt="' . ':hubzilla:' . '" />';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/fediverse/hubzilla.png' . '" alt="' . ':hubzilla:' . '" />';
|
||||
|
||||
$b['texts'][] = ':pixelfed:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/fediverse/pixelfed.gif' . '" alt="' . ':pixelfeed:' . '" />';
|
||||
|
@ -539,4 +544,107 @@ function smiley_pack_smilies(array &$b)
|
|||
|
||||
$b['texts'][] = ':twitch:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/commercial/twitch.gif' . '" alt="' . ':twitch:' . '" />';
|
||||
|
||||
$b['texts'][] = ':facebook:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/commercial/facebook.gif' . '" alt="' . ':facebook:' . '" />';
|
||||
|
||||
$b['texts'][] = ':threads:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/commercial/threads.png' . '" alt="' . ':threads:' . '" />';
|
||||
|
||||
$b['texts'][] = ':google:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/commercial/google.gif' . '" alt="' . ':google:' . '" />';
|
||||
|
||||
$b['texts'][] = ':signal:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/commercial/signal.gif' . '" alt="' . ':signal:' . '" />';
|
||||
|
||||
$b['texts'][] = ':tiktok:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/commercial/tiktok.gif' . '" alt="' . ':tiktok:' . '" />';
|
||||
|
||||
$b['texts'][] = ':whatsapp:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/commercial/whatsapp.gif' . '" alt="' . ':whatsapp:' . '" />';
|
||||
|
||||
$b['texts'][] = ':instagram:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/commercial/instagram.gif' . '" alt="' . ':instagram:' . '" />';
|
||||
|
||||
$b['texts'][] = ':telegram:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/commercial/telegram.gif' . '" alt="' . ':telegram:' . '" />';
|
||||
|
||||
$b['texts'][] = ':windows:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/commercial/windows.png' . '" alt="' . ':windows:' . '" />';
|
||||
|
||||
$b['texts'][] = ':github:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/commercial/github.png' . '" alt="' . ':github:' . '" />';
|
||||
|
||||
$b['texts'][] = ':threema:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/commercial/threema.png' . '" alt="' . ':threema:' . '" />';
|
||||
|
||||
# nonCommercial
|
||||
|
||||
$b['texts'][] = ':invidious:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/noncommercial/invidious.gif' . '" alt="' . ':invidious:' . '" />';
|
||||
|
||||
$b['texts'][] = ':bluesky:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/noncommercial/bluesky.png' . '" alt="' . ':bluesky:' . '" />';
|
||||
|
||||
$b['texts'][] = ':vivaldi:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/noncommercial/vivaldi.png' . '" alt="' . ':vivaldi:' . '" />';
|
||||
|
||||
# opensource
|
||||
|
||||
$b['texts'][] = ':firefox:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/firefox.png' . '" alt="' . ':firefox:' . '" />';
|
||||
|
||||
$b['texts'][] = ':linuxopensuse:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/opensuse.png' . '" alt="' . ':linuxopensuse:' . '" />';
|
||||
|
||||
$b['texts'][] = ':linuxdebian:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/debian.png' . '" alt="' . ':linuxdebian:' . '" />';
|
||||
|
||||
$b['texts'][] = ':linuxfedora:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/fedora.png' . '" alt="' . ':linuxfedora:' . '" />';
|
||||
|
||||
$b['texts'][] = ':linuxubuntu:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/ubuntu.png' . '" alt="' . ':linuxubuntu:' . '" />';
|
||||
|
||||
$b['texts'][] = ':linuxmint:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/mint.png' . '" alt="' . ':linuxmint:' . '" />';
|
||||
|
||||
$b['texts'][] = ':fdroid:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/fdroid.png' . '" alt="' . ':fdroid:' . '" />';
|
||||
|
||||
$b['texts'][] = ':tutanota:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/tutanota.png' . '" alt="' . ':tutanota:' . '" />';
|
||||
|
||||
$b['texts'][] = ':raspi:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/raspi.png' . '" alt="' . ':raspi:' . '" />';
|
||||
|
||||
$b['texts'][] = ':linux:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/linux.png' . '" alt="' . ':linux:' . '" />';
|
||||
|
||||
$b['texts'][] = ':kde:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/kde.png' . '" alt="' . ':kde:' . '" />';
|
||||
|
||||
$b['texts'][] = ':firefoxnightly:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/firefoxnightly.png' . '" alt="' . ':firefoxnightly:' . '" />';
|
||||
|
||||
$b['texts'][] = ':archlinux:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/archlinux.png' . '" alt="' . ':archlinux:' . '" />';
|
||||
|
||||
$b['texts'][] = ':thunderbird:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/thunderbird.png' . '" alt="' . ':thunderbird:' . '" />';
|
||||
|
||||
$b['texts'][] = ':vivaldi:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/vivaldi.png' . '" alt="' . ':vivaldi:' . '" />';
|
||||
|
||||
$b['texts'][] = ':jabber:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/jabber.png' . '" alt="' . ':jabber:' . '" />';
|
||||
|
||||
$b['texts'][] = ':matrix:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/matrix.png' . '" alt="' . ':matrix:' . '" />';
|
||||
|
||||
$b['texts'][] = ':xmpp:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/xmpp.png' . '" alt="' . ':xmpp:' . '" />';
|
||||
|
||||
$b['texts'][] = ':foss:';
|
||||
$b['icons'][] = '<img class="smiley" src="' . DI::baseUrl() . '/addon/smiley_pack/icons/opensource/foss.png' . '" alt="' . ':foss:' . '" />';
|
||||
}
|
||||
|
|
|
@ -133,6 +133,7 @@ function tumblr_item_by_link(array &$hookData)
|
|||
Logger::debug('Got post', ['blog' => $matches[1], 'id' => $matches[2], 'result' => $result->response->posts]);
|
||||
if (!empty($result->response->posts)) {
|
||||
$hookData['item_id'] = tumblr_process_post($result->response->posts[0], $hookData['uid'], Item::PR_FETCHED);
|
||||
Item::incrementInbound(Protocol::TUMBLR);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -203,9 +204,9 @@ function tumblr_block(array &$hook_data)
|
|||
$hook_data['result'] = ($result->meta->status <= 399);
|
||||
|
||||
if ($hook_data['result']) {
|
||||
$cdata = Contact::getPublicAndUserContactID($hook_data['contact']['id'], $hook_data['uid']);
|
||||
if (!empty($cdata['user'])) {
|
||||
Contact::remove($cdata['user']);
|
||||
$ucid = Contact::getUserContactId($hook_data['contact']['id'], $hook_data['uid']);
|
||||
if ($ucid) {
|
||||
Contact::remove($ucid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -238,9 +239,7 @@ function tumblr_get_contact_uuid(array $contact): string
|
|||
* existence of this method is checked to figure out if the addon offers a
|
||||
* module.
|
||||
*/
|
||||
function tumblr_module()
|
||||
{
|
||||
}
|
||||
function tumblr_module() {}
|
||||
|
||||
function tumblr_content()
|
||||
{
|
||||
|
@ -756,6 +755,7 @@ function tumblr_fetch_tags(int $uid, int $last_poll)
|
|||
$post = Post::selectFirst(['uri-id'], ['id' => $id]);
|
||||
$stored = Post\Category::storeFileByURIId($post['uri-id'], $uid, Post\Category::SUBCRIPTION, $tag);
|
||||
Logger::debug('Stored tag subscription for user', ['uri-id' => $post['uri-id'], 'uid' => $uid, 'tag' => $tag, 'stored' => $stored]);
|
||||
Item::incrementInbound(Protocol::TUMBLR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -795,6 +795,7 @@ function tumblr_fetch_dashboard(int $uid, int $last_poll)
|
|||
Logger::debug('Importing post', ['uid' => $uid, 'created' => date(DateTimeFormat::MYSQL, $post->timestamp), 'id' => $post->id_string]);
|
||||
|
||||
tumblr_process_post($post, $uid, Item::PR_NONE, $last_poll);
|
||||
Item::incrementInbound(Protocol::TUMBLR);
|
||||
|
||||
DI::pConfig()->set($uid, 'tumblr', 'last_id', $last);
|
||||
}
|
||||
|
@ -1167,6 +1168,7 @@ function tumblr_get_contact_fields(stdClass $blog, int $uid, bool $update): arra
|
|||
Logger::notice('Error fetching blog info', ['meta' => $info->meta, 'response' => $info->response, 'errors' => $info->errors]);
|
||||
return $fields;
|
||||
}
|
||||
Item::incrementInbound(Protocol::TUMBLR);
|
||||
|
||||
$avatar = $info->response->blog->avatar;
|
||||
if (!empty($avatar)) {
|
||||
|
@ -1231,6 +1233,8 @@ function tumblr_get_blogs(int $uid): array
|
|||
return [];
|
||||
}
|
||||
|
||||
Item::incrementInbound(Protocol::TUMBLR);
|
||||
|
||||
$blogs = [];
|
||||
foreach ($userinfo->response->user->blogs as $blog) {
|
||||
$blogs[$blog->uuid] = $blog->name;
|
||||
|
@ -1287,10 +1291,11 @@ function tumblr_get_contact_by_url(string $url, int $uid): ?array
|
|||
if ($info->meta->status > 399) {
|
||||
Logger::notice('Error fetching blog info', ['meta' => $info->meta, 'response' => $info->response, 'errors' => $info->errors, 'blog' => $blog, 'uid' => $uid]);
|
||||
return null;
|
||||
} else {
|
||||
Logger::debug('Got data', ['blog' => $blog, 'meta' => $info->meta]);
|
||||
}
|
||||
|
||||
Logger::debug('Got data', ['blog' => $blog, 'meta' => $info->meta]);
|
||||
Item::incrementInbound(Protocol::TUMBLR);
|
||||
|
||||
$baseurl = 'https://tumblr.com';
|
||||
$url = $baseurl . '/' . $info->response->blog->name;
|
||||
|
||||
|
@ -1355,6 +1360,7 @@ function tumblr_get(int $uid, string $url, array $parameters = []): stdClass
|
|||
*/
|
||||
function tumblr_post(int $uid, string $url, array $parameters): stdClass
|
||||
{
|
||||
Item::incrementOutbound(Protocol::TUMBLR);
|
||||
$url = 'https://api.tumblr.com/v2/' . $url;
|
||||
|
||||
$curlResult = DI::httpClient()->post($url, $parameters, ['Authorization' => ['Bearer ' . tumblr_get_token($uid)]]);
|
||||
|
|
|
@ -1293,6 +1293,8 @@ function unicode_smilies_smilies(array &$b)
|
|||
Smilies::add($b, ':microscope:', '🔬');
|
||||
Smilies::add($b, ':telescope:', '🔭');
|
||||
Smilies::add($b, ':satellite antenna:', '📡');
|
||||
Smilies::add($b, ':asterism:', '⁂');
|
||||
Smilies::add($b, ':outlines white star:', '⚝');
|
||||
|
||||
// medical
|
||||
Smilies::add($b, ':syringe:', '💉');
|
||||
|
|