mirror of
https://github.com/pixelfed/pixelfed.git
synced 2024-11-26 00:03:16 +00:00
commit
d2545b2850
7 changed files with 135 additions and 121 deletions
|
@ -41,6 +41,9 @@
|
||||||
- Updated PublicApiController, add LikeService to Network timeline. ([82895591](https://github.com/pixelfed/pixelfed/commit/82895591))
|
- Updated PublicApiController, add LikeService to Network timeline. ([82895591](https://github.com/pixelfed/pixelfed/commit/82895591))
|
||||||
- Updated moderator api, expire cached status in StatusService. ([f215ee26](https://github.com/pixelfed/pixelfed/commit/f215ee26))
|
- Updated moderator api, expire cached status in StatusService. ([f215ee26](https://github.com/pixelfed/pixelfed/commit/f215ee26))
|
||||||
- Updated StatusHashtagService, fix null status bug. ([51a277e1](https://github.com/pixelfed/pixelfed/commit/51a277e1))
|
- Updated StatusHashtagService, fix null status bug. ([51a277e1](https://github.com/pixelfed/pixelfed/commit/51a277e1))
|
||||||
|
- Updated NotificationService, use zrevrangebyscore for api. ([d43e6d8d](https://github.com/pixelfed/pixelfed/commit/d43e6d8d))
|
||||||
|
- Updated ApiV1Controller, use PublicTimelineService. ([f67c67bc](https://github.com/pixelfed/pixelfed/commit/f67c67bc))
|
||||||
|
- Updated ApiV1Controller, use ProfileService for verify_credentials. ([352aa573](https://github.com/pixelfed/pixelfed/commit/352aa573))
|
||||||
- ([](https://github.com/pixelfed/pixelfed/commit/))
|
- ([](https://github.com/pixelfed/pixelfed/commit/))
|
||||||
|
|
||||||
## [v0.11.0 (2021-06-01)](https://github.com/pixelfed/pixelfed/compare/v0.10.10...v0.11.0)
|
## [v0.11.0 (2021-06-01)](https://github.com/pixelfed/pixelfed/compare/v0.10.10...v0.11.0)
|
||||||
|
|
|
@ -49,8 +49,11 @@ use App\Jobs\VideoPipeline\{
|
||||||
VideoThumbnail
|
VideoThumbnail
|
||||||
};
|
};
|
||||||
use App\Services\{
|
use App\Services\{
|
||||||
|
LikeService,
|
||||||
NotificationService,
|
NotificationService,
|
||||||
MediaPathService,
|
MediaPathService,
|
||||||
|
PublicTimelineService,
|
||||||
|
ProfileService,
|
||||||
SearchApiV2Service,
|
SearchApiV2Service,
|
||||||
StatusService,
|
StatusService,
|
||||||
MediaBlocklistService
|
MediaBlocklistService
|
||||||
|
@ -116,25 +119,13 @@ class ApiV1Controller extends Controller
|
||||||
public function verifyCredentials(Request $request)
|
public function verifyCredentials(Request $request)
|
||||||
{
|
{
|
||||||
abort_if(!$request->user(), 403);
|
abort_if(!$request->user(), 403);
|
||||||
$id = $request->user()->id;
|
$id = $request->user()->profile_id;
|
||||||
|
|
||||||
if($request->user()->last_active_at) {
|
$res = ProfileService::get($id);
|
||||||
$key = 'user:last_active_at:id:'.$id;
|
|
||||||
$ttl = now()->addMinutes(5);
|
|
||||||
Cache::remember($key, $ttl, function() use($id) {
|
|
||||||
$user = User::findOrFail($id);
|
|
||||||
$user->last_active_at = now();
|
|
||||||
$user->save();
|
|
||||||
return;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$profile = Profile::whereNull('status')->whereUserId($id)->firstOrFail();
|
|
||||||
$resource = new Fractal\Resource\Item($profile, new AccountTransformer());
|
|
||||||
$res = $this->fractal->createData($resource)->toArray();
|
|
||||||
$res['source'] = [
|
$res['source'] = [
|
||||||
'privacy' => $profile->is_private ? 'private' : 'public',
|
'privacy' => $res['locked'] ? 'private' : 'public',
|
||||||
'sensitive' => $profile->cw ? true : false,
|
'sensitive' => false,
|
||||||
'language' => null,
|
'language' => null,
|
||||||
'note' => '',
|
'note' => '',
|
||||||
'fields' => []
|
'fields' => []
|
||||||
|
@ -1283,7 +1274,6 @@ class ApiV1Controller extends Controller
|
||||||
|
|
||||||
$pid = $request->user()->profile_id;
|
$pid = $request->user()->profile_id;
|
||||||
$limit = $request->input('limit', 20);
|
$limit = $request->input('limit', 20);
|
||||||
$timeago = now()->subMonths(6);
|
|
||||||
|
|
||||||
$since = $request->input('since_id');
|
$since = $request->input('since_id');
|
||||||
$min = $request->input('min_id');
|
$min = $request->input('min_id');
|
||||||
|
@ -1293,27 +1283,20 @@ class ApiV1Controller extends Controller
|
||||||
$min = 1;
|
$min = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
$dir = $since ? '>' : ($min ? '>=' : '<');
|
$maxId = null;
|
||||||
$id = $since ?? $min ?? $max;
|
$minId = null;
|
||||||
|
|
||||||
$notifications = Notification::whereProfileId($pid)
|
if($max) {
|
||||||
->where('id', $dir, $id)
|
$res = NotificationService::getMax($pid, $max, $limit);
|
||||||
->whereDate('created_at', '>', $timeago)
|
$ids = NotificationService::getRankedMaxId($pid, $max, $limit);
|
||||||
->orderByDesc('id')
|
$maxId = max($ids);
|
||||||
->limit($limit)
|
$minId = min($ids);
|
||||||
->get();
|
} else {
|
||||||
|
$res = NotificationService::getMin($pid, $min ?? $since, $limit);
|
||||||
$minId = $notifications->min('id');
|
$ids = NotificationService::getRankedMinId($pid, $min ?? $since, $limit);
|
||||||
$maxId = $notifications->max('id');
|
$maxId = max($ids);
|
||||||
|
$minId = min($ids);
|
||||||
$resource = new Fractal\Resource\Collection(
|
}
|
||||||
$notifications,
|
|
||||||
new NotificationTransformer()
|
|
||||||
);
|
|
||||||
|
|
||||||
$res = $this->fractal
|
|
||||||
->createData($resource)
|
|
||||||
->toArray();
|
|
||||||
|
|
||||||
$baseUrl = config('app.url') . '/api/v1/notifications?';
|
$baseUrl = config('app.url') . '/api/v1/notifications?';
|
||||||
|
|
||||||
|
@ -1470,90 +1453,37 @@ class ApiV1Controller extends Controller
|
||||||
public function timelinePublic(Request $request)
|
public function timelinePublic(Request $request)
|
||||||
{
|
{
|
||||||
$this->validate($request,[
|
$this->validate($request,[
|
||||||
'page' => 'nullable|integer|max:40',
|
|
||||||
'min_id' => 'nullable|integer|min:0|max:' . PHP_INT_MAX,
|
'min_id' => 'nullable|integer|min:0|max:' . PHP_INT_MAX,
|
||||||
'max_id' => 'nullable|integer|min:0|max:' . PHP_INT_MAX,
|
'max_id' => 'nullable|integer|min:0|max:' . PHP_INT_MAX,
|
||||||
'limit' => 'nullable|integer|max:80'
|
'limit' => 'nullable|integer|max:80'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$page = $request->input('page');
|
|
||||||
$min = $request->input('min_id');
|
$min = $request->input('min_id');
|
||||||
$max = $request->input('max_id');
|
$max = $request->input('max_id');
|
||||||
$limit = $request->input('limit') ?? 3;
|
$limit = $request->input('limit') ?? 3;
|
||||||
$user = $request->user();
|
$user = $request->user();
|
||||||
|
|
||||||
if($user) {
|
if(PublicTimelineService::count() == 0) {
|
||||||
$key = 'user:last_active_at:id:'.$user->id;
|
PublicTimelineService::warmCache(true, 400);
|
||||||
$ttl = now()->addMinutes(5);
|
|
||||||
Cache::remember($key, $ttl, function() use($user) {
|
|
||||||
$user->last_active_at = now();
|
|
||||||
$user->save();
|
|
||||||
return;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if($min || $max) {
|
if ($max) {
|
||||||
$dir = $min ? '>' : '<';
|
$feed = PublicTimelineService::getRankedMaxId($max, $limit);
|
||||||
$id = $min ?? $max;
|
} else if ($min) {
|
||||||
$timeline = Status::select(
|
$feed = PublicTimelineService::getRankedMinId($min, $limit);
|
||||||
'id',
|
|
||||||
'uri',
|
|
||||||
'caption',
|
|
||||||
'rendered',
|
|
||||||
'profile_id',
|
|
||||||
'type',
|
|
||||||
'in_reply_to_id',
|
|
||||||
'reblog_of_id',
|
|
||||||
'is_nsfw',
|
|
||||||
'scope',
|
|
||||||
'local',
|
|
||||||
'reply_count',
|
|
||||||
'comments_disabled',
|
|
||||||
'place_id',
|
|
||||||
'likes_count',
|
|
||||||
'reblogs_count',
|
|
||||||
'created_at',
|
|
||||||
'updated_at'
|
|
||||||
)->whereNull('uri')
|
|
||||||
->whereIn('type', ['photo', 'photo:album', 'video', 'video:album'])
|
|
||||||
->with('profile', 'hashtags', 'mentions')
|
|
||||||
->where('id', $dir, $id)
|
|
||||||
->whereScope('public')
|
|
||||||
->where('created_at', '>', now()->subDays(14))
|
|
||||||
->latest()
|
|
||||||
->limit($limit)
|
|
||||||
->get();
|
|
||||||
} else {
|
} else {
|
||||||
$timeline = Status::select(
|
$feed = PublicTimelineService::get(0, $limit);
|
||||||
'id',
|
|
||||||
'uri',
|
|
||||||
'caption',
|
|
||||||
'rendered',
|
|
||||||
'profile_id',
|
|
||||||
'type',
|
|
||||||
'in_reply_to_id',
|
|
||||||
'reblog_of_id',
|
|
||||||
'is_nsfw',
|
|
||||||
'scope',
|
|
||||||
'local',
|
|
||||||
'reply_count',
|
|
||||||
'comments_disabled',
|
|
||||||
'place_id',
|
|
||||||
'likes_count',
|
|
||||||
'reblogs_count',
|
|
||||||
'created_at',
|
|
||||||
'updated_at'
|
|
||||||
)->whereNull('uri')
|
|
||||||
->whereIn('type', ['photo', 'photo:album', 'video', 'video:album'])
|
|
||||||
->with('profile', 'hashtags', 'mentions')
|
|
||||||
->whereScope('public')
|
|
||||||
->where('created_at', '>', now()->subDays(14))
|
|
||||||
->latest()
|
|
||||||
->simplePaginate($limit);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$fractal = new Fractal\Resource\Collection($timeline, new StatusTransformer());
|
$res = collect($feed)
|
||||||
$res = $this->fractal->createData($fractal)->toArray();
|
->map(function($k) use($user) {
|
||||||
|
$status = StatusService::get($k);
|
||||||
|
if($user) {
|
||||||
|
$status['favourited'] = (bool) LikeService::liked($user->profile_id, $k);
|
||||||
|
}
|
||||||
|
return $status;
|
||||||
|
})
|
||||||
|
->toArray();
|
||||||
return response()->json($res);
|
return response()->json($res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,60 @@ class NotificationService {
|
||||||
return $ids;
|
return $ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getMax($id = false, $start, $limit = 10)
|
||||||
|
{
|
||||||
|
$ids = self::getRankedMaxId($id, $start, $limit);
|
||||||
|
|
||||||
|
if(empty($ids)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$res = collect([]);
|
||||||
|
foreach($ids as $id) {
|
||||||
|
$res->push(self::getNotification($id));
|
||||||
|
}
|
||||||
|
return $res->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getMin($id = false, $start, $limit = 10)
|
||||||
|
{
|
||||||
|
$ids = self::getRankedMinId($id, $start, $limit);
|
||||||
|
|
||||||
|
if(empty($ids)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$res = collect([]);
|
||||||
|
foreach($ids as $id) {
|
||||||
|
$res->push(self::getNotification($id));
|
||||||
|
}
|
||||||
|
return $res->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getRankedMaxId($id = false, $start = null, $limit = 10)
|
||||||
|
{
|
||||||
|
if(!$start || !$id) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_keys(Redis::zrevrangebyscore(self::CACHE_KEY.$id, $start, '-inf', [
|
||||||
|
'withscores' => true,
|
||||||
|
'limit' => [1, $limit]
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getRankedMinId($id = false, $end = null, $limit = 10)
|
||||||
|
{
|
||||||
|
if(!$end || !$id) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_keys(Redis::zrevrangebyscore(self::CACHE_KEY.$id, '+inf', $end, [
|
||||||
|
'withscores' => true,
|
||||||
|
'limit' => [0, $limit]
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
public static function set($id, $val)
|
public static function set($id, $val)
|
||||||
{
|
{
|
||||||
return Redis::zadd(self::CACHE_KEY . $id, $val, $val);
|
return Redis::zadd(self::CACHE_KEY . $id, $val, $val);
|
||||||
|
@ -53,6 +107,7 @@ class NotificationService {
|
||||||
|
|
||||||
public static function del($id, $val)
|
public static function del($id, $val)
|
||||||
{
|
{
|
||||||
|
Cache::forget('service:notification:' . $val);
|
||||||
return Redis::zrem(self::CACHE_KEY . $id, $val);
|
return Redis::zrem(self::CACHE_KEY . $id, $val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +128,7 @@ class NotificationService {
|
||||||
|
|
||||||
public static function getNotification($id)
|
public static function getNotification($id)
|
||||||
{
|
{
|
||||||
return Cache::remember('service:notification:'.$id, now()->addMonths(3), function() use($id) {
|
return Cache::remember('service:notification:'.$id, now()->addDays(3), function() use($id) {
|
||||||
$n = Notification::with('item')->findOrFail($id);
|
$n = Notification::with('item')->findOrFail($id);
|
||||||
$fractal = new Fractal\Manager();
|
$fractal = new Fractal\Manager();
|
||||||
$fractal->setSerializer(new ArraySerializer());
|
$fractal->setSerializer(new ArraySerializer());
|
||||||
|
@ -84,7 +139,7 @@ class NotificationService {
|
||||||
|
|
||||||
public static function setNotification(Notification $notification)
|
public static function setNotification(Notification $notification)
|
||||||
{
|
{
|
||||||
return Cache::remember('service:notification:'.$notification->id, now()->addMonths(3), function() use($notification) {
|
return Cache::remember('service:notification:'.$notification->id, now()->addDays(3), function() use($notification) {
|
||||||
$fractal = new Fractal\Manager();
|
$fractal = new Fractal\Manager();
|
||||||
$fractal->setSerializer(new ArraySerializer());
|
$fractal->setSerializer(new ArraySerializer());
|
||||||
$resource = new Fractal\Resource\Item($notification, new NotificationTransformer());
|
$resource = new Fractal\Resource\Item($notification, new NotificationTransformer());
|
||||||
|
|
|
@ -18,18 +18,41 @@ class PublicTimelineService {
|
||||||
if($stop > 100) {
|
if($stop > 100) {
|
||||||
$stop = 100;
|
$stop = 100;
|
||||||
}
|
}
|
||||||
$tl = [];
|
|
||||||
$keys = Redis::zrevrange(self::CACHE_KEY, $start, $stop);
|
return Redis::zrevrange(self::CACHE_KEY, $start, $stop);
|
||||||
foreach($keys as $key) {
|
|
||||||
array_push($tl, StatusService::get($key));
|
|
||||||
}
|
}
|
||||||
return $tl;
|
|
||||||
|
public static function getRankedMaxId($start = null, $limit = 10)
|
||||||
|
{
|
||||||
|
if(!$start) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_keys(Redis::zrevrangebyscore(self::CACHE_KEY, $start, '-inf', [
|
||||||
|
'withscores' => true,
|
||||||
|
'limit' => [1, $limit]
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getRankedMinId($end = null, $limit = 10)
|
||||||
|
{
|
||||||
|
if(!$end) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_keys(Redis::zrevrangebyscore(self::CACHE_KEY, '+inf', $end, [
|
||||||
|
'withscores' => true,
|
||||||
|
'limit' => [0, $limit]
|
||||||
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function add($val)
|
public static function add($val)
|
||||||
{
|
{
|
||||||
// return Redis::zadd(self::CACHE_KEY, $val, $val);
|
if(self::count() > 400) {
|
||||||
return;
|
Redis::zpopmin(self::CACHE_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Redis::zadd(self::CACHE_KEY, $val, $val);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function rem($val)
|
public static function rem($val)
|
||||||
|
@ -44,7 +67,7 @@ class PublicTimelineService {
|
||||||
|
|
||||||
public static function count()
|
public static function count()
|
||||||
{
|
{
|
||||||
return Redis::zcount(self::CACHE_KEY, '-inf', '+inf');
|
return Redis::zcard(self::CACHE_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function warmCache($force = false, $limit = 100)
|
public static function warmCache($force = false, $limit = 100)
|
||||||
|
@ -55,7 +78,7 @@ class PublicTimelineService {
|
||||||
->whereNull('reblog_of_id')
|
->whereNull('reblog_of_id')
|
||||||
->whereIn('type', ['photo', 'photo:album', 'video', 'video:album', 'photo:video:album'])
|
->whereIn('type', ['photo', 'photo:album', 'video', 'video:album', 'photo:video:album'])
|
||||||
->whereScope('public')
|
->whereScope('public')
|
||||||
->latest()
|
->orderByDesc('id')
|
||||||
->limit($limit)
|
->limit($limit)
|
||||||
->pluck('id');
|
->pluck('id');
|
||||||
foreach($ids as $id) {
|
foreach($ids as $id) {
|
||||||
|
|
|
@ -37,6 +37,7 @@ class StatusService {
|
||||||
|
|
||||||
public static function del($id)
|
public static function del($id)
|
||||||
{
|
{
|
||||||
|
PublicTimelineService::rem($id);
|
||||||
return Cache::forget(self::key($id));
|
return Cache::forget(self::key($id));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -85,6 +85,7 @@
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@push('scripts')
|
@push('scripts')
|
||||||
|
<script type="text/javascript" src="{{mix('js/components.js')}}"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
$('.filesize').each(function(k,v) {
|
$('.filesize').each(function(k,v) {
|
||||||
|
|
|
@ -103,6 +103,7 @@
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@push('scripts')
|
@push('scripts')
|
||||||
|
<script type="text/javascript" src="{{mix('js/components.js')}}"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
$('.filesize').each(function(k,v) {
|
$('.filesize').each(function(k,v) {
|
||||||
|
|
Loading…
Reference in a new issue