forked from friendica/friendica-addons
Compare commits
4 commits
454e9834bf
...
6c43a14198
Author | SHA1 | Date | |
---|---|---|---|
Tobias Diekershoff | 6c43a14198 | ||
Michael | 0dfb345f85 | ||
Tobias Diekershoff | ab837dfec5 | ||
Michael | 2f9076bffd |
|
@ -45,10 +45,12 @@ use Friendica\Model\Tag;
|
||||||
use Friendica\Model\User;
|
use Friendica\Model\User;
|
||||||
use Friendica\Network\HTTPClient\Client\HttpClientAccept;
|
use Friendica\Network\HTTPClient\Client\HttpClientAccept;
|
||||||
use Friendica\Network\HTTPClient\Client\HttpClientOptions;
|
use Friendica\Network\HTTPClient\Client\HttpClientOptions;
|
||||||
|
use Friendica\Network\HTTPClient\Client\HttpClientRequest;
|
||||||
use Friendica\Object\Image;
|
use Friendica\Object\Image;
|
||||||
use Friendica\Protocol\Activity;
|
use Friendica\Protocol\Activity;
|
||||||
use Friendica\Protocol\Relay;
|
use Friendica\Protocol\Relay;
|
||||||
use Friendica\Util\DateTimeFormat;
|
use Friendica\Util\DateTimeFormat;
|
||||||
|
use Friendica\Util\Network;
|
||||||
use Friendica\Util\Strings;
|
use Friendica\Util\Strings;
|
||||||
|
|
||||||
const BLUESKY_DEFAULT_POLL_INTERVAL = 10; // given in minutes
|
const BLUESKY_DEFAULT_POLL_INTERVAL = 10; // given in minutes
|
||||||
|
@ -129,8 +131,13 @@ function bluesky_probe_detect(array &$hookData)
|
||||||
|
|
||||||
if (parse_url($hookData['uri'], PHP_URL_SCHEME) == 'did') {
|
if (parse_url($hookData['uri'], PHP_URL_SCHEME) == 'did') {
|
||||||
$did = $hookData['uri'];
|
$did = $hookData['uri'];
|
||||||
} elseif (preg_match('#^' . BLUESKY_WEB . '/profile/(.+)#', $hookData['uri'], $matches)) {
|
} elseif (parse_url($hookData['uri'], PHP_URL_PATH) == $hookData['uri'] && strpos($hookData['uri'], '@') === false) {
|
||||||
$did = bluesky_get_did($matches[1]);
|
$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']);
|
||||||
if (empty($did)) {
|
if (empty($did)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -148,19 +155,14 @@ function bluesky_probe_detect(array &$hookData)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$hookData['result'] = bluesky_get_contact_fields($data, 0, $pconfig['uid'], false);
|
$hookData['result'] = bluesky_get_contact_fields($data, 0, $pconfig['uid'], true);
|
||||||
|
|
||||||
$hookData['result']['baseurl'] = bluesky_get_pds($did);
|
|
||||||
|
|
||||||
// Preparing probe data. This differs slightly from the contact array
|
// Preparing probe data. This differs slightly from the contact array
|
||||||
$hookData['result']['about'] = HTML::toBBCode($data->description ?? '');
|
|
||||||
$hookData['result']['photo'] = $data->avatar ?? '';
|
$hookData['result']['photo'] = $data->avatar ?? '';
|
||||||
$hookData['result']['header'] = $data->banner ?? '';
|
|
||||||
$hookData['result']['batch'] = '';
|
$hookData['result']['batch'] = '';
|
||||||
$hookData['result']['notify'] = '';
|
$hookData['result']['notify'] = '';
|
||||||
$hookData['result']['poll'] = '';
|
$hookData['result']['poll'] = '';
|
||||||
$hookData['result']['poco'] = '';
|
$hookData['result']['poco'] = '';
|
||||||
$hookData['result']['pubkey'] = '';
|
|
||||||
$hookData['result']['priority'] = 0;
|
$hookData['result']['priority'] = 0;
|
||||||
$hookData['result']['guid'] = '';
|
$hookData['result']['guid'] = '';
|
||||||
}
|
}
|
||||||
|
@ -177,21 +179,21 @@ function bluesky_item_by_link(array &$hookData)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!preg_match('#^' . BLUESKY_WEB . '/profile/(.+)/post/(.+)#', $hookData['uri'], $matches)) {
|
$did = bluesky_get_did_by_profile($hookData['uri']);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$did = bluesky_get_did($matches[1]);
|
|
||||||
if (empty($did)) {
|
if (empty($did)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger::debug('Found bluesky post', ['url' => $hookData['uri'], 'handle' => $matches[1], 'did' => $did, 'cid' => $matches[2]]);
|
if (!preg_match('#/profile/.+/post/(.+)#', $hookData['uri'], $matches)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$uri = 'at://' . $did . '/app.bsky.feed.post/' . $matches[2];
|
Logger::debug('Found bluesky post', ['url' => $hookData['uri'], 'did' => $did, 'cid' => $matches[1]]);
|
||||||
|
|
||||||
|
$uri = 'at://' . $did . '/app.bsky.feed.post/' . $matches[1];
|
||||||
|
|
||||||
$uri = bluesky_fetch_missing_post($uri, $hookData['uid'], $hookData['uid'], Item::PR_FETCHED, 0, 0, 0);
|
$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[1], 'result' => $uri]);
|
||||||
if (!empty($uri)) {
|
if (!empty($uri)) {
|
||||||
$item = Post::selectFirst(['id'], ['uri' => $uri, 'uid' => $hookData['uid']]);
|
$item = Post::selectFirst(['id'], ['uri' => $uri, 'uid' => $hookData['uid']]);
|
||||||
if (!empty($item['id'])) {
|
if (!empty($item['id'])) {
|
||||||
|
@ -1678,11 +1680,15 @@ function bluesky_get_contact_fields(stdClass $author, int $uid, int $fetch_uid,
|
||||||
return $fields;
|
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'])) {
|
if (!empty($fields['baseurl'])) {
|
||||||
GServer::check($fields['baseurl'], Protocol::BLUESKY);
|
GServer::check($fields['baseurl'], Protocol::BLUESKY);
|
||||||
$fields['gsid'] = GServer::getID($fields['baseurl'], true);
|
$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]);
|
$data = bluesky_xrpc_get($fetch_uid, 'app.bsky.actor.getProfile', ['actor' => $author->did]);
|
||||||
if (empty($data)) {
|
if (empty($data)) {
|
||||||
|
@ -1748,6 +1754,42 @@ function bluesky_get_preferences(int $uid): ?stdClass
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function bluesky_get_did_by_profile(string $url): string
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$curlResult = DI::httpClient()->get($url, HttpClientAccept::HTML, [HttpClientOptions::REQUEST => HttpClientRequest::CONTACTINFO]);
|
||||||
|
} catch (\Throwable $th) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
if (!$curlResult->isSuccess()) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
$profile = $curlResult->getBodyString();
|
||||||
|
|
||||||
|
$doc = new DOMDocument();
|
||||||
|
@$doc->loadHTML($profile);
|
||||||
|
$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
|
function bluesky_get_did_by_wellknown(string $handle): string
|
||||||
{
|
{
|
||||||
$curlResult = DI::httpClient()->get('http://' . $handle . '/.well-known/atproto-did');
|
$curlResult = DI::httpClient()->get('http://' . $handle . '/.well-known/atproto-did');
|
||||||
|
@ -1757,7 +1799,6 @@ function bluesky_get_did_by_wellknown(string $handle): string
|
||||||
Logger::notice('Invalid DID', ['handle' => $handle, 'did' => $did]);
|
Logger::notice('Invalid DID', ['handle' => $handle, 'did' => $did]);
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
Logger::debug('Got DID by wellknown', ['handle' => $handle, 'did' => $did]);
|
|
||||||
return $did;
|
return $did;
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
|
@ -1776,14 +1817,13 @@ function bluesky_get_did_by_dns(string $handle): string
|
||||||
Logger::notice('Invalid DID', ['handle' => $handle, 'did' => $did]);
|
Logger::notice('Invalid DID', ['handle' => $handle, 'did' => $did]);
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
Logger::debug('Got DID by DNS', ['handle' => $handle, 'did' => $did]);
|
|
||||||
return $did;
|
return $did;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function bluesky_get_did(string $handle): string
|
function bluesky_get_did(string $handle, int $uid): string
|
||||||
{
|
{
|
||||||
if ($handle == '') {
|
if ($handle == '') {
|
||||||
return '';
|
return '';
|
||||||
|
@ -1793,19 +1833,39 @@ function bluesky_get_did(string $handle): string
|
||||||
$handle .= '.' . BLUESKY_HOSTNAME;
|
$handle .= '.' . BLUESKY_HOSTNAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = bluesky_get(BLUESKY_PDS . '/xrpc/com.atproto.identity.resolveHandle?handle=' . urlencode($handle));
|
// 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)) {
|
if (!empty($data) && !empty($data->did)) {
|
||||||
Logger::debug('Got DID by PDS call', ['handle' => $handle, 'did' => $data->did]);
|
Logger::debug('Got DID by user PDS call', ['handle' => $handle, 'did' => $data->did]);
|
||||||
return $data->did;
|
return $data->did;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Possibly a custom PDS.
|
// 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);
|
$did = bluesky_get_did_by_dns($handle);
|
||||||
if ($did != '') {
|
if ($did != '') {
|
||||||
|
Logger::debug('Got DID by DNS', ['handle' => $handle, 'did' => $did]);
|
||||||
return $did;
|
return $did;
|
||||||
}
|
}
|
||||||
|
|
||||||
return bluesky_get_did_by_wellknown($handle);
|
// 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
|
function bluesky_get_user_did(int $uid, bool $refresh = false): ?string
|
||||||
|
@ -1822,7 +1882,7 @@ function bluesky_get_user_did(int $uid, bool $refresh = false): ?string
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$did = bluesky_get_did($handle);
|
$did = bluesky_get_did($handle, $uid);
|
||||||
if (empty($did)) {
|
if (empty($did)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -1853,9 +1913,11 @@ function bluesky_get_user_pds(int $uid): ?string
|
||||||
return $pds;
|
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);
|
$data = bluesky_get(BLUESKY_DIRECTORY . '/' . $did);
|
||||||
|
}
|
||||||
if (empty($data) || empty($data->service)) {
|
if (empty($data) || empty($data->service)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -1869,6 +1931,22 @@ function bluesky_get_pds(string $did): ?string
|
||||||
return null;
|
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
|
function bluesky_valid_did(string $did, string $handle): bool
|
||||||
{
|
{
|
||||||
$data = bluesky_get(BLUESKY_DIRECTORY . '/' . $did);
|
$data = bluesky_get(BLUESKY_DIRECTORY . '/' . $did);
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
* Author: Matthew Exon <http://mat.exon.name>
|
* Author: Matthew Exon <http://mat.exon.name>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Friendica\App;
|
|
||||||
use Friendica\Content\Text\BBCode;
|
use Friendica\Content\Text\BBCode;
|
||||||
use Friendica\Core\Hook;
|
use Friendica\Core\Hook;
|
||||||
use Friendica\Core\Logger;
|
use Friendica\Core\Logger;
|
||||||
|
@ -16,12 +15,11 @@ use Friendica\Core\Worker;
|
||||||
use Friendica\Database\DBA;
|
use Friendica\Database\DBA;
|
||||||
use Friendica\DI;
|
use Friendica\DI;
|
||||||
use Friendica\Model\Contact;
|
use Friendica\Model\Contact;
|
||||||
use Friendica\Model\Item;
|
|
||||||
use Friendica\Model\Post;
|
use Friendica\Model\Post;
|
||||||
use Friendica\Model\User;
|
use Friendica\Model\User;
|
||||||
use Friendica\Network\HTTPClient\Client\HttpClientAccept;
|
use Friendica\Network\HTTPClient\Client\HttpClientAccept;
|
||||||
|
use Friendica\Network\HTTPClient\Client\HttpClientOptions;
|
||||||
use Friendica\Protocol\Activity;
|
use Friendica\Protocol\Activity;
|
||||||
use Friendica\Util\DateTimeFormat;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up the addon hooks and the database table
|
* Sets up the addon hooks and the database table
|
||||||
|
@ -53,10 +51,12 @@ function mailstream_addon_admin(string &$o)
|
||||||
{
|
{
|
||||||
$frommail = DI::config()->get('mailstream', 'frommail');
|
$frommail = DI::config()->get('mailstream', 'frommail');
|
||||||
$template = Renderer::getMarkupTemplate('admin.tpl', 'addon/mailstream/');
|
$template = Renderer::getMarkupTemplate('admin.tpl', 'addon/mailstream/');
|
||||||
$config = ['frommail',
|
$config = [
|
||||||
|
'frommail',
|
||||||
DI::l10n()->t('From Address'),
|
DI::l10n()->t('From Address'),
|
||||||
$frommail,
|
$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, [
|
$o .= Renderer::replaceMacros($template, [
|
||||||
'$frommail' => $config,
|
'$frommail' => $config,
|
||||||
'$submit' => DI::l10n()->t('Save Settings')
|
'$submit' => DI::l10n()->t('Save Settings')
|
||||||
|
@ -198,10 +198,13 @@ function mailstream_do_images(array &$item, array &$attachments)
|
||||||
|
|
||||||
$cookiejar = tempnam(System::getTempPath(), 'cookiejar-mailstream-');
|
$cookiejar = tempnam(System::getTempPath(), 'cookiejar-mailstream-');
|
||||||
try {
|
try {
|
||||||
$curlResult = DI::httpClient()->fetchFull($url, HttpClientAccept::DEFAULT, 0, $cookiejar);
|
$curlResult = DI::httpClient()->get($url, HttpClientAccept::DEFAULT, [HttpClientOptions::COOKIEJAR => $cookiejar]);
|
||||||
if (!$curlResult->isSuccess()) {
|
if (!$curlResult->isSuccess()) {
|
||||||
Logger::debug('mailstream: fetch image url failed', [
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
} catch (InvalidArgumentException $e) {
|
} catch (InvalidArgumentException $e) {
|
||||||
|
@ -409,7 +412,8 @@ function mailstream_send(string $message_id, array $item, array $user): bool
|
||||||
'$upstream' => DI::l10n()->t('Upstream'),
|
'$upstream' => DI::l10n()->t('Upstream'),
|
||||||
'$uri' => DI::l10n()->t('URI'),
|
'$uri' => DI::l10n()->t('URI'),
|
||||||
'$local' => DI::l10n()->t('Local'),
|
'$local' => DI::l10n()->t('Local'),
|
||||||
'$item' => $item]);
|
'$item' => $item
|
||||||
|
]);
|
||||||
$mail->Body = mailstream_html_wrap($mail->Body);
|
$mail->Body = mailstream_html_wrap($mail->Body);
|
||||||
if (!$mail->Send()) {
|
if (!$mail->Send()) {
|
||||||
throw new Exception($mail->ErrorInfo);
|
throw new Exception($mail->ErrorInfo);
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Name: Mastodon Custom Emojis
|
* Name: Mastodon Custom Emojis
|
||||||
* Description: Replace emojis shortcodes in Mastodon posts with their originating server custom emojis images.
|
* Description: Replace emojis shortcodes in Mastodon posts with their originating server custom emojis images.
|
||||||
|
@ -9,7 +8,6 @@
|
||||||
* Status: Unsupported
|
* Status: Unsupported
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Friendica\App;
|
|
||||||
use Friendica\Content\Smilies;
|
use Friendica\Content\Smilies;
|
||||||
use Friendica\Core\Cache\Enum\Duration;
|
use Friendica\Core\Cache\Enum\Duration;
|
||||||
use Friendica\Core\Hook;
|
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';
|
$api_url = $api_base_url . '/api/v1/custom_emojis';
|
||||||
|
|
||||||
$fetchResult = DI::httpClient()->fetchFull($api_url);
|
$fetchResult = DI::httpClient()->get($api_url);
|
||||||
|
|
||||||
if ($fetchResult->isSuccess()) {
|
if ($fetchResult->isSuccess()) {
|
||||||
$emojis_array = json_decode($fetchResult->getBodyString(), true);
|
$emojis_array = json_decode($fetchResult->getBodyString(), true);
|
||||||
|
|
Loading…
Reference in a new issue