mirror of https://github.com/pixelfed/pixelfed.git
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);
|
||||
}
|
||||
}
|
|
@ -4,43 +4,60 @@ namespace App\Util\Webfinger;
|
|||
|
||||
class Webfinger
|
||||
{
|
||||
protected $user;
|
||||
protected $subject;
|
||||
protected $aliases;
|
||||
protected $links;
|
||||
protected $user;
|
||||
protected $subject;
|
||||
protected $aliases;
|
||||
protected $links;
|
||||
|
||||
public function __construct($user)
|
||||
{
|
||||
$this->subject = 'acct:'.$user->username.'@'.parse_url(config('app.url'), PHP_URL_HOST);
|
||||
$this->aliases = [
|
||||
$user->url(),
|
||||
$user->permalink(),
|
||||
];
|
||||
$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(),
|
||||
],
|
||||
];
|
||||
}
|
||||
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';
|
||||
|
||||
public function generate()
|
||||
{
|
||||
return [
|
||||
'subject' => $this->subject,
|
||||
'aliases' => $this->aliases,
|
||||
'links' => $this->links,
|
||||
];
|
||||
}
|
||||
$this->subject = 'acct:'.$user->username.'@'.parse_url(config('app.url'), PHP_URL_HOST);
|
||||
$this->aliases = [
|
||||
$user->url(),
|
||||
$user->permalink(),
|
||||
];
|
||||
$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,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,16 @@
|
|||
</div>
|
||||
<div v-else-if="n.type == 'comment'">
|
||||
<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>
|
||||
</div>
|
||||
<div v-else-if="n.type == 'group:comment'">
|
||||
|
@ -64,7 +73,16 @@
|
|||
</div>
|
||||
<div v-else-if="n.type == 'share'">
|
||||
<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>
|
||||
</div>
|
||||
<div v-else-if="n.type == 'modlog'">
|
||||
|
|
Loading…
Reference in New Issue