├── config.php ├── cg ├── 1.jpg ├── 2.jpg └── 3.jpg ├── images ├── alipay.png └── weixin_wallet.png ├── webhook.php ├── README.md ├── ImageBot.php ├── TelegramBot.php └── LICENSE /config.php: -------------------------------------------------------------------------------- 1 | setWebhook(BOT_WEBHOOK); 12 | echo BOT_WEBHOOK; 13 | } else if ($argv[1] == 'remove') { 14 | $bot->removeWebhook(); 15 | } 16 | exit; 17 | } 18 | 19 | $response = file_get_contents('php://input'); 20 | $update = json_decode($response, true); 21 | //var_dump($update); 22 | $bot->init(); 23 | $bot->onUpdateReceived($update); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Telegram-Simple-Image-Bot 2 | A simple telegram bot which can return a random picture. 3 | 4 | 5 | You can import images through the crawler tool such as [Sina Weibo Album Downloader](https://github.com/lincanbin/Sina-Weibo-Album-Downloader). 6 | 7 | 8 | Demo 9 | ------------ 10 | * https://telegram.me/canbin_bot 11 | 12 | 13 | Deployment 14 | ------------ 15 | 1. Fill `config.php` with Token. 16 | 2. Open `https://www.yourdomain.com/webhook.php?wekhook=set` in browser to set webhook. 17 | 3. Put your images to dir `images`. 18 | 4. Chat with the robot and enter `/pic`. 19 | 20 | 21 | License 22 | ------------ 23 | ``` 24 | Copyright 2015 Canbin Lin (lincanbin@hotmail.com) 25 | 26 | Licensed under the Apache License, Version 2.0 (the "License"); 27 | you may not use this file except in compliance with the License. 28 | You may obtain a copy of the License at 29 | 30 | http://www.apache.org/licenses/LICENSE-2.0 31 | 32 | Unless required by applicable law or agreed to in writing, software 33 | distributed under the License is distributed on an "AS IS" BASIS, 34 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 35 | See the License for the specific language governing permissions and 36 | limitations under the License. 37 | ``` -------------------------------------------------------------------------------- /ImageBot.php: -------------------------------------------------------------------------------- 1 | array('text'=>'晚安'), 25 | '睡觉' => array('text'=>'晚安'), 26 | '睡了' => array('text'=>'晚安'), 27 | //'买' => array('photo'=>'buy'), 28 | '好污' => array( 29 | 'photo'=>'images', 30 | 'text'=>' 31 | 👌👉🏿👌👌👌👌👌👌👌👌👌👌 32 | 👌👌👉🏿👌👌👉🏿👉🏿👉🏿👉🏿👉🏿👉🏿👌 33 | 👌👌👌👌👌👌👌👌👌👌👌👌 34 | 👉🏿👌👌👌👌👌👌👌👌👌👌👌 35 | 👌👉🏿👌👌👉🏿👉🏿👉🏿👉🏿👉🏿👉🏿👉🏿👉🏿 36 | 👌👌👌👌👌👌👉🏿👌👌👌👌👌 37 | 👌👌👉🏿👌👌👌👉🏿👌👌👌👌👌 38 | 👌👉🏿👌👌👌👉🏿👉🏿👉🏿👉🏿👉🏿👉🏿👌 39 | 👉🏿👉🏿👌👌👌👌👌👌👌👌👉🏿👌 40 | 👌👉🏿👌👌👌👌👌👌👌👌👉🏿👌 41 | 👌👉🏿👌👌👌👌👉🏿👌👌👉🏿👌👌 42 | 👌👉🏿👌👌👌👌👌👉🏿👉🏿👌👌👌 43 | '), 44 | 45 | '噫!' => array('text'=>' 46 | 🌚🌚🌚🌚🌚🌚🌚🌚🌚🌚🌝🌚🌚🌚🌚🌚 47 | 🌚🌚🌚🌚🌚🌚🌚🌚🌚🌚🌚🌝🌚🌚🌝🌚 48 | 🌚🌝🌝🌝🌝🌚🌝🌝🌝🌝🌝🌝🌝🌝🌝🌝 49 | 🌚🌝🌚🌚🌝🌚🌚🌚🌝🌚🌚🌚🌚🌝🌚🌚 50 | 🌚🌝🌚🌚🌝🌚🌚🌚🌚🌝🌚🌚🌝🌚🌚🌚 51 | 🌚🌝🌚🌚🌝🌚🌝🌝🌝🌝🌝🌝🌝🌝🌝🌝 52 | 🌚🌝🌚🌚🌝🌚🌚🌚🌚🌚🌚🌚🌚🌚🌚🌚 53 | 🌚🌝🌚🌚🌝🌚🌚🌝🌝🌝🌝🌝🌝🌝🌝🌚 54 | 🌚🌝🌚🌚🌝🌚🌚🌝🌚🌚🌚🌚🌚🌚🌝🌚 55 | 🌚🌝🌝🌝🌝🌚🌚🌝🌝🌝🌝🌝🌝🌝🌝🌚 56 | 🌚🌝🌚🌚🌝🌚🌚🌝🌚🌚🌚🌚🌚🌚🌝🌚 57 | 🌚🌝🌚🌚🌚🌚🌚🌝🌝🌝🌝🌝🌝🌝🌝🌚 58 | 🌚🌚🌚🌚🌚🌚🌝🌚🌝🌚🌝🌚🌚🌚🌚🌝 59 | 🌚🌚🌚🌚🌚🌚🌝🌚🌝🌚🌚🌝🌚🌝🌚🌚 60 | 🌚🌚🌚🌚🌚🌝🌚🌚🌝🌚🌚🌚🌚🌝🌚🌚 61 | 🌚🌚🌚🌚🌚🌚🌚🌚🌚🌝🌝🌝🌝🌝🌚🌚'), 62 | /* 63 | '噫'=> array('text'=>' 64 | 🌚🌚🌚🌚🌚🌚🌚🌝🌚🌚🌚🌚 65 | 🌝🌝🌝🌚🌝🌝🌝🌝🌝🌝🌝🌚 66 | 🌝🌚🌝🌚🌚🌝🌚🌚🌝🌚🌚🌚 67 | 🌝🌚🌝🌝🌝🌝🌝🌝🌝🌝🌝🌝 68 | 🌝🌚🌝🌚🌝🌚🌚🌚🌚🌝🌚🌚 69 | 🌝🌚🌝🌚🌝🌝🌝🌝🌝🌝🌚🌚 70 | 🌝🌚🌝🌚🌝🌚🌚🌚🌚🌝🌚🌚 71 | 🌝🌝🌝🌚🌝🌝🌝🌝🌝🌝🌚🌚 72 | 🌝🌚🌝🌚🌚🌝🌚🌝🌚🌚🌚🌚 73 | 🌚🌚🌚🌚🌝🌝🌚🌚🌝🌚🌝🌚 74 | 🌚🌚🌚🌝🌚🌝🌚🌚🌚🌝🌚🌝 75 | 🌚🌚🌚🌚🌚🌚🌝🌝🌝🌝🌚🌚 76 | '), 77 | */ 78 | '😂😂😂' => array('text'=>'😂😂😂') 79 | ); 80 | public function __construct($core, $chat_id) { 81 | parent::__construct($core, $chat_id); 82 | } 83 | public function init() { 84 | } 85 | 86 | public function some_command($command, $params, $message) { 87 | switch ($command) { 88 | case 'start': 89 | case 'help': 90 | $this->apiSendMessage("我是一个脱离了高级趣味的Bot. /pic or /hentai "); 91 | break; 92 | case 'about': 93 | $this->apiSendMessage("https://github.com/lincanbin"); 94 | break; 95 | case 'yi': 96 | $this->apiSendMessage($this->responseTable['噫!']['text']); 97 | break; 98 | case 'pic': 99 | $this->returnPicture($this->getRandomPictureObject("images")); 100 | break; 101 | case 'hentai': 102 | case 'cg': 103 | $this->returnPicture($this->getRandomPictureObject("cg")); 104 | break; 105 | default: 106 | //$this->returnPicture($this->getRandomPictureObject("images")); 107 | break; 108 | } 109 | return; 110 | } 111 | 112 | 113 | public function message($text, $message) { 114 | /* 115 | $reply_string = file_get_contents('./reply.txt', FILE_USE_INCLUDE_PATH); 116 | if($reply_string){ 117 | $this->apiSendMessage($reply_string); 118 | file_put_contents('./reply.txt', ""); 119 | } 120 | */ 121 | 122 | foreach ($this->responseTable as $key => $value) { 123 | if(strpos($text, $key) !== false){ 124 | if(isset($value['photo'])){ 125 | $this->returnPicture($this->getRandomPictureObject($value['photo'])); 126 | sleep(5); 127 | } 128 | if(isset($value['text'])){ 129 | $this->apiSendMessage($value['text']); 130 | } 131 | break; 132 | } 133 | } 134 | 135 | return; 136 | } 137 | 138 | private function getRandomPictureObject($dir_name){ 139 | $image_list = scandir(__DIR__ . "/". $dir_name); 140 | $image_path = realpath($dir_name . "/" . $image_list[mt_rand(2, (count($image_list)-1))]); 141 | $image_object = new CURLFile($image_path); 142 | error_log($image_path . "\n\n", 3, __DIR__ . "/my-errors.log"); 143 | return $image_object; 144 | } 145 | 146 | private function returnPicture($image_object){ 147 | $this->core->request('sendPhoto', 148 | array( 149 | 'chat_id' => $this->chatId, 150 | 'photo' => $image_object 151 | ), 152 | array( 153 | 'http_method' => 'POST' 154 | ) 155 | ); 156 | } 157 | 158 | } -------------------------------------------------------------------------------- /TelegramBot.php: -------------------------------------------------------------------------------- 1 | 'api.telegram.org', 29 | 'port' => 443, 30 | ); 31 | 32 | $this->host = $host = $options['host']; 33 | $this->port = $port = $options['port']; 34 | $this->botToken = $token; 35 | 36 | $proto_part = ($port == 443 ? 'https' : 'http'); 37 | $port_part = ($port == 443 || $port == 80) ? '' : ':'.$port; 38 | 39 | $this->apiUrl = "{$proto_part}://{$host}{$port_part}/bot{$token}"; 40 | } 41 | 42 | public function init() { 43 | if ($this->inited) { 44 | return true; 45 | } 46 | 47 | $this->handle = curl_init(); 48 | 49 | $response = $this->request('getMe'); 50 | if (!$response['ok']) { 51 | throw new Exception("Can't connect to server"); 52 | } 53 | 54 | $bot = $response['result']; 55 | $this->botId = $bot['id']; 56 | $this->botUsername = $bot['username']; 57 | 58 | $this->inited = true; 59 | return true; 60 | } 61 | 62 | public function runLongpoll() { 63 | $this->init(); 64 | $this->longpoll(); 65 | } 66 | 67 | public function setWebhook($url) { 68 | $this->init(); 69 | $result = $this->request('setWebhook', array('url' => $url)); 70 | return $result['ok']; 71 | } 72 | 73 | public function removeWebhook() { 74 | $this->init(); 75 | $result = $this->request('setWebhook', array('url' => '')); 76 | return $result['ok']; 77 | } 78 | 79 | public function request($method, $params = array(), $options = array()) { 80 | $options += array( 81 | 'http_method' => 'GET', 82 | 'timeout' => $this->netTimeout, 83 | ); 84 | foreach ($params as $key => &$val) { 85 | if (!is_numeric($val) && !is_string($val) && !is_object($val)) { 86 | $params[$key] = json_encode($val); 87 | //$val = json_encode($val); 88 | } 89 | } 90 | 91 | $url = $this->apiUrl.'/'.$method; 92 | 93 | error_log($url . "\n", 3, __DIR__ . "/my-errors.log"); 94 | error_log(var_export($params) . "\n", 3, __DIR__ . "/my-errors.log"); 95 | if ($options['http_method'] === 'POST') { 96 | //var_dump($url); 97 | //var_dump($params); 98 | //curl_setopt($this->handle, CURLOPT_SAFE_UPLOAD, false); 99 | curl_setopt($this->handle, CURLOPT_POST, true); 100 | curl_setopt($this->handle, CURLOPT_POSTFIELDS, $params); 101 | } else { 102 | $query_string = http_build_query($params); 103 | $url .= ($query_string ? '?'.$query_string : ''); 104 | curl_setopt($this->handle, CURLOPT_HTTPGET, true); 105 | } 106 | 107 | $connect_timeout = $this->netConnectTimeout; 108 | $timeout = $options['timeout'] ?: $this->netTimeout; 109 | 110 | curl_setopt($this->handle, CURLOPT_URL, $url); 111 | curl_setopt($this->handle, CURLOPT_RETURNTRANSFER, true); 112 | curl_setopt($this->handle, CURLOPT_CONNECTTIMEOUT, $connect_timeout); 113 | curl_setopt($this->handle, CURLOPT_TIMEOUT, $timeout); 114 | 115 | $response_str = curl_exec($this->handle); 116 | $errno = curl_errno($this->handle); 117 | $http_code = intval(curl_getinfo($this->handle, CURLINFO_HTTP_CODE)); 118 | 119 | if ($http_code == 401) { 120 | throw new Exception('Invalid access token provided'); 121 | } else if ($http_code >= 500 || $errno) { 122 | sleep($this->netDelay); 123 | if ($this->netDelay < 30) { 124 | $this->netDelay *= 2; 125 | } 126 | } 127 | 128 | $response = json_decode($response_str, true); 129 | 130 | return $response; 131 | } 132 | 133 | protected function longpoll() { 134 | $params = array( 135 | 'limit' => $this->updatesLimit, 136 | 'timeout' => $this->updatesTimeout, 137 | ); 138 | if ($this->updatesOffset) { 139 | $params['offset'] = $this->updatesOffset; 140 | } 141 | $options = array( 142 | 'timeout' => $this->netConnectTimeout + $this->updatesTimeout + 2, 143 | ); 144 | $response = $this->request('getUpdates', $params, $options); 145 | if ($response['ok']) { 146 | $updates = $response['result']; 147 | if (is_array($updates)) { 148 | foreach ($updates as $update) { 149 | $this->updatesOffset = $update['update_id'] + 1; 150 | $this->onUpdateReceived($update); 151 | } 152 | } 153 | } 154 | $this->longpoll(); 155 | } 156 | 157 | abstract public function onUpdateReceived($update); 158 | 159 | } 160 | 161 | class TelegramBot extends TelegramBotCore { 162 | 163 | protected $chatClass; 164 | protected $chatInstances = array(); 165 | 166 | public function __construct($token, $chat_class, $options = array()) { 167 | parent::__construct($token, $options); 168 | 169 | $instance = new $chat_class($this, 0); 170 | if (!($instance instanceof TelegramBotChat)) { 171 | throw new Exception('ChatClass must be extends TelegramBotChat'); 172 | } 173 | $this->chatClass = $chat_class; 174 | } 175 | 176 | public function onUpdateReceived($update) { 177 | if ($update['message']) { 178 | $message = $update['message']; 179 | $chat_id = intval($message['chat']['id']); 180 | if ($chat_id) { 181 | $chat = $this->getChatInstance($chat_id); 182 | if (isset($message['group_chat_created'])) { 183 | $chat->bot_added_to_chat($message); 184 | } else if (isset($message['new_chat_participant'])) { 185 | if ($message['new_chat_participant']['id'] == $this->botId) { 186 | $chat->bot_added_to_chat($message); 187 | } 188 | } else if (isset($message['left_chat_participant'])) { 189 | if ($message['left_chat_participant']['id'] == $this->botId) { 190 | $chat->bot_kicked_from_chat($message); 191 | } 192 | } else { 193 | $text = trim($message['text']); 194 | $username = strtolower('@'.$this->botUsername); 195 | $username_len = strlen($username); 196 | if (strtolower(substr($text, 0, $username_len)) == $username) { 197 | $text = trim(substr($text, $username_len)); 198 | } 199 | if (preg_match('/^(?:\/([a-z0-9_]+)(@[a-z0-9_]+)?(?:\s+(.*))?)$/is', $text, $matches)) { 200 | $command = $matches[1]; 201 | $command_owner = empty($matches[2]) ? null : strtolower($matches[2]); 202 | $command_params = empty($matches[3]) ? null : $matches[3]; 203 | if (!$command_owner || $command_owner == $username) { 204 | $method = 'command_'.$command; 205 | if (method_exists($chat, $method)) { 206 | $chat->$method($command_params, $message); 207 | } else { 208 | $chat->some_command($command, $command_params, $message); 209 | } 210 | } 211 | } else { 212 | $chat->message($text, $message); 213 | } 214 | } 215 | } 216 | } 217 | } 218 | 219 | protected function getChatInstance($chat_id) { 220 | if (!isset($this->chatInstances[$chat_id])) { 221 | $instance = new $this->chatClass($this, $chat_id); 222 | $this->chatInstances[$chat_id] = $instance; 223 | $instance->init(); 224 | } 225 | return $this->chatInstances[$chat_id]; 226 | } 227 | } 228 | 229 | 230 | 231 | abstract class TelegramBotChat { 232 | 233 | protected $core; 234 | protected $chatId; 235 | protected $isGroup; 236 | 237 | public function __construct($core, $chat_id) { 238 | if (!($core instanceof TelegramBot)) { 239 | throw new Exception('$core must be TelegramBot instance'); 240 | } 241 | $this->core = $core; 242 | $this->chatId = $chat_id; 243 | $this->isGroup = $chat_id < 0; 244 | } 245 | 246 | public function init() {} 247 | 248 | public function bot_added_to_chat($message) {} 249 | public function bot_kicked_from_chat($message) {} 250 | //public function command_commandname($params, $message) {} 251 | public function some_command($command, $params, $message) {} 252 | public function message($text, $message) {} 253 | 254 | protected function apiSendMessage($text, $params = array()) { 255 | $params += array( 256 | 'chat_id' => $this->chatId, 257 | 'text' => $text, 258 | ); 259 | return $this->core->request('sendMessage', $params); 260 | } 261 | 262 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2015 Canbin Lin (lincanbin@hotmail.com) 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | --------------------------------------------------------------------------------