<?php
							 | 
						|
								use Symfony\Component\HttpFoundation\Request;
							 | 
						|
								use Symfony\Component\HttpFoundation\Response;
							 | 
						|
								
							 | 
						|
								class Controller {
							 | 
						|
								
							 | 
						|
								  public $http;
							 | 
						|
								
							 | 
						|
								  public function __construct() {
							 | 
						|
								    $this->http = new Telegraph\HTTP();
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  private function _is_logged_in(Request $request, Response $response) {
							 | 
						|
								    session_start();
							 | 
						|
								    if(!session('user_id')) {
							 | 
						|
								      session_destroy();
							 | 
						|
								      $response->setStatusCode(302);
							 | 
						|
								      $response->headers->set('Location', '/login?return_to='.$request->getRequestURI());
							 | 
						|
								      return false;
							 | 
						|
								    } else {
							 | 
						|
								      return true;
							 | 
						|
								    }
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  private function _get_role(Request $request, Response $response) {
							 | 
						|
								    // Default to load their first site, but let the query string override it
							 | 
						|
								    $role = ORM::for_table('roles')->join('sites', 'roles.site_id = sites.id')
							 | 
						|
								      ->where('user_id', session('user_id'))->order_by_asc('sites.created_at')->find_one();
							 | 
						|
								
							 | 
						|
								    if($request->get('account')) {
							 | 
						|
								      $role = ORM::for_table('roles')->where('user_id', session('user_id'))->where('site_id', $request->get('account'))->find_one();
							 | 
						|
								      // Check that the user has permission to access this account
							 | 
						|
								      if(!$role) {
							 | 
						|
								        $response->setStatusCode(302);
							 | 
						|
								        $response->headers->set('Location', '/dashboard');
							 | 
						|
								        return false;
							 | 
						|
								      }
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    return $role;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  public function index(Request $request, Response $response) {
							 | 
						|
								    p3k\session_setup();
							 | 
						|
								
							 | 
						|
								    $response->setContent(view('index', [
							 | 
						|
								      'title' => 'Telegraph',
							 | 
						|
								      'user' => $this->_user(),
							 | 
						|
								    ]));
							 | 
						|
								    return $response;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  public function api(Request $request, Response $response) {
							 | 
						|
								    session_start();
							 | 
						|
								    if(session('user_id')) {
							 | 
						|
								      $role = $this->_get_role($request, $response);
							 | 
						|
								      $site = ORM::for_table('sites')->where_id_is($role->site_id)->find_one();
							 | 
						|
								    } else {
							 | 
						|
								      $role = false;
							 | 
						|
								      $site = false;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    $response->setContent(view('api', [
							 | 
						|
								      'title' => 'Telegraph API Documentation',
							 | 
						|
								      'user' => $this->_user(),
							 | 
						|
								      'accounts' => $this->_accounts(),
							 | 
						|
								      'site' => $site,
							 | 
						|
								      'role' => $role,
							 | 
						|
								      'return_to' => $request->getRequestURI()
							 | 
						|
								    ]));
							 | 
						|
								    return $response;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  public function superfeedr(Request $request, Response $response) {
							 | 
						|
								    session_start();
							 | 
						|
								    if(session('user_id')) {
							 | 
						|
								      $role = $this->_get_role($request, $response);
							 | 
						|
								      $site = ORM::for_table('sites')->where_id_is($role->site_id)->find_one();
							 | 
						|
								    } else {
							 | 
						|
								      $role = false;
							 | 
						|
								      $site = false;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    $response->setContent(view('superfeedr', [
							 | 
						|
								      'title' => 'Telegraph Superfeedr Documentation',
							 | 
						|
								      'user' => $this->_user(),
							 | 
						|
								      'accounts' => $this->_accounts(),
							 | 
						|
								      'site' => $site,
							 | 
						|
								      'role' => $role,
							 | 
						|
								      'return_to' => $request->getRequestURI()
							 | 
						|
								    ]));
							 | 
						|
								    return $response;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  private static function _icon_for_status($status) {
							 | 
						|
								    switch($status) {
							 | 
						|
								      case 'success':
							 | 
						|
								      case 'accepted':
							 | 
						|
								        return 'green checkmark';
							 | 
						|
								      case 'not_supported':
							 | 
						|
								        return 'yellow x';
							 | 
						|
								      case 'error':
							 | 
						|
								        return 'red x';
							 | 
						|
								      case 'pending':
							 | 
						|
								        return 'orange wait';
							 | 
						|
								      default:
							 | 
						|
								        return '';
							 | 
						|
								    }
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  public function dashboard(Request $request, Response $response) {
							 | 
						|
								    if(!$this->_is_logged_in($request, $response)) {
							 | 
						|
								      return $response;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    if(!$role=$this->_get_role($request, $response)) {
							 | 
						|
								      return $response;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    $site = ORM::for_table('sites')->where_id_is($role->site_id)->find_one();
							 | 
						|
								
							 | 
						|
								    $query = ORM::for_table('webmentions')->where('site_id', $site->id)
							 | 
						|
								      ->order_by_desc('created_at')
							 | 
						|
								      ->limit(20)
							 | 
						|
								      ->find_many();
							 | 
						|
								
							 | 
						|
								    $webmentions = [];
							 | 
						|
								    foreach($query as $m) {
							 | 
						|
								      $statuses = ORM::for_table('webmention_status')->where('webmention_id', $m->id)->order_by_desc('created_at')->find_many();
							 | 
						|
								      if(count($statuses) == 0) {
							 | 
						|
								        $status = 'pending';
							 | 
						|
								      } else {
							 | 
						|
								        $status = $statuses[0]->status;
							 | 
						|
								      }
							 | 
						|
								      $icon = self::_icon_for_status($status);
							 | 
						|
								
							 | 
						|
								      $webmentions[] = [
							 | 
						|
								        'webmention' => $m,
							 | 
						|
								        'statuses' => $statuses,
							 | 
						|
								        'status' => $status,
							 | 
						|
								        'icon' => $icon
							 | 
						|
								      ];
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    $response->setContent(view('dashboard', [
							 | 
						|
								      'title' => 'Telegraph Dashboard',
							 | 
						|
								      'user' => $this->_user(),
							 | 
						|
								      'accounts' => $this->_accounts(),
							 | 
						|
								      'site' => $site,
							 | 
						|
								      'role' => $role,
							 | 
						|
								      'webmentions' => $webmentions
							 | 
						|
								    ]));
							 | 
						|
								    return $response;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  public function send_a_webmention(Request $request, Response $response) {
							 | 
						|
								    session_start();
							 | 
						|
								
							 | 
						|
								    $_SESSION['_csrf'] = random_string(16);
							 | 
						|
								
							 | 
						|
								    $response->setContent(view('send-a-webmention', [
							 | 
						|
								      'title' => 'Send a Webmention with Telegraph',
							 | 
						|
								      'user' => $this->_user(),
							 | 
						|
								      'accounts' => $this->_accounts(),
							 | 
						|
								      'csrf' => $_SESSION['_csrf'],
							 | 
						|
								    ]));
							 | 
						|
								    return $response;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  public function new_site(Request $request, Response $response) {
							 | 
						|
								    if(!$this->_is_logged_in($request, $response)) {
							 | 
						|
								      return $response;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    if(!$role=$this->_get_role($request, $response)) {
							 | 
						|
								      return $response;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    if($request->get('account')) {
							 | 
						|
								      // permissions are checked already by _get_role
							 | 
						|
								      $site = ORM::for_table('sites')->where_id_is($request->get('account'))->find_one();
							 | 
						|
								    } else {
							 | 
						|
								      $site = null;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    $response->setContent(view('new-site', [
							 | 
						|
								      'title' => 'Create New Site',
							 | 
						|
								      'user' => $this->_user(),
							 | 
						|
								      'accounts' => $this->_accounts(),
							 | 
						|
								      'role' => $role,
							 | 
						|
								      'site' => $site
							 | 
						|
								    ]));
							 | 
						|
								    return $response;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  public function save_site(Request $request, Response $response) {
							 | 
						|
								    if(!$this->_is_logged_in($request, $response)) {
							 | 
						|
								      return $response;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    if(!$role=$this->_get_role($request, $response)) {
							 | 
						|
								      return $response;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    if($request->get('account')) {
							 | 
						|
								      // permissions are checked already by _get_role
							 | 
						|
								      $site = ORM::for_table('sites')->where_id_is($request->get('account'))->find_one();
							 | 
						|
								      $site->name = $request->get('name');
							 | 
						|
								      $site->url = $request->get('url');
							 | 
						|
								      $site->save();
							 | 
						|
								    } else {
							 | 
						|
								      $site = ORM::for_table('sites')->create();
							 | 
						|
								      $site->created_by = session('user_id');
							 | 
						|
								      $site->created_at = date('Y-m-d H:i:s');
							 | 
						|
								      $site->name = $request->get('name');
							 | 
						|
								      $site->url = $request->get('url');
							 | 
						|
								      $site->save();
							 | 
						|
								
							 | 
						|
								      $role = ORM::for_table('roles')->create();
							 | 
						|
								      $role->site_id = $site->id;
							 | 
						|
								      $role->user_id = session('user_id');
							 | 
						|
								      $role->role = 'owner';
							 | 
						|
								      $role->token = random_string(32);
							 | 
						|
								      $role->save();
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    $response->setStatusCode(302);
							 | 
						|
								    $response->headers->set('Location', '/dashboard?account='.$site->id);
							 | 
						|
								    return $response;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  public function webmention_details(Request $request, Response $response, $args) {
							 | 
						|
								    session_start();
							 | 
						|
								
							 | 
						|
								    // Look up the webmention by its token
							 | 
						|
								    $webmention = ORM::for_table('webmentions')->where('token', $args['code'])->find_one();
							 | 
						|
								
							 | 
						|
								    if(!$webmention) {
							 | 
						|
								      $response->setContent(view('not-found'));
							 | 
						|
								      return $response;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    $site = ORM::for_table('sites')->where_id_is($webmention->site_id)->find_one();
							 | 
						|
								
							 | 
						|
								    // Find the user's role for this site
							 | 
						|
								    if($site && $this->_user()) {
							 | 
						|
								      $role = ORM::for_table('roles')
							 | 
						|
								        ->where('site_id', $site['id'])
							 | 
						|
								        ->where('user_id', $this->_user()['id'])
							 | 
						|
								        ->find_one();
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    $statuses = ORM::for_table('webmention_status')->where('webmention_id', $webmention->id)->order_by_desc('created_at')->find_many();
							 | 
						|
								
							 | 
						|
								    if(count($statuses) == 0) {
							 | 
						|
								      $status = 'pending';
							 | 
						|
								    } else {
							 | 
						|
								      $status = $statuses[0]->status;
							 | 
						|
								    }
							 | 
						|
								    $icon = self::_icon_for_status($status);
							 | 
						|
								
							 | 
						|
								    $response->setContent(view('webmention-details', [
							 | 
						|
								      'title' => 'Webmention Details',
							 | 
						|
								      'user' => $this->_user(),
							 | 
						|
								      'accounts' => $this->_accounts(),
							 | 
						|
								      'site' => $site,
							 | 
						|
								      'role' => isset($role) ? $role : false,
							 | 
						|
								      'webmention' => $webmention,
							 | 
						|
								      'statuses' => $statuses,
							 | 
						|
								      'icon' => $icon,
							 | 
						|
								      'status' => $status
							 | 
						|
								    ]));
							 | 
						|
								    return $response;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  public function dashboard_send(Request $request, Response $response) {
							 | 
						|
								    if(!$this->_is_logged_in($request, $response)) {
							 | 
						|
								      return $response;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    if(!$role=$this->_get_role($request, $response)) {
							 | 
						|
								      return $response;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    $site = ORM::for_table('sites')->where_id_is($role->site_id)->find_one();
							 | 
						|
								
							 | 
						|
								    $response->setContent(view('webmention-send', [
							 | 
						|
								      'title' => 'Webmention Details',
							 | 
						|
								      'user' => $this->_user(),
							 | 
						|
								      'accounts' => $this->_accounts(),
							 | 
						|
								      'site' => $site,
							 | 
						|
								      'role' => $role,
							 | 
						|
								      'url' => $request->get('url')
							 | 
						|
								    ]));
							 | 
						|
								    return $response;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  public function get_outgoing_links(Request $request, Response $response) {
							 | 
						|
								    if(!$this->_is_logged_in($request, $response)) {
							 | 
						|
								      return $response;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    $sourceURL = $request->get('url');
							 | 
						|
								
							 | 
						|
								    $source = $this->http->get($sourceURL, ['Accept: text/html, */*']);
							 | 
						|
								    $xray = new \p3k\XRay();
							 | 
						|
								    $parsed = $xray->parse($sourceURL, $source['body']);
							 | 
						|
								
							 | 
						|
								    if($parsed && isset($parsed['data'])) {
							 | 
						|
								      // Remove the author object to avoid sending webmentions to your own home page
							 | 
						|
								      if(isset($parsed['data']['author']))
							 | 
						|
								        unset($parsed['data']['author']);
							 | 
						|
								      $links = Telegraph\FindLinks::all($parsed['data']);
							 | 
						|
								    } else {
							 | 
						|
								      $links = [];
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    // Remove the source URL from the list if present
							 | 
						|
								    $links = array_filter($links, function($link) use($sourceURL) {
							 | 
						|
								      // Remove URL fragment when comparing to ignore more self-links
							 | 
						|
								      $link = preg_replace('/#.+$/', '', $link);
							 | 
						|
								      return $link != $sourceURL;
							 | 
						|
								    });
							 | 
						|
								
							 | 
						|
								    $response->headers->set('Content-Type', 'application/json');
							 | 
						|
								    $response->setContent(json_encode([
							 | 
						|
								      'links' => $links
							 | 
						|
								    ]));
							 | 
						|
								    return $response;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  public function discover_endpoint(Request $request, Response $response) {
							 | 
						|
								    if(!$this->_is_logged_in($request, $response)) {
							 | 
						|
								      return $response;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    $targetURL = $request->get('target');
							 | 
						|
								
							 | 
						|
								    if(!Telegraph\Webmention::isProbablySupported($targetURL)) {
							 | 
						|
								      $status = 'none';
							 | 
						|
								      $cached = -1;
							 | 
						|
								    } else {
							 | 
						|
								      // Cache the discovered result
							 | 
						|
								      $cacheKey = 'telegraph:discover_endpoint:'.$targetURL;
							 | 
						|
								      if($request->get('ignore_cache') == 'true' || (!$status = redis()->get($cacheKey))) {
							 | 
						|
								        $client = new IndieWeb\MentionClient();
							 | 
						|
								        $endpoint = $client->discoverWebmentionEndpoint($targetURL);
							 | 
						|
								        if($endpoint) {
							 | 
						|
								          $status = 'webmention';
							 | 
						|
								        } else {
							 | 
						|
								          $endpoint = $client->discoverPingbackEndpoint($targetURL);
							 | 
						|
								          if($endpoint) {
							 | 
						|
								            $status = 'pingback';
							 | 
						|
								          } else {
							 | 
						|
								            $status = 'none';
							 | 
						|
								          }
							 | 
						|
								        }
							 | 
						|
								        $cached = false;
							 | 
						|
								        redis()->setex($cacheKey, 600, $status);
							 | 
						|
								      } else {
							 | 
						|
								        $cached = true;
							 | 
						|
								      }
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    $response->headers->set('Content-Type', 'application/json');
							 | 
						|
								    $response->setContent(json_encode([
							 | 
						|
								      'status' => $status,
							 | 
						|
								      'cached' => $cached
							 | 
						|
								    ]));
							 | 
						|
								    return $response;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  private function _user() {
							 | 
						|
								    if(!session('user_id')) return null;
							 | 
						|
								    return ORM::for_table('users')->where_id_is(session('user_id'))->find_one();
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  private function _accounts() {
							 | 
						|
								    if(!session('user_id')) return [];
							 | 
						|
								    return ORM::for_table('sites')->join('roles', 'roles.site_id = sites.id')
							 | 
						|
								      ->where('roles.user_id', session('user_id'))
							 | 
						|
								      ->find_many();
							 | 
						|
								  }
							 | 
						|
								}
							 |