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);
 | 
						|
}
 |