Bouncer.php 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. <?php
  2. namespace App\Util\Sentiment;
  3. use App\AccountInterstitial;
  4. use App\Status;
  5. use Cache;
  6. use Illuminate\Support\Str;
  7. use App\Services\NotificationService;
  8. use App\Services\StatusService;
  9. use App\Jobs\ReportPipeline\AutospamNotifyAdminViaEmail;
  10. use App\Notification;
  11. use App\Services\AutospamService;
  12. class Bouncer {
  13. public static function get(Status $status)
  14. {
  15. if($status->uri || $status->scope != 'public') {
  16. return;
  17. }
  18. if($status->profile->user->is_admin == true) {
  19. return;
  20. }
  21. $exemptionKey = 'pf:bouncer_v0:exemption_by_pid:' . $status->profile_id;
  22. $exemptionTtl = now()->addDays(12);
  23. if( $status->in_reply_to_id != null &&
  24. $status->in_reply_to_profile_id == $status->profile_id
  25. ) {
  26. return;
  27. }
  28. $exemption = Cache::remember($exemptionKey, $exemptionTtl, function() use($status) {
  29. $uid = $status->profile->user_id;
  30. $ids = AccountInterstitial::whereUserId($uid)
  31. ->whereType('post.autospam')
  32. ->whereItemType('App\Status')
  33. ->whereNotNull('appeal_handled_at')
  34. ->latest()
  35. ->take(5)
  36. ->pluck('item_id');
  37. if($ids->count() == 0) {
  38. return false;
  39. }
  40. $count = Status::select('id', 'scope')
  41. ->whereScope('public')
  42. ->find($ids)
  43. ->count();
  44. return $count >= 1 ? true : false;
  45. });
  46. if($exemption == true) {
  47. return;
  48. }
  49. if( $status->profile->created_at->gt(now()->subMonths(6)) &&
  50. $status->profile->bio &&
  51. $status->profile->website
  52. ) {
  53. return (new self)->handle($status);
  54. }
  55. $recentKey = 'pf:bouncer_v0:recent_by_pid:' . $status->profile_id;
  56. $recentTtl = now()->addHours(28);
  57. $recent = Cache::remember($recentKey, $recentTtl, function() use($status) {
  58. return $status
  59. ->profile
  60. ->created_at
  61. ->gt(now()->subMonths(6)) ||
  62. $status
  63. ->profile
  64. ->statuses()
  65. ->whereScope('public')
  66. ->count() == 0;
  67. });
  68. if(!$recent) {
  69. return;
  70. }
  71. if($status->profile->followers()->count() > 100) {
  72. return;
  73. }
  74. if(AutospamService::active()) {
  75. if(AutospamService::check($status->caption)) {
  76. return (new self)->handle($status);
  77. }
  78. }
  79. if(!Str::contains($status->caption, [
  80. 'https://',
  81. 'http://',
  82. 'hxxps://',
  83. 'hxxp://',
  84. 'www.',
  85. '.com',
  86. '.net',
  87. '.org'
  88. ])) {
  89. return;
  90. }
  91. return (new self)->handle($status);
  92. }
  93. protected function handle($status)
  94. {
  95. $media = $status->media;
  96. $ai = new AccountInterstitial;
  97. $ai->user_id = $status->profile->user_id;
  98. $ai->type = 'post.autospam';
  99. $ai->view = 'account.moderation.post.autospam';
  100. $ai->item_type = 'App\Status';
  101. $ai->item_id = $status->id;
  102. $ai->has_media = (bool) $media->count();
  103. $ai->blurhash = $media->count() ? $media->first()->blurhash : null;
  104. $ai->meta = json_encode([
  105. 'caption' => $status->caption,
  106. 'created_at' => $status->created_at,
  107. 'type' => $status->type,
  108. 'url' => $status->url(),
  109. 'is_nsfw' => $status->is_nsfw,
  110. 'scope' => $status->scope,
  111. 'reblog' => $status->reblog_of_id,
  112. 'likes_count' => $status->likes_count,
  113. 'reblogs_count' => $status->reblogs_count,
  114. ]);
  115. $ai->save();
  116. if(config('instance.reports.email.enabled') && config('instance.reports.email.autospam')) {
  117. AutospamNotifyAdminViaEmail::dispatch($ai);
  118. }
  119. $u = $status->profile->user;
  120. $u->has_interstitial = true;
  121. $u->save();
  122. $status->scope = 'unlisted';
  123. $status->visibility = 'unlisted';
  124. // $status->is_nsfw = true;
  125. $status->save();
  126. $notification = new Notification();
  127. $notification->profile_id = $status->profile_id;
  128. $notification->actor_id = $status->profile_id;
  129. $notification->action = 'autospam.warning';
  130. $notification->item_id = $status->id;
  131. $notification->item_type = "App\Status";
  132. $notification->save();
  133. StatusService::del($status->id);
  134. Cache::forget('pf:bouncer_v0:exemption_by_pid:' . $status->profile_id);
  135. Cache::forget('pf:bouncer_v0:recent_by_pid:' . $status->profile_id);
  136. }
  137. }