mirror of
https://gitlab.com/SpaccInc/SpaccCommunityPlatform.git
synced 2025-02-02 01:36:44 +01:00
[activitypub] v0.0.2: make posts loadable by url, with text and attached imgs
This commit is contained in:
parent
2067f380b5
commit
5bd77be244
@ -14,14 +14,16 @@
|
||||
<fieldset>
|
||||
<legend>{{ lang('SETTINGS') }}</legend>
|
||||
<dl>
|
||||
<dt><label for="spaccincphpbb_activitypub_setfederation">{{ lang('ACP_SPACCINC_ACTIVITYPUB_SETFEDERATION') ~ lang('COLON') }}</label></dt>
|
||||
<dd><label><input type="radio" class="radio" name="spaccincphpbb_activitypub_setfederation" value="1"{% if SPACCINCPHPBB_ACTIVITYPUB_SETFEDERATION %} checked="checked"{% endif %} /> {{ lang('YES') }}</label>
|
||||
<label><input type="radio" class="radio" name="spaccincphpbb_activitypub_setfederation" value="0"{% if not SPACCINCPHPBB_ACTIVITYPUB_SETFEDERATION %} checked="checked"{% endif %} /> {{ lang('NO') }}</label></dd>
|
||||
<dt><label for="spaccinc_activitypub_setfederation">{{ lang('ACP_SPACCINC_ACTIVITYPUB_SETFEDERATION') ~ lang('COLON') }}</label></dt>
|
||||
<dd><label><input type="radio" class="radio" name="spaccinc_activitypub_setfederation" value="1" {% if SPACCINC_ACTIVITYPUB_SETFEDERATION %} checked="checked" {% endif %} /> {{ lang('YES') }}</label>
|
||||
<label><input type="radio" class="radio" name="spaccinc_activitypub_setfederation" value="0" {% if not SPACCINC_ACTIVITYPUB_SETFEDERATION %} checked="checked" {% endif %} /> {{ lang('NO') }}</label></dd>
|
||||
</dl>
|
||||
<!--<dl>
|
||||
<dt><label for="spaccincphpbb_activitypub_setdomain">{{ lang('ACP_SPACCINC_ACTIVITYPUB_SETDOMAIN') ~ lang('COLON') }}</label><br /><span>{{ lang('ACP_SPACCINC_ACTIVITYPUB_SETDOMAIN_INFO') }}</span></dt>
|
||||
<dd><input name="spaccincphpbb_activitypub_setdomain" type="text" placeholder="TODO" value="TODO" disabled="TODO" /></dd>
|
||||
</dl>-->
|
||||
<!--
|
||||
<dl>
|
||||
<dt><label for="spaccinc_activitypub_setdomain">{{ lang('ACP_SPACCINC_ACTIVITYPUB_SETDOMAIN') ~ lang('COLON') }}</label><br /><span>{{ lang('ACP_SPACCINC_ACTIVITYPUB_SETDOMAIN_INFO') }}</span></dt>
|
||||
<dd><input name="spaccinc_activitypub_setdomain" type="text" placeholder="{{ SYS_SERVER_NAME }}" value="{{ SPACCINC_ACTIVITYPUB_SETDOMAIN }}" {% if SPACCINC_ACTIVITYPUB_SETDOMAIN != '' %} disabled="disabled" {% endif %} /></dd>
|
||||
</dl>
|
||||
-->
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="submit-buttons">
|
||||
|
@ -3,8 +3,8 @@
|
||||
"type": "phpbb-extension",
|
||||
"description": "ActivityPub for phpBB",
|
||||
"homepage": "https://gitlab.com/SpaccInc/SpaccCommunityPlatform",
|
||||
"version": "0.0.2-dev",
|
||||
"time": "2023-09-09",
|
||||
"version": "0.0.2",
|
||||
"time": "2023-09-13",
|
||||
"license": "[to be defined]",
|
||||
"authors": [
|
||||
{
|
||||
|
@ -3,8 +3,8 @@ services:
|
||||
class: spaccincphpbb\activitypub\controller\activitypub_controller
|
||||
arguments:
|
||||
- '@config'
|
||||
- '@request'
|
||||
- '@dbal.conn'
|
||||
- '@request'
|
||||
|
||||
spaccincphpbb.activitypub.controller.acp:
|
||||
class: spaccincphpbb\activitypub\controller\acp_controller
|
||||
|
@ -43,7 +43,8 @@ class acp_controller
|
||||
|
||||
if (empty($errors))
|
||||
{
|
||||
$this->config->set('spaccincphpbb_activitypub_setfederation', $this->request->variable('spaccincphpbb_activitypub_setfederation', 0));
|
||||
$this->config->set('spaccinc_activitypub_setfederation', $this->request->variable('spaccinc_activitypub_setfederation', 0));
|
||||
//$this->config->set('spaccinc_activitypub_setfederation', $this->request->variable('spaccinc_activitypub_setdomain', ''));
|
||||
$this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_ACP_SPACCINC_ACTIVITYPUB_SETTINGS');
|
||||
trigger_error($this->language->lang('CONFIG_UPDATED') . adm_back_link($this->u_action));
|
||||
}
|
||||
@ -53,9 +54,11 @@ class acp_controller
|
||||
|
||||
$this->template->assign_vars([
|
||||
'S_ERROR' => $s_errors,
|
||||
'ERROR_MSG' => $s_errors ? implode('<br />', $errors) : '',
|
||||
'ERROR_MSG' => ($s_errors ? implode('<br />', $errors) : ''),
|
||||
'U_ACTION' => $this->u_action,
|
||||
'SPACCINCPHPBB_ACTIVITYPUB_SETFEDERATION' => (bool)$this->config['spaccincphpbb_activitypub_setfederation'],
|
||||
'SYS_SERVER_NAME' => $this->config['server_name'],
|
||||
'SPACCINC_ACTIVITYPUB_SETFEDERATION' => (bool)$this->config['spaccinc_activitypub_setfederation'],
|
||||
'SPACCINC_ACTIVITYPUB_SETDOMAIN' => $this->config['spaccinc_activitypub_setdomain'],
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -3,48 +3,45 @@
|
||||
namespace spaccincphpbb\activitypub\controller;
|
||||
|
||||
use ErrorException;
|
||||
use DOMDocument;
|
||||
use DOMXpath;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class activitypub_controller
|
||||
{
|
||||
protected $config;
|
||||
protected $request;
|
||||
protected $db;
|
||||
protected $request;
|
||||
|
||||
// Quick way to force any PHP warning to be an error that halts execution and makes nothing return,
|
||||
// so that we don't need complex error handling in case of bad queries
|
||||
public function exception_error_handler($severity, $message, $file, $line)
|
||||
{
|
||||
if ($message !== 'Only variables should be passed by reference')
|
||||
{
|
||||
if ($message !== 'Return type of phpbb\datetime::format($format = \'\', $force_absolute = false) should either be compatible with DateTime::format(string $format): string, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice' && $message !== 'Only variables should be passed by reference' && !(str_contains($message, ' service is private, getting it from the container is deprecated ') || str_contains($message, 'You should either make the service public, or stop using the container directly and use dependency injection instead.'))
|
||||
){
|
||||
print $message;
|
||||
throw new ErrorException($message, 0, $severity, $file, $line);
|
||||
}
|
||||
}
|
||||
|
||||
public function __construct(
|
||||
\phpbb\config\config $config,
|
||||
\phpbb\request\request $request,
|
||||
\phpbb\db\driver\driver_interface $db,
|
||||
\phpbb\request\request $request,
|
||||
){
|
||||
$this->config = $config;
|
||||
$this->request = $request;
|
||||
$this->db = $db;
|
||||
$this->request = $request;
|
||||
|
||||
$this->site_name = $this->get_sql_row('
|
||||
SELECT config_value
|
||||
FROM ' . CONFIG_TABLE . "
|
||||
WHERE config_name = 'sitename'
|
||||
")['config_value'];
|
||||
|
||||
$this->server_name = $this->get_sql_row('
|
||||
SELECT config_value
|
||||
FROM ' . CONFIG_TABLE . "
|
||||
WHERE config_name = 'server_name'
|
||||
")['config_value'];
|
||||
|
||||
$this->server_name = $this->config['server_name'];
|
||||
$this->server_addr = ((!empty($this->request->server('HTTPS')) && (strtolower($this->request->server('HTTPS')) == 'on' || $this->request->server('HTTPS') == '1')) ? 'https://' : 'http://') . $this->server_name;
|
||||
}
|
||||
|
||||
private function iso_time($time)
|
||||
{
|
||||
return gmdate("Y-m-d\TH:i:s\Z", $time);
|
||||
}
|
||||
|
||||
private function get_sql_row($sql)
|
||||
{
|
||||
$result = $this->db->sql_query($sql);
|
||||
@ -53,9 +50,122 @@ class activitypub_controller
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function get_sql_rows($sql)
|
||||
{
|
||||
$result = $this->db->sql_query($sql);
|
||||
$data = $this->db->sql_fetchrowset($result);
|
||||
$this->db->sql_freeresult($result);
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function get_bbcode_flags($data)
|
||||
{
|
||||
return
|
||||
($data['enable_bbcode'] ? OPTION_FLAG_BBCODE : 0) +
|
||||
($data['enable_smilies'] ? OPTION_FLAG_SMILIES : 0) +
|
||||
($data['enable_magic_url'] ? OPTION_FLAG_LINKS : 0);
|
||||
}
|
||||
|
||||
private function make_post_attachments($html)
|
||||
{
|
||||
$attachments = [];
|
||||
|
||||
$dom = new DOMDocument;
|
||||
$dom->loadHTML($html);
|
||||
$xpath = new DOMXpath($dom);
|
||||
$imgs = $dom->getElementsByTagName('img');
|
||||
$atts = $xpath->query('//div[@class="inline-attachment"]');
|
||||
|
||||
// TODO: currently this picks up emojis, and must so be fixed
|
||||
//foreach($imgs as $item){
|
||||
// $attachments[] = [
|
||||
// 'type' => 'Document',
|
||||
// 'mediaType' => 'image/*',
|
||||
// 'url' => $item->getAttribute('src'),
|
||||
// //'name' => null,
|
||||
// ];
|
||||
//}
|
||||
unset($item);
|
||||
|
||||
foreach($atts as $item){
|
||||
$file_name = explode('<!--', explode('-->', $item->ownerDocument->saveHtml($item))[1])[0];
|
||||
|
||||
$file_id = $this->get_sql_row('
|
||||
SELECT attach_id
|
||||
FROM ' . ATTACHMENTS_TABLE . "
|
||||
WHERE real_filename='" . $this->db->sql_escape($file_name) . "'
|
||||
")['attach_id'];
|
||||
|
||||
$attachments[] = [
|
||||
'type' => 'Document',
|
||||
'mediaType' => 'image/jpeg',
|
||||
'url' => $this->server_addr . '/download/file.php?id=' . $file_id,
|
||||
'name' => null,
|
||||
];
|
||||
}
|
||||
unset($item);
|
||||
|
||||
return $attachments;
|
||||
}
|
||||
|
||||
private function make_post_object($data, $in_create)
|
||||
{
|
||||
$uri_id = $this->server_addr . '/activitypub?&mode=post&post_id=' . $data['post_id'];
|
||||
$uri_user = $this->server_addr . '/activitypub?&mode=user&user_id=' . $data['poster_id'];
|
||||
|
||||
$post_html = generate_text_for_display($data['post_text'], $data['bbcode_uid'], $data['bbcode_bitfield'], $this->get_bbcode_flags($data));
|
||||
$post_time = $this->iso_time($data['post_time']);
|
||||
// Note: #Public in to and followers in cc for public post, opposite for unlisted!
|
||||
$post_to = ['https://www.w3.org/ns/activitystreams#Public'];
|
||||
$post_cc = [];
|
||||
|
||||
$note = [
|
||||
'id' => $uri_id,
|
||||
'type' => 'Note',
|
||||
'published' => $post_time,
|
||||
//'updated' => ,
|
||||
'attributedTo' => $uri_user,
|
||||
//'inReplyTo' => null,
|
||||
'to' => $post_to,
|
||||
'cc' => $post_cc,
|
||||
'url' => $this->server_addr . '/viewtopic.php?p=' . $data['post_id'] . '#p' . $data['post_id'],
|
||||
//'mediaType' => 'text/html',
|
||||
//'summary' => null,
|
||||
'content' => $post_html,
|
||||
//'contentMap' => [ 'it' => '' ],
|
||||
'attachment' => $this->make_post_attachments($post_html),
|
||||
];
|
||||
|
||||
if ($in_create)
|
||||
{
|
||||
return [
|
||||
'@context' => [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
],
|
||||
'id' => $uri_id,
|
||||
'type' => 'Create',
|
||||
'actor' => $uri_user,
|
||||
'published' => $post_time,
|
||||
//'updated' => ,
|
||||
'to' => $post_to,
|
||||
'cc' => $post_cc,
|
||||
'object' => $note,
|
||||
];
|
||||
}
|
||||
else
|
||||
{
|
||||
$response[] = $note;
|
||||
return array_merge([
|
||||
'@context' => [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
]
|
||||
], $note);
|
||||
}
|
||||
}
|
||||
|
||||
public function nodeinfo_known()
|
||||
{
|
||||
if (!$this->config['spaccincphpbb_activitypub_setfederation']) {
|
||||
if (!$this->config['spaccinc_activitypub_setfederation']) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -74,7 +184,7 @@ class activitypub_controller
|
||||
|
||||
public function webfinger()
|
||||
{
|
||||
if (!$this->config['spaccincphpbb_activitypub_setfederation']) {
|
||||
if (!$this->config['spaccinc_activitypub_setfederation']) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -86,11 +196,6 @@ class activitypub_controller
|
||||
$subject = '';
|
||||
$href = [];
|
||||
|
||||
//if ($resource == '')
|
||||
//{
|
||||
// return new JsonResponse([], 500);
|
||||
//}
|
||||
|
||||
if (str_starts_with($resource, 'acct:'))
|
||||
{
|
||||
$tokens = explode('@', substr($resource, strlen('acct:')));
|
||||
@ -107,8 +212,8 @@ class activitypub_controller
|
||||
WHERE username_clean = '" . $this->db->sql_escape($name) . "'
|
||||
");
|
||||
|
||||
$href['self'] = '&mode=user&u=' . $data['user_id'];
|
||||
$href['profile-page'] = '/memberlist.php?mode=viewprofile&u=' . $data['user_id'];
|
||||
$href['self'] = '&mode=user&user_id=' . $data['user_id'];
|
||||
$href['profile-page'] = '/memberlist.php?mode=viewprofile&user_id=' . $data['user_id'];
|
||||
}
|
||||
|
||||
$response = new Response(json_encode([
|
||||
@ -130,7 +235,7 @@ class activitypub_controller
|
||||
|
||||
public function activitypub()
|
||||
{
|
||||
if (!$this->config['spaccincphpbb_activitypub_setfederation']) {
|
||||
if (!$this->config['spaccinc_activitypub_setfederation']) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -139,7 +244,7 @@ class activitypub_controller
|
||||
$uri_id = htmlspecialchars_decode($server_addr . $this->request->server('REQUEST_URI'));
|
||||
$mode = $this->request->variable('mode', '');
|
||||
|
||||
$response = [];
|
||||
$response = null;
|
||||
|
||||
switch ($mode)
|
||||
{
|
||||
@ -173,7 +278,7 @@ class activitypub_controller
|
||||
//],
|
||||
//'openRegistrations' => true,
|
||||
'metadata' => [
|
||||
'nodeName' => $this->site_name,
|
||||
'nodeName' => $this->config['sitename'],
|
||||
],
|
||||
];
|
||||
break;
|
||||
@ -181,12 +286,12 @@ class activitypub_controller
|
||||
break;
|
||||
|
||||
case 'user':
|
||||
$u = $this->request->variable('u', '');
|
||||
$user_id = $this->request->variable('user_id', '');
|
||||
|
||||
$data = $this->get_sql_row('
|
||||
SELECT *
|
||||
FROM ' . USERS_TABLE . "
|
||||
WHERE user_id = '" . $this->db->sql_escape($u) . "'
|
||||
WHERE user_id = '" . $this->db->sql_escape($user_id) . "'
|
||||
");
|
||||
|
||||
$icon_ext = end(explode('.', $data['user_avatar']));
|
||||
@ -208,18 +313,18 @@ class activitypub_controller
|
||||
'https://w3id.org/security/v1',
|
||||
],
|
||||
'id' => $uri_id,
|
||||
'inbox' => $server_addr . '/activitypub?&mode=inbox&u=' . $u,
|
||||
'outbox' => $server_addr . '/activitypub?&mode=outbox&u=' . $u,
|
||||
'inbox' => $server_addr . '/activitypub?&mode=inbox&user_id=' . $user_id,
|
||||
'outbox' => $server_addr . '/activitypub?&mode=outbox&user_id=' . $user_id,
|
||||
'endpoints' => [
|
||||
'sharedInbox' => $server_addr . '/activitypub&mode=inbox',
|
||||
],
|
||||
'type' => 'Person',
|
||||
//'discoverable' => true,
|
||||
//'manuallyApprovesFollowers' => false,
|
||||
//'published' => $data['user_regdate'],
|
||||
'published' => $this->iso_time($data['user_regdate']),
|
||||
'preferredUsername' => $data['username_clean'],
|
||||
'name' => $data['username'],
|
||||
'url' => $server_addr . '/memberlist.php?mode=viewprofile&u=' . $u,
|
||||
'url' => $server_addr . '/memberlist.php?mode=viewprofile&user_id=' . $user_id,
|
||||
'icon' => [
|
||||
'type' => 'Image',
|
||||
'mediaType' => 'image/' . ($icon_ext === 'jpg' ? 'jpeg' : $icon_ext),
|
||||
@ -238,27 +343,95 @@ class activitypub_controller
|
||||
break;
|
||||
|
||||
case 'outbox':
|
||||
$u = $this->request->variable('u', '');
|
||||
$user_id = $this->request->variable('user_id', '');
|
||||
$page = $this->request->variable('page', '');
|
||||
//$min_id = $this->request->variable('min_id', -1);
|
||||
//$max_id = $this->request->variable('max_id', -1);
|
||||
|
||||
$user_posts = $this->get_sql_row('
|
||||
$post_count = (int)$this->get_sql_row('
|
||||
SELECT user_posts
|
||||
FROM ' . USERS_TABLE . "
|
||||
WHERE user_id = '" . $this->db->sql_escape($u) . "'
|
||||
WHERE user_id = '" . $this->db->sql_escape($user_id) . "'
|
||||
")['user_posts'];
|
||||
|
||||
$response = [
|
||||
'@context' => 'https://www.w3.org/ns/activitystreams',
|
||||
'id' => $uri_id,
|
||||
'type' => 'OrderedCollection',
|
||||
'totalItems' => (int)$user_posts,
|
||||
'first' => $uri_id . '&view=page',
|
||||
'last' => $uri_id . '&view=page&min_id=0',
|
||||
];
|
||||
if ($page === '')
|
||||
{
|
||||
$response = [
|
||||
'@context' => [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
],
|
||||
'id' => $uri_id,
|
||||
'type' => 'OrderedCollection',
|
||||
'totalItems' => $post_count,
|
||||
'first' => $uri_id . '&page=-1',
|
||||
'last' => $uri_id . '&page=0',
|
||||
];
|
||||
}
|
||||
else
|
||||
{
|
||||
$items = [];
|
||||
$order = 'DESC';
|
||||
$limit = 20;
|
||||
$offset = 0;
|
||||
|
||||
switch ($page)
|
||||
{
|
||||
// Oldest
|
||||
case '0':
|
||||
$order = 'DESC';
|
||||
break;
|
||||
|
||||
// Newest
|
||||
case '-1':
|
||||
// ...
|
||||
break;
|
||||
|
||||
// Any other page
|
||||
default:
|
||||
// ...
|
||||
break;
|
||||
}
|
||||
|
||||
$data = $this->get_sql_rows('
|
||||
SELECT *
|
||||
FROM ' . POSTS_TABLE . "
|
||||
WHERE poster_id = '" . $this->db->sql_escape($user_id) . "'
|
||||
ORDER BY post_id " . $order . '
|
||||
LIMIT ' . $limit . '
|
||||
OFFSET ' . $offset
|
||||
);
|
||||
|
||||
foreach ($data as &$item)
|
||||
{
|
||||
$items[] = $this->make_post_object($item, true);
|
||||
}
|
||||
unset($item);
|
||||
|
||||
$response = [
|
||||
'@context' => [
|
||||
'https://www.w3.org/ns/activitystreams',
|
||||
],
|
||||
'id' => $uri_id,
|
||||
'type' => 'OrderedCollectionPage',
|
||||
//'prev' => '',
|
||||
//'next' => '',
|
||||
// ...
|
||||
'partOf' => $server_addr . '/activitypub?&mode=outbox&user_id=' . $user_id,
|
||||
//'ordererdItems' => $items,
|
||||
];
|
||||
}
|
||||
break;
|
||||
|
||||
//case 'post':
|
||||
//case 'thread':
|
||||
//
|
||||
//break;
|
||||
|
||||
case 'post':
|
||||
$response = $this->make_post_object($this->get_sql_row('
|
||||
SELECT *
|
||||
FROM ' . POSTS_TABLE . "
|
||||
WHERE post_id = '" . $this->db->sql_escape($this->request->variable('post_id', '')) . "'
|
||||
"), false);
|
||||
break;
|
||||
}
|
||||
|
||||
$response = new Response(json_encode($response), 200);
|
||||
|
@ -14,5 +14,6 @@ $lang = array_merge($lang, [
|
||||
'ACP_SPACCINC_ACTIVITYPUB_TITLE' => 'ActivityPub for phpBB Module',
|
||||
'ACP_SPACCINC_ACTIVITYPUB_SETFEDERATION' => 'Enable ActivityPub federation for this board',
|
||||
'ACP_SPACCINC_ACTIVITYPUB_SETDOMAIN' => 'Full domain name to use for federation',
|
||||
'ACP_SPACCINC_ACTIVITYPUB_SETDOMAIN_INFO' => 'The domain on which federation will be handled. NEVER change this after enabling federation, unless you know the implications.',
|
||||
'ACP_SPACCINC_ACTIVITYPUB_SETDOMAIN_INFO' => 'The domain on which federation will be handled. You will never be able to change this later! (unless you know all implications)',
|
||||
'ACP_SPACCINC_ACTIVITYPUB_SETDOMAIN_CONFIRM' => 'I understand that the federation domain will not be able to be changed after having set it.'
|
||||
]);
|
||||
|
@ -6,7 +6,7 @@ class install_acp_module extends \phpbb\db\migration\migration
|
||||
{
|
||||
public function effectively_installed()
|
||||
{
|
||||
return isset($this->config['spaccincphpbb_activitypub_setfederation']);
|
||||
return isset($this->config['spaccinc_activitypub_setfederation']);
|
||||
}
|
||||
|
||||
public static function depends_on()
|
||||
@ -17,7 +17,8 @@ class install_acp_module extends \phpbb\db\migration\migration
|
||||
public function update_data()
|
||||
{
|
||||
return [
|
||||
['config.add', ['spaccincphpbb_activitypub_setfederation', 0]],
|
||||
['config.add', ['spaccinc_activitypub_setfederation', 0]],
|
||||
['config.add', ['spaccinc_activitypub_setdomain', '']],
|
||||
|
||||
['module.add', [
|
||||
'acp',
|
||||
|
Loading…
x
Reference in New Issue
Block a user