2022-01-19 06:03:21 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace App\Services;
|
|
|
|
|
2022-01-19 07:46:30 +00:00
|
|
|
use App\Models\CustomEmoji;
|
2022-01-19 06:03:21 +00:00
|
|
|
use App\Util\ActivityPub\Helpers;
|
|
|
|
use Illuminate\Support\Facades\Http;
|
2022-01-19 07:46:30 +00:00
|
|
|
use Illuminate\Support\Facades\Cache;
|
2022-12-24 08:07:44 +00:00
|
|
|
use Illuminate\Support\Facades\Storage;
|
|
|
|
use Illuminate\Http\Client\RequestException;
|
2022-01-19 06:03:21 +00:00
|
|
|
|
|
|
|
class CustomEmojiService
|
|
|
|
{
|
2022-01-19 06:26:44 +00:00
|
|
|
public static function get($shortcode)
|
2022-01-19 06:03:21 +00:00
|
|
|
{
|
2024-03-12 04:42:26 +00:00
|
|
|
if((bool) config_cache('federation.custom_emoji.enabled') == false) {
|
2022-01-19 07:46:30 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-01-19 06:03:21 +00:00
|
|
|
return CustomEmoji::whereShortcode($shortcode)->first();
|
|
|
|
}
|
|
|
|
|
2022-01-21 08:28:36 +00:00
|
|
|
public static function import($url, $id = false)
|
2022-01-19 06:03:21 +00:00
|
|
|
{
|
2024-03-12 04:42:26 +00:00
|
|
|
if((bool) config_cache('federation.custom_emoji.enabled') == false) {
|
2022-01-19 07:46:30 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-01-19 06:03:21 +00:00
|
|
|
if(Helpers::validateUrl($url) == false) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
$emoji = CustomEmoji::whereUri($url)->first();
|
|
|
|
if($emoji) {
|
2022-01-19 07:46:30 +00:00
|
|
|
return;
|
2022-01-19 06:03:21 +00:00
|
|
|
}
|
|
|
|
|
2022-12-24 08:07:44 +00:00
|
|
|
try {
|
|
|
|
$res = Http::acceptJson()->get($url);
|
|
|
|
} catch (RequestException $e) {
|
|
|
|
return;
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
return;
|
|
|
|
}
|
2022-01-19 06:03:21 +00:00
|
|
|
|
|
|
|
if($res->successful()) {
|
|
|
|
$json = $res->json();
|
|
|
|
|
|
|
|
if(
|
|
|
|
!$json ||
|
|
|
|
!isset($json['id']) ||
|
|
|
|
!isset($json['type']) ||
|
|
|
|
$json['type'] !== 'Emoji' ||
|
|
|
|
!isset($json['icon']) ||
|
|
|
|
!isset($json['icon']['mediaType']) ||
|
|
|
|
!isset($json['icon']['url']) ||
|
|
|
|
!isset($json['icon']['type']) ||
|
|
|
|
$json['icon']['type'] !== 'Image' ||
|
|
|
|
!in_array($json['icon']['mediaType'], ['image/jpeg', 'image/png', 'image/jpg'])
|
|
|
|
) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!self::headCheck($json['icon']['url'])) {
|
|
|
|
return;
|
|
|
|
}
|
2022-01-19 07:46:30 +00:00
|
|
|
|
2022-12-24 08:07:44 +00:00
|
|
|
$emoji = CustomEmoji::firstOrCreate([
|
|
|
|
'shortcode' => $json['name'],
|
|
|
|
'domain' => parse_url($json['id'], PHP_URL_HOST)
|
|
|
|
], [
|
|
|
|
'uri' => $json['id'],
|
|
|
|
'image_remote_url' => $json['icon']['url']
|
|
|
|
]);
|
|
|
|
|
|
|
|
if($emoji->wasRecentlyCreated == false) {
|
|
|
|
if(Storage::exists('public/' . $emoji->media_path)) {
|
|
|
|
Storage::delete('public/' . $emoji->media_path);
|
|
|
|
}
|
|
|
|
}
|
2022-01-19 06:03:21 +00:00
|
|
|
|
|
|
|
$ext = '.' . last(explode('/', $json['icon']['mediaType']));
|
|
|
|
$dest = storage_path('app/public/emoji/') . $emoji->id . $ext;
|
2022-12-24 08:07:44 +00:00
|
|
|
copy($json['icon']['url'], $dest);
|
2022-01-19 06:03:21 +00:00
|
|
|
$emoji->media_path = 'emoji/' . $emoji->id . $ext;
|
|
|
|
$emoji->save();
|
|
|
|
|
2022-01-19 07:46:30 +00:00
|
|
|
$name = str_replace(':', '', $json['name']);
|
2022-01-25 09:08:50 +00:00
|
|
|
Cache::forget('pf:custom_emoji');
|
2022-01-19 07:46:30 +00:00
|
|
|
Cache::forget('pf:custom_emoji:' . $name);
|
2022-01-21 08:28:36 +00:00
|
|
|
if($id) {
|
|
|
|
StatusService::del($id);
|
|
|
|
}
|
2022-01-19 07:46:30 +00:00
|
|
|
return;
|
2022-01-19 06:03:21 +00:00
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static function headCheck($url)
|
|
|
|
{
|
2022-12-24 08:07:44 +00:00
|
|
|
try {
|
|
|
|
$res = Http::head($url);
|
|
|
|
} catch (RequestException $e) {
|
|
|
|
return false;
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
return false;
|
|
|
|
}
|
2022-01-19 06:03:21 +00:00
|
|
|
|
|
|
|
if(!$res->successful()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
$type = $res->header('content-type');
|
|
|
|
$length = $res->header('content-length');
|
|
|
|
|
|
|
|
if(
|
|
|
|
!$type ||
|
|
|
|
!$length ||
|
|
|
|
!in_array($type, ['image/jpeg', 'image/png', 'image/jpg']) ||
|
|
|
|
$length > config('federation.custom_emoji.max_size')
|
|
|
|
) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2022-01-25 09:08:50 +00:00
|
|
|
|
|
|
|
public static function all()
|
|
|
|
{
|
|
|
|
return Cache::rememberForever('pf:custom_emoji', function() {
|
|
|
|
$pgsql = config('database.default') === 'pgsql';
|
|
|
|
return CustomEmoji::when(!$pgsql, function($q, $pgsql) {
|
|
|
|
return $q->groupBy('shortcode');
|
|
|
|
})
|
2024-04-23 11:54:24 +00:00
|
|
|
->whereNull('uri')
|
2022-01-25 09:08:50 +00:00
|
|
|
->get()
|
|
|
|
->map(function($emojo) {
|
|
|
|
$url = url('storage/' . $emojo->media_path);
|
|
|
|
return [
|
|
|
|
'shortcode' => str_replace(':', '', $emojo->shortcode),
|
|
|
|
'url' => $url,
|
2022-04-01 22:40:13 +00:00
|
|
|
'static_url' => $url,
|
2022-01-25 09:08:50 +00:00
|
|
|
'visible_in_picker' => $emojo->disabled == false
|
|
|
|
];
|
|
|
|
})
|
|
|
|
->when($pgsql, function($collection) {
|
|
|
|
return $collection->unique('shortcode');
|
|
|
|
})
|
|
|
|
->toJson(JSON_UNESCAPED_SLASHES);
|
|
|
|
});
|
|
|
|
}
|
2022-01-19 06:03:21 +00:00
|
|
|
}
|