Merge pull request #4847 from pixelfed/staging

Staging
This commit is contained in:
daniel 2024-01-03 04:13:11 -07:00 committed by GitHub
commit d8a5dc00bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 192 additions and 39 deletions

View File

@ -0,0 +1,118 @@
<?php
namespace App\Console\Commands;
use App\Models\CustomEmoji;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Storage;
class ImportEmojis extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'import:emojis
{path : Path to a tar.gz archive with the emojis}
{--prefix : Define a prefix for the emjoi shortcode}
{--suffix : Define a suffix for the emjoi shortcode}
{--overwrite : Overwrite existing emojis}
{--disabled : Import all emojis as disabled}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Import emojis to the database';
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$path = $this->argument('path');
if (!file_exists($path) || !mime_content_type($path) == 'application/x-tar') {
$this->error('Path does not exist or is not a tarfile');
return Command::FAILURE;
}
$imported = 0;
$skipped = 0;
$failed = 0;
$tar = new \PharData($path);
$tar->decompress();
foreach (new \RecursiveIteratorIterator($tar) as $entry) {
$this->line("Processing {$entry->getFilename()}");
if (!$entry->isFile() || !$this->isImage($entry) || !$this->isEmoji($entry->getPathname())) {
$failed++;
continue;
}
$filename = pathinfo($entry->getFilename(), PATHINFO_FILENAME);
$extension = pathinfo($entry->getFilename(), PATHINFO_EXTENSION);
// Skip macOS shadow files
if (str_starts_with($filename, '._')) {
continue;
}
$shortcode = implode('', [
$this->option('prefix'),
$filename,
$this->option('suffix'),
]);
$customEmoji = CustomEmoji::whereShortcode($shortcode)->first();
if ($customEmoji && !$this->option('overwrite')) {
$skipped++;
continue;
}
$emoji = $customEmoji ?? new CustomEmoji();
$emoji->shortcode = $shortcode;
$emoji->domain = config('pixelfed.domain.app');
$emoji->disabled = $this->option('disabled');
$emoji->save();
$fileName = $emoji->id . '.' . $extension;
Storage::putFileAs('public/emoji', $entry->getPathname(), $fileName);
$emoji->media_path = 'emoji/' . $fileName;
$emoji->save();
$imported++;
Cache::forget('pf:custom_emoji');
}
$this->line("Imported: {$imported}");
$this->line("Skipped: {$skipped}");
$this->line("Failed: {$failed}");
//delete file
unlink(str_replace('.tar.gz', '.tar', $path));
return Command::SUCCESS;
}
private function isImage($file)
{
$image = getimagesize($file->getPathname());
return $image !== false;
}
private function isEmoji($filename)
{
$allowedMimeTypes = ['image/png', 'image/jpeg', 'image/webp'];
$mimeType = mime_content_type($filename);
return in_array($mimeType, $allowedMimeTypes);
}
}

View File

