_data = collect(); if ($o) { // Message is to a channel if ($o instanceof Channel) { $this->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; } $this->blocks = new Blocks; } /** * Add a block to the message * * @param Blocks $blocks * @return Message * @todo to test */ public function addBlock(Blocks $blocks): self { $this->blocks = $blocks; return $this; } /** * Empty the message * * @return Message */ public function blank(): self { $this->_data = collect(); $this->blocks = new Blocks; return $this; } /* * @todo This doesnt appear to work public function ephemeral(): self { $this->_data->put('ephemeral',TRUE); 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() { if ($this->blocks->count()) $this->_data->put('blocks',$this->blocks); // For interactive messages that generate a dialog, we need to return NULL return $this->_data->count() ? $this->_data : NULL; } /** * Post this message to slack * * @param Carbon|null $delete * @return Generic * @throws \Exception */ public function post(Carbon $delete=NULL): Generic { if ($this->_data->has('ephemeral')) abort('500','Cannot post ephemeral messages.'); if ($this->blocks->count() && $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; } public function setReplace(bool $replace=TRUE): self { $this->_data->put('replace_original',$replace ? 'true' : 'false'); return $this; } /** * To slack from rendering URLs in the message * * @param bool $unfurl * @return $this */ public function setUnfurlLinks(bool $unfurl): self { $this->_data->put('unfurl_links',$unfurl ? 'true' : 'false'); return $this; } /** * 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; } /** * Make the message self destruct * * @param Carbon $time * @return Generic * @throws \Exception */ public function selfdestruct(Carbon $time): Generic { $this->blocks->addContextElements( collect() ->push(Blocks\Text::item(sprintf('This message will self destruct in %s...',$time->diffForHumans(Carbon::now(),['syntax' => CarbonInterface::DIFF_RELATIVE_TO_NOW]))))); return $this->post($time); } /** * Add an attachment to a message * * @param Attachment $attachments * @return Message */ public function setAttachments(Attachments $attachments): self { $this->_data->put('attachments',[$attachments]); return $this; } /** * Add blocks to the message * * @param Blocks $blocks * @return Message * @throws \Exception */ public function setBlocks(Blocks $blocks): self { if ($this->blocks->count()) throw new \Exception('Blocks already defined'); $this->blocks = $blocks; return $this; } /** * Set our channel * * @param Channel $o * @return Message */ public function setChannel(Channel $o): self { $this->_data->put('channel',$o->channel_id); $this->o = $o; return $this; } /** * Set the icon next to the message * * @param string $icon * @return Message * @deprecated */ public function setIcon(string $icon): self { $this->_data->put('icon_emoji',$icon); return $this; } /** * Option groups are used by the interactive Options controller and hold no other attributes * * @param array $array * @return void */ public function setOptionGroup(array $array): void { $this->_data = collect(); // @todo Why are clearing our data? $this->_data->put('option_groups',$array); } /** * Message text * * @param string $string * @return Message */ public function setText(string $string): self { $this->_data->put('text',$string); return $this; } /** * Set the timestamp, used when replacing messages * * @param string $string * @return Message */ 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 */ public function setThreadTS(string $string): self { $this->_data->put('thread_ts',$string); return $this; } /** * Set our channel * * @param User $o * @return Message */ public function setUser(User $o): self { $this->_data->put('channel',$o->user_id); $this->o = $o; return $this; } public function setUserName(string $user): self { $this->_data->put('username',$user); return $this; } }