NotificationAppGatewayService.php 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. <?php
  2. namespace App\Services;
  3. use Cache;
  4. use Exception;
  5. use Illuminate\Http\Client\RequestException;
  6. use Illuminate\Support\Facades\Http;
  7. class NotificationAppGatewayService
  8. {
  9. const GATEWAY_SUPPORT_CHECK = 'px:nags:gateway-support-check';
  10. public static function config()
  11. {
  12. return config('instance.notifications.nag');
  13. }
  14. public static function enabled()
  15. {
  16. if ((bool) config('instance.notifications.nag.enabled') === false) {
  17. return false;
  18. }
  19. $apiKey = config('instance.notifications.nag.api_key');
  20. if (! $apiKey || empty($apiKey) || strlen($apiKey) !== 45) {
  21. return false;
  22. }
  23. return Cache::remember(self::GATEWAY_SUPPORT_CHECK, 43200, function () {
  24. return self::checkServerSupport();
  25. });
  26. }
  27. public static function checkServerSupport()
  28. {
  29. $endpoint = 'https://'.config('instance.notifications.nag.endpoint').'/api/v1/instance-check?domain='.config('pixelfed.domain.app');
  30. try {
  31. $res = Http::withHeaders(['X-PIXELFED-API' => 1])
  32. ->retry(3, 500)
  33. ->throw()
  34. ->get($endpoint);
  35. $data = $res->json();
  36. } catch (RequestException $e) {
  37. return false;
  38. } catch (Exception $e) {
  39. return false;
  40. }
  41. if ($res->successful() && isset($data['active']) && $data['active'] === true) {
  42. return true;
  43. }
  44. return false;
  45. }
  46. public static function forceSupportRecheck()
  47. {
  48. Cache::forget(self::GATEWAY_SUPPORT_CHECK);
  49. return self::enabled();
  50. }
  51. public static function isValidExpoPushToken($token)
  52. {
  53. if (! $token || empty($token)) {
  54. return false;
  55. }
  56. if (str_starts_with($token, 'ExponentPushToken[') && mb_strlen($token) < 26) {
  57. return false;
  58. }
  59. if (! str_starts_with($token, 'ExponentPushToken[') && ! str_starts_with($token, 'ExpoPushToken[')) {
  60. return false;
  61. }
  62. if (! str_ends_with($token, ']')) {
  63. return false;
  64. }
  65. return true;
  66. }
  67. public static function send($userToken, $type, $actor = '')
  68. {
  69. if (! self::enabled()) {
  70. return false;
  71. }
  72. if (! $userToken || empty($userToken) || ! self::isValidExpoPushToken($userToken)) {
  73. return false;
  74. }
  75. $types = PushNotificationService::NOTIFY_TYPES;
  76. if (! $type || empty($type) || ! in_array($type, $types)) {
  77. return false;
  78. }
  79. $apiKey = config('instance.notifications.nag.api_key');
  80. if (! $apiKey || empty($apiKey)) {
  81. return false;
  82. }
  83. $url = 'https://'.config('instance.notifications.nag.endpoint').'/api/v1/relay/deliver';
  84. try {
  85. $response = Http::withToken($apiKey)
  86. ->withHeaders(['X-PIXELFED-API' => 1])
  87. ->post($url, [
  88. 'token' => $userToken,
  89. 'type' => $type,
  90. 'actor' => $actor,
  91. ]);
  92. $response->throw();
  93. } catch (RequestException $e) {
  94. return;
  95. } catch (Exception $e) {
  96. return;
  97. }
  98. }
  99. }