Merge branch 'release/0.9'
This commit is contained in:
commit
b33c0cca08
27 changed files with 480 additions and 93 deletions
20
app/Http/Controllers/LikesController.php
Normal file
20
app/Http/Controllers/LikesController.php
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Like;
|
||||
|
||||
class LikesController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$likes = Like::latest()->paginate(20);
|
||||
|
||||
return view('likes.index', compact('likes'));
|
||||
}
|
||||
|
||||
public function show(Like $like)
|
||||
{
|
||||
return view('likes.show', compact('like'));
|
||||
}
|
||||
}
|
||||
|
|
@ -6,8 +6,9 @@ use Storage;
|
|||
use Monolog\Logger;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use App\Jobs\ProcessImage;
|
||||
use App\{Media, Note, Place};
|
||||
use App\Services\LikeService;
|
||||
use Monolog\Handler\StreamHandler;
|
||||
use App\{Like, Media, Note, Place};
|
||||
use Intervention\Image\ImageManager;
|
||||
use Illuminate\Http\{Request, Response};
|
||||
use App\Exceptions\InvalidTokenException;
|
||||
|
|
@ -73,6 +74,14 @@ class MicropubController extends Controller
|
|||
if (stristr($tokenData->getClaim('scope'), 'create') === false) {
|
||||
return $this->returnInsufficientScopeResponse();
|
||||
}
|
||||
if ($request->has('properties.like-of') || $request->has('like-of')) {
|
||||
$like = (new LikeService())->createLike($request);
|
||||
|
||||
return response()->json([
|
||||
'response' => 'created',
|
||||
'location' => config('app.url') . "/likes/$like->id",
|
||||
], 201)->header('Location', config('app.url') . "/likes/$like->id");
|
||||
}
|
||||
$data = [];
|
||||
$data['client-id'] = $tokenData->getClaim('client_id');
|
||||
if ($request->header('Content-Type') == 'application/json') {
|
||||
|
|
|
|||
|
|
@ -22,14 +22,13 @@ class NotesController extends Controller
|
|||
return (new ActivityStreamsService)->siteOwnerResponse();
|
||||
}
|
||||
|
||||
$notes = Note::orderBy('id', 'desc')
|
||||
$notes = Note::latest()
|
||||
->with('place', 'media', 'client')
|
||||
->withCount(['webmentions As replies' => function ($query) {
|
||||
$query->where('type', 'in-reply-to');
|
||||
}])->paginate(10);
|
||||
$aslink = config('app.url');
|
||||
|
||||
return view('notes.index', compact('notes', 'aslink'));
|
||||
return view('notes.index', compact('notes'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -46,9 +45,7 @@ class NotesController extends Controller
|
|||
return (new ActivityStreamsService)->singleNoteResponse($note);
|
||||
}
|
||||
|
||||
$aslink = $note->longurl;
|
||||
|
||||
return view('notes.show', compact('note', 'aslink'));
|
||||
return view('notes.show', compact('note'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ class Kernel extends HttpKernel
|
|||
\App\Http\Middleware\LinkHeadersMiddleware::class,
|
||||
//\App\Http\Middleware\DevTokenMiddleware::class,
|
||||
\App\Http\Middleware\LocalhostSessionMiddleware::class,
|
||||
\App\Http\Middleware\ActivityStreamLinks::class,
|
||||
],
|
||||
|
||||
'api' => [
|
||||
|
|
|
|||
28
app/Http/Middleware/ActivityStreamLinks.php
Normal file
28
app/Http/Middleware/ActivityStreamLinks.php
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
|
||||
class ActivityStreamLinks
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
$response = $next($request);
|
||||
if ($request->path() === '/') {
|
||||
$response->header('Link', '<' . config('app.url') . '>; rel="application/activity+json"', false);
|
||||
}
|
||||
if ($request->is('notes/*')) {
|
||||
$response->header('Link', '<' . $request->url() . '>; rel="application/activity+json"', false);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
59
app/Jobs/ProcessLike.php
Normal file
59
app/Jobs/ProcessLike.php
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Like;
|
||||
use GuzzleHttp\Client;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Jonnybarnes\WebmentionsParser\Authorship;
|
||||
use Jonnybarnes\WebmentionsParser\Exceptions\AuthorshipParserException;
|
||||
|
||||
class ProcessLike implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
protected $like;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Like $like)
|
||||
{
|
||||
$this->like = $like;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle(Client $client, Authorship $authorship)
|
||||
{
|
||||
$response = $client->request('GET', $this->like->url);
|
||||
$mf2 = \Mf2\parse((string) $response->getBody(), $this->like->url);
|
||||
if (array_has($mf2, 'items.0.properties.content')) {
|
||||
$this->like->content = $mf2['items'][0]['properties']['content'][0]['html'];
|
||||
}
|
||||
|
||||
try {
|
||||
$author = $authorship->findAuthor($mf2);
|
||||
if (is_array($author)) {
|
||||
$this->like->author_name = $author['name'];
|
||||
$this->like->author_url = $author['url'];
|
||||
}
|
||||
if (is_string($author) && $author !== '') {
|
||||
$this->like->author_name = $author;
|
||||
}
|
||||
} catch (AuthorshipParserException $exception) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->like->save();
|
||||
}
|
||||
}
|
||||
|
|
@ -40,6 +40,7 @@ class SyndicateToFacebook implements ShouldQueue
|
|||
'form_params' => [
|
||||
'source' => $this->note->longurl,
|
||||
'target' => 'https://brid.gy/publish/facebook',
|
||||
'bridgy_omit_link' => 'maybe',
|
||||
],
|
||||
]
|
||||
);
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ class SyndicateToTwitter implements ShouldQueue
|
|||
'form_params' => [
|
||||
'source' => $this->note->longurl,
|
||||
'target' => 'https://brid.gy/publish/twitter',
|
||||
'bridgy_omit_link' => 'maybe',
|
||||
],
|
||||
]
|
||||
);
|
||||
|
|
|
|||
44
app/Like.php
Normal file
44
app/Like.php
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Mf2;
|
||||
use HTMLPurifier;
|
||||
use HTMLPurifier_Config;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Like extends Model
|
||||
{
|
||||
protected $fillable = ['url'];
|
||||
|
||||
public function setUrlAttribute($value)
|
||||
{
|
||||
$this->attributes['url'] = normalize_url($value);
|
||||
}
|
||||
|
||||
public function setAuthorUrlAttribute($value)
|
||||
{
|
||||
$this->attributes['author_url'] = normalize_url($value);
|
||||
}
|
||||
|
||||
public function getContentAttribute($value)
|
||||
{
|
||||
if ($value === null) {
|
||||
return $this->url;
|
||||
}
|
||||
|
||||
$mf2 = Mf2\parse($value, $this->url);
|
||||
|
||||
return $this->filterHTML($mf2['items'][0]['properties']['content'][0]['html']);
|
||||
}
|
||||
|
||||
public 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);
|
||||
}
|
||||
}
|
||||
37
app/Services/LikeService.php
Normal file
37
app/Services/LikeService.php
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Like;
|
||||
use App\Jobs\ProcessLike;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class LikeService
|
||||
{
|
||||
/**
|
||||
* Create a new Like.
|
||||
*
|
||||
* @param Request $request
|
||||
*/
|
||||
public function createLike(Request $request): Like
|
||||
{
|
||||
if ($request->header('Content-Type') == 'application/json') {
|
||||
//micropub request
|
||||
$url = normalize_url($request->input('properties.like-of.0'));
|
||||
}
|
||||
if (
|
||||
($request->header('Content-Type') == 'x-www-url-formencoded')
|
||||
||
|
||||
($request->header('Content-Type') == 'multipart/form-data')
|
||||
) {
|
||||
$url = normalize_url($request->input('like-of'));
|
||||
}
|
||||
|
||||
$like = Like::create(['url' => $url]);
|
||||
ProcessLike::dispatch($like);
|
||||
|
||||
return $like;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,13 @@
|
|||
# Changelog
|
||||
|
||||
## Version 0.9 (2017-10-06)
|
||||
- Add support for `likes` (issue#69)
|
||||
- Only included links on truncated syndicated notes https://brid.gy/about#omit-link
|
||||
|
||||
## Version 0.8.1 (2017-09-16)
|
||||
- Order notes by latest (issue#70)
|
||||
- AcitivtyStream support is now indicated with HTTP Link headers
|
||||
|
||||
## Version 0.8 (2017-09-16)
|
||||
- Improve embedding of tweets (issue#66)
|
||||
- Allow for “responsive” images (issue#62)
|
||||
|
|
|
|||
20
composer.lock
generated
20
composer.lock
generated
|
|
@ -8,16 +8,16 @@
|
|||
"packages": [
|
||||
{
|
||||
"name": "aws/aws-sdk-php",
|
||||
"version": "3.36.7",
|
||||
"version": "3.36.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/aws/aws-sdk-php.git",
|
||||
"reference": "421088947540b1c7956cd693b032124e2c74eb76"
|
||||
"reference": "7b89fa65cccb966da1599b715dcea8c09eafc175"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/421088947540b1c7956cd693b032124e2c74eb76",
|
||||
"reference": "421088947540b1c7956cd693b032124e2c74eb76",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/7b89fa65cccb966da1599b715dcea8c09eafc175",
|
||||
"reference": "7b89fa65cccb966da1599b715dcea8c09eafc175",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -84,7 +84,7 @@
|
|||
"s3",
|
||||
"sdk"
|
||||
],
|
||||
"time": "2017-09-13T18:56:17+00:00"
|
||||
"time": "2017-09-15T19:12:04+00:00"
|
||||
},
|
||||
{
|
||||
"name": "barnabywalters/mf-cleaner",
|
||||
|
|
@ -2085,16 +2085,16 @@
|
|||
},
|
||||
{
|
||||
"name": "laravel/scout",
|
||||
"version": "v3.0.9",
|
||||
"version": "v3.0.10",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/scout.git",
|
||||
"reference": "84762c8ed51cb57f09b5f465e09993e48baf9d55"
|
||||
"reference": "681c15a26bbc973528af2e77e0bb61981dc07206"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/scout/zipball/84762c8ed51cb57f09b5f465e09993e48baf9d55",
|
||||
"reference": "84762c8ed51cb57f09b5f465e09993e48baf9d55",
|
||||
"url": "https://api.github.com/repos/laravel/scout/zipball/681c15a26bbc973528af2e77e0bb61981dc07206",
|
||||
"reference": "681c15a26bbc973528af2e77e0bb61981dc07206",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -2146,7 +2146,7 @@
|
|||
"laravel",
|
||||
"search"
|
||||
],
|
||||
"time": "2017-09-13T18:24:31+00:00"
|
||||
"time": "2017-09-14T12:32:30+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/tinker",
|
||||
|
|
|
|||
12
database/factories/LikeFactory.php
Normal file
12
database/factories/LikeFactory.php
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
use Faker\Generator as Faker;
|
||||
|
||||
$factory->define(App\Like::class, function (Faker $faker) {
|
||||
return [
|
||||
'url' => $faker->url,
|
||||
'author_name' => $faker->name,
|
||||
'author_url' => $faker->url,
|
||||
'content' => '<html><body><div class="h-entry"><div class="e-content">' . $faker->realtext() . '</div></div></body></html>',
|
||||
];
|
||||
});
|
||||
35
database/migrations/2017_09_16_191741_create_likes_table.php
Normal file
35
database/migrations/2017_09_16_191741_create_likes_table.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateLikesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('likes', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('url');
|
||||
$table->string('author_name')->nullable();
|
||||
$table->string('author_url')->nullable();
|
||||
$table->text('content')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('likes');
|
||||
}
|
||||
}
|
||||
|
|
@ -18,5 +18,6 @@ class DatabaseSeeder extends Seeder
|
|||
$this->call(NotesTableSeeder::class);
|
||||
$this->call(WebMentionsTableSeeder::class);
|
||||
$this->call(IndieWebUserTableSeeder::class);
|
||||
$this->call(LikesTableSeeder::class);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
16
database/seeds/LikesTableSeeder.php
Normal file
16
database/seeds/LikesTableSeeder.php
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class LikesTableSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
factory(App\Like::class, 10)->create();
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ class NotesTableSeeder extends Seeder
|
|||
public function run()
|
||||
{
|
||||
factory(App\Note::class, 10)->create();
|
||||
sleep(1);
|
||||
$noteWithPlace = App\Note::create([
|
||||
'note' => 'Having a #beer at the local. 🍺',
|
||||
'tweet_id' => '123456789',
|
||||
|
|
@ -19,17 +20,21 @@ class NotesTableSeeder extends Seeder
|
|||
$place = App\Place::find(1);
|
||||
$noteWithPlace->place()->associate($place);
|
||||
$noteWithPlace->save();
|
||||
sleep(1);
|
||||
$noteWithContact = App\Note::create([
|
||||
'note' => 'Hi @tantek'
|
||||
]);
|
||||
sleep(1);
|
||||
$noteWithContactPlusPic = App\Note::create([
|
||||
'note' => 'Hi @aaron',
|
||||
'client_id' => 'https://jbl5.dev/notes/new'
|
||||
]);
|
||||
sleep(1);
|
||||
$noteWithoutContact = App\Note::create([
|
||||
'note' => 'Hi @bob',
|
||||
'client_id' => 'https://quill.p3k.io'
|
||||
]);
|
||||
sleep(1);
|
||||
//copy aaron’s profile pic in place
|
||||
$spl = new SplFileInfo(public_path() . '/assets/profile-images/aaronparecki.com');
|
||||
if ($spl->isDir() === false) {
|
||||
|
|
@ -40,6 +45,7 @@ class NotesTableSeeder extends Seeder
|
|||
'note' => 'Note from somehwere',
|
||||
'location' => '53.499,-2.379'
|
||||
]);
|
||||
sleep(1);
|
||||
$noteSyndicated = App\Note::create([
|
||||
'note' => 'This note has all the syndication targets',
|
||||
'tweet_id' => '123456',
|
||||
|
|
|
|||
27
resources/views/likes/index.blade.php
Normal file
27
resources/views/likes/index.blade.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
@extends('master')
|
||||
|
||||
@section('title')
|
||||
Likes «
|
||||
@stop
|
||||
|
||||
@section('content')
|
||||
<div class="h-feed">
|
||||
@foreach($likes as $like)
|
||||
<div class="h-entry">
|
||||
<div class="h-cite u-like-of">
|
||||
Liked <a class="u-url" href="{{ $like->url }}">a post</a> by
|
||||
<span class="p-author h-card">
|
||||
@isset($like->author_url)
|
||||
<a class="u-url p-name" href="{{ $like->author_url }}">{{ $like->author_name }}</a>
|
||||
@else
|
||||
<span class="p-name">{{ $like->author_name }}</span>
|
||||
@endisset
|
||||
</span>:
|
||||
<blockquote class="e-content">
|
||||
{!! $like->content !!}
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@stop
|
||||
23
resources/views/likes/show.blade.php
Normal file
23
resources/views/likes/show.blade.php
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
@extends('master')
|
||||
|
||||
@section('title')
|
||||
Like «
|
||||
@stop
|
||||
|
||||
@section('content')
|
||||
<div class="h-entry">
|
||||
<div class="h-cite u-like-of">
|
||||
Liked <a class="u-url" href="{{ $like->url }}">a post</a> by
|
||||
<span class="p-author h-card">
|
||||
@isset($like->author_url)
|
||||
<a class="u-url p-name" href="{{ $like->author_url }}">{{ $like->author_name }}</a>
|
||||
@else
|
||||
<span class="p-name">{{ $like->author_name }}</span>
|
||||
@endisset
|
||||
</span>:
|
||||
<blockquote class="e-content">
|
||||
{!! $like->content !!}
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
@stop
|
||||
|
|
@ -12,8 +12,6 @@
|
|||
<link rel="alternate" type="application/rss+xml" title="Notes RSS Feed" href="/notes/feed.rss">
|
||||
<link rel="alternate" type="application/atom+xml" title="Notes Atom Feed" href="/notes/feed.atom">
|
||||
<link rel="alternate" type="application/json" title="Notes JSON Feed" href="/notes/feed.json">
|
||||
@isset($aslink) <link rel="alternate" type="application/activity+json" href="{{ $aslink }}">
|
||||
@endisset
|
||||
<link rel="openid.server" href="https://indieauth.com/openid">
|
||||
<link rel="openid.delegate" href="{{ config('app.url') }}">
|
||||
<link rel="authorization_endpoint" href="https://indieauth.com/auth">
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue