Bouncer.php 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. <?php
  2. namespace App\Util\Sentiment;
  3. use App\AccountInterstitial;
  4. use App\Status;
  5. use Cache;
  6. use Illuminate\Support\Str;
  7. class Bouncer {
  8. public static function get(Status $status)
  9. {
  10. if($status->uri || $status->scope != 'public') {
  11. return;
  12. }
  13. $exemptionKey = 'pf:bouncer_v0:exemption_by_pid:' . $status->profile_id;
  14. $exemptionTtl = now()->addDays(12);
  15. $exemption = Cache::remember($exemptionKey, $exemptionTtl, function() use($status) {
  16. $uid = $status->profile->user_id;
  17. $ids = AccountInterstitial::whereUserId($uid)
  18. ->whereType('post.autospam')
  19. ->whereItemType('App\Status')
  20. ->whereNotNull('appeal_handled_at')
  21. ->latest()
  22. ->take(5)
  23. ->pluck('item_id');
  24. if($ids->count() == 0) {
  25. return false;
  26. }
  27. $count = Status::select('id', 'scope')
  28. ->whereScope('public')
  29. ->find($ids)
  30. ->count();
  31. return $count >= 1 ? true : false;
  32. });
  33. if($exemption == true) {
  34. return;
  35. }
  36. $recentKey = 'pf:bouncer_v0:recent_by_pid:' . $status->profile_id;
  37. $recentTtl = now()->addHours(28);
  38. $recent = Cache::remember($recentKey, $recentTtl, function() use($status) {
  39. return $status
  40. ->profile
  41. ->created_at
  42. ->gt(now()->subMonths(6)) ||
  43. $status
  44. ->profile
  45. ->statuses()
  46. ->whereScope('public')
  47. ->count() == 0;
  48. });
  49. if(!$recent) {
  50. return;
  51. }
  52. if($status->profile->followers()->count() > 100) {
  53. return;
  54. }
  55. if(!Str::contains($status->caption, [
  56. 'https://',
  57. 'http://',
  58. 'hxxps://',
  59. 'hxxp://',
  60. 'www.',
  61. '.com',
  62. '.net',
  63. '.org'
  64. ])) {
  65. return;
  66. }
  67. if($status->profile->user->is_admin == true) {
  68. return;
  69. }
  70. return (new self)->handle($status);
  71. }
  72. protected function handle($status)
  73. {
  74. $media = $status->media;
  75. $ai = new AccountInterstitial;
  76. $ai->user_id = $status->profile->user_id;
  77. $ai->type = 'post.autospam';
  78. $ai->view = 'account.moderation.post.autospam';
  79. $ai->item_type = 'App\Status';
  80. $ai->item_id = $status->id;
  81. $ai->has_media = (bool) $media->count();
  82. $ai->blurhash = $media->count() ? $media->first()->blurhash : null;
  83. $ai->meta = json_encode([
  84. 'caption' => $status->caption,
  85. 'created_at' => $status->created_at,
  86. 'type' => $status->type,
  87. 'url' => $status->url(),
  88. 'is_nsfw' => $status->is_nsfw,
  89. 'scope' => $status->scope,
  90. 'reblog' => $status->reblog_of_id,
  91. 'likes_count' => $status->likes_count,
  92. 'reblogs_count' => $status->reblogs_count,
  93. ]);
  94. $ai->save();
  95. $u = $status->profile->user;
  96. $u->has_interstitial = true;
  97. $u->save();
  98. $status->scope = 'unlisted';
  99. $status->visibility = 'unlisted';
  100. $status->is_nsfw = true;
  101. $status->save();
  102. Cache::forget('pf:bouncer_v0:exemption_by_pid:' . $status->profile_id);
  103. Cache::forget('pf:bouncer_v0:recent_by_pid:' . $status->profile_id);
  104. }
  105. }