StoryService.php 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. <?php
  2. namespace App\Services;
  3. use Illuminate\Support\Facades\Cache;
  4. use Illuminate\Support\Facades\Redis;
  5. use Illuminate\Support\Facades\Storage;
  6. use App\Story;
  7. use App\StoryView;
  8. class StoryService
  9. {
  10. const STORY_KEY = 'pf:services:stories:v1:';
  11. public static function get($id)
  12. {
  13. $account = AccountService::get($id);
  14. if(!$account) {
  15. return false;
  16. }
  17. $res = [
  18. 'profile' => [
  19. 'id' => (string) $account['id'],
  20. 'avatar' => $account['avatar'],
  21. 'username' => $account['username'],
  22. 'url' => $account['url']
  23. ]
  24. ];
  25. $res['stories'] = self::getStories($id);
  26. return $res;
  27. }
  28. public static function getById($id)
  29. {
  30. return Cache::remember(self::STORY_KEY . 'by-id:id-' . $id, 3600, function() use ($id) {
  31. return Story::find($id);
  32. });
  33. }
  34. public static function delById($id)
  35. {
  36. return Cache::forget(self::STORY_KEY . 'by-id:id-' . $id);
  37. }
  38. public static function getStories($id, $pid)
  39. {
  40. return Story::whereProfileId($id)
  41. ->latest()
  42. ->get()
  43. ->map(function($s) use($pid) {
  44. return [
  45. 'id' => (string) $s->id,
  46. 'type' => $s->type,
  47. 'duration' => 10,
  48. 'seen' => in_array($pid, self::views($s->id)),
  49. 'created_at' => $s->created_at->toAtomString(),
  50. 'expires_at' => $s->expires_at->toAtomString(),
  51. 'media' => url(Storage::url($s->path)),
  52. 'can_reply' => (bool) $s->can_reply,
  53. 'can_react' => (bool) $s->can_react,
  54. 'poll' => $s->type == 'poll' ? PollService::storyPoll($s->id) : null
  55. ];
  56. })
  57. ->toArray();
  58. }
  59. public static function views($id)
  60. {
  61. return StoryView::whereStoryId($id)
  62. ->pluck('profile_id')
  63. ->toArray();
  64. }
  65. public static function hasSeen($pid, $sid)
  66. {
  67. $key = self::STORY_KEY . 'seen:' . $pid . ':' . $sid;
  68. return Cache::remember($key, 3600, function() use($pid, $sid) {
  69. return StoryView::whereStoryId($sid)
  70. ->whereProfileId($pid)
  71. ->exists();
  72. });
  73. }
  74. public static function latest($pid)
  75. {
  76. return Cache::remember(self::STORY_KEY . 'latest:pid-' . $pid, 3600, function() use ($pid) {
  77. return Story::whereProfileId($pid)
  78. ->latest()
  79. ->first()
  80. ->id;
  81. });
  82. }
  83. public static function delLatest($pid)
  84. {
  85. return Cache::forget(self::STORY_KEY . 'latest:pid-' . $pid);
  86. }
  87. public static function addSeen($pid, $sid)
  88. {
  89. return Cache::put(self::STORY_KEY . 'seen:' . $pid . ':' . $sid, true, 86400);
  90. }
  91. public static function adminStats()
  92. {
  93. return Cache::remember('pf:admin:stories:stats', 300, function() {
  94. $total = Story::count();
  95. return [
  96. 'active' => [
  97. 'today' => Story::whereDate('created_at', now()->today())->count(),
  98. 'month' => Story::whereMonth('created_at', now()->month)->whereYear('created_at', now()->year)->count()
  99. ],
  100. 'total' => $total,
  101. 'remote' => [
  102. 'today' => Story::whereLocal(false)->whereDate('created_at', now()->today())->count(),
  103. 'month' => Story::whereLocal(false)->whereMonth('created_at', now()->month)->whereYear('created_at', now()->year)->count()
  104. ],
  105. 'storage' => [
  106. 'sum' => (int) Story::sum('size'),
  107. 'average' => (int) Story::avg('size')
  108. ],
  109. 'avg_spu' => $total ? (int) ($total / Story::groupBy('profile_id')->pluck('profile_id')->count()) : 'N/A',
  110. 'avg_duration' => (int) floor(Story::avg('duration')),
  111. 'avg_type' => $total ? Story::selectRaw('type, count(id) as count')->groupBy('type')->orderByDesc('count')->first()->type : 'N/A'
  112. ];
  113. });
  114. }
  115. public static function rotateQueue()
  116. {
  117. return Redis::smembers('pf:stories:rotate-queue');
  118. }
  119. public static function addRotateQueue($id)
  120. {
  121. return Redis::sadd('pf:stories:rotate-queue', $id);
  122. }
  123. public static function removeRotateQueue($id)
  124. {
  125. self::delById($id);
  126. return Redis::srem('pf:stories:rotate-queue', $id);
  127. }
  128. public static function reactIncrement($storyId, $profileId)
  129. {
  130. $key = 'pf:stories:react-counter:storyid-' . $storyId . ':profileid-' . $profileId;
  131. if(Redis::get($key) == null) {
  132. Redis::setex($key, 86400, 1);
  133. } else {
  134. return Redis::incr($key);
  135. }
  136. }
  137. public static function reactCounter($storyId, $profileId)
  138. {
  139. $key = 'pf:stories:react-counter:storyid-' . $storyId . ':profileid-' . $profileId;
  140. return (int) Redis::get($key) ?? 0;
  141. }
  142. }