@ -4,43 +4,60 @@ namespace App\Util\Webfinger;
class Webfinger class Webfinger
{ {
protected $user; protected $user;
protected $subject; protected $subject;
protected $aliases; protected $aliases;
protected $links; protected $links;
public function __construct($user) public function __construct($user)
{ {
$this->subject = 'acct:'.$user->username.'@'.parse_url(config('app.url'), PHP_URL_HOST); $avatar = $user ? $user->avatarUrl() : url('/storage/avatars/default.jpg');
$this->aliases = [ $avatarPath = parse_url($avatar, PHP_URL_PATH);
$user->url(), $extension = pathinfo($avatarPath, PATHINFO_EXTENSION);
$user->permalink(), $mimeTypes = [
]; 'jpg' => 'image/jpeg',
$this->links = [ 'jpeg' => 'image/jpeg',
[ 'png' => 'image/png',
'rel' => 'http://webfinger.net/rel/profile-page', 'gif' => 'image/gif',
'type' => 'text/html', 'svg' => 'image/svg',
'href' => $user->url(), ];
], $avatarType = $mimeTypes[$extension] ?? 'application/octet-stream';
[
'rel' => 'http://schemas.google.com/g/2010#updates-from',
'type' => 'application/atom+xml',
'href' => $user->permalink('.atom'),
],
[
'rel' => 'self',
'type' => 'application/activity+json',
'href' => $user->permalink(),
],
];
}
public function generate() $this->subject = 'acct:'.$user->username.'@'.parse_url(config('app.url'), PHP_URL_HOST);
{ $this->aliases = [
return [ $user->url(),
'subject' => $this->subject, $user->permalink(),
'aliases' => $this->aliases, ];
'links' => $this->links, $this->links = [
]; [
} 'rel' => 'http://webfinger.net/rel/profile-page',
'type' => 'text/html',
'href' => $user->url(),
],
[
'rel' => 'http://schemas.google.com/g/2010#updates-from',
'type' => 'application/atom+xml',
'href' => $user->permalink('.atom'),
],
[
'rel' => 'self',
'type' => 'application/activity+json',
'href' => $user->permalink(),
],
[
'rel' => 'http://webfinger.net/rel/avatar',
'type' => $avatarType,
'href' => $avatar,
],
];
}
public function generate()
{
return [
'subject' => $this->subject,
'aliases' => $this->aliases,
'links' => $this->links,
];
}
} }

View File

@ -34,7 +34,16 @@
</div> </div>
<div v-else-if="n.type == 'comment'"> <div v-else-if="n.type == 'comment'">
<p class="my-0"> <p class="my-0">
<a :href="getProfileUrl(n.account)" class="font-weight-bold text-dark word-break" :title="n.account.username">{{n.account.local == false ? '@':''}}{{truncate(n.account.username)}}</a> commented on your <a class="font-weight-bold" v-bind:href="getPostUrl(n.status)">post</a>. <a :href="getProfileUrl(n.account)" class="font-weight-bold text-dark word-break" :title="n.account.username">{{n.account.local == false ? '@':''}}{{truncate(n.account.username)}}</a> commented on your
<span v-if="n.status && n.status.hasOwnProperty('media_attachments')">
<a class="font-weight-bold" v-bind:href="getPostUrl(n.status)" :id="'fvn-' + n.id">post</a>.
<b-popover :target="'fvn-' + n.id" title="" triggers="hover" placement="top" boundary="window">
<img :src="notificationPreview(n)" width="100px" height="100px" style="object-fit: cover;">
</b-popover>
</span>
<span v-else>
<a class="font-weight-bold" v-bind:href="getPostUrl(n.status)">post</a>.
</span>
</p> </p>
</div> </div>
<div v-else-if="n.type == 'group:comment'"> <div v-else-if="n.type == 'group:comment'">
@ -64,7 +73,16 @@
</div> </div>
<div v-else-if="n.type == 'share'"> <div v-else-if="n.type == 'share'">
<p class="my-0"> <p class="my-0">
<a :href="getProfileUrl(n.account)" class="font-weight-bold text-dark word-break" :title="n.account.username">{{n.account.local == false ? '@':''}}{{truncate(n.account.username)}}</a> shared your <a class="font-weight-bold" v-bind:href="getPostUrl(n.status)">post</a>. <a :href="getProfileUrl(n.account)" class="font-weight-bold text-dark word-break" :title="n.account.username">{{n.account.local == false ? '@':''}}{{truncate(n.account.username)}}</a> shared your
<span v-if="n.status && n.status.hasOwnProperty('media_attachments')">
<a class="font-weight-bold" v-bind:href="getPostUrl(n.status)" :id="'fvn-' + n.id">post</a>.
<b-popover :target="'fvn-' + n.id" title="" triggers="hover" placement="top" boundary="window">
<img :src="notificationPreview(n)" width="100px" height="100px" style="object-fit: cover;">
</b-popover>
</span>
<span v-else>
<a class="font-weight-bold" v-bind:href="getPostUrl(n.status)">post</a>.
</span>
</p> </p>
</div> </div>
<div v-else-if="n.type == 'modlog'"> <div v-else-if="n.type == 'modlog'">