forked from grumpydevelop/federator
249 lines
8.7 KiB
PHP
249 lines
8.7 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('articles', $r)) {
|
|
$articles = $r['articles'];
|
|
$host = $_SERVER['SERVER_NAME'];
|
|
$imgpath = $this->config['userdata']['path'];
|
|
$userdata = $this->config['userdata']['url'];
|
|
foreach ($articles as $article) {
|
|
$create = new \Federator\Data\ActivityPub\Common\Create();
|
|
$create->setAActor('https://' . $host .'/' . $article['profilename']);
|
|
$create->setID($article['id'])
|
|
->setURL('https://'.$host.'/' . $article['profilename']
|
|
. '/statuses/' . $article['id'] . '/activity')
|
|
->setPublished(max($article['published'], $article['modified']))
|
|
->addTo("https://www.w3.org/ns/activitystreams#Public")
|
|
->addCC('https://' . $host . '/' . $article['profilename'] . '/followers.json');
|
|
$apArticle = new \Federator\Data\ActivityPub\Common\Article();
|
|
if (array_key_exists('tags', $article)) {
|
|
foreach ($article['tags'] as $tag) {
|
|
$href = 'https://' . $host . '/' . $article['language']
|
|
. '/search.htm?tagsearch=' . urlencode($tag);
|
|
$tagObj = new \Federator\Data\ActivityPub\Common\Tag();
|
|
$tagObj->setHref($href)
|
|
->setName('#' . urlencode(str_replace(' ', '', $tag)))
|
|
->setType('Hashtag');
|
|
$article->addTag($tagObj);
|
|
}
|
|
}
|
|
$apArticle->setPublished($article['published'])
|
|
->setName($article['title'])
|
|
->setAttributedTo('https://' . $host .'/' . $article['profilename'])
|
|
->setContent(
|
|
$article['teaser'] ??
|
|
$this->main->translate(
|
|
$article['language'],
|
|
'article',
|
|
'newarticle'
|
|
)
|
|
)
|
|
->addTo("https://www.w3.org/ns/activitystreams#Public")
|
|
->addCC('https://' . $host . '/' . $article['profilename'] . '/followers.json');
|
|
$articleimage = $article['imagealt'] ??
|
|
$this->main->translate($article['language'], 'article', 'image');
|
|
$idurl = 'https://' . $host . '/' . $article['language']
|
|
. '/' . $article['profilename'] . '/'. $article['name'];
|
|
$apArticle->setID($idurl)
|
|
->setURL($idurl);
|
|
$image = $article['image'] !== "" ? $article['image'] : $article['profileimg'];
|
|
$mediaType = @mime_content_type($imgpath . $article['profile'] . '/' . $image) | 'text/plain';
|
|
$img = new \Federator\Data\ActivityPub\Common\Image();
|
|
$img->setMediaType($mediaType)
|
|
->setName($articleimage)
|
|
->setURL($userdata . $article['profile'] . '/' . $image);
|
|
$apArticle->addImage($img);
|
|
$create->setObject($apArticle);
|
|
$posts[] = $create;
|
|
}
|
|
}
|
|
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);
|
|
}
|