Massive simplification of code for displaying webmentions of notes, and the micropub client used to make a note
This commit is contained in:
parent
c96539f9c8
commit
8477aba87b
6 changed files with 173 additions and 117 deletions
|
@ -2,16 +2,9 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Twitter;
|
||||
use HTMLPurifier;
|
||||
use App\{Note, Tag};
|
||||
use GuzzleHttp\Client;
|
||||
use HTMLPurifier_Config;
|
||||
use App\Note;
|
||||
use Illuminate\Http\Request;
|
||||
use Jonnybarnes\IndieWeb\Numbers;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Jonnybarnes\WebmentionsParser\Authorship;
|
||||
|
||||
// Need to sort out Twitter and webmentions!
|
||||
|
||||
|
@ -44,50 +37,18 @@ class NotesController extends Controller
|
|||
*/
|
||||
public function show($urlId)
|
||||
{
|
||||
$authorship = new Authorship();
|
||||
$note = Note::nb60($urlId)->first();
|
||||
$replies = [];
|
||||
$reposts = [];
|
||||
$likes = [];
|
||||
$carbon = new \Carbon\Carbon();
|
||||
foreach ($note->webmentions as $webmention) {
|
||||
/*
|
||||
reply->url |
|
||||
reply->photo | Author
|
||||
reply->name |
|
||||
reply->source
|
||||
reply->date
|
||||
reply->reply
|
||||
|
||||
repost->url |
|
||||
repost->photo | Author
|
||||
repost->name |
|
||||
repost->date
|
||||
repost->source
|
||||
|
||||
like->url |
|
||||
like->photo | Author
|
||||
like->name |
|
||||
*/
|
||||
$microformats = json_decode($webmention->mf2, true);
|
||||
$authorHCard = $authorship->findAuthor($microformats);
|
||||
$content['url'] = $authorHCard['properties']['url'][0];
|
||||
$content['photo'] = $this->createPhotoLink($authorHCard['properties']['photo'][0]);
|
||||
$content['name'] = $authorHCard['properties']['name'][0];
|
||||
$content['author'] = $webmention->author;
|
||||
$content['published'] = $webmention->published;
|
||||
$content['source'] = $webmention->source;
|
||||
switch ($webmention->type) {
|
||||
case 'in-reply-to':
|
||||
$content['source'] = $webmention->source;
|
||||
if (isset($microformats['items'][0]['properties']['published'][0])) {
|
||||
try {
|
||||
$content['date'] = $carbon->parse(
|
||||
$microformats['items'][0]['properties']['published'][0]
|
||||
)->toDayDateTimeString();
|
||||
} catch (\Exception $exception) {
|
||||
$content['date'] = $webmention->updated_at->toDayDateTimeString();
|
||||
}
|
||||
} else {
|
||||
$content['date'] = $webmention->updated_at->toDayDateTimeString();
|
||||
}
|
||||
$content['reply'] = $webmention->reply;
|
||||
$microformats = json_decode($webmention->mf2, true);
|
||||
$content['reply'] = $this->filterHTML(
|
||||
$microformats['items'][0]['properties']['content'][0]['html']
|
||||
);
|
||||
|
@ -95,10 +56,6 @@ class NotesController extends Controller
|
|||
break;
|
||||
|
||||
case 'repost-of':
|
||||
$content['date'] = $carbon->parse(
|
||||
$microformats['items'][0]['properties']['published'][0]
|
||||
)->toDayDateTimeString();
|
||||
$content['source'] = $webmention->source;
|
||||
$reposts[] = $content;
|
||||
break;
|
||||
|
||||
|
@ -138,66 +95,7 @@ class NotesController extends Controller
|
|||
$notes = Note::whereHas('tags', function ($query) use ($tag) {
|
||||
$query->where('tag', $tag);
|
||||
})->get();
|
||||
foreach ($notes as $note) {
|
||||
$note->iso8601_time = $note->updated_at->toISO8601String();
|
||||
$note->human_time = $note->updated_at->diffForHumans();
|
||||
}
|
||||
|
||||
return view('notes.tagged', compact('notes', 'tag'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the photo link.
|
||||
*
|
||||
* We shall leave twitter.com and twimg.com links as they are. Then we shall
|
||||
* check for local copies, if that fails leave the link as is.
|
||||
*
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
public function createPhotoLink($url)
|
||||
{
|
||||
$host = parse_url($url, PHP_URL_HOST);
|
||||
if ($host == 'pbs.twimg.com') {
|
||||
//make sure we use HTTPS, we know twitter supports it
|
||||
return str_replace('http://', 'https://', $url);
|
||||
}
|
||||
if ($host == 'twitter.com') {
|
||||
if (Cache::has($url)) {
|
||||
return Cache::get($url);
|
||||
}
|
||||
$username = parse_url($url, PHP_URL_PATH);
|
||||
try {
|
||||
$info = Twitter::getUsers(['screen_name' => $username]);
|
||||
$profile_image = $info->profile_image_url_https;
|
||||
Cache::put($url, $profile_image, 10080); //1 week
|
||||
} catch (Exception $e) {
|
||||
return $url; //not sure here
|
||||
}
|
||||
|
||||
return $profile_image;
|
||||
}
|
||||
$filesystem = new Filesystem();
|
||||
if ($filesystem->exists(public_path() . '/assets/profile-images/' . $host . '/image')) {
|
||||
return '/assets/profile-images/' . $host . '/image';
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the HTML in a reply webmention.
|
||||
*
|
||||
* @param string The reply HTML
|
||||
* @return string The filtered HTML
|
||||
*/
|
||||
private function filterHTML($html)
|
||||
{
|
||||
$config = HTMLPurifier_Config::createDefault();
|
||||
$config->set('Cache.SerializerPath', storage_path() . '/HTMLPurifier');
|
||||
$config->set('HTML.TargetBlank', true);
|
||||
$purifier = new HTMLPurifier($config);
|
||||
|
||||
return $purifier->purify($html);
|
||||
}
|
||||
}
|
||||
|
|
42
app/Jobs/AddClientToDatabase.php
Normal file
42
app/Jobs/AddClientToDatabase.php
Normal file
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\MicropubClient;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
|
||||
class AddClientToDatabase implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
protected $client_id;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(string $client_id)
|
||||
{
|
||||
$this->client_id = $client_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
if (MicropubClient::where('client_url', $this->client_id)->count() == 0) {
|
||||
$client = MicropubClient::create([
|
||||
'client_url' => $this->client_id,
|
||||
'client_name' => $this->client_id, // default client name is the URL
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Jobs\AddClientToDatabase;
|
||||
use Lcobucci\JWT\Signer\Hmac\Sha256;
|
||||
use App\Exceptions\InvalidTokenException;
|
||||
use Lcobucci\JWT\{Builder, Parser, Token};
|
||||
|
@ -26,6 +27,7 @@ class TokenService
|
|||
->set('nonce', bin2hex(random_bytes(8)))
|
||||
->sign($signer, config('app.key'))
|
||||
->getToken();
|
||||
dispatch(new AddClientToDatabase($data['client_id']));
|
||||
|
||||
return (string) $token;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,13 @@
|
|||
|
||||
namespace App;
|
||||
|
||||
use Twitter;
|
||||
use HTMLPurifier;
|
||||
use Carbon\Carbon;
|
||||
use HTMLPurifier_Config;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Jonnybarnes\WebmentionsParser\Authorship;
|
||||
|
||||
class WebMention extends Model
|
||||
{
|
||||
|
@ -29,4 +35,112 @@ class WebMention extends Model
|
|||
* @var array
|
||||
*/
|
||||
protected $guarded = ['id'];
|
||||
|
||||
/**
|
||||
* Get the author of the webmention.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAuthorAttribute()
|
||||
{
|
||||
$authorship = new Authorship();
|
||||
$hCard = $authorship->findAuthor(json_decode($this->mf2, true));
|
||||
if (array_key_exists('properties', $hCard) &&
|
||||
array_key_exists('photo', $hCard['properties'])
|
||||
) {
|
||||
$hCard['properties']['photo'][0] = $this->createPhotoLink($hCard['properties']['photo'][0]);
|
||||
}
|
||||
|
||||
return $hCard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the published value for the webmention.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPublishedAttribute()
|
||||
{
|
||||
$microformats = json_decode($this->mf2, true);
|
||||
$carbon = new Carbon();
|
||||
if (isset($microformats['items'][0]['properties']['published'][0])) {
|
||||
try {
|
||||
$published = $carbon->parse(
|
||||
$microformats['items'][0]['properties']['published'][0]
|
||||
)->toDayDateTimeString();
|
||||
} catch (\Exception $exception) {
|
||||
$published = $webmention->updated_at->toDayDateTimeString();
|
||||
}
|
||||
} else {
|
||||
$published = $webmention->updated_at->toDayDateTimeString();
|
||||
}
|
||||
|
||||
return $published;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the filteres HTML of a reply.
|
||||
*
|
||||
* @return strin|null
|
||||
*/
|
||||
public function getReplyAttribute()
|
||||
{
|
||||
$microformats = json_decode($this->mf2, true);
|
||||
if (isset($microformats['items'][0]['properties']['content'][0]['html'])) {
|
||||
return $this->filterHTML($microformats['items'][0]['properties']['content'][0]['html']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the photo link.
|
||||
*
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
public function createPhotoLink(string $url): string
|
||||
{
|
||||
$url = normalize_url($url);
|
||||
$host = parse_url($url, PHP_URL_HOST);
|
||||
if ($host == 'pbs.twimg.com') {
|
||||
//make sure we use HTTPS, we know twitter supports it
|
||||
return str_replace('http://', 'https://', $url);
|
||||
}
|
||||
if ($host == 'twitter.com') {
|
||||
if (Cache::has($url)) {
|
||||
return Cache::get($url);
|
||||
}
|
||||
$username = parse_url($url, PHP_URL_PATH);
|
||||
try {
|
||||
$info = Twitter::getUsers(['screen_name' => $username]);
|
||||
$profile_image = $info->profile_image_url_https;
|
||||
Cache::put($url, $profile_image, 10080); //1 week
|
||||
} catch (Exception $e) {
|
||||
return $url; //not sure here
|
||||
}
|
||||
|
||||
return $profile_image;
|
||||
}
|
||||
$filesystem = new Filesystem();
|
||||
if ($filesystem->exists(public_path() . '/assets/profile-images/' . $host . '/image')) {
|
||||
return '/assets/profile-images/' . $host . '/image';
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the HTML in a reply webmention.
|
||||
*
|
||||
* @param string The reply HTML
|
||||
* @return string The filtered HTML
|
||||
*/
|
||||
private function filterHTML($html)
|
||||
{
|
||||
$config = HTMLPurifier_Config::createDefault();
|
||||
$config->set('Cache.SerializerPath', storage_path() . '/HTMLPurifier');
|
||||
$config->set('HTML.TargetBlank', true);
|
||||
$purifier = new HTMLPurifier($config);
|
||||
|
||||
return $purifier->purify($html);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue