setChannel($o); // Message is to a user } elseif ($o instanceof User) { $this->setUser($o); } else { throw new SlackException('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 Blocks $blocks * @return Message * @todo to test */ 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 Exception(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); return $this; } public function clearAttachments(): self { $this->attachments = ''; 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() ? FALSE : TRUE; } /** * 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 $this->_data->count() ? 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->has('ephemeral')) abort('500','Cannot post ephemeral messages.'); if ($this->_data->get('blocks') && $this->_data->get('attachments')) throw new SlackException('Message cannot have blocks and attachments.'); $api = $this->o->team->slackAPI(); $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('low')->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 * @return string * @throws SlackException */ public function respond(string $url) { $request = curl_init(); curl_setopt($request,CURLOPT_URL,$url); curl_setopt($request,CURLOPT_RETURNTRANSFER,TRUE); curl_setopt($request,CURLINFO_HEADER_OUT,TRUE); curl_setopt($request,CURLOPT_HTTPHEADER,['Content-Type: application/json; charset=utf-8']); curl_setopt($request,CURLOPT_SSL_VERIFYPEER,FALSE); curl_setopt($request,CURLOPT_POSTFIELDS,json_encode($this)); try { $result = curl_exec($request); if (! $result) throw new \Exception('CURL exec returned an empty response: '.serialize(curl_getinfo($request))); } 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 ($result !== 'ok') { switch ($result) { default: Log::critical(sprintf('%s:Generic Error',static::LOGKEY),['m'=>__METHOD__,'r'=>$result]); throw new SlackException($result,curl_getinfo($request,CURLINFO_HTTP_CODE)); } } curl_close($request); return $result; } /** * 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 * @todo - Check this is a valid option */ 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; } /** * @return Message * @todo - Check this is a valid option */ 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; } /** * Add an attachment to a message * * @param Attachment $attachments * @return Message * @deprecated use addAttachment() */ public function setAttachments(Attachment $attachments): self { $this->_data->put('attachments',[$attachments]); return $this; } /** * Add blocks to the message * * @param Blocks $blocks * @return Message * @throws \Exception * @deprecated use addBlocks() */ public function setBlocks(Blocks $blocks): self { if ($this->blocks->count()) throw new \Exception('Blocks already defined'); $this->blocks = $blocks; return $this; } /** * Message text * * @param string $string * @return Message * @deprecated use text() */ public function setText(string $string): self { $this->text = $string; return $this; } /** * Set the timestamp, used when replacing messages * * @param string $string * @return Message * @deprecated use ts() */ public function setTS(string $string): self { $this->_data->put('ts',$string); return $this; } /** * Set the thread timestamp, used when adding a threaded response * * @param string $string * @return Message * @deprecated use thead_ts() */ public function setThreadTS(string $string): self { $this->_data->put('thread_ts',$string); return $this; } }