FollowerService.php 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. <?php
  2. namespace App\Services;
  3. use Illuminate\Support\Facades\Redis;
  4. use Cache;
  5. use DB;
  6. use App\{
  7. Follower,
  8. Profile,
  9. User
  10. };
  11. class FollowerService
  12. {
  13. const CACHE_KEY = 'pf:services:followers:';
  14. const FOLLOWING_KEY = 'pf:services:follow:following:id:';
  15. const FOLLOWERS_KEY = 'pf:services:follow:followers:id:';
  16. public static function add($actor, $target)
  17. {
  18. RelationshipService::refresh($actor, $target);
  19. Redis::zadd(self::FOLLOWING_KEY . $actor, $target, $target);
  20. Redis::zadd(self::FOLLOWERS_KEY . $target, $actor, $actor);
  21. }
  22. public static function remove($actor, $target)
  23. {
  24. RelationshipService::refresh($actor, $target);
  25. Redis::zrem(self::FOLLOWING_KEY . $actor, $target);
  26. Redis::zrem(self::FOLLOWERS_KEY . $target, $actor);
  27. Cache::forget('pf:services:follow:audience:' . $actor);
  28. Cache::forget('pf:services:follow:audience:' . $target);
  29. }
  30. public static function followers($id, $start = 0, $stop = 10)
  31. {
  32. return Redis::zrange(self::FOLLOWERS_KEY . $id, $start, $stop);
  33. }
  34. public static function following($id, $start = 0, $stop = 10)
  35. {
  36. return Redis::zrange(self::FOLLOWING_KEY . $id, $start, $stop);
  37. }
  38. public static function follows(string $actor, string $target)
  39. {
  40. return Follower::whereProfileId($actor)->whereFollowingId($target)->exists();
  41. }
  42. public static function audience($profile, $scope = null)
  43. {
  44. return (new self)->getAudienceInboxes($profile, $scope);
  45. }
  46. public static function softwareAudience($profile, $software = 'pixelfed')
  47. {
  48. return collect(self::audience($profile))
  49. ->filter(function($inbox) use($software) {
  50. $domain = parse_url($inbox, PHP_URL_HOST);
  51. if(!$domain) {
  52. return false;
  53. }
  54. return InstanceService::software($domain) === strtolower($software);
  55. })
  56. ->unique()
  57. ->values()
  58. ->toArray();
  59. }
  60. protected function getAudienceInboxes($pid, $scope = null)
  61. {
  62. $key = 'pf:services:follow:audience:' . $pid;
  63. return Cache::remember($key, 86400, function() use($pid) {
  64. $profile = Profile::find($pid);
  65. if(!$profile) {
  66. return [];
  67. }
  68. return $profile
  69. ->followers()
  70. ->whereLocalProfile(false)
  71. ->get()
  72. ->map(function($follow) {
  73. return $follow->sharedInbox ?? $follow->inbox_url;
  74. })
  75. ->unique()
  76. ->values()
  77. ->toArray();
  78. });
  79. }
  80. public static function mutualCount($pid, $mid)
  81. {
  82. return Cache::remember(self::CACHE_KEY . ':mutualcount:' . $pid . ':' . $mid, 3600, function() use($pid, $mid) {
  83. return DB::table('followers as u')
  84. ->join('followers as s', 'u.following_id', '=', 's.following_id')
  85. ->where('s.profile_id', $mid)
  86. ->where('u.profile_id', $pid)
  87. ->count();
  88. });
  89. }
  90. public static function mutualIds($pid, $mid, $limit = 3)
  91. {
  92. $key = self::CACHE_KEY . ':mutualids:' . $pid . ':' . $mid . ':limit_' . $limit;
  93. return Cache::remember($key, 3600, function() use($pid, $mid, $limit) {
  94. return DB::table('followers as u')
  95. ->join('followers as s', 'u.following_id', '=', 's.following_id')
  96. ->where('s.profile_id', $mid)
  97. ->where('u.profile_id', $pid)
  98. ->limit($limit)
  99. ->pluck('s.following_id')
  100. ->toArray();
  101. });
  102. }
  103. }