federator/plugins/federator/contentnation.php
2024-08-03 19:55:50 +02:00

303 lines
12 KiB
PHP

<?php
/**
* SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
* SPDX-License-Identifier: GPL-3.0-or-later
*
* @author Sascha Nitsch (grumpydeveloper)
**/
namespace Federator\Connector;
/**
* Connector to ContentNation.net
*/
class ContentNation implements Connector
{
/**
* config parameter
*
* @var array<string, mixed> $config
*/
private $config;
/**
* main instance
*
* @var \Federator\Main $main
*/
private $main;
/**
* service-URL
*
* @var string $service
*/
private $service;
/**
* constructor
*
* @param \Federator\Main $main
*/
public function __construct($main)
{
$config = parse_ini_file($_SERVER['DOCUMENT_ROOT'] . '../contentnation.ini', true);
if ($config !== false) {
$this->config = $config;
}
$this->service = $config['contentnation']['service-uri'];
$this->main = $main;
}
/**
* get posts by given user
*
* @param string $userId user id
* @param string $min min date
* @param string $max max date
* @return \Federator\Data\ActivityPub\Common\APObject[]|false
*/
public function getRemotePostsByUser($userId, $min, $max)
{
$remoteURL = $this->service . '/api/profile/' . $userId . '/activities';
if ($min !== '') {
$remoteURL .= '&minTS=' . urlencode($min);
}
if ($max !== '') {
$remoteURL .= '&maxTS=' . urlencode($max);
}
[$response, $info] = \Federator\Main::getFromRemote($remoteURL, []);
if ($info['http_code'] != 200) {
print_r($info);
return false;
}
$r = json_decode($response, true);
if ($r === false || $r === null || !is_array($r)) {
return false;
}
$posts = [];
if (array_key_exists('activities', $r)) {
$activities = $r['activities'];
$host = $_SERVER['SERVER_NAME'];
$imgpath = $this->config['userdata']['path'];
$userdata = $this->config['userdata']['url'];
foreach ($activities as $activity) {
$create = new \Federator\Data\ActivityPub\Common\Create();
$create->setAActor('https://' . $host .'/' . $userId);
$create->setID($activity['id'])
->setPublished($activity['timestamp'])
->addTo("https://www.w3.org/ns/activitystreams#Public")
->addCC('https://' . $host . '/' . $userId . '/followers.json');
switch ($activity['type']) {
case 'Article':
$create->setURL('https://'.$host . '/' . $activity['language'] . '/' . $userId . '/'
. $activity['name']);
$apArticle = new \Federator\Data\ActivityPub\Common\Article();
if (array_key_exists('tags', $activity)) {
foreach ($activity['tags'] as $tag) {
$href = 'https://' . $host . '/' . $activity['language']
. '/search.htm?tagsearch=' . urlencode($tag);
$tagObj = new \Federator\Data\ActivityPub\Common\Tag();
$tagObj->setHref($href)
->setName('#' . urlencode(str_replace(' ', '', $tag)))
->setType('Hashtag');
$apArticle->addTag($tagObj);
}
}
$apArticle->setPublished($activity['published'])
->setName($activity['title'])
->setAttributedTo('https://' . $host .'/' . $activity['profilename'])
->setContent(
$activity['teaser'] ??
$this->main->translate(
$activity['language'],
'article',
'newarticle'
)
)
->addTo("https://www.w3.org/ns/activitystreams#Public")
->addCC('https://' . $host . '/' . $userId . '/followers.json');
$articleimage = $activity['imagealt'] ??
$this->main->translate($activity['language'], 'article', 'image');
$idurl = 'https://' . $host . '/' . $activity['language']
. '/' . $userId . '/'. $activity['name'];
$apArticle->setID($idurl)
->setURL($idurl);
$image = $activity['image'] ?? $activity['profileimg'];
$mediaType = @mime_content_type($imgpath . $activity['profile'] . '/' . $image) | 'text/plain';
$img = new \Federator\Data\ActivityPub\Common\Image();
$img->setMediaType($mediaType)
->setName($articleimage)
->setURL($userdata . '/' . $activity['profile'] . $image);
$apArticle->addImage($img);
$create->setObject($apArticle);
$posts[] = $create;
break; // Article
case 'Comment':
// echo "comment\n";
// print_r($activity);
break; // Comment
case 'Vote':
$url = 'https://'.$host . '/' . $activity['articlelang'] . $userId . '/'
. $activity['articlename'];
$url .= '/vote/' . $activity['id'];
$create->setURL($url);
if ($activity['upvote'] === true) {
$like = new \Federator\Data\ActivityPub\Common\Activity('Like');
$like->setSummary(
$this->main->translate(
$activity['articlelang'],
'vote',
'like',
[$activity['username']]
)
);
} else {
$like = new \Federator\Data\ActivityPub\Common\Activity('Dislike');
$like->setSummary(
$this->main->translate(
$activity['articlelang'],
'vote',
'dislike',
[$activity['username']]
)
);
}
$actor = new \Federator\Data\ActivityPub\Common\APObject('Person');
$actor->setName($activity['username']);
$like->setActor($actor);
$url = 'https://' . $host . '/' . $activity['articlelang']
. '/' . $userId . '/'. $activity['articlename'];
if ($activity['comment'] !== '') {
$url .= '/comment/' . $activity['comment'];
}
$type = 'Article';
switch ($activity['votetype']) {
case 'comment':
$type = 'Comment';
break;
}
$object = new \Federator\Data\ActivityPub\Common\APObject($type);
$object->setHref($url);
$like->setObject($object);
$create->setObject($like);
$posts[] = $create;
break; // Vote
}
}
}
return $posts;
}
/**
* get statistics from remote system
*
* @return \Federator\Data\Stats|false
*/
public function getRemoteStats()
{
$remoteURL = $this->service . '/api/stats';
[$response, $info] = \Federator\Main::getFromRemote($remoteURL, []);
if ($info['http_code'] != 200) {
return false;
}
$r = json_decode($response, true);
if ($r === false || $r === null || !is_array($r)) {
return false;
}
$stats = new \Federator\Data\Stats();
$stats->userCount = array_key_exists('userCount', $r) ? $r['userCount'] : 0;
$stats->postCount = array_key_exists('pageCount', $r) ? $r['pageCount'] : 0;
$stats->commentCount = array_key_exists('commentCount', $r) ? $r['commentCount'] : 0;
return $stats;
}
/**
* get remote user by given name
*
* @param string $_name user/profile name
* @return \Federator\Data\User | false
*/
public function getRemoteUserByName(string $_name)
{
// validate name
if (preg_match("/^[a-zA-Z0-9_\-]+$/", $_name) != 1) {
return false;
}
$remoteURL = $this->service . '/api/users/info?user=' . urlencode($_name);
$headers = ['Accept: application/json'];
[$response, $info] = \Federator\Main::getFromRemote($remoteURL, $headers);
if ($info['http_code'] != 200) {
return false;
}
$r = json_decode($response, true);
if ($r === false || $r === null || !is_array($r)) {
return false;
}
$user = new \Federator\Data\User();
$user->externalid = $_name;
$user->iconMediaType = $r['iconMediaType'];
$user->iconURL = $r['iconURL'];
$user->imageMediaType = $r['imageMediaType'];
$user->imageURL = $r['imageURL'];
$user->name = $r['name'];
$user->summary = $r['summary'];
$user->type = $r['type'];
$user->registered = intval($r['registered'], 10);
return $user;
}
/**
* get remote user by given session
*
* @param string $_session session id
* @param string $_user user or profile name
* @return \Federator\Data\User | false
*/
public function getRemoteUserBySession(string $_session, string $_user)
{
// validate $_session and $user
if (preg_match("/^[a-z0-9]{16}$/", $_session) != 1) {
return false;
}
if (preg_match("/^[a-zA-Z0-9_\-]+$/", $_user) != 1) {
return false;
}
$remoteURL = $this->service . '/api/users/permissions?profile=' . urlencode($_user);
$headers = ['Cookie: session=' . $_session, 'Accept: application/json'];
[$response, $info] = \Federator\Main::getFromRemote($remoteURL, $headers);
if ($info['http_code'] != 200) {
return false;
}
$r = json_decode($response, true);
if ($r === false || !is_array($r) || !array_key_exists($_user, $r)) {
return false;
}
$user = $this->getRemoteUserByName($_user);
if ($user === false) {
return false;
}
// extend with permissions
$user->permissions = [];
$user->session = $_session;
foreach ($r[$_user] as $p) {
$user->permissions[] = $p;
}
return $user;
}
}
namespace Federator;
/**
* Function to initialize plugin
*
* @param \Federator\Main $main main instance
* @return void
*/
function contentnation_load($main)
{
$cn = new Connector\ContentNation($main);
$main->setConnector($cn);
}