├── README.md └── CalcuBot.php /README.md: -------------------------------------------------------------------------------- 1 | ### Using: 2 | Console calculator on Telegram via Bot webHooks API, PHP, SSL https://t.me/calcubot 3 | ..or look for @calcubot in telegram 4 | ### Creating another one. Requirements: 5 | Check php version 6 | ```php --version``` 7 | Install curl 8 | ```sudo apt-get install php7.4-curl``` 9 | Add domain in etc/hosts: 10 | ```sudo nano /etc/hosts``` 11 | 127.0.0.1 localhost yourdomain.com 12 | ```sudo apt install php7.4-mbstring``` 13 | ```sudo systemctl restart apache2``` 14 | -------------------------------------------------------------------------------- /CalcuBot.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | $n) 13 | { 14 | return NaN; 15 | } 16 | if (($n - $r) < $r) 17 | { 18 | return ncr($n, ($n - $r)); 19 | } 20 | $return = 1; 21 | for ($i = 0; $i < $r; $i++) 22 | { 23 | $return *= ($n - $i) / ($i +1); 24 | } 25 | return $return; 26 | } 27 | 28 | /* Permutations */ 29 | function npr($n, $r) 30 | { 31 | if ($r > $n) 32 | { 33 | return NaN; 34 | } 35 | if ($r) 36 | { 37 | return $n * (npr($n -1, $r -1)); 38 | } 39 | else 40 | { 41 | return 1; 42 | } 43 | } 44 | 45 | /* number_format */ 46 | function nf( float $number , int $decimals = 0 , string $dec_point = "." , string $thousands_sep = "," ) 47 | { 48 | return number_format($number,$decimals,$dec_point,$thousands_sep); 49 | } 50 | 51 | function SqlQuery($query) 52 | { 53 | $host = "host"; 54 | $user = "user"; 55 | $pwd = "pass"; 56 | $dbase = "dbase"; 57 | $answerLine = ""; 58 | 59 | $link = mysqli_connect($host, $user, $pwd, $dbase); 60 | 61 | /* check connection */ 62 | if (mysqli_connect_errno()) { 63 | $answerLine = $answerLine."Unable to connect DB: %s\n".mysqli_connect_error(); 64 | exit(); 65 | } 66 | 67 | /* run multiquery */ 68 | if (mysqli_multi_query($link, $query)) { 69 | //do { 70 | /* get first result data */ 71 | if ($result = mysqli_store_result($link)) { 72 | while ($row = mysqli_fetch_row($result)) { 73 | $answerLine = $answerLine.implode(' # ',$row)."\n"; 74 | } 75 | mysqli_free_result($result); 76 | } 77 | /* print divider */ 78 | if (mysqli_more_results($link)) { 79 | $answerLine = $answerLine."### "; 80 | } 81 | 82 | //} while (mysqli_next_result($link)); 83 | } 84 | /* close connection */ 85 | mysqli_close($link); 86 | 87 | return $answerLine; 88 | 89 | } 90 | 91 | class curl 92 | { 93 | private $curl_obj; 94 | public function __construct() 95 | { 96 | if(!function_exists('curl_init')) 97 | { 98 | echo 'ERROR: Install CURL module for php'; 99 | exit(); 100 | } 101 | $this->init(); 102 | } 103 | public function init() 104 | { 105 | $this->curl_obj = curl_init(); 106 | } 107 | public function request($url, $method = 'GET', $params = array(), $opts = array()) 108 | { 109 | $method = trim(strtoupper($method)); 110 | // default opts 111 | $opts[CURLOPT_FOLLOWLOCATION] = true; 112 | $opts[CURLOPT_RETURNTRANSFER] = 1; 113 | $opts[CURLOPT_SSL_VERIFYPEER] = true; 114 | $opts[CURLOPT_CAINFO] = "curl-ca-bundle.crt"; 115 | if($method==='GET') 116 | { 117 | $url .= "?".$params; 118 | $params = http_build_query($params); 119 | } 120 | elseif($method==='POST') 121 | { 122 | $opts[CURLOPT_POST] = 1; 123 | $opts[CURLOPT_POSTFIELDS] = $params; 124 | } 125 | $opts[CURLOPT_URL] = $url; 126 | curl_setopt_array($this->curl_obj, $opts); 127 | $content = curl_exec($this->curl_obj); 128 | if ($content===false) echo 'Ошибка curl: ' . curl_error($this->curl_obj); 129 | return $content; 130 | } 131 | public function close() 132 | { 133 | if(gettype($this->curl_obj) === 'resource') 134 | curl_close($this->curl_obj); 135 | } 136 | public function __destruct() 137 | { 138 | $this->close(); 139 | } 140 | } 141 | 142 | function exec_curl_request($handle) { 143 | curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, true); 144 | curl_setopt($handle, CURLOPT_CAINFO, "curl-ca-bundle.crt"); 145 | $response = curl_exec($handle); 146 | if ($response === false) { 147 | $errno = curl_errno($handle); 148 | $error = curl_error($handle); 149 | error_log("Curl returned error $errno: $error\n"); 150 | curl_close($handle); 151 | return false; 152 | } 153 | 154 | $http_code = intval(curl_getinfo($handle, CURLINFO_HTTP_CODE)); 155 | curl_close($handle); 156 | 157 | if ($http_code >= 500) { 158 | // do not wat to DDOS server if something goes wrong 159 | sleep(10); 160 | return false; 161 | } else if ($http_code != 200) { 162 | $response = json_decode($response, true); 163 | error_log("Request has failed with error {$response['error_code']}: {$response['description']}\n"); 164 | if ($http_code == 401) { 165 | throw new Exception('Invalid access token provided'); 166 | } 167 | return false; 168 | } else { 169 | $response = json_decode($response, true); 170 | if (isset($response['description'])) { 171 | error_log("Request was successfull: {$response['description']}\n"); 172 | } 173 | $response = $response['result']; 174 | } 175 | 176 | return $response; 177 | } 178 | 179 | function apiRequestJson($method, $parameters) { 180 | if (!is_string($method)) { 181 | error_log("Method name must be a string\n"); 182 | return false; 183 | } 184 | 185 | if (!$parameters) { 186 | $parameters = array(); 187 | } else if (!is_array($parameters)) { 188 | error_log("Parameters must be an array\n"); 189 | return false; 190 | } 191 | 192 | $parameters["method"] = $method; 193 | $moken=preg_replace('/\s+/', '', SqlQuery('SELECT matrix.mind FROM `matrix` as matrix where matrix.person="calcubot"')); 194 | $apiu="https://api.telegram.org/bot$moken/"; 195 | $handle = curl_init($apiu); 196 | curl_setopt($handle, CURLOPT_RETURNTRANSFER, true); 197 | curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, 5); 198 | curl_setopt($handle, CURLOPT_TIMEOUT, 60); 199 | curl_setopt($handle, CURLOPT_POSTFIELDS, json_encode($parameters)); 200 | curl_setopt($handle, CURLOPT_HTTPHEADER, array("Content-Type: application/json")); 201 | 202 | return exec_curl_request($handle); 203 | } 204 | 205 | function addInlineResult($resultId,$title,$message_text) 206 | { 207 | global $results; 208 | $input_message_content=array("message_text"=>$message_text); 209 | $results[]=array( 210 | "type" => "article", 211 | "id" => $resultId, 212 | "title" => $title, 213 | //"message_text" => $message_text 214 | "input_message_content"=>$input_message_content 215 | ); 216 | return $results; 217 | } 218 | //CALCUBOT 219 | function strExists($value, $string) 220 | { 221 | foreach ((array) $value as $v) { 222 | if (false !== strpos($string, $v)) return true; 223 | } 224 | } 225 | 226 | function checkWords($query) 227 | { 228 | $query=strToLower($query); 229 | //get words list 230 | $wordSymbols='Aabcdefghijklmnopqrstuvwxyz_CP'; 231 | $data=str_split($query); 232 | $j=0; 233 | $badWords=""; 234 | $words[$j]=""; 235 | for ($i=0;$i0) 242 | { 243 | $j++; 244 | $words[$j]=""; 245 | } 246 | } 247 | $goodWords= 248 | [ 249 | 'cl', 250 | 'help', 251 | 'help@CalcuBot', 252 | 'about', 253 | 'example', 254 | 'functions', 255 | 'abs', 256 | 'acos', 257 | 'acosh', 258 | 'asin', 259 | 'asinh', 260 | 'atan2', 261 | 'atan', 262 | 'atanh', 263 | 'base_convert', 264 | 'bindec', 265 | 'ceil', 266 | 'cos', 267 | 'cosh', 268 | 'decbin', 269 | 'dechex', 270 | 'decoct', 271 | 'deg2rad', 272 | 'exp', 273 | 'floor', 274 | 'fmod', 275 | 'getrandmax', 276 | 'hexdec', 277 | 'hypot', 278 | 'is_finite', 279 | 'is_infinite', 280 | 'is_nan', 281 | 'lcg_value', 282 | 'log10', 283 | 'log', 284 | 'max', 285 | 'min', 286 | 'mt_getrandmax', 287 | 'mt_rand', 288 | 'octdec', 289 | 'pi', 290 | 'pow', 291 | 'rad2deg', 292 | 'rand', 293 | 'round', 294 | 'sin', 295 | 'sinh', 296 | 'sqrt', 297 | 'srand', 298 | 'tan', 299 | 'tanh', 300 | 'ncr', 301 | 'npr', 302 | 'number_format', 303 | 'nf' 304 | ]; 305 | $otherSymbols='Aabcdefghijklmnopqrstuvwxyz01234567890!%^:&?*/()[]{}_-+'; 306 | $splittedSymbols=str_split($otherSymbols); 307 | for ($i=0;$i0) //===== contains%% 329 | { 330 | if((substr_count($mycode,"**")%2)==1) return false; 331 | else 332 | { 333 | $isText = true; 334 | $queryParts = explode("**",$mycode); 335 | foreach ($queryParts as $part) 336 | { 337 | if ($isText) $res.=$part; 338 | else 339 | { 340 | $calculation=0; 341 | $wrongWords = checkWords($part); 342 | if (strlen(str_replace(' ', '', $wrongWords))) $calculation.='Wrong words: '.$wrongWords; 343 | elseif (eval('$calculation='.str_replace(' ','',strtolower($part)).';')===false) return false; 344 | $res.=$calculation; 345 | } 346 | $isText=!$isText; 347 | } 348 | } 349 | } 350 | else //===== not contains %% 351 | { 352 | $wrongWords = checkWords($mycode); 353 | if (strlen(str_replace(' ', '', $wrongWords))) return 'Wrong words: '.$wrongWords; 354 | elseif (eval('$res='.$mycode.";")===false) return false; 355 | } 356 | return $res; 357 | } 358 | 359 | function sendMessage($chatID, $messaggio) { 360 | $moken=preg_replace('/\s+/', '', SqlQuery('SELECT matrix.mind FROM `matrix` as matrix where matrix.person="calcubot"')); 361 | $url = "https://api.telegram.org/bot" . $moken . "/sendMessage?chat_id=" . $chatID; 362 | $url = $url . "&text=" . urlencode($messaggio); 363 | $ch = curl_init(); 364 | $optArray = array( 365 | CURLOPT_URL => $url, 366 | CURLOPT_RETURNTRANSFER => true 367 | ); 368 | curl_setopt_array($ch, $optArray); 369 | $result = curl_exec($ch); 370 | curl_close($ch); 371 | return $result; 372 | } 373 | 374 | //START 375 | $content = file_get_contents("php://input"); 376 | $update = json_decode($content, true); 377 | //PERSONAL OR GROUP MESSAGE 378 | $AnswerText = "empty"; 379 | if (isset($update["message"])) 380 | { 381 | $chat = $update["message"]['chat']['id']; 382 | $user = $update["message"]['from']['id']; 383 | $message = $update["message"]['text']; 384 | 385 | if ($message=='/help@calcubot'||$message=='/help'||$message=='/start') 386 | { 387 | $AnswerText = "Hi! im console calculator based on PHP and his eval function"; 388 | sendMessage($chat,$AnswerText); 389 | } 390 | 391 | if ($message=='/example@calcubot'||$message=='/example') 392 | { 393 | $AnswerText = "/cl 2+2###4 = 2+2###/cl abs(-3)###3 = abs(-3)###/cl sin(4)###-0.75680249530793 = sin(4)###/cl atan2(3,4)###0.64350110879328 = atan2(3,4)###/cl base_convert(34,10,2)###100010 = base_convert(34,10,2)###/cl bindec(100101)###37 = bindec(100101)###/cl ceil(2.3)###3 = ceil(2.3)###/cl decbin(48)###110000 = decbin(48)###/cl dechex(250)###fa = dechex(250)###/cl decoct(9)###11 = decoct(9)###/cl deg2rad(3)###0.05235987755983 = deg2rad(3)###/cl exp(3)###20.085536923188 = exp(3)###/cl floor(2.7)###2 = floor(2.7)###/cl fmod(2,7)###2 = fmod(2,7)###/cl hexdec(fa)###250 = hexdec(fa)###/cl hypot(4,7)###8.0622577482985 = hypot(4,7)###/cl is_finite(1/0)###1 = is_finite(1/0)###/cl is_infinite(log(0))###1 = is_infinite(log(0))###/cl is_nan(acos(1.01))###1 = is_nan(acos(1.01))###/cl lcg_value()###0.38509916446214 = lcg_value()###/cl log10(7)###0.84509804001426 = log10(7)###/cl log(7,10)###0.84509804001426 = log(7,10)###/cl max(3,4,8,2,19,7)###19 = max(3,4,8,2,19,7)###/cl min(8,2,-9,17)###-9 = min(8,2,-9,17)###/cl mt_getrandmax()###2147483647 = mt_getrandmax()###/cl mt_rand()###1148623558 = mt_rand()###/cl octdec(11)###9 = octdec(11)###/cl pi()###3.1415926535898 = pi()###/cl pow(3,2)###9 = pow(3,2)###/cl rad2deg(3)###171.88733853925 = rad2deg(3)###/cl rand(50,100)###57 = rand(50,100)###/cl round(3.01234,3)###3.012 = round(3.01234,3)###/cl sin(1)###0.8414709848079 = sin(1)###/cl sqrt(9)###3 = sqrt(9)######And the middle mass of Mercury, Venus and Earth planets is:/cl (3.33022*pow(10,23)+4.8676*pow(10,24)+5.97219*pow(10,24))/3######3.7242706666667E 24 = (3.33022*pow(10,23)+4.8676*pow(10,24)+5.97219*pow(10,24))/3###By the way, maximum lenght of query is 512 symbols!"; 394 | $AnswerText = str_replace('###','%0a',$AnswerText); 395 | $AnswerText = str_replace('/cl','%0a/cl',$AnswerText); 396 | sendMessage($chat,$AnswerText); 397 | } 398 | 399 | if ($message=='/functions@calcubot'||$message=='/functions') 400 | { 401 | $AnswerText = "Supported functions: 402 | abs(number) - Absolute value. Returns the absolute value of number. 403 | acos(arg) - Arc cosine. Returns the arc cosine of arg in radians. 404 | acosh(arg) - Inverse hyperbolic cosine. Returns the inverse hyperbolic cosine of arg, i.e. the value whose hyperbolic cosine is arg. 405 | asin(arg) - Arc sine. Returns the arc sine of arg in radians. 406 | asinh(arg) - Inverse hyperbolic sine. Returns the inverse hyperbolic sine of arg, i.e. the value whose hyperbolic sine is arg. 407 | atan2(y Dividend,x Divisor) - Arc tangent of two variables. calculates the arc tangent of the two variables x and y. It is similar to calculating the arc tangent of y / x, except that the signs of both arguments are used to determine the quadrant of the result. Returns the result in radians, which is between -PI and PI (inclusive). 408 | atan(arg) - Arc tangent. Returns the arc tangent of arg in radians. 409 | atanh(arg) - Inverse hyperbolic tangent. Returns the inverse hyperbolic tangent of arg, i.e. the value whose hyperbolic tangent is arg. 410 | base_convert(number the number to convert,frombase the base number is in,tobase the base to convert number to) - Convert a number between arbitrary bases. Returns a string containing number represented in base tobase. The base in which number is given is specified in frombase. Both frombase and tobase have to be between 2 and 36, inclusive. Digits in numbers with a base higher than 10 will be represented with the letters a-z, with a meaning 10, b meaning 11 and z meaning 35. 411 | bindec(binary_string) - Binary to decimal. Returns the decimal equivalent of the binary number represented by the binary_string argument. 412 | ceil(value) - Round fractions up. Returns the next highest integer value by rounding up value if necessary. 413 | cos(arg) - Cosine. Returns the cosine of the arg parameter. 414 | cosh(arg) - Hyperbolic cosine. Returns the hyperbolic cosine of arg, defined as (exp(arg) + exp(-arg))/2. 415 | decbin(number) - Decimal to binary. Returns a string containing a binary representation of the given number argument. 416 | dechex(number) - Decimal to hexadecimal. Returns a string containing a hexadecimal representation of the given unsigned number argument. 417 | decoct(number) - Decimal to octal. Returns a string containing an octal representation of the given number argument. The largest number that can be converted is 4294967295 in decimal resulting to 37777777777. 418 | deg2rad(number) - Converts the number in degrees to the radian equivalent. converts number from degrees to the radian equivalent. 419 | exp(arg) - Calculates the exponent of e. Returns e raised to the power of arg. 'e' is the base of the natural system of logarithms, or approximately 2.718282. 420 | floor(value) - Round fractions down. Returns the next lowest integer value by rounding down value if necessary. 421 | fmod(x divident, y divisor) - Returns the floating point remainder (modulo) of the division of the arguments. Returns the floating point remainder of dividing the dividend (x) by the divisor (y). The remainder (r) is defined as: x = i * y + r, for some integer i. If y is non-zero, r has the same sign as x and a magnitude less than the magnitude of y."; 422 | //$AnswerText = str_replace('###','%0a%0a',$AnswerText); 423 | sendMessage($chat,$AnswerText); 424 | 425 | $AnswerText = " 426 | getrandmax() - Show largest possible random value. Returns the maximum value that can be returned by a call to rand(). 427 | hexdec(hex_string) - Hexadecimal to decimal. Returns the decimal equivalent of the hexadecimal number represented by the hex_string argument. hexdec() converts a hexadecimal string to a decimal number. 428 | hypot(x length of first side,y length of second side) - Calculate the length of the hypotenuse of a right-angle triangle. Returns the length of the hypotenuse of a right-angle triangle with sides of length x and y, or the distance of the point (x, y) from the origin. This is equivalent to sqrt(x*x + y*y). 429 | is_finite(val) - Finds whether a value is a legal finite number. Checks whether val is a legal finite on this platform. 430 | is_infinite(val) - Finds whether a value is infinite. Returns TRUE if val is infinite (positive or negative), like the result of log(0) or any value too big to fit into a float on this platform. 431 | is_nan(val) - Finds whether a value is not a number. Checks whether val is 'not a number', like the result of acos(1.01). 432 | lcg_value() - Combined linear congruential generator. lcg_value() returns a pseudo random number in the range of (0, 1). The function combines two CGs with periods of 2^31 - 85 and 2^31 - 249. The period of this function is equal to the product of both primes. 433 | log10(arg) - Base-10 logarithm. Returns the base-10 logarithm of arg. 434 | log(arg,base) - Natural logarithm. If the optional base parameter is specified, log() returns log_base arg, otherwise log() returns the natural logarithm of arg. 435 | max(value_1,value_2,value_n,..) - Find highest value 436 | min(value_1,value_2,value_n,..) - Find lowest value 437 | mt_getrandmax() - Show largest possible random value. Returns the maximum value that can be returned by a call to rand(). 438 | mt_rand() - Generate a better random value. Produce random numbers four times faster than what the average libc rand() provides."; 439 | //$AnswerText = str_replace('###','%0a%0a',$AnswerText); 440 | sendMessage($chat,$AnswerText); 441 | 442 | $AnswerText = " 443 | octdec(octal_string) - Octal to decimal. Returns the decimal equivalent of the octal number represented by the octal_string argument. 444 | pi() - Get value of pi. Returns an approximation of pi. 445 | pow(base,exp) - Exponential expression. Returns base raised to the power of exp. 446 | rad2deg(number) - Converts the radian number to the equivalent number in degrees. 447 | rand(min,max) - Generate a random integer. If called without the optional min, max arguments rand() returns a pseudo-random integer between 0 and getrandmax(). If you want a random number between 5 and 15 (inclusive), for example, use rand(5, 15). 448 | round(val the value to round,precision the optional number of decimal digits to round to) - Rounds a float. Returns the rounded value of val to specified precision (number of digits after the decimal point). precision can also be negative or zero (default). 449 | sin(arg) - Sine. returns the sine of the arg parameter. The arg parameter is in radians. 450 | sinh(arg) - Hyperbolic sine. Returns the hyperbolic sine of arg, defined as (exp(arg) - exp(-arg))/2. 451 | sqrt(arg) - Square root. Returns the square root of arg. 452 | srand(seed) - Seed the random number generator. Seeds the random number generator with seed or with a random value if no seed is given. 453 | tan(arg) - Tangent. Returns the tangent of the arg parameter. The arg parameter is in radians. 454 | tanh(arg) - Hyperbolic tangent. Returns the hyperbolic tangent of arg, defined as sinh(arg)/cosh(arg). 455 | ncr(n,r) - Combinations. 456 | npr(n,r) - Permutations. 457 | number_format(number,decimals,dec_point,thousands_sep) - Number format. For example: number_format(123456.789,2) 458 | nf(number) - short version of number_format"; 459 | //$AnswerText = str_replace('###','%0a%0a',$AnswerText); 460 | sendMessage($chat,$AnswerText); 461 | } 462 | 463 | if ($message=='/about@calcubot'||$message=='/about') 464 | { 465 | $AnswerText = "v 3.2 Developer Alexey Yurasov%0aformat37@gmail.com%0a@AlexMoscow"; 466 | sendMessage($chat,$AnswerText); 467 | } 468 | $crop=0; 469 | if (substr($message,0,3)=='/cl') $crop=3; 470 | if (substr($message,0,12)=='/cl@calcubot') $crop=12; 471 | $source = substr($message,$crop); 472 | //if (!strExists("round(", $source)&&!strExists("ncr(", $source)&&!strExists("npr(", $source)&&!strExists("rand(", $source)&&!strExists("max(", $source)&&!strExists("min(", $source)&&!strExists("hypot(", $source)&&!strExists("fmod(", $source)&&!strExists("base_convert(", $source)&&!strExists("atan2(", $source)&&!strExists("pow(", $source)&&!strExists("log(", $source)) $source = str_replace(',','.',$source); 473 | if ($crop||($chat==$user&&substr($message,0,1)!='/')) 474 | { 475 | $result = myeval($source); 476 | if ($result===false) $result='[wrong request "'.$source.'"]'; 477 | elseif (substr_count($source,"**")==0) $result = "$result = $source"; 478 | sendMessage($chat,$result); 479 | } 480 | } 481 | //QUERY FROM USER 482 | if (isset($update["inline_query"])) { 483 | $inlineQuery = $update["inline_query"]; 484 | $queryId = $inlineQuery["id"]; 485 | $source = $inlineQuery["query"]; 486 | $results = array(); 487 | $badRequest = FALSE; 488 | $result = 0; 489 | 490 | if (mb_strlen($source)>512) addInlineResult("11","query should be shortly than 512 symbols", "wrong query"); 491 | else 492 | { 493 | $result = myeval($source); 494 | if ($result===false) addInlineResult("10","waiting for complete query","wrong query"); 495 | else 496 | { 497 | 498 | 499 | $resultString = strval($result); 500 | addInlineResult("1",$resultString,$resultString); 501 | if (substr_count($source,"**")==0) 502 | { 503 | addInlineResult("2",$resultString.' = '.$source,$resultString.' = '.$source); 504 | addInlineResult("3",$source.' = '.$resultString,$source.' = '.$resultString); 505 | } 506 | } 507 | } 508 | apiRequestJson 509 | ( 510 | "answerInlineQuery", array( 511 | "inline_query_id" => $queryId, 512 | "results" => $results, 513 | "cache_time" => 1, 514 | ) 515 | ); 516 | } 517 | ?> 518 | 519 | --------------------------------------------------------------------------------