the browser-facing portion of osu!
at master 3.6 kB view raw
1<?php 2 3// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0. 4// See the LICENCE file in the repository root for full licence text. 5 6namespace App\Libraries; 7 8use App\Exceptions\API; 9use App\Exceptions\InvariantException; 10use App\Models\Chat\Channel; 11use App\Models\User; 12use LaravelRedis as Redis; 13 14class Chat 15{ 16 public static function ack(User $user) 17 { 18 $channelIds = $user->channels()->public()->pluck((new Channel())->qualifyColumn('channel_id')); 19 $userId = $user->getKey(); 20 $timestamp = time(); 21 $transaction = Redis::transaction(); 22 23 foreach ($channelIds as $channelId) { 24 Channel::ack($channelId, $userId, $timestamp, $transaction); 25 } 26 27 $transaction->exec(); 28 } 29 30 public static function createAnnouncement(User $sender, array $rawParams) 31 { 32 priv_check_user($sender, 'ChatAnnounce')->ensureCan(); 33 34 $params = get_params($rawParams, null, [ 35 'channel:array', 36 'message:string', 37 'target_ids:int[]', 38 'uuid', 39 ], ['null_missing' => true]); 40 41 if (!isset($params['target_ids'])) { 42 throw new InvariantException('missing target_ids parameter'); 43 } 44 45 if (!isset($params['channel'])) { 46 throw new InvariantException('missing channel parameter'); 47 } 48 49 $users = User::find($params['target_ids']); 50 if ($users->isEmpty()) { 51 throw new InvariantException('Nobody to broadcast to!'); 52 } 53 54 $users = $users->push($sender)->uniqueStrict('user_id'); 55 56 $channel = (new Channel())->getConnection()->transaction(function () use ($sender, $params, $users) { 57 $channel = Channel::createAnnouncement($users, $params['channel'], $params['uuid']); 58 static::sendMessage($sender, $channel, $params['message'], false); 59 60 return $channel; 61 }); 62 63 return $channel; 64 } 65 66 // Do the restricted user lookup before calling this. 67 public static function sendPrivateMessage(User $sender, User $target, ?string $message, ?bool $isAction, ?string $uuid = null) 68 { 69 if ($target->is($sender)) { 70 abort(422, "can't send message to same user"); 71 } 72 73 priv_check_user($sender, 'ChatPmStart', $target)->ensureCan(); 74 75 return (new Channel())->getConnection()->transaction(function () use ($sender, $target, $message, $isAction, $uuid) { 76 $channel = Channel::findPM($target, $sender) ?? Channel::createPM($target, $sender); 77 78 return static::sendMessage($sender, $channel, $message, $isAction, $uuid); 79 }); 80 } 81 82 public static function sendMessage(User $sender, Channel $channel, ?string $message, ?bool $isAction, ?string $uuid = null) 83 { 84 if ($channel->isPM()) { 85 // restricted users should be treated as if they do not exist 86 if (optional($channel->pmTargetFor($sender))->isRestricted()) { 87 abort(404, 'target user not found'); 88 } 89 } 90 91 priv_check_user($sender, 'ChatChannelSend', $channel)->ensureCan(); 92 93 try { 94 return $channel->receiveMessage($sender, $message, $isAction ?? false, $uuid); 95 } catch (API\ChatMessageEmptyException $e) { 96 abort(422, $e->getMessage()); 97 } catch (API\ChatMessageTooLongException $e) { 98 abort(422, $e->getMessage()); 99 } catch (API\ExcessiveChatMessagesException $e) { 100 abort(429, $e->getMessage()); 101 } 102 } 103}