setChannel($o); // Message is to a user } elseif ($o instanceof User) { $this->setUser($o); } else { throw new \Exception('Model not handled: '.get_class($o)); } $this->o = $o; } } /** * Empty the message * * @return Message */ public static function blank(): self { return new self; } /* HELPER METHODS */ /** * Add a block to the message * * @param Attachment $attachment * @return Message * @throws SlackSyntaxException */ public function addAttachment(Attachment $attachment): self { if (! Arr::get($this->_data,'attachments')) $this->attachments = collect(); $this->attachments->push($attachment); if (count($this->attachments) > self::MAX_ATTACHMENTS) throw new SlackSyntaxException(sprintf('Messages should not have more than %d attachments',self::MAX_ATTACHMENTS)); return $this; } public function addBlock(Blocks $block): self { if (! Arr::get($this->_data,'blocks')) $this->blocks = collect(); $this->blocks->push($block); if (count($this->blocks) > self::MAX_BLOCKS) throw new SlackSyntaxException(sprintf('Messages should not have more than %d blocks',self::MAX_BLOCKS)); return $this; } public function clearAttachments(): self { $this->attachments = ''; return $this; } /** * For messages that we interact with via a response_url * * @param bool $bool * @return Message */ public function delete_original(bool $bool=TRUE): self { $this->delete_original = $bool; return $this; } public function forgetTS(): self { $this->_data->forget('ts'); return $this; } /** * Return if this is an empty message * * @return bool */ public function isEmpty(): bool { return ! $this->jsonSerialize(); } /** * When we json_encode this object, this is the data that will be returned */ public function jsonSerialize() { // For interactive messages that generate a dialog, we need to return NULL return count($this) ? parent::jsonSerialize() : NULL; } /** * Post this message to slack * * @param Carbon|null $delete * @return Generic * @throws \Exception */ public function post(Carbon $delete=NULL): Generic { if (! $delete && $this->selfdestruct) $delete = $this->selfdestruct; if ($this->_data->get('blocks') && $this->_data->get('attachments')) throw new SlackSyntaxException('Message cannot have blocks and attachments.'); if ((! isset($this->o)) || ((! $this->o->team) && (! $this->o->user_team))) throw new SlackSyntaxException('Message needs to have a user or a channel to work out the team.'); $api = $this->o->team ? $this->o->team->slackAPI() : $this->o->user_team->slackAPI(); if ($this->ephemeral) { $response = $api->postEphemeral($this); } else { $response = $this->_data->has('ts') ? $api->updateMessage($this) : $api->postMessage($this); } if ($delete) { Log::debug(sprintf('%s:Scheduling Delete of [%s:%s] on [%s]',static::LOGKEY,object_get($this->o,'channel_id',$this->o->id),$response->ts,$delete->format('Y-m-d')),['m'=>__METHOD__]); // Queue the delete of the message if requested dispatch((new DeleteChat($this->o,$response->ts))->onQueue('slack')->delay($delete)); } return $response; } /** * Post a message to slack using the respond_url * * @note This URL can only be used 5 times in 30 minutes * @param string $url * @param Carbon|null $delete * @return object * @throws SlackException */ public function respond(string $url,Carbon $delete=NULL): object { if (! $delete && $this->selfdestruct) $delete = $this->selfdestruct; $http = Http::acceptJson(); $http->withBody(json_encode($this),'application/json'); try { $request = $http->post($url)->throw(); $response = $request->object(); } catch (\Exception $e) { Log::error(sprintf('%s:Got an error while posting to [%s] (%s)',static::LOGKEY,$url,$e->getMessage()),['m'=>__METHOD__]); throw new \Exception($e->getMessage()); } if (! $response->ok) { Log::critical(sprintf('%s:Generic Error',static::LOGKEY),['m'=>__METHOD__,'r'=>$response]); throw new SlackException(serialize($response),$request->status()); } if ($delete) { Log::debug(sprintf('%s:Scheduling Delete of [%s:%s] on [%s]',static::LOGKEY,object_get($this->o,'channel_id',$this->o->id),$url,$delete->format('Y-m-d')),['m'=>__METHOD__]); // Queue the delete of the response if requested dispatch((new DeleteResponse($url))->onQueue('slack')->delay($delete)); } return $response; } /** * Schedule a message * * @param Carbon $time * @return Generic */ public function schedule(Carbon $time): Generic { $this->_data->put('post_at',$time->timestamp); $api = $this->o->team->slackAPI(); $response = $this->_data->has('ts') ? $api->updateMessage($this) : $api->scheduleMessage($this); return $response; } /** * Make the message self destruct * * @param Carbon $time * @return Message */ public function selfdestruct(Carbon $time): self { $this->addBlock( Context::item(collect([ Text::item(sprintf('This message will self destruct in %s...',$time->diffForHumans(Carbon::now(),['syntax' => CarbonInterface::DIFF_RELATIVE_TO_NOW]))) ])) ); $this->selfdestruct = $time; return $this; } /** * Set our channel * * @param Channel $o * @return Message */ public function setChannel(Channel $o): self { $this->channel = $o->channel_id; $this->o = $o; return $this; } /** * Set our channel * * @param User $o * @return Message */ public function setUser(User $o): self { $this->channel = $o->user_id; $this->o = $o; return $this; } /* CONFIGURATION METHODS */ /** * @return Message */ public function ephemeral(): self { $this->ephemeral = TRUE; return $this; } /** * Set the icon next to the message * * @param string $icon * @return Message * @deprecated */ public function icon_emoji(string $icon): self { $this->icon_emoji = $icon; return $this; } /** * Option groups are used by the interactive Options controller and hold no other attributes * * @param Collection $collection * @return Message */ public function option_groups(Collection $collection): self { $this->option_groups = $collection; return $this; } /** * Replace the original message * * @param bool $bool * @return Message */ public function replace_original(bool $bool=TRUE): self { $this->replace_original = $bool; return $this; } /** * Message text * * @param string $string * @return Message */ public function text(string $string): self { $this->text = $string; return $this; } /** * Set the thread timestamp, used when adding a threaded response * * @param string $string * @return Message */ public function thread_ts(string $string): self { $this->thread_ts = $string; return $this; } /** * Set the timestamp, used when replacing messages * * @param string $string * @return Message */ public function ts(string $string): self { $this->ts = $string; return $this; } /** * To slack from rendering URLs in the message * * @param bool $bool * @return $this */ public function unfurl_links(bool $bool): self { $this->unfurl_links = $bool; return $this; } public function username(string $user): self { $this->username = $user; return $this; } }