forked from mirror/pixelfed
commit
d8a5dc00bb
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,18 @@ class Webfinger
|
||||||
|
|
||||||
public function __construct($user)
|
public function __construct($user)
|
||||||
{
|
{
|
||||||
|
$avatar = $user ? $user->avatarUrl() : url('/storage/avatars/default.jpg');
|
||||||
|
$avatarPath = parse_url($avatar, PHP_URL_PATH);
|
||||||
|
$extension = pathinfo($avatarPath, PATHINFO_EXTENSION);
|
||||||
|
$mimeTypes = [
|
||||||
|
'jpg' => 'image/jpeg',
|
||||||
|
'jpeg' => 'image/jpeg',
|
||||||
|
'png' => 'image/png',
|
||||||
|
'gif' => 'image/gif',
|
||||||
|
'svg' => 'image/svg',
|
||||||
|
];
|
||||||
|
$avatarType = $mimeTypes[$extension] ?? 'application/octet-stream';
|
||||||
|
|
||||||
$this->subject = 'acct:'.$user->username.'@'.parse_url(config('app.url'), PHP_URL_HOST);
|
$this->subject = 'acct:'.$user->username.'@'.parse_url(config('app.url'), PHP_URL_HOST);
|
||||||
$this->aliases = [
|
$this->aliases = [
|
||||||
$user->url(),
|
$user->url(),
|
||||||
|
@ -32,6 +44,11 @@ class Webfinger
|
||||||
'type' => 'application/activity+json',
|
'type' => 'application/activity+json',
|
||||||
'href' => $user->permalink(),
|
'href' => $user->permalink(),
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'rel' => 'http://webfinger.net/rel/avatar',
|
||||||
|
'type' => $avatarType,
|
||||||
|
'href' => $avatar,
|
||||||
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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'">
|
||||||
|
|
Loading…
Reference in New Issue