├── LICENSE
├── README.md
├── composer.json
├── discovery.json
├── src
├── Extras
│ └── TypingIndicator.php
├── Laravel
│ ├── routes.php
│ └── views
│ │ └── chat.blade.php
├── Providers
│ └── WebServiceProvider.php
└── WebDriver.php
└── stubs
└── web.php
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Marcel Pociot
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # BotMan Web Driver
2 |
3 | [](https://packagist.org/packages/botman/driver-web)
4 | [](https://travis-ci.org/botman/driver-web)
5 | [](https://codecov.io/gh/botman/driver-web)
6 |
7 | BotMan driver to use [BotMan](https://github.com/botman/botman) within your website / API
8 |
9 | ## Contributing
10 |
11 | Please see [CONTRIBUTING](CONTRIBUTING.md) for details.
12 |
13 | ## Security Vulnerabilities
14 |
15 | If you discover a security vulnerability within BotMan, please send an e-mail to Marcel Pociot at m.pociot@gmail.com. All security vulnerabilities will be promptly addressed.
16 |
17 | ## License
18 |
19 | BotMan is free software distributed under the terms of the MIT license.
20 |
21 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "botman/driver-web",
3 | "license": "MIT",
4 | "description": "Web driver for BotMan",
5 | "keywords": [
6 | "Bot",
7 | "BotMan",
8 | "Web"
9 | ],
10 | "homepage": "http://github.com/botman/driver-web",
11 | "authors": [{
12 | "name": "Marcel Pociot",
13 | "email": "m.pociot@gmail.com"
14 | }],
15 | "require": {
16 | "php": ">=7.0",
17 | "botman/botman": ">=2.0"
18 | },
19 | "require-dev": {
20 | "botman/studio-addons": "~1.0",
21 | "illuminate/support": "~5.5.0",
22 | "phpunit/phpunit": "~5.0",
23 | "mockery/mockery": "^1.1",
24 | "botman/driver-facebook": "~2.0",
25 | "ext-curl": "*"
26 | },
27 | "autoload": {
28 | "psr-4": {
29 | "BotMan\\Drivers\\Web\\": "src/"
30 | }
31 | },
32 | "autoload-dev": {
33 | "psr-4": {
34 | "Tests\\": "tests/"
35 | }
36 | },
37 | "scripts": {
38 | "test": "vendor/bin/phpunit",
39 | "cs": "php-cs-fixer fix"
40 | },
41 | "extra": {
42 | "branch-alias": {
43 | "dev-master": "2.0-dev"
44 | },
45 | "laravel": {
46 | "providers": [
47 | "BotMan\\Drivers\\Web\\Providers\\WebServiceProvider"
48 | ]
49 | }
50 | },
51 | "minimum-stability": "dev",
52 | "prefer-stable": true
53 | }
--------------------------------------------------------------------------------
/discovery.json:
--------------------------------------------------------------------------------
1 | {
2 | "botman/driver-config": [
3 | "stubs/web.php"
4 | ],
5 | "botman/driver": [
6 | "BotMan\\Drivers\\Web\\WebDriver"
7 | ]
8 | }
--------------------------------------------------------------------------------
/src/Extras/TypingIndicator.php:
--------------------------------------------------------------------------------
1 | timeout = $timeout;
29 | }
30 |
31 | /**
32 | * Get the instance as a web accessible array.
33 | * This will be used within the WebDriver.
34 | *
35 | * @return array
36 | */
37 | public function toWebDriver()
38 | {
39 | return [
40 | 'type' => 'typing_indicator',
41 | 'timeout' => $this->timeout,
42 | ];
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/Laravel/routes.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | BotMan Widget
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/Providers/WebServiceProvider.php:
--------------------------------------------------------------------------------
1 | isRunningInBotManStudio()) {
20 | $this->loadDrivers();
21 |
22 | $this->publishes([
23 | __DIR__.'/../../stubs/web.php' => config_path('botman/web.php'),
24 | ]);
25 |
26 | $this->mergeConfigFrom(__DIR__.'/../../stubs/web.php', 'botman.web');
27 | }
28 |
29 | $this->loadRoutesFrom(__DIR__.'/../Laravel/routes.php');
30 | $this->loadViewsFrom(__DIR__.'/../Laravel/views', 'botman-web');
31 | $this->publishes([
32 | __DIR__.'/../Laravel/views' => resource_path('views/vendor/botman-web'),
33 | ]);
34 | }
35 |
36 | /**
37 | * Load BotMan drivers.
38 | */
39 | protected function loadDrivers()
40 | {
41 | DriverManager::loadDriver(WebDriver::class);
42 | }
43 |
44 | /**
45 | * @return bool
46 | */
47 | protected function isRunningInBotManStudio()
48 | {
49 | return class_exists(StudioServiceProvider::class);
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/WebDriver.php:
--------------------------------------------------------------------------------
1 | payload = $request->request->all();
54 | $this->event = Collection::make($this->payload);
55 | $this->files = Collection::make($request->files->all());
56 | $this->config = Collection::make($this->config->get('web', []));
57 | }
58 |
59 | /**
60 | * @param IncomingMessage $matchingMessage
61 | * @return \BotMan\BotMan\Users\User
62 | */
63 | public function getUser(IncomingMessage $matchingMessage)
64 | {
65 | return new User($matchingMessage->getSender());
66 | }
67 |
68 | /**
69 | * Determine if the request is for this driver.
70 | *
71 | * @return bool
72 | */
73 | public function matchesRequest()
74 | {
75 | return Collection::make($this->config->get('matchingData'))->diffAssoc($this->event)->isEmpty();
76 | }
77 |
78 | /**
79 | * @param IncomingMessage $matchingMessage
80 | * @return void
81 | */
82 | public function types(IncomingMessage $matchingMessage)
83 | {
84 | $this->replies[] = [
85 | 'message' => TypingIndicator::create(),
86 | 'additionalParameters' => [],
87 | ];
88 | }
89 |
90 | /**
91 | * Send a typing indicator and wait for the given amount of seconds.
92 | *
93 | * @param IncomingMessage $matchingMessage
94 | * @param float $seconds
95 | * @return mixed
96 | */
97 | public function typesAndWaits(IncomingMessage $matchingMessage, float $seconds)
98 | {
99 | $this->replies[] = [
100 | 'message' => TypingIndicator::create($seconds),
101 | 'additionalParameters' => [],
102 | ];
103 | }
104 |
105 | /**
106 | * @param IncomingMessage $message
107 | * @return \BotMan\BotMan\Messages\Incoming\Answer
108 | */
109 | public function getConversationAnswer(IncomingMessage $message)
110 | {
111 | $interactive = $this->event->get('interactive', false);
112 | if (is_string($interactive)) {
113 | $interactive = ($interactive !== 'false') && ($interactive !== '0');
114 | } else {
115 | $interactive = (bool) $interactive;
116 | }
117 |
118 | return Answer::create($message->getText())
119 | ->setValue($this->event->get('value', $message->getText()))
120 | ->setMessage($message)
121 | ->setInteractiveReply($interactive);
122 | }
123 |
124 | /**
125 | * @return bool
126 | */
127 | public function hasMatchingEvent()
128 | {
129 | $event = false;
130 |
131 | if ($this->event->has('eventData')) {
132 | $event = new GenericEvent($this->event->get('eventData'));
133 | $event->setName($this->event->get('eventName'));
134 | }
135 |
136 | return $event;
137 | }
138 |
139 | /**
140 | * Retrieve the chat message.
141 | *
142 | * @return array
143 | */
144 | public function getMessages()
145 | {
146 | if (empty($this->messages)) {
147 | $message = $this->event->get('message');
148 | $userId = $this->event->get('userId');
149 | $sender = $this->event->get('sender', $userId);
150 |
151 | $incomingMessage = new IncomingMessage($message, $sender, $userId, $this->payload);
152 |
153 | $incomingMessage = $this->addAttachments($incomingMessage);
154 |
155 | $this->messages = [$incomingMessage];
156 | }
157 |
158 | return $this->messages;
159 | }
160 |
161 | /**
162 | * @return bool
163 | */
164 | public function isBot()
165 | {
166 | return false;
167 | }
168 |
169 | /**
170 | * @param string|Question|OutgoingMessage $message
171 | * @param IncomingMessage $matchingMessage
172 | * @param array $additionalParameters
173 | * @return Response
174 | */
175 | public function buildServicePayload($message, $matchingMessage, $additionalParameters = [])
176 | {
177 | if (! $message instanceof WebAccess && ! $message instanceof OutgoingMessage) {
178 | $this->errorMessage = 'Unsupported message type.';
179 | $this->replyStatusCode = 500;
180 | }
181 |
182 | return [
183 | 'message' => $message,
184 | 'additionalParameters' => $additionalParameters,
185 | ];
186 | }
187 |
188 | /**
189 | * @param mixed $payload
190 | * @return Response
191 | */
192 | public function sendPayload($payload)
193 | {
194 | $this->replies[] = $payload;
195 | }
196 |
197 | /**
198 | * @param $messages
199 | * @return array
200 | */
201 | protected function buildReply($messages)
202 | {
203 | $replyData = Collection::make($messages)->transform(function ($replyData) {
204 | $reply = [];
205 | $message = $replyData['message'];
206 | $additionalParameters = $replyData['additionalParameters'];
207 |
208 | if ($message instanceof WebAccess) {
209 | $reply = $message->toWebDriver();
210 | } elseif ($message instanceof OutgoingMessage) {
211 | $attachmentData = (is_null($message->getAttachment())) ? null : $message->getAttachment()->toWebDriver();
212 | $reply = [
213 | 'type' => 'text',
214 | 'text' => $message->getText(),
215 | 'attachment' => $attachmentData,
216 | ];
217 | }
218 | $reply['additionalParameters'] = $additionalParameters;
219 |
220 | return $reply;
221 | })->toArray();
222 |
223 | return $replyData;
224 | }
225 |
226 | /**
227 | * Send out message response.
228 | */
229 | public function messagesHandled()
230 | {
231 | $messages = $this->buildReply($this->replies);
232 |
233 | // Reset replies
234 | $this->replies = [];
235 |
236 | (new Response(json_encode([
237 | 'status' => $this->replyStatusCode,
238 | 'messages' => $messages,
239 | ]), $this->replyStatusCode, [
240 | 'Content-Type' => 'application/json',
241 | 'Access-Control-Allow-Credentials' => true,
242 | 'Access-Control-Allow-Origin' => '*',
243 | ]))->send();
244 | }
245 |
246 | /**
247 | * @return bool
248 | */
249 | public function isConfigured()
250 | {
251 | return false;
252 | }
253 |
254 | /**
255 | * Low-level method to perform driver specific API requests.
256 | *
257 | * @param string $endpoint
258 | * @param array $parameters
259 | * @param \BotMan\BotMan\Messages\Incoming\IncomingMessage $matchingMessage
260 | * @return void
261 | */
262 | public function sendRequest($endpoint, array $parameters, IncomingMessage $matchingMessage)
263 | {
264 | // Not available with the web driver.
265 | }
266 |
267 | /**
268 | * Add potential attachments to the message object.
269 | *
270 | * @param IncomingMessage $incomingMessage
271 | * @return IncomingMessage
272 | */
273 | protected function addAttachments($incomingMessage)
274 | {
275 | $attachment = $this->event->get('attachment');
276 |
277 | if ($attachment === self::ATTACHMENT_IMAGE) {
278 | $images = $this->files->map(function ($file) {
279 | if ($file instanceof UploadedFile) {
280 | $path = $file->getRealPath();
281 | } else {
282 | $path = $file['tmp_name'];
283 | }
284 |
285 | return new Image($this->getDataURI($path));
286 | })->values()->toArray();
287 | $incomingMessage->setText(Image::PATTERN);
288 | $incomingMessage->setImages($images);
289 | } elseif ($attachment === self::ATTACHMENT_AUDIO) {
290 | $audio = $this->files->map(function ($file) {
291 | if ($file instanceof UploadedFile) {
292 | $path = $file->getRealPath();
293 | } else {
294 | $path = $file['tmp_name'];
295 | }
296 |
297 | return new Audio($this->getDataURI($path));
298 | })->values()->toArray();
299 | $incomingMessage->setText(Audio::PATTERN);
300 | $incomingMessage->setAudio($audio);
301 | } elseif ($attachment === self::ATTACHMENT_VIDEO) {
302 | $videos = $this->files->map(function ($file) {
303 | if ($file instanceof UploadedFile) {
304 | $path = $file->getRealPath();
305 | } else {
306 | $path = $file['tmp_name'];
307 | }
308 |
309 | return new Video($this->getDataURI($path));
310 | })->values()->toArray();
311 | $incomingMessage->setText(Video::PATTERN);
312 | $incomingMessage->setVideos($videos);
313 | } elseif ($attachment === self::ATTACHMENT_FILE) {
314 | $files = $this->files->map(function ($file) {
315 | if ($file instanceof UploadedFile) {
316 | $path = $file->getRealPath();
317 | } else {
318 | $path = $file['tmp_name'];
319 | }
320 |
321 | return new File($this->getDataURI($path));
322 | })->values()->toArray();
323 | $incomingMessage->setText(File::PATTERN);
324 | $incomingMessage->setFiles($files);
325 | }
326 |
327 | return $incomingMessage;
328 | }
329 |
330 | /**
331 | * @param $file
332 | * @param string $mime
333 | * @return string
334 | */
335 | protected function getDataURI($file, $mime = '')
336 | {
337 | return 'data: '.(function_exists('mime_content_type') ? mime_content_type($file) : $mime).';base64,'.base64_encode(file_get_contents($file));
338 | }
339 | }
340 |
--------------------------------------------------------------------------------
/stubs/web.php:
--------------------------------------------------------------------------------
1 | [
15 | 'driver' => 'web',
16 | ],
17 | ];
18 |
--------------------------------------------------------------------------------