├── .gitignore
├── examples
├── endpoint.php
├── index.php
├── MyBotServer.php
└── MyBotClient.php
├── src
├── Libs
│ ├── Helpers.php
│ ├── Options.php
│ └── CommonExceptionHandler.php
├── Bot
│ ├── TestBot.php
│ ├── BotException.php
│ ├── SkypeBot.php
│ ├── EmailBot.php
│ ├── SlackBot.php
│ ├── TelegramBot.php
│ ├── FacebookBot.php
│ └── WebchatBot.php
├── Auth
│ ├── AuthException.php
│ └── Auth.php
├── Http
│ ├── HttpException.php
│ └── Http.php
└── Bot.php
├── phpunit.php
├── readme.md
├── LICENSE
└── composer.json
/.gitignore:
--------------------------------------------------------------------------------
1 | /vendor
2 | composer.phar
3 | composer.lock
4 | .DS_Store
5 | Thumbs.db
6 |
--------------------------------------------------------------------------------
/examples/endpoint.php:
--------------------------------------------------------------------------------
1 | init();
--------------------------------------------------------------------------------
/examples/index.php:
--------------------------------------------------------------------------------
1 | sendMessage( $to, "Hey! What's up! Here goes a duck picture!" );
10 |
11 | $server->sendImage( $to, 'http://www.publicdomainpictures.net/pictures/30000/t2/duck-on-a-rock.jpg' );
--------------------------------------------------------------------------------
/src/Libs/Helpers.php:
--------------------------------------------------------------------------------
1 | code}]: {$this->message}\n";
30 | }
31 |
32 | }
--------------------------------------------------------------------------------
/src/Auth/AuthException.php:
--------------------------------------------------------------------------------
1 | code}]: {$this->message}\n";
30 | }
31 |
32 | }
--------------------------------------------------------------------------------
/phpunit.php:
--------------------------------------------------------------------------------
1 | **Note:** This repository contains the php library for the Bot framework. If you want to build a bot in another language, visit the oficial web [Bot Framework](https://dev.botframework.com/).
4 |
5 | ## Bot Framework
6 |
7 | Bot Framework allow you build and connect intelligent bots to interact with your users naturally wherever they are — from your website or app to text/SMS, Skype, Slack, Facebook Messenger, Office 365 mail, Teams and other popular services.
8 |
9 | This is the implementation non-oficial of the Bot Framework api in php.
10 |
11 | ## Official Documentation
12 |
13 | Documentation for the bot framework can be found on the [Bot framework](https://docs.botframework.com/).
14 |
15 | ## Security Vulnerabilities
16 |
17 | If you discover a security vulnerability within Bot, please send an e-mail to Andrés Téllez at a.tellez@neversyn.com. All security vulnerabilities will be promptly addressed.
18 |
19 | ### License
20 |
21 | The Bot framework is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT)
22 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Andrés Téllez
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 |
--------------------------------------------------------------------------------
/src/Libs/CommonExceptionHandler.php:
--------------------------------------------------------------------------------
1 | code}]: {$this->message}\n";
29 | }
30 |
31 | /**
32 | * [funciónPersonalizada description]
33 | * @return [type] [description]
34 | */
35 | public function funciónPersonalizada() {
36 | echo "Una función personalizada para este tipo de excepción\n";
37 | }
38 |
39 | }
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hatxor/bot-framework-php",
3 | "description": "A complete bot framework library write in php, plug and play!",
4 | "homepage": "https://github.com/hatxor/bot-framework-php",
5 | "license": "MIT",
6 | "type": "library",
7 | "keywords": [
8 | "Microsoft",
9 | "Bot",
10 | "Microsoft Bot",
11 | "Skype",
12 | "Skype Bot",
13 | "Facebook",
14 | "Facebook Bot",
15 | "Telegram",
16 | "Telegram Bot",
17 | "Slack",
18 | "Slack Bot",
19 | "Email",
20 | "Email Bot",
21 | "Webchat",
22 | "Webchat Bot"
23 | ],
24 | "authors": [
25 | {
26 | "name": "Andrés Téllez",
27 | "email": "a.tellez@neversyn.com",
28 | "homepage": "https://github.com/hatxor"
29 | }
30 | ],
31 | "require": {
32 | "php": ">=5.5.0"
33 | },
34 | "require-dev": {
35 | "monolog/monolog": "~1.17",
36 | "squizlabs/php_codesniffer": "~2.3",
37 | "phpunit/phpunit": ">=5.2",
38 | "phpunit/php-code-coverage": "~3.3"
39 | },
40 | "autoload": {
41 | "psr-4": {
42 | "hatxor\\BotFramework\\": "src"
43 | }
44 | },
45 | "autoload-dev": {
46 | "psr-4": {
47 | "hatxor\\BotFramework\\tests\\": "tests"
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/examples/MyBotServer.php:
--------------------------------------------------------------------------------
1 | loadConfig( $config );
35 |
36 | // 2. Init our bot depending of the channel
37 | $this->bot = Bot::getBotByChannel( $channelID, $this->client, $this->secret, $config, $config ); // TODO Try / catch para controlar los errores de que no encuentre la clase
38 |
39 | // 3. Do the auth
40 | $this->bot->authenticate();
41 |
42 | }
43 |
44 |
45 | /**
46 | * Load the configuration from the config.php file
47 | */
48 | private function loadConfig( $config = [] ) {
49 |
50 | $this->hash = ( isset( $config['hash'] ) ) ? $config['hash'] : null;
51 |
52 | $this->client = ( isset( $config['app_client_id'] ) ) ? $config['app_client_id'] : null;
53 |
54 | $this->secret = ( isset( $config['app_secret_id'] ) ) ? $config['app_secret_id'] : null;
55 |
56 | }
57 |
58 | /**
59 | * ######################################
60 | * YOU CAN CREATE FROM HERE
61 | * ######################################
62 | */
63 |
64 |
65 | /**
66 | * Send a normal message with text to the given user
67 | * @param string $to Recipient ID
68 | * @param string $message The message to send
69 | * @return array HTTP response
70 | */
71 | public function sendMessage( $to, $message ) {
72 |
73 | return $this->bot->addMessage( $to, $message );
74 |
75 | }
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/src/Bot/EmailBot.php:
--------------------------------------------------------------------------------
1 | serviceUrl . '/' . $this->serviceVersion . '/conversations/' . $to . '/activities';
36 |
37 | $params = array(
38 |
39 | 'type' => $this->type_text_message,
40 | "text" => $message,
41 |
42 | );
43 |
44 | $httpResponse = $this->do_request( $url, 'POST_RAW', $params, array( 'Content-Type: application/json' ) );
45 |
46 | return $httpResponse;
47 |
48 | }
49 |
50 |
51 | /**
52 | * [addAttachment description]
53 | * @param string $to [description]
54 | * @param string $message [description]
55 | * @return array [description]
56 | */
57 | public function addAttachment( $to, $type, $content, $extra = array(), $options = array() ) {
58 |
59 | if( !isset( $this->type_attachment[ $type ] ) )
60 |
61 | throw new BotException( "Wuops! The media type doesn't exist.", 1 );
62 |
63 | // Execute
64 | $url = $this->serviceUrl . '/' . $this->serviceVersion . '/conversations/' . $to . '/activities';
65 |
66 | $methodName = "_create" . $type;
67 |
68 | $params = array(
69 |
70 | 'type' => $this->type_attachment[ $type ],
71 | "attachments" => $this->$methodName( $content, $extra, $options ),
72 |
73 | );
74 |
75 | if( isset( $options['summary'] ) )
76 |
77 | $params['summary'] = $options['summary'];
78 |
79 | $httpResponse = $this->do_request( $url, 'POST_RAW', $params, array( 'Content-Type: application/json' ) );
80 |
81 | return $httpResponse;
82 |
83 | }
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/src/Bot/SlackBot.php:
--------------------------------------------------------------------------------
1 | serviceUrl . '/' . $this->serviceVersion . '/conversations/' . $to . '/activities';
36 |
37 | $params = array(
38 |
39 | 'type' => $this->type_text_message,
40 | "text" => $message,
41 |
42 | );
43 |
44 | $httpResponse = $this->do_request( $url, 'POST_RAW', $params, array( 'Content-Type: application/json' ) );
45 |
46 | return $httpResponse;
47 |
48 | }
49 |
50 |
51 | /**
52 | * [addAttachment description]
53 | * @param string $to [description]
54 | * @param string $message [description]
55 | * @return array [description]
56 | */
57 | public function addAttachment( $to, $type, $content, $extra = array(), $options = array() ) {
58 |
59 | if( !isset( $this->type_attachment[ $type ] ) )
60 |
61 | throw new BotException( "Wuops! The media type doesn't exist.", 1 );
62 |
63 | // Execute
64 | $url = $this->serviceUrl . '/' . $this->serviceVersion . '/conversations/' . $to . '/activities';
65 |
66 | $methodName = "_create" . $type;
67 |
68 | $params = array(
69 |
70 | 'type' => $this->type_attachment[ $type ],
71 | "attachments" => $this->$methodName( $content, $extra, $options ),
72 |
73 | );
74 |
75 | if( isset( $options['summary'] ) )
76 |
77 | $params['summary'] = $options['summary'];
78 |
79 | $httpResponse = $this->do_request( $url, 'POST_RAW', $params, array( 'Content-Type: application/json' ) );
80 |
81 | return $httpResponse;
82 |
83 | }
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/src/Bot/TelegramBot.php:
--------------------------------------------------------------------------------
1 | serviceUrl . '/' . $this->serviceVersion . '/conversations/' . $to . '/activities';
36 |
37 | $params = array(
38 |
39 | 'type' => $this->type_text_message,
40 | "text" => $message,
41 |
42 | );
43 |
44 | $httpResponse = $this->do_request( $url, 'POST_RAW', $params, array( 'Content-Type: application/json' ) );
45 |
46 | return $httpResponse;
47 |
48 | }
49 |
50 |
51 | /**
52 | * [addAttachment description]
53 | * @param string $to [description]
54 | * @param string $message [description]
55 | * @return array [description]
56 | */
57 | public function addAttachment( $to, $type, $content, $extra = array(), $options = array() ) {
58 |
59 | if( !isset( $this->type_attachment[ $type ] ) )
60 |
61 | throw new BotException( "Wuops! The media type doesn't exist.", 1 );
62 |
63 | // Execute
64 | $url = $this->serviceUrl . '/' . $this->serviceVersion . '/conversations/' . $to . '/activities';
65 |
66 | $methodName = "_create" . $type;
67 |
68 | $params = array(
69 |
70 | 'type' => $this->type_attachment[ $type ],
71 | "attachments" => $this->$methodName( $content, $extra, $options ),
72 |
73 | );
74 |
75 | if( isset( $options['summary'] ) )
76 |
77 | $params['summary'] = $options['summary'];
78 |
79 | $httpResponse = $this->do_request( $url, 'POST_RAW', $params, array( 'Content-Type: application/json' ) );
80 |
81 | return $httpResponse;
82 |
83 | }
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/src/Auth/Auth.php:
--------------------------------------------------------------------------------
1 | http = new Http;
22 |
23 | try {
24 | $this->getToken( $client, $secret );
25 | }
26 |
27 | catch (AuthException $e) {
28 |
29 | die( __CLASS__ . ' Wuops! ' . $e->getMessage() );
30 |
31 | }
32 |
33 | }
34 |
35 | /**
36 | * [auth description]
37 | * @param [type] $client [description]
38 | * @param [type] $secret [description]
39 | * @return [type] [description]
40 | */
41 | public function getToken( $client, $secret ) {
42 |
43 | $params = array(
44 | 'grant_type' => 'client_credentials',
45 | 'client_id' => $client,
46 | 'client_secret' => $secret,
47 | 'scope' => 'https://graph.microsoft.com/.default',
48 | );
49 |
50 | try {
51 |
52 | $httpResponse = $this->http->request( $this->authURL, 'POST', $params );
53 |
54 | if( $httpResponse['status'] == 200 ) {
55 |
56 | $httpResponseObj = json_decode( $httpResponse['result'] );
57 |
58 | if( isset( $httpResponseObj->access_token ) && $httpResponseObj->access_token != '' ) {
59 |
60 | $this->token = $httpResponseObj->access_token;
61 |
62 | return $this->token;
63 |
64 | }
65 |
66 | else
67 |
68 | throw new AuthException( 'Error getting the access token!' );
69 |
70 | }
71 |
72 | throw new AuthException( 'Error getting the access token!' );
73 |
74 | } catch (HttpException $e) {
75 |
76 | if( $e->getCode() == 401 )
77 |
78 | throw new AuthException( 'Unauthorized - The authentication information is not provided or is invalid.' );
79 |
80 | else if( $e->getCode() == 403 )
81 |
82 | throw new AuthException( 'Forbidden - The provided credentials do not grant the client permission to access the resource. For example: a recognized user attempted to access restricted content..' );
83 |
84 | else
85 |
86 | die( $e->manageError() );
87 |
88 | }
89 |
90 | }
91 |
92 | }
--------------------------------------------------------------------------------
/src/Bot/FacebookBot.php:
--------------------------------------------------------------------------------
1 | serviceUrl . '/' . $this->serviceVersion . '/conversations/' . $to . '/activities';
36 |
37 | $params = array(
38 |
39 | 'type' => $this->type_text_message,
40 | "text" => $message,
41 | "from" => array( "id" => $this->config['fb_bot_id'], "name" => $this->config['fb_bot_name'] ),
42 |
43 | );
44 |
45 | $httpResponse = $this->do_request( $url, 'POST_RAW', $params, array( 'Content-Type: application/json' ) );
46 |
47 | return $httpResponse;
48 |
49 | }
50 |
51 |
52 | /**
53 | * [addAttachment description]
54 | * @param string $to [description]
55 | * @param string $message [description]
56 | * @return array [description]
57 | */
58 | public function addAttachment( $to, $type, $content, $extra = array(), $options = array() ) {
59 |
60 | if( !isset( $this->type_attachment[ $type ] ) )
61 |
62 | throw new BotException( "Wuops! The media type doesn't exist.", 1 );
63 |
64 | // Execute
65 | $url = $this->serviceUrl . '/' . $this->serviceVersion . '/conversations/' . $to . '/activities';
66 |
67 | $methodName = "_create" . $type;
68 |
69 | $params = array(
70 |
71 | 'type' => $this->type_attachment[ $type ],
72 | "attachments" => $this->$methodName( $content, $extra, $options ),
73 | "from" => array( "id" => $this->config['fb_bot_id'], "name" => $this->config['fb_bot_name'] ),
74 |
75 | );
76 |
77 | if( isset( $options['summary'] ) )
78 |
79 | $params['summary'] = $options['summary'];
80 |
81 | $httpResponse = $this->do_request( $url, 'POST_RAW', $params, array( 'Content-Type: application/json' ) );
82 |
83 | return $httpResponse;
84 |
85 | }
86 |
87 | }
88 |
--------------------------------------------------------------------------------
/src/Http/HttpException.php:
--------------------------------------------------------------------------------
1 | alt_message = $message;
19 |
20 | parent::__construct( "Wuops! Error in curl call!", $code, $previous);
21 |
22 | }
23 |
24 |
25 | /**
26 | * [__toString description]
27 | * @return string [description]
28 | */
29 | public function __toString() {
30 | return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
31 | }
32 |
33 | /**
34 | * [funciónPersonalizada description]
35 | * @return [type] [description]
36 | */
37 | public function manageError() {
38 |
39 | if( $this->getCode() == 400 )
40 |
41 | $this->alt_message['known_error'] = 'Bad Request - The request can’t be fulfilled because of bad syntax.';
42 |
43 | else if( $this->getCode() == 401 )
44 |
45 | $this->alt_message['known_error'] = 'Unauthorized - The authentication information is not provided or is invalid.';
46 |
47 | else if( $this->getCode() == 403 )
48 |
49 | $this->alt_message['known_error'] = 'Forbidden - The provided credentials do not grant the client permission to access the resource. For example: a recognized user attempted to access restricted content..';
50 |
51 | // Make the http error message
52 | $html = "
".__CLASS__ ." Wuops! Curl error: ".$this->alt_message['curl_string_error']." [".$this->alt_message['http_code']."]
";
53 |
54 | $html .= "";
55 |
56 | foreach ($this->alt_message as $field => $value) {
57 |
58 | if( is_numeric( $value ) || is_string( $value ) )
59 |
60 | $html .= "- ".$field.": ".$value."
";
61 |
62 | else if ( is_bool( $value ) ) {
63 |
64 | if( $value == true )
65 |
66 | $html .= "- ".$field.": true
";
67 |
68 | else
69 |
70 | $html .= "- ".$field.": false
";
71 |
72 | }
73 |
74 | else if ( is_object( $value ) || is_array( $value ) )
75 |
76 | $html .= "- ".$field.": ".json_encode($value)."
";
77 |
78 | }
79 |
80 | $html .= "
";
81 |
82 | return $html;
83 |
84 | }
85 |
86 | }
--------------------------------------------------------------------------------
/src/Bot/WebchatBot.php:
--------------------------------------------------------------------------------
1 | serviceUrl . '/' . $this->serviceVersion . '/conversations/' . $to . '/activities';
36 |
37 | $params = array(
38 |
39 | 'type' => $this->type_text_message,
40 | "text" => $message,
41 | "conversation" => array( "id" => $to),
42 | "from" => array( "id" => ( isset( $extra['from'] ) ) ? $extra['from'] : $this->config['webchat_name'] ),
43 |
44 | );
45 |
46 | $httpResponse = $this->do_request( $url, 'POST_RAW', $params, array( 'Content-Type: application/json' ) );
47 |
48 | return $httpResponse;
49 |
50 | }
51 |
52 |
53 | /**
54 | * [addAttachment description]
55 | * @param string $to [description]
56 | * @param string $message [description]
57 | * @return array [description]
58 | */
59 | public function addAttachment( $to, $type, $content, $extra = array(), $options = array() ) {
60 |
61 | if( !isset( $this->type_attachment[ $type ] ) )
62 |
63 | throw new BotException( "Wuops! The media type doesn't exist.", 1 );
64 |
65 | // Execute
66 | $url = $this->serviceUrl . '/' . $this->serviceVersion . '/conversations/' . $to . '/activities';
67 |
68 | $methodName = "_create" . $type;
69 |
70 | $params = array(
71 |
72 | 'type' => $this->type_attachment[ $type ],
73 | "attachments" => $this->$methodName( $content, $extra, $options ),
74 | "conversation" => array( "id" => $to),
75 | "from" => array( "id" => ( isset( $extra['from'] ) ) ? $extra['from'] : $this->config['webchat_name'] ),
76 |
77 | );
78 |
79 | if( isset( $options['summary'] ) )
80 |
81 | $params['summary'] = $options['summary'];
82 |
83 | $httpResponse = $this->do_request( $url, 'POST_RAW', $params, array( 'Content-Type: application/json' ) );
84 |
85 | return $httpResponse;
86 |
87 | }
88 |
89 | }
90 |
--------------------------------------------------------------------------------
/src/Http/Http.php:
--------------------------------------------------------------------------------
1 | connection = curl_init();
19 |
20 | }
21 |
22 |
23 | /**
24 | * [request description]
25 | * @param [type] $url [description]
26 | * @param string $method [description]
27 | * @param array $params [description]
28 | * @param boolean $secure [description]
29 | * @return [type] [description]
30 | */
31 | public function request( $url, $method = 'GET', $params = array(), $headers = array(), $secure = true, $excludePermHeaders = false, $debug = false ) {
32 |
33 | curl_setopt( $this->connection, CURLOPT_URL, $url );
34 | curl_setopt( $this->connection, CURLOPT_RETURNTRANSFER, true );
35 | curl_setopt( $this->connection, CURLOPT_MAXREDIRS, 10 );
36 | curl_setopt( $this->connection, CURLOPT_FOLLOWLOCATION, 1 );
37 |
38 | $original_method = $method;
39 |
40 | // Secure opts
41 | if( $secure == false ) {
42 | curl_setopt( $this->connection, CURLOPT_SSL_VERIFYHOST, 0 );
43 | curl_setopt( $this->connection, CURLOPT_SSL_VERIFYPEER, 0 );
44 | }
45 |
46 | // Debug
47 | if( $debug === true ) {
48 |
49 | curl_setopt( $this->connection, CURLOPT_VERBOSE, true );
50 | $verbose = fopen( $this->debugFile, 'a+' );
51 | curl_setopt( $this->connection, CURLOPT_STDERR, $verbose );
52 |
53 | }
54 |
55 | // Headers
56 | if ( $excludePermHeaders == false && $this->permHeaders !== null && count( $this->permHeaders ) > 0 )
57 |
58 | $headers = array_merge( $headers, $this->permHeaders );
59 |
60 | if( isset( $headers ) && count( $headers ) > 0 )
61 |
62 | curl_setopt( $this->connection, CURLOPT_HTTPHEADER, $headers );
63 |
64 | // POST || PUT
65 | if( $method == 'POST' || $method == 'PUT' ) {
66 |
67 | curl_setopt( $this->connection, CURLOPT_CUSTOMREQUEST, $method );
68 | curl_setopt( $this->connection, CURLOPT_POST, count( $params ) );
69 | curl_setopt( $this->connection, CURLOPT_POSTFIELDS, http_build_query ( $params ) );
70 |
71 | }
72 |
73 | // POST RAW
74 | else if( $method == 'POST_RAW' ) {
75 |
76 | $params = json_encode ( $params );
77 |
78 | curl_setopt( $this->connection, CURLOPT_POSTFIELDS, $params );
79 | curl_setopt( $this->connection, CURLOPT_CUSTOMREQUEST, "POST" );
80 |
81 | //die( "Es: " . json_encode ( $headers ) );
82 |
83 | }
84 |
85 | // DELETE
86 | else if( $method == 'DELETE' ) {
87 |
88 | curl_setopt( $this->connection, CURLOPT_CUSTOMREQUEST, $method );
89 | curl_setopt( $this->connection, CURLOPT_POST, count( $params ) );
90 | curl_setopt( $this->connection, CURLOPT_POSTFIELDS, $fields_string );
91 |
92 | }
93 |
94 | // GET
95 | else {
96 |
97 | if( isset( $params ) && count( $params ) > 0 )
98 |
99 | curl_setopt( $this->connection, CURLOPT_URL, $url . '?' . $fields_string );
100 |
101 | else
102 |
103 | curl_setopt( $this->connection, CURLOPT_URL, $url );
104 |
105 | }
106 |
107 | // Exec
108 | $result = curl_exec( $this->connection );
109 |
110 | $http_code = curl_getinfo( $this->connection, CURLINFO_HTTP_CODE);
111 |
112 | if ( $errno = curl_errno( $this->connection ) || substr ( $http_code, 0, 1) != 2 ) {
113 |
114 | $error_params = array(
115 |
116 | 'url' => $url,
117 | 'method' => $original_method,
118 | 'secure' => $secure,
119 | 'headers' => $headers,
120 | 'response' => $result,
121 | 'http_code' => $http_code,
122 | 'curl_string_error' => curl_strerror( $errno ),
123 | 'params' => $params,
124 | 'debug_mode' => $debug,
125 |
126 | );
127 |
128 | throw new HttpException( $error_params, $http_code );
129 |
130 | }
131 |
132 | else
133 |
134 | return array( 'result' => $result, 'status' => $http_code );
135 |
136 | }
137 |
138 |
139 | /**
140 | * [__destruct description]
141 | */
142 | public function __destruct() {
143 |
144 | curl_close( $this->connection );
145 |
146 | $this->connection = null;
147 |
148 | }
149 |
150 |
151 | }
--------------------------------------------------------------------------------
/examples/MyBotClient.php:
--------------------------------------------------------------------------------
1 | loadConfig( $config );
36 |
37 | // 2. We take the input data
38 | $this->input = $this->getPostRaw();
39 |
40 | // 3. Check the hash
41 | if( !isset( $_GET['hash'] ) || $_GET['hash'] != $this->hash )
42 |
43 | die("Unauthorized!"); // TODO Change by an exception
44 |
45 | // 4. Check the channel
46 | if( !isset( $this->input->channelId ) )
47 |
48 | die("Channel not found."); // TODO Change by an exception
49 |
50 | // 5. Init our bot depending of the channel
51 | $this->bot = Bot::getBotByChannel( $this->input->channelId, $this->client, $this->secret, $config ); // TODO Try / catch to manage other errors
52 |
53 | }
54 |
55 | /**
56 | * [init description]
57 | * @return [type] [description]
58 | */
59 | public function init() {
60 |
61 | if( !isset( $this->input->type ) )
62 |
63 | die("Method not found."); // TODO Cambiar por una excepcion
64 |
65 | // Get the type of request and execute the right method
66 | return $this->fireEventHandler( $this->input->type );
67 |
68 | }
69 |
70 |
71 | /**
72 | * Load the configuration from the config.php file
73 | */
74 | private function loadConfig( $config = [] ) {
75 |
76 | $this->hash = ( isset( $config['hash'] ) ) ? $config['hash'] : null;
77 |
78 | $this->client = ( isset( $config['app_client_id'] ) ) ? $config['app_client_id'] : null;
79 |
80 | $this->secret = ( isset( $config['app_secret_id'] ) ) ? $config['app_secret_id'] : null;
81 |
82 | }
83 |
84 |
85 | /**
86 | * Get the info from the bot response
87 | * @param boolean $to_object To enable if the response must ve given in object or in raw
88 | * @return mixed String or Object depending. Response from the bot api.
89 | */
90 | private function getPostRaw( $to_object = true ) {
91 |
92 | $postRaw = file_get_contents('php://input');
93 |
94 | if( $to_object === true && Helpers::isJson( $postRaw ) === true )
95 |
96 | return json_decode( $postRaw );
97 |
98 | else
99 |
100 | return $postRaw;
101 |
102 | }
103 |
104 |
105 | /**
106 | * Manage the event firing the right method
107 | * @param string $type Method to fire
108 | * @return mixed The response of the selected method
109 | */
110 | private function fireEventHandler ( $type ) {
111 |
112 | $methodName = $type . 'EventHandler';
113 |
114 | $specificMethodName = $this->input->channelId . ucfirst($type) . 'EventHandler';
115 |
116 | if ( !method_exists( $this, $specificMethodName ) ) {
117 |
118 | if ( !method_exists( $this, $methodName ) ) {
119 |
120 | $botClassName = Bot::getBotName( $this->input->channelId );
121 |
122 | // If not exist in the client, we search for it in the Bot
123 | if ( !method_exists( $this->bot, $methodName ) )
124 |
125 | die("No se encuentra el método!!"); // TODO Cambiar por una excepcion
126 |
127 | else
128 |
129 | return $this->bot->$methodName( $this->input );
130 |
131 | }
132 |
133 | else
134 |
135 | return $this->$methodName();
136 |
137 | }
138 |
139 | else
140 |
141 | return $this->$specificMethodName();
142 |
143 | }
144 |
145 | /**
146 | * ######################################
147 | * YOU CAN CREATE FROM HERE
148 | * ######################################
149 | */
150 |
151 |
152 | /**
153 | * Default skype message event handler
154 | */
155 | public function skypeMessageEventHandler() {
156 |
157 | $to = $this->input->from->id;
158 |
159 | $message = "I have received \"" . $this->input->text . "\" from " . $this->input->from->name . ".";
160 |
161 | $this->bot->addMessage( $to, $message );
162 |
163 | return 0;
164 |
165 | }
166 |
167 |
168 | /**
169 | * Default skype conversation update event handlers
170 | */
171 | public function skypeConversationUpdateEventHandler() {
172 |
173 | // Members added in group
174 | if( isset( $this->input->conversation->isGroup ) && $this->input->conversation->isGroup == true ) {
175 |
176 | $to = $this->input->conversation->id;
177 |
178 | if( isset( $this->input->membersAdded ) ) {
179 |
180 | $message = "Hi guys!! :)";
181 |
182 | $this->bot->addMessage( $to, $message );
183 |
184 | }
185 |
186 | }
187 |
188 | return 0;
189 |
190 | }
191 |
192 | /**
193 | * Default skype contact relation update event handlers
194 | * @return [type] [description]
195 | */
196 | public function skypeContactRelationUpdateEventHandler() {
197 |
198 | $to = $this->input->from->id;
199 |
200 | $name = explode(" ", $this->input->from->name)[0];
201 |
202 | $message = "Hey " . $name . "! What's up?? :)";
203 |
204 | $this->bot->addMessage( $to, $message );
205 |
206 | return 0;
207 |
208 | }
209 |
210 | }
211 |
--------------------------------------------------------------------------------
/src/Bot.php:
--------------------------------------------------------------------------------
1 | "message/image",
37 | "audio" => "message/audio",
38 | "video" => "message/video",
39 | "card" => "message/card.carousel",
40 |
41 | );
42 |
43 |
44 | /**
45 | * [__construct description]
46 | * @param [type] $client [description]
47 | * @param [type] $secret [description]
48 | */
49 | public function __construct( $client, $secret, $config ) {
50 |
51 | $this->client = $client;
52 |
53 | $this->secret = $secret;
54 |
55 | $this->config = $config;
56 |
57 | $this->http = new Http();
58 |
59 | }
60 |
61 |
62 | /**
63 | * [getBotByChannel description]
64 | * @param [type] $channelID [description]
65 | * @param [type] $client [description]
66 | * @param [type] $secret [description]
67 | * @return [type] [description]
68 | */
69 | public static function getBotByChannel( $channelID, $client, $secret, $config ) {
70 |
71 | $botClassName = self::getBotName( $channelID );
72 |
73 | if( !class_exists( $botClassName ) )
74 |
75 | throw new BotException( "Wuops! Not exist a bot for the channelId '" . $channelID . "' (".$botClassName.")", 1 );
76 |
77 | else {
78 |
79 | //file_put_contents('/var/www/cartasian/public/microsoft-bot/tmp/debug.txt', PHP_EOL . PHP_EOL . date("\[d-m-Y H:m:i\]") . ': '. $botClassName . PHP_EOL, FILE_APPEND );
80 |
81 | return new $botClassName( $client, $secret, $config ); // TODO Lanzar excepcion si no se encuentra la clase
82 |
83 | }
84 |
85 | }
86 |
87 |
88 | /**
89 | * [getBotName description]
90 | * @param [type] $channelID [description]
91 | * @return [type] [description]
92 | */
93 | public static function getBotName( $channelID ) {
94 |
95 | return __NAMESPACE__ . "\\" . ucfirst( $channelID ) . 'Bot';
96 |
97 | }
98 |
99 |
100 | /**
101 | * [authenticate description]
102 | * @param [type] $client [description]
103 | * @param [type] $secret [description]
104 | * @return [type] [description]
105 | */
106 | public function authenticate( $client = null, $secret = null ) {
107 |
108 | if( $client == null )
109 |
110 | $client = $this->client;
111 |
112 | if( $secret == null )
113 |
114 | $secret = $this->secret;
115 |
116 | $auth = new Auth( $client, $secret );
117 |
118 | $this->token = $auth->token;
119 |
120 | $this->http->permHeaders = array( 'Authorization: Bearer ' . $this->token );
121 |
122 | }
123 |
124 |
125 | /**
126 | * [authenticate description]
127 | * @param [type] $client [description]
128 | * @param [type] $secret [description]
129 | * @return [type] [description]
130 | */
131 | protected function do_request( $url, $method = 'GET', $params = array(), $headers = array(), $secure = true, $excludePermHeaders = false, $debug = false ) {
132 |
133 | try {
134 |
135 | // We check by the auth
136 | if( $this->token == null)
137 |
138 | $this->authenticate();
139 |
140 | // Do request
141 | $result = $this->http->request( $url, $method, $params, $headers, $secure, $excludePermHeaders, $debug );
142 |
143 | return $result;
144 |
145 | } catch (HttpException $e) {
146 |
147 | if( $e->getCode() == 401 )
148 |
149 | throw new AuthException( 'Unauthorized - The authentication information is not provided or is invalid.' );
150 |
151 | else if( $e->getCode() == 403 )
152 |
153 | throw new AuthException( 'Forbidden - The provided credentials do not grant the client permission to access the resource. For example: a recognized user attempted to access restricted content..' );
154 |
155 | else
156 |
157 | die( $e->manageError() );
158 |
159 | }
160 |
161 | }
162 |
163 | /**
164 | * COMMUNICATION METHODS
165 | */
166 |
167 |
168 | /**
169 | * [addMessage description]
170 | * @param string $to [description]
171 | * @param string $message [description]
172 | * @return array [description]
173 | */
174 | public function addMessage( $to, $message, $extra = array() ) {
175 |
176 | // Execute
177 | $url = $this->serviceUrl . '/' . $this->serviceVersion . '/conversations/' . $to . '/activities';
178 |
179 | $params = array(
180 |
181 | 'type' => $this->type_text_message,
182 | "text" => $message,
183 |
184 | );
185 |
186 | $httpResponse = $this->do_request( $url, 'POST_RAW', $params, array( 'Content-Type: application/json' ) );
187 |
188 | return $httpResponse;
189 |
190 | }
191 |
192 |
193 | /**
194 | * [addAttachment description]
195 | * @param string $to [description]
196 | * @param string $message [description]
197 | * @return array [description]
198 | */
199 | public function addAttachment( $to, $type, $content, $extra = array(), $options = array() ) {
200 |
201 | if( !isset( $this->type_attachment[ $type ] ) )
202 |
203 | throw new BotException( "Wuops! The media type doesn't exist.", 1 );
204 |
205 | // Execute
206 | $url = $this->serviceUrl . '/' . $this->serviceVersion . '/conversations/' . $to . '/activities';
207 |
208 | $methodName = "_create" . $type;
209 |
210 | $params = array(
211 |
212 | 'type' => $this->type_attachment[ $type ],
213 | "attachments" => $this->$methodName( $content, $extra, $options ),
214 |
215 | );
216 |
217 | if( isset( $options['summary'] ) )
218 |
219 | $params['summary'] = $options['summary'];
220 |
221 | $httpResponse = $this->do_request( $url, 'POST_RAW', $params, array( 'Content-Type: application/json' ) );
222 |
223 | return $httpResponse;
224 |
225 | }
226 |
227 |
228 | /**
229 | * [_createImage description]
230 | * @param [type] $content [description]
231 | * @param [type] $extra [description]
232 | * @param [type] $options [description]
233 | */
234 | protected function _createImage( $content, $extra, $options ) {
235 |
236 | // Manipulate depending of the mode
237 | if( isset( $content['tmp_name'] ) ) {
238 |
239 | $imageEncoded = file_get_contents( $content['tmp_name'] );
240 |
241 | $mimeType = $content['type'];
242 |
243 | $imageEncoded = 'data:image/' . $mimeType . ';base64,' . base64_encode( $image );
244 |
245 | $response = array(
246 |
247 | "contentUrl" => $imageEncoded,
248 | "contentType" => $mimeType,
249 |
250 | );
251 |
252 | }
253 |
254 | else if( file_exists( $content ) ) {
255 |
256 | $fileInfo = new \finfo( FILEINFO_MIME_TYPE );
257 |
258 | $image = file_get_contents( $content );
259 |
260 | $mimeType = $fileInfo->buffer( $image );
261 |
262 | $imageEncoded = 'data:image/' . $mimeType . ';base64,' . base64_encode( $image );
263 |
264 | $response = array(
265 |
266 | "contentUrl" => $imageEncoded,
267 | "contentType" => $mimeType,
268 |
269 | );
270 |
271 | }
272 |
273 | else if( strpos( $content, 'http://' ) !== false || strpos( $content, 'https://' ) !== false ) {
274 |
275 | $fileInfo = new \finfo( FILEINFO_MIME_TYPE );
276 |
277 | $image = file_get_contents( $content );
278 |
279 | $mimeType = $fileInfo->buffer( $image );
280 |
281 | $imageEncoded = 'data:' . $mimeType . ';base64,' . base64_encode( $image );
282 |
283 | $response = array(
284 |
285 | "contentUrl" => $imageEncoded,
286 | "contentType" => $mimeType,
287 |
288 | );
289 |
290 | }
291 |
292 | else if( strpos( $content, 'data:image' ) !== false ) {
293 |
294 | $imageEncoded = $content;
295 |
296 | $mimeTypeAlt1 = strpos( $content, ';' );
297 |
298 | $mimeType = explode( ':', substr( $content, 0, $mimeTypeAlt1 ) )[1];
299 |
300 | $response = array(
301 |
302 | "contentUrl" => $content,
303 | "contentType" => $mimeType,
304 |
305 | );
306 |
307 | }
308 |
309 | else
310 |
311 | throw new BotException( "Wuops! The media type doesn't exist.", 1 );
312 |
313 | // Extra
314 | $response = array_merge( $response, $extra );
315 |
316 | return array( $response );
317 |
318 | }
319 |
320 |
321 | /**
322 | * [_createAudio description]
323 | * @param [type] $content [description]
324 | * @param [type] $extra [description]
325 | * @param [type] $options [description]
326 | */
327 | protected function _createAudio( $content, $extra, $options ) {
328 |
329 | //TODO
330 |
331 | }
332 |
333 |
334 | /**
335 | * [_createVideo description]
336 | * @param [type] $content [description]
337 | * @param [type] $extra [description]
338 | * @param [type] $options [description]
339 | */
340 | protected function _createVideo( $content, $extra, $options ) {
341 |
342 | //TODO
343 |
344 | }
345 |
346 |
347 | /**
348 | * [_createVideo description]
349 | * @param [type] $content [description]
350 | * @param [type] $extra [description]
351 | * @param [type] $options [description]
352 | */
353 | protected function _createCard( $content, $extra, $options ) {
354 |
355 | if( !is_array( $content ) )
356 |
357 | $content = array( $content );
358 |
359 | if( !isset( $content[0] ) || !is_array( $content[0] ) || isset( $content['type'] ) )
360 |
361 | $content = array( $content );
362 |
363 | $final_response = array();
364 |
365 | foreach ($content as $key => $value) {
366 |
367 | //die( json_encode( $value ) );
368 |
369 | // General check
370 | if( !isset( $value['content'] ) || !is_array( $value['content'] ) || count( $value['content'] ) == 0 )
371 |
372 | throw new BotException( "Wuops! You need to provide an array with the content key.", 1 );
373 |
374 | if( !isset( $value['content']['title'] ) || $value['content']['title'] == '' )
375 |
376 | throw new BotException( "Wuops! You need to provide a title.", 1 );
377 |
378 | // Check by type
379 | if( $value['type'] == 'thumbnail' ) {
380 |
381 | // Image
382 | if( !isset( $value['content']['image'] ) || $value['content']['image'] == '' )
383 |
384 | throw new BotException( "Wuops! In card thumbnail, you need to provide a image url.", 1 );
385 |
386 | }
387 |
388 | if( $value['type'] == 'hero' ) {
389 |
390 | // Text
391 | if( !isset( $value['content']['text'] ) || $value['content']['text'] == '' )
392 |
393 | throw new BotException( "Wuops! In card hero, you need to provide a text.", 1 );
394 |
395 | }
396 |
397 | $response = array(
398 |
399 | 'contentType' => 'application/vnd.microsoft.card.' . $value['type'], // thumbnail / hero /
400 | 'content' => array(
401 |
402 | 'title' => $value['content']['title'],
403 |
404 | ),
405 |
406 | );
407 |
408 | // Other values
409 | // Images
410 | if( isset( $value['content']['image'] ) ) {
411 |
412 | $response['content']['images'] = array();
413 |
414 | if( is_array( $value['content']['image'] ) ) {
415 |
416 | $image = array( 'url' => $value['content']['image']['url'] );
417 |
418 | if( isset( $value['content']['image']['alt'] ) )
419 |
420 | $image['alt'] = $value['content']['image']['alt'];
421 |
422 | }
423 |
424 | else
425 |
426 | $image = array( 'url' => $value['content']['image'] );
427 |
428 | $response['content']['images'][] = $image;
429 |
430 | }
431 |
432 | // Buttons
433 | if( isset( $value['content']['buttons'] ) ) {
434 |
435 | if( !is_array( $value['content']['buttons'] ) )
436 |
437 | throw new BotException( "Wuops! The buttons of the card must be in an array.", 1 );
438 |
439 | $response['content']['buttons'] = array();
440 |
441 | foreach ($value['content']['buttons'] as $key => $button) {
442 |
443 | if( !is_array( $button ) || !isset( $button['type'] ) || !isset( $button['title'] ) || !isset( $button['value'] ) )
444 |
445 | throw new BotException( "Wuops! Each button of the card must to have the fields type, titlle and value.", 1 );
446 |
447 | $response['content']['buttons'][] = $button;
448 |
449 | }
450 |
451 | }
452 |
453 | // Text
454 | if( isset( $value['content']['text'] ) )
455 |
456 | $response['content']['text'] = $value['content']['text'];
457 |
458 | // Subtitle
459 | if( isset( $value['content']['text'] ) )
460 |
461 | $response['content']['subtitle'] = $value['content']['subtitle'];
462 |
463 | // Extra
464 | if( isset( $extra[$key] ) )
465 |
466 | $response['content'] = array_merge( $response['content'], $extra[$key] );
467 |
468 | $final_response[] = $response;
469 |
470 | }
471 |
472 | return $final_response;
473 |
474 | }
475 |
476 | }
477 |
--------------------------------------------------------------------------------