├── README.md ├── bot_platform.sql └── telegram.sql /README.md: -------------------------------------------------------------------------------- 1 | # apex_telegramm 2 | Oracle Apex telegram bot integration 3 | -------------------------------------------------------------------------------- /bot_platform.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE "BOT_ERR_JOURN" 2 | ( "CRT" DATE, 3 | "METOD" VARCHAR2(50), 4 | "ERR_MSG" CLOB 5 | ) 6 | / 7 | CREATE TABLE "BOT_JOURN" 8 | ( "CRT" DATE, 9 | "CHAT_ID" NUMBER, 10 | "METOD" VARCHAR2(20), 11 | "BODY" CLOB, 12 | "RESULT" CLOB, 13 | "TOKEN" VARCHAR2(200) 14 | ) 15 | / 16 | CREATE TABLE "BOT_USERS" 17 | ( "CHAT_ID" NUMBER NOT NULL ENABLE, 18 | "FIRST_NAME" VARCHAR2(100), 19 | "LAST_NAME" VARCHAR2(100), 20 | "PHONE" VARCHAR2(50), 21 | "CRT" DATE, 22 | "LOGIN" VARCHAR2(50), 23 | "MDF" DATE, 24 | "PIN" NUMBER, 25 | CONSTRAINT "BOT_USERS_PK" PRIMARY KEY ("CHAT_ID") ENABLE 26 | ) 27 | / 28 | CREATE TABLE "BOT_SESSIONS" 29 | ( "CHAT_ID" NUMBER NOT NULL ENABLE, 30 | "TEXT" CLOB, 31 | "MDF" DATE, 32 | "ST" NUMBER(1,0), 33 | "MENU" VARCHAR2(20), 34 | CONSTRAINT "BOT_SESSIONS_PK" PRIMARY KEY ("CHAT_ID") ENABLE 35 | ) 36 | / 37 | CREATE GLOBAL TEMPORARY TABLE "REPLY_MARKUP_INLINE_KEYBOARD" 38 | ( "TEXT" VARCHAR2(255) NOT NULL ENABLE, 39 | "CALLBACK_DATA" VARCHAR2(255) NOT NULL ENABLE, 40 | CONSTRAINT "REPLY_INLINE_UK1" UNIQUE ("CALLBACK_DATA") ENABLE 41 | ) ON COMMIT DELETE ROWS 42 | / 43 | CREATE GLOBAL TEMPORARY TABLE "REPLY_MARKUP_KEYBOARD" 44 | ( "TEXT" VARCHAR2(255) NOT NULL ENABLE, 45 | "REQUEST_CONTACT" NUMBER(1,0) DEFAULT 0, 46 | "REQUEST_LOCATION" NUMBER(1,0), 47 | CONSTRAINT "REPLY_MARKUP_KEYBOARD_PK" PRIMARY KEY ("TEXT") ENABLE 48 | ) ON COMMIT DELETE ROWS 49 | / 50 | ALTER TABLE "BOT_SESSIONS" ADD CONSTRAINT "BOT_SESSIONS_FK1" FOREIGN KEY ("CHAT_ID") 51 | REFERENCES "BOT_USERS" ("CHAT_ID") ON DELETE CASCADE ENABLE 52 | / 53 | CREATE UNIQUE INDEX "BOT_SESSIONS_PK" ON "BOT_SESSIONS" ("CHAT_ID") 54 | / 55 | CREATE UNIQUE INDEX "BOT_USERS_PK" ON "BOT_USERS" ("CHAT_ID") 56 | / 57 | CREATE UNIQUE INDEX "REPLY_INLINE_UK1" ON "REPLY_MARKUP_INLINE_KEYBOARD" ("CALLBACK_DATA") 58 | / 59 | CREATE UNIQUE INDEX "REPLY_MARKUP_KEYBOARD_PK" ON "REPLY_MARKUP_KEYBOARD" ("TEXT") 60 | / 61 | CREATE OR REPLACE PACKAGE "TELEGRAM" AS 62 | v_err_msg CLOB; 63 | p_url CLOB := 'https://api.telegram.org/bot'; 64 | p_token VARCHAR(200) := ''; 65 | p_debug INT := 1; 66 | 67 | -- параметры входящего сообщения -- 68 | in_chat_id INT; 69 | in_message_id INT; 70 | in_text VARCHAR2(32000); 71 | in_phone_number VARCHAR2(100); 72 | in_first_name VARCHAR2(100); 73 | in_last_name VARCHAR2(100); 74 | -- callback -- 75 | in_data VARCHAR2(1024); 76 | -- параметры сессиии -- 77 | session_st INT; -- текущее значение шага -- 78 | session_menu VARCHAR2(100); -- текущее значение меню -- 79 | 80 | ------------------------ 81 | FUNCTION blob2clob ( 82 | p_blob IN BLOB, 83 | p_blob_csid IN INTEGER DEFAULT dbms_lob.default_csid 84 | ) RETURN CLOB; 85 | 86 | -- отправка сообщения -- 87 | 88 | PROCEDURE sendmessage ( 89 | p_chat_id INT DEFAULT in_chat_id, 90 | p_text IN CLOB, 91 | p_parse_mode IN VARCHAR DEFAULT 'HTML', 92 | p_resize_keyboard IN BOOLEAN DEFAULT true, 93 | p_one_time_keyboard IN BOOLEAN DEFAULT true, 94 | p_buttons_colum IN INT DEFAULT 2 95 | ); 96 | -- редактировать сообщение -- 97 | 98 | PROCEDURE editmessage ( 99 | p_chat_id INT DEFAULT in_chat_id, 100 | p_message_id INT DEFAULT in_message_id, 101 | p_text IN CLOB, 102 | p_parse_mode IN VARCHAR DEFAULT 'HTML', 103 | p_resize_keyboard IN BOOLEAN DEFAULT true, 104 | p_one_time_keyboard IN BOOLEAN DEFAULT true, 105 | p_buttons_colum IN INT DEFAULT 2 106 | ); 107 | 108 | 109 | -- настройка webhook для входящих сообщений -- 110 | 111 | PROCEDURE setwebhook ( 112 | p_webhook_url IN VARCHAR 113 | ); 114 | 115 | -- разбор входящего сообщения -- 116 | 117 | PROCEDURE in_parse ( 118 | p_body CLOB 119 | ); 120 | 121 | -- проверка и регистрация пользователя -- 122 | 123 | PROCEDURE check_user ( 124 | v_ex OUT NUMBER 125 | ); 126 | 127 | -- сброс счетчика шагов -- 128 | 129 | PROCEDURE reset_st ( 130 | p_chat_id IN INT DEFAULT in_chat_id 131 | ); 132 | -- запись сесии -- 133 | 134 | PROCEDURE save_session ( 135 | v_menu IN VARCHAR2 DEFAULT NULL, 136 | v_st IN INT DEFAULT 0 137 | ); 138 | -- получение сесии -- 139 | 140 | PROCEDURE get_session; 141 | 142 | -- авторизация пользователя через телеграм -- 143 | 144 | PROCEDURE auth_pin ( 145 | v_username IN VARCHAR2 146 | ); 147 | -- сообщение о входе в приложение -- 148 | 149 | PROCEDURE auth_reg ( 150 | v_username IN VARCHAR2, 151 | v_app_name IN VARCHAR2 152 | ); 153 | 154 | END telegram; 155 | / 156 | CREATE OR REPLACE PACKAGE BODY "TELEGRAM" AS 157 | 158 | PROCEDURE add_journ ( 159 | v_body IN CLOB DEFAULT NULL, 160 | v_result IN CLOB DEFAULT NULL, 161 | v_chat_id IN NUMBER DEFAULT NULL, 162 | v_metod IN VARCHAR2 DEFAULT NULL 163 | ) 164 | AS 165 | BEGIN 166 | INSERT INTO bot_journ ( 167 | crt, 168 | chat_id, 169 | metod, 170 | body, 171 | result, 172 | token 173 | ) VALUES ( 174 | SYSDATE, 175 | v_chat_id, 176 | v_metod, 177 | v_body, 178 | v_result, 179 | telegram.p_token 180 | ); 181 | 182 | END add_journ; 183 | -- подготовка номера телефона -- 184 | 185 | FUNCTION clr_phone ( 186 | v_phone IN VARCHAR2 187 | ) RETURN VARCHAR2 AS 188 | v_res VARCHAR2(30); 189 | BEGIN 190 | IF 191 | v_phone IS NULL 192 | THEN 193 | RETURN NULL; 194 | END IF; 195 | v_res := replace(v_phone,'(',''); 196 | v_res := replace(v_res,')',''); 197 | v_res := replace(v_res,' ',''); 198 | v_res := replace(v_res,'-',''); 199 | v_res := substr(v_res,length(v_res) - 9); 200 | RETURN '+38' 201 | || v_res; 202 | END clr_phone; 203 | ---------------------- 204 | 205 | FUNCTION blob2clob ( 206 | p_blob IN BLOB, 207 | p_blob_csid IN INTEGER DEFAULT dbms_lob.default_csid 208 | ) RETURN CLOB AS 209 | 210 | l_clob CLOB; 211 | l_dest_offset INTEGER := 1; 212 | l_src_offset INTEGER := 1; 213 | l_lang_context INTEGER := dbms_lob.default_lang_ctx; 214 | l_warning INTEGER; 215 | BEGIN 216 | IF 217 | p_blob IS NULL 218 | THEN 219 | RETURN NULL; 220 | END IF; 221 | dbms_lob.createtemporary(lob_loc => l_clob,cache => false); 222 | dbms_lob.converttoclob(dest_lob => l_clob,src_blob => p_blob,amount => dbms_lob.lobmaxsize,dest_offset => l_dest_offset,src_offset => l_src_offset 223 | ,blob_csid => p_blob_csid,lang_context => l_lang_context,warning => l_warning); 224 | 225 | RETURN l_clob; 226 | END blob2clob; 227 | 228 | -- подготовка тела сообщения -- 229 | 230 | FUNCTION message_body ( 231 | p_chat_id INT DEFAULT in_chat_id, 232 | p_message_id INT DEFAULT in_message_id, 233 | p_text IN CLOB, 234 | p_parse_mode IN VARCHAR DEFAULT 'HTML', 235 | p_resize_keyboard IN BOOLEAN DEFAULT true, 236 | p_one_time_keyboard IN BOOLEAN DEFAULT true, 237 | p_buttons_colum IN INT DEFAULT 2 238 | ) RETURN CLOB AS 239 | 240 | v_body CLOB; 241 | v_ex1 INT; 242 | v_ex2 INT; 243 | CURSOR cur1 IS SELECT 244 | * 245 | FROM 246 | reply_markup_keyboard; 247 | 248 | CURSOR cur2 IS SELECT 249 | * 250 | FROM 251 | reply_markup_inline_keyboard; 252 | 253 | v_i INT; 254 | BEGIN 255 | SELECT 256 | COUNT(*) 257 | INTO 258 | v_ex1 259 | FROM 260 | reply_markup_keyboard; 261 | -- inline keyboard -- 262 | 263 | SELECT 264 | COUNT(*) 265 | INTO 266 | v_ex2 267 | FROM 268 | reply_markup_inline_keyboard; 269 | 270 | -- отправляем запрос -- 271 | 272 | apex_json.initialize_clob_output; 273 | apex_json.open_object; 274 | apex_json.write('chat_id',p_chat_id); 275 | apex_json.write('message_id',p_message_id); 276 | apex_json.write('text',p_text); 277 | apex_json.write('parse_mode',p_parse_mode); 278 | IF 279 | v_ex1 != 0 OR v_ex2 != 0 280 | THEN 281 | v_i := 0; 282 | apex_json.open_object('reply_markup'); 283 | apex_json.write('one_time_keyboard',p_one_time_keyboard); 284 | apex_json.write('resize_keyboard',p_resize_keyboard); 285 | END IF; 286 | 287 | IF 288 | v_ex1 != 0 289 | THEN 290 | apex_json.open_array('keyboard'); 291 | apex_json.open_array (); 292 | FOR c1 IN cur1 LOOP 293 | v_i := v_i + 1; 294 | apex_json.open_object; 295 | apex_json.write('text',c1.text); 296 | apex_json.write('request_contact',1 = c1.request_contact); 297 | apex_json.close_object; 298 | IF 299 | v_i = p_buttons_colum 300 | THEN 301 | apex_json.close_array; 302 | apex_json.open_array; 303 | v_i := 0; 304 | END IF; 305 | 306 | END LOOP; 307 | 308 | apex_json.close_array; 309 | apex_json.close_array; 310 | END IF; 311 | 312 | IF 313 | v_ex2 != 0 314 | THEN 315 | v_i := 0; 316 | apex_json.open_array('inline_keyboard'); 317 | apex_json.open_array (); 318 | FOR c2 IN cur2 LOOP 319 | v_i := v_i + 1; 320 | apex_json.open_object; 321 | apex_json.write('text',c2.text); 322 | apex_json.write('callback_data',c2.callback_data); 323 | apex_json.close_object; 324 | IF 325 | v_i = p_buttons_colum 326 | THEN 327 | apex_json.close_array; 328 | apex_json.open_array; 329 | v_i := 0; 330 | END IF; 331 | 332 | END LOOP; 333 | 334 | apex_json.close_array; 335 | apex_json.close_array; 336 | END IF; 337 | 338 | IF 339 | v_ex1 != 0 OR v_ex2 != 0 340 | THEN 341 | apex_json.close_object; 342 | END IF; 343 | apex_json.close_object; 344 | v_body := apex_json.get_clob_output; 345 | RETURN v_body; 346 | EXCEPTION 347 | WHEN OTHERS THEN 348 | v_err_msg := sqlerrm; 349 | INSERT INTO bot_err_journ ( 350 | crt, 351 | metod, 352 | err_msg 353 | ) VALUES ( 354 | SYSDATE, 355 | 'message_body', 356 | v_err_msg 357 | ); 358 | 359 | END message_body; 360 | 361 | --отправка сообщения -- 362 | 363 | PROCEDURE sendmessage ( 364 | p_chat_id INT DEFAULT in_chat_id, 365 | p_text IN CLOB, 366 | p_parse_mode IN VARCHAR DEFAULT 'HTML', 367 | p_resize_keyboard IN BOOLEAN DEFAULT true, 368 | p_one_time_keyboard IN BOOLEAN DEFAULT true, 369 | p_buttons_colum IN INT DEFAULT 2 370 | ) AS 371 | v_body CLOB; 372 | v_result CLOB; 373 | BEGIN 374 | v_body := message_body(p_chat_id,NULL,p_text,p_parse_mode,p_resize_keyboard,p_one_time_keyboard,p_buttons_colum); 375 | 376 | apex_web_service.g_request_headers(1).name := 'Content-Type'; 377 | apex_web_service.g_request_headers(1).value := 'application/json'; 378 | v_result := apex_web_service.make_rest_request(p_url => p_url 379 | || p_token 380 | || '/sendMessage',p_http_method => 'POST',p_body => v_body); 381 | 382 | apex_json.free_output; 383 | IF 384 | p_debug = 1 385 | THEN 386 | add_journ(v_body => v_body,v_result => v_result,v_chat_id => p_chat_id,v_metod => 'sendMessage'); 387 | END IF; 388 | 389 | EXCEPTION 390 | WHEN OTHERS THEN 391 | v_err_msg := sqlerrm; 392 | INSERT INTO bot_err_journ ( 393 | crt, 394 | metod, 395 | err_msg 396 | ) VALUES ( 397 | SYSDATE, 398 | 'sendmessage', 399 | v_err_msg 400 | ); 401 | 402 | END sendmessage; 403 | 404 | -- редактировать сообщение -- 405 | 406 | PROCEDURE editmessage ( 407 | p_chat_id INT DEFAULT in_chat_id, 408 | p_message_id INT DEFAULT in_message_id, 409 | p_text IN CLOB, 410 | p_parse_mode IN VARCHAR DEFAULT 'HTML', 411 | p_resize_keyboard IN BOOLEAN DEFAULT true, 412 | p_one_time_keyboard IN BOOLEAN DEFAULT true, 413 | p_buttons_colum IN INT DEFAULT 2 414 | ) AS 415 | v_result CLOB; 416 | v_body CLOB; 417 | BEGIN 418 | v_body := message_body(p_chat_id,p_message_id,p_text,p_parse_mode,p_resize_keyboard,p_one_time_keyboard,p_buttons_colum); 419 | 420 | apex_web_service.g_request_headers(1).name := 'Content-Type'; 421 | apex_web_service.g_request_headers(1).value := 'application/json'; 422 | v_result := apex_web_service.make_rest_request(p_url => p_url 423 | || p_token 424 | || '/editMessageText',p_http_method => 'POST',p_body => v_body); 425 | 426 | apex_json.free_output; 427 | IF 428 | p_debug = 1 429 | THEN 430 | add_journ(v_body => v_body,v_result => v_result,v_chat_id => p_chat_id,v_metod => 'editMessage'); 431 | END IF; 432 | 433 | EXCEPTION 434 | WHEN OTHERS THEN 435 | v_err_msg := sqlerrm; 436 | INSERT INTO bot_err_journ ( 437 | crt, 438 | metod, 439 | err_msg 440 | ) VALUES ( 441 | SYSDATE, 442 | 'editmessage', 443 | v_err_msg 444 | ); 445 | 446 | END editmessage; 447 | 448 | -- настройка webhook для входящих сообщений -- 449 | 450 | PROCEDURE setwebhook ( 451 | p_webhook_url IN VARCHAR 452 | ) AS 453 | v_result CLOB; 454 | v_body CLOB; 455 | BEGIN 456 | -- отправляем запрос -- 457 | apex_json.initialize_clob_output; 458 | -- json -- 459 | apex_json.open_object; 460 | apex_json.write('url',p_webhook_url 461 | || '/' 462 | || p_token); 463 | apex_json.close_object; 464 | v_body := apex_json.get_clob_output; 465 | apex_web_service.g_request_headers(1).name := 'Content-Type'; 466 | apex_web_service.g_request_headers(1).value := 'application/json'; 467 | v_result := apex_web_service.make_rest_request(p_url => p_url 468 | || p_token 469 | || '/setWebhook',p_http_method => 'POST',p_body => v_body); 470 | 471 | apex_json.free_output; 472 | IF 473 | p_debug = 1 474 | THEN 475 | add_journ(v_body => v_body,v_result => v_result,v_metod => 'setWebhook'); 476 | END IF; 477 | 478 | EXCEPTION 479 | WHEN OTHERS THEN 480 | v_err_msg := sqlerrm; 481 | INSERT INTO bot_err_journ ( 482 | crt, 483 | metod, 484 | err_msg 485 | ) VALUES ( 486 | SYSDATE, 487 | 'setwebhook', 488 | v_err_msg 489 | ); 490 | 491 | END setwebhook; 492 | 493 | -- разбор входящего сообщения -- 494 | 495 | PROCEDURE in_parse ( 496 | p_body CLOB 497 | ) 498 | AS 499 | BEGIN 500 | IF 501 | p_debug = 1 502 | THEN 503 | add_journ(v_body => p_body,v_metod => 'in_parse'); 504 | END IF; 505 | 506 | apex_json.parse(p_body); 507 | -- проверим callback -- 508 | in_data := apex_json.get_varchar2('callback_query.data'); 509 | IF 510 | in_data IS NOT NULL 511 | THEN 512 | in_chat_id := apex_json.get_number(p_path => 'callback_query.message.chat.id'); 513 | in_message_id := apex_json.get_number(p_path => 'callback_query.message.message_id'); 514 | in_text := apex_json.get_varchar2('callback_query.message.text'); 515 | ELSE 516 | in_chat_id := apex_json.get_number(p_path => 'message.chat.id'); 517 | in_message_id := apex_json.get_number(p_path => 'message.message_id'); 518 | in_text := apex_json.get_varchar2('message.text'); 519 | END IF; 520 | -- contact -- 521 | 522 | in_phone_number := clr_phone(apex_json.get_varchar2('message.contact.phone_number') ); 523 | in_first_name := apex_json.get_varchar2('message.contact.first_name'); 524 | in_last_name := apex_json.get_varchar2('message.contact.last_name'); 525 | --- 526 | bot_in_point; 527 | EXCEPTION 528 | WHEN OTHERS THEN 529 | v_err_msg := sqlerrm; 530 | INSERT INTO bot_err_journ ( 531 | crt, 532 | metod, 533 | err_msg 534 | ) VALUES ( 535 | SYSDATE, 536 | 'in_parse', 537 | v_err_msg 538 | ); 539 | 540 | END in_parse; 541 | 542 | -- проверка и регистрация пользователя -- 543 | 544 | PROCEDURE check_user ( 545 | v_ex OUT NUMBER 546 | ) 547 | AS 548 | BEGIN 549 | 550 | -- проверка регистрации пользователя -- 551 | SELECT 552 | COUNT(*) 553 | INTO 554 | v_ex 555 | FROM 556 | bot_users 557 | WHERE 558 | chat_id = in_chat_id; 559 | 560 | IF 561 | v_ex = 0 AND in_phone_number IS NULL 562 | THEN 563 | -- пользователь не зарегистрирован, запрос на регистрацию - 564 | INSERT INTO reply_markup_keyboard ( 565 | text, 566 | request_contact 567 | ) VALUES ( 568 | 'Зареєструватись', 569 | 1 570 | ); 571 | 572 | sendmessage(p_text => 'Натисніть кнопку "Зареєструватись" для відправки свого номеру телефону модератору.',p_one_time_keyboard => false 573 | ); 574 | ELSIF v_ex = 0 AND in_phone_number IS NOT NULL THEN 575 | -- добавим пользователя -- 576 | INSERT INTO bot_users ( 577 | chat_id, 578 | first_name, 579 | last_name, 580 | phone, 581 | crt 582 | ) VALUES ( 583 | in_chat_id, 584 | in_first_name, 585 | in_last_name, 586 | in_phone_number, 587 | SYSDATE 588 | ); 589 | 590 | bot_main_menu; 591 | v_ex := 1; 592 | END IF; 593 | 594 | EXCEPTION 595 | WHEN OTHERS THEN 596 | v_err_msg := sqlerrm; 597 | INSERT INTO bot_err_journ ( 598 | crt, 599 | metod, 600 | err_msg 601 | ) VALUES ( 602 | SYSDATE, 603 | 'check_user', 604 | v_err_msg 605 | ); 606 | 607 | END check_user; 608 | 609 | -- сброс счетчика сессий -- 610 | 611 | PROCEDURE reset_st ( 612 | p_chat_id IN INT DEFAULT in_chat_id 613 | ) 614 | AS 615 | BEGIN 616 | UPDATE bot_sessions 617 | SET 618 | st = 0, 619 | menu = NULL, 620 | text = NULL 621 | WHERE 622 | chat_id = p_chat_id; 623 | 624 | session_st := 0; 625 | session_menu := NULL; 626 | END reset_st; 627 | 628 | -- запись сесии -- 629 | 630 | PROCEDURE save_session ( 631 | v_menu IN VARCHAR2 DEFAULT NULL, 632 | v_st IN INT DEFAULT 0 633 | ) AS 634 | v_ex INT; 635 | r_ bot_sessions%rowtype; 636 | BEGIN 637 | r_.chat_id := in_chat_id; 638 | SELECT 639 | COUNT(*) 640 | INTO 641 | v_ex 642 | FROM 643 | bot_sessions 644 | WHERE 645 | chat_id = r_.chat_id; 646 | 647 | ---------------------------------------- 648 | -- запишем значения сесии -------------- 649 | 650 | r_.mdf := SYSDATE; 651 | r_.text := in_text; 652 | r_.menu := v_menu; 653 | r_.st := v_st; 654 | IF 655 | v_ex = 0 656 | THEN 657 | INSERT INTO bot_sessions VALUES r_; 658 | 659 | ELSE 660 | UPDATE bot_sessions 661 | SET 662 | row = r_ 663 | WHERE 664 | chat_id = r_.chat_id; 665 | 666 | END IF; 667 | 668 | session_st := v_st; 669 | session_menu := v_menu; 670 | EXCEPTION 671 | WHEN OTHERS THEN 672 | v_err_msg := sqlerrm; 673 | INSERT INTO bot_err_journ ( 674 | crt, 675 | metod, 676 | err_msg 677 | ) VALUES ( 678 | SYSDATE, 679 | 'save_session', 680 | v_err_msg 681 | ); 682 | 683 | END save_session; 684 | 685 | -- получение сесии -- 686 | 687 | PROCEDURE get_session AS 688 | r_ bot_sessions%rowtype; 689 | BEGIN 690 | SELECT 691 | * 692 | INTO 693 | r_ 694 | FROM 695 | bot_sessions 696 | WHERE 697 | chat_id = in_chat_id; 698 | 699 | session_st := r_.st; 700 | session_menu := r_.menu; 701 | EXCEPTION 702 | WHEN OTHERS THEN 703 | v_err_msg := sqlerrm; 704 | INSERT INTO bot_err_journ ( 705 | crt, 706 | metod, 707 | err_msg 708 | ) VALUES ( 709 | SYSDATE, 710 | 'get_session', 711 | v_err_msg 712 | ); 713 | 714 | END get_session; 715 | 716 | -- авторизация пользователя через телеграм -- 717 | 718 | PROCEDURE auth_pin ( 719 | v_username IN VARCHAR2 720 | ) AS 721 | v_pin VARCHAR2(10); 722 | r_ bot_users%rowtype; 723 | BEGIN 724 | v_pin := round(dbms_random.value(1000,9999),0); 725 | SELECT 726 | * 727 | INTO 728 | r_ 729 | FROM 730 | bot_users 731 | WHERE 732 | upper(login) = upper(v_username); 733 | 734 | UPDATE bot_users 735 | SET 736 | pin = v_pin, 737 | mdf = SYSDATE 738 | WHERE 739 | upper(login) = upper(v_username); 740 | 741 | sendmessage(p_chat_id => r_.chat_id,p_text => v_pin); 742 | EXCEPTION 743 | WHEN OTHERS THEN 744 | v_err_msg := sqlerrm; 745 | INSERT INTO bot_err_journ ( 746 | crt, 747 | metod, 748 | err_msg 749 | ) VALUES ( 750 | SYSDATE, 751 | 'auth_pin', 752 | v_username 753 | || ': ' 754 | || v_err_msg 755 | ); 756 | 757 | END auth_pin; 758 | 759 | -- сообщение о входе в приложение -- 760 | 761 | PROCEDURE auth_reg ( 762 | v_username IN VARCHAR2, 763 | v_app_name IN VARCHAR2 764 | ) AS 765 | r_ bot_users%rowtype; 766 | BEGIN 767 | SELECT 768 | * 769 | INTO 770 | r_ 771 | FROM 772 | bot_users 773 | WHERE 774 | upper(login) = upper(v_username); 775 | 776 | UPDATE bot_users 777 | SET 778 | pin = NULL, 779 | mdf = SYSDATE 780 | WHERE 781 | upper(login) = upper(v_username); 782 | 783 | sendmessage(p_chat_id => r_.chat_id,p_text => 'Вход в приложение ' 784 | || v_app_name 785 | || ' в ' 786 | || TO_CHAR(SYSDATE,'dd.mm.yyyy hh24:mi:ss') ); 787 | 788 | EXCEPTION 789 | WHEN OTHERS THEN 790 | v_err_msg := sqlerrm; 791 | INSERT INTO bot_err_journ ( 792 | crt, 793 | metod, 794 | err_msg 795 | ) VALUES ( 796 | SYSDATE, 797 | 'auth_reg', 798 | v_err_msg 799 | ); 800 | 801 | END auth_reg; 802 | 803 | END telegram; 804 | / 805 | 806 | CREATE OR REPLACE PROCEDURE "BOT_MAIN_MENU" 807 | AS 808 | BEGIN 809 | telegram.sendmessage(p_text => ' Вас вітає бот '); 810 | 811 | DELETE FROM reply_markup_keyboard; 812 | INSERT INTO reply_markup_keyboard ( text ) VALUES ( 'Меню' ); 813 | telegram.sendmessage(p_text => 'Головне меню',p_one_time_keyboard => false); 814 | END bot_main_menu; 815 | / 816 | 817 | CREATE OR REPLACE PROCEDURE "BOT_IN_POINT" AS 818 | v_ex INT; 819 | v_err_msg CLOB; 820 | BEGIN 821 | -- проверка и регистрация пользователя -- 822 | telegram.check_user(v_ex); 823 | IF 824 | v_ex = 0 825 | THEN 826 | return; 827 | END IF; 828 | 829 | -- прочитаем значения сесии -- 830 | telegram.get_session; 831 | CASE 832 | WHEN telegram.in_text = 'Меню' THEN 833 | telegram.reset_st; 834 | bot_main_menu; 835 | ELSE 836 | telegram.reset_st; 837 | bot_main_menu; 838 | END CASE; 839 | 840 | EXCEPTION 841 | WHEN OTHERS THEN 842 | v_err_msg := sqlerrm; 843 | INSERT INTO bot_err_journ ( 844 | crt, 845 | metod, 846 | err_msg 847 | ) VALUES ( 848 | SYSDATE, 849 | 'in_point', 850 | v_err_msg 851 | ); 852 | 853 | END bot_in_point; 854 | / 855 | 856 | 857 | -------------------------------------------------------------------------------- /telegram.sql: -------------------------------------------------------------------------------- 1 | set define off verify off feedback off 2 | whenever sqlerror exit sql.sqlcode rollback 3 | -------------------------------------------------------------------------------- 4 | -- 5 | -- ORACLE Application Express (APEX) export file 6 | -- 7 | -- You should run the script connected to SQL*Plus as the Oracle user 8 | -- APEX_050100 or as the owner (parsing schema) of the application. 9 | -- 10 | -- NOTE: Calls to apex_application_install override the defaults below. 11 | -- 12 | -------------------------------------------------------------------------------- 13 | begin 14 | wwv_flow_api.import_begin ( 15 | p_version_yyyy_mm_dd=>'2016.08.24' 16 | ,p_default_workspace_id=>2262647084844870 17 | ); 18 | end; 19 | / 20 | begin 21 | wwv_flow_api.remove_restful_service( 22 | p_id=>wwv_flow_api.id(2267957667151445) 23 | ,p_name=>'telegram' 24 | ); 25 | 26 | end; 27 | / 28 | prompt --application/restful_services/telegram 29 | begin 30 | wwv_flow_api.create_restful_module( 31 | p_id=>wwv_flow_api.id(2267957667151445) 32 | ,p_name=>'telegram' 33 | ,p_uri_prefix=>'telegram/' 34 | ,p_parsing_schema=>'BOT_PLATFORM' 35 | ,p_items_per_page=>25 36 | ,p_status=>'PUBLISHED' 37 | ,p_row_version_number=>13 38 | ); 39 | wwv_flow_api.create_restful_template( 40 | p_id=>wwv_flow_api.id(2268097510151446) 41 | ,p_module_id=>wwv_flow_api.id(2267957667151445) 42 | ,p_uri_template=>'ping' 43 | ,p_priority=>0 44 | ,p_etag_type=>'HASH' 45 | ); 46 | wwv_flow_api.create_restful_handler( 47 | p_id=>wwv_flow_api.id(2268150030151446) 48 | ,p_template_id=>wwv_flow_api.id(2268097510151446) 49 | ,p_source_type=>'PLSQL' 50 | ,p_format=>'DEFAULT' 51 | ,p_method=>'GET' 52 | ,p_require_https=>'YES' 53 | ,p_source=>wwv_flow_string.join(wwv_flow_t_varchar2( 54 | 'DECLARE BEGIN', 55 | ' apex_json.open_object; -- {', 56 | ' apex_json.write(''status'',true);', 57 | ' apex_json.close_object; -- } ', 58 | ' :status := 200;', 59 | 'EXCEPTION', 60 | ' WHEN OTHERS THEN', 61 | ' :status := 500;', 62 | ' apex_json.open_object; -- {', 63 | ' apex_json.write(''status'',false);', 64 | ' apex_json.write(''msg'',substr(sqlerrm,1,4000) );', 65 | ' apex_json.close_object; -- } ', 66 | 'END;')) 67 | ); 68 | wwv_flow_api.create_restful_param( 69 | p_id=>wwv_flow_api.id(2268201141156300) 70 | ,p_handler_id=>wwv_flow_api.id(2268150030151446) 71 | ,p_name=>'X-APEX-STATUS-CODE' 72 | ,p_bind_variable_name=>'status' 73 | ,p_source_type=>'HEADER' 74 | ,p_access_method=>'OUT' 75 | ,p_param_type=>'STRING' 76 | ); 77 | wwv_flow_api.create_restful_template( 78 | p_id=>wwv_flow_api.id(2268302669159665) 79 | ,p_module_id=>wwv_flow_api.id(2267957667151445) 80 | ,p_uri_template=>'webhook/{token}' 81 | ,p_priority=>0 82 | ,p_etag_type=>'HASH' 83 | ); 84 | wwv_flow_api.create_restful_handler( 85 | p_id=>wwv_flow_api.id(2268416224175894) 86 | ,p_template_id=>wwv_flow_api.id(2268302669159665) 87 | ,p_source_type=>'PLSQL' 88 | ,p_format=>'DEFAULT' 89 | ,p_method=>'POST' 90 | ,p_require_https=>'YES' 91 | ,p_source=>wwv_flow_string.join(wwv_flow_t_varchar2( 92 | 'declare', 93 | 'v_body clob;', 94 | 'begin', 95 | 'v_body := telegram.blob2clob(:body);', 96 | 'telegram.in_parse(v_body);', 97 | 'end;')) 98 | ); 99 | end; 100 | / 101 | begin 102 | wwv_flow_api.import_end(p_auto_install_sup_obj => nvl(wwv_flow_application_install.get_auto_install_sup_obj, false)); 103 | commit; 104 | end; 105 | / 106 | set verify on feedback on define on 107 | prompt ...done 108 | --------------------------------------------------------------------------------