2016-08-14 04:35:03 +02:00
|
|
|
; cl-telegram-bot
|
|
|
|
;
|
|
|
|
; MIT License
|
|
|
|
;
|
2017-07-10 20:59:11 +01:00
|
|
|
; Copyright (c) 2016 Rei <https://github.com/sovietspaceship>
|
2016-08-14 04:35:03 +02:00
|
|
|
;
|
|
|
|
; Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
; of this software and associated documentation files (the "Software"), to deal
|
|
|
|
; in the Software without restriction, including without limitation the rights
|
|
|
|
; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
; copies of the Software, and to permit persons to whom the Software is
|
|
|
|
; furnished to do so, subject to the following conditions:
|
|
|
|
;
|
|
|
|
; The above copyright notice and this permission notice shall be included in all
|
|
|
|
; copies or substantial portions of the Software.
|
|
|
|
;
|
|
|
|
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
2016-08-14 13:18:43 +03:00
|
|
|
; SOFTWARE.
|
2016-08-14 04:35:03 +02:00
|
|
|
|
2016-08-17 19:55:19 +02:00
|
|
|
(in-package :cl-telegram-bot)
|
2016-08-14 04:35:03 +02:00
|
|
|
|
2017-07-10 20:56:04 +01:00
|
|
|
(define-constant +http-ok+ 200 :test #'=)
|
|
|
|
|
2016-08-14 04:35:03 +02:00
|
|
|
(defclass bot ()
|
|
|
|
((id
|
|
|
|
:documentation "Update id"
|
2016-08-14 13:18:43 +03:00
|
|
|
:initform 0
|
|
|
|
:accessor id)
|
2016-08-14 04:35:03 +02:00
|
|
|
(token
|
|
|
|
:initarg :token
|
|
|
|
:documentation "Bot token given by BotFather"
|
2016-08-17 19:57:24 +02:00
|
|
|
:accessor token
|
2016-08-14 13:18:43 +03:00
|
|
|
:initform nil)
|
2017-07-10 20:56:04 +01:00
|
|
|
(api-uri
|
|
|
|
:initarg :api-uri
|
|
|
|
:initform "https://api.telegram.org/"
|
|
|
|
:accessor api-uri)
|
2016-08-14 04:35:03 +02:00
|
|
|
(endpoint
|
|
|
|
:initarg :endpoint
|
2016-08-14 13:18:43 +03:00
|
|
|
:accessor endpoint
|
2017-07-10 20:56:04 +01:00
|
|
|
:documentation "HTTPS endpoint")
|
|
|
|
(file-endpoint
|
|
|
|
:initarg :file-endpoint
|
|
|
|
:accessor file-endpoint
|
|
|
|
:documentation "HTTPS file-endpoint"
|
2016-08-14 13:18:43 +03:00
|
|
|
:initform nil)))
|
2016-08-14 04:35:03 +02:00
|
|
|
|
2017-07-10 20:56:04 +01:00
|
|
|
(defmethod initialize-instance :after ((object bot) &key &allow-other-keys)
|
|
|
|
(with-accessors ((token token)
|
|
|
|
(endpoint endpoint)
|
|
|
|
(file-endpoint file-endpoint)
|
|
|
|
(api-uri api-uri)) object
|
|
|
|
(setf endpoint (concatenate 'string api-uri "bot" token "/")
|
|
|
|
file-endpoint (concatenate 'string api-uri "file/" "bot" token "/"))))
|
2016-08-14 04:35:03 +02:00
|
|
|
|
|
|
|
(defun make-bot (token)
|
|
|
|
"Create a new bot instance. Takes a token string."
|
|
|
|
(make-instance 'bot :token token))
|
|
|
|
|
|
|
|
#+sbcl
|
|
|
|
(defun get-class-slots (obj)
|
|
|
|
"Get a list of class slots, useful to inspect Fluid classes. SBCL only."
|
|
|
|
(mapcar #'sb-mop:slot-definition-name
|
|
|
|
(sb-mop:class-slots
|
|
|
|
(class-of obj))))
|
|
|
|
|
2017-05-17 13:17:58 +02:00
|
|
|
(defun make-request (b name options &key (streamp nil))
|
2016-08-14 04:35:03 +02:00
|
|
|
"Perform HTTP request to 'name API method with 'options JSON-encoded object."
|
|
|
|
(drakma:http-request
|
2016-08-14 13:18:43 +03:00
|
|
|
(concatenate 'string (endpoint b) name)
|
2016-08-14 04:35:03 +02:00
|
|
|
:method :post
|
2017-05-17 13:17:58 +02:00
|
|
|
:want-stream streamp
|
2016-08-14 04:35:03 +02:00
|
|
|
:content-type "application/json"
|
|
|
|
:content (json:encode-json-alist-to-string options)))
|
|
|
|
|
|
|
|
(defun access (update &rest args)
|
|
|
|
"Access update field. update.first.second. ... => (access update 'first 'second ...). Nil if unbound."
|
2016-08-18 04:24:09 +02:00
|
|
|
(unless update
|
|
|
|
(return-from access nil))
|
2016-08-14 04:35:03 +02:00
|
|
|
(let ((current update))
|
|
|
|
(dolist (r args)
|
|
|
|
(unless (slot-boundp current r)
|
|
|
|
(return-from access nil))
|
|
|
|
(setf current (slot-value current r)))
|
|
|
|
current))
|
2016-08-14 13:18:43 +03:00
|
|
|
|
2016-08-14 04:35:03 +02:00
|
|
|
(defun get-slot (update slot)
|
|
|
|
"Access slot. Since fluid classes signal error on unbound slot access, this instead returns nil."
|
|
|
|
(if (slot-boundp update slot)
|
|
|
|
(slot-value update slot)
|
|
|
|
nil))
|
|
|
|
|
2016-08-18 04:24:09 +02:00
|
|
|
(defmacro with-package (package &rest body)
|
|
|
|
`(let ((json:*json-symbols-package* ,package)) ,@body))
|
|
|
|
|
2017-05-17 13:17:58 +02:00
|
|
|
(defgeneric decode (object))
|
|
|
|
|
|
|
|
(defmethod decode ((object stream))
|
|
|
|
(json:with-decoder-simple-clos-semantics
|
|
|
|
(prog1
|
|
|
|
(json:decode-json object)
|
|
|
|
(close object))))
|
|
|
|
|
|
|
|
(defmethod decode ((object string))
|
|
|
|
(json:with-decoder-simple-clos-semantics
|
|
|
|
(with-input-from-string (stream object)
|
|
|
|
(json:decode-json stream))))
|
2016-08-14 04:35:03 +02:00
|
|
|
|
2017-07-10 20:56:04 +01:00
|
|
|
(defmethod decode ((object vector))
|
|
|
|
(decode (map 'string #'code-char object)))
|
|
|
|
|
2016-08-14 04:35:03 +02:00
|
|
|
(define-condition request-error (error)
|
|
|
|
((what :initarg :what :reader what)))
|
|
|
|
|
2016-08-18 04:24:09 +02:00
|
|
|
(defmacro find-json-symbol (sym)
|
|
|
|
`(find-symbol (symbol-name ,sym) json:*json-symbols-package*))
|
|
|
|
|
|
|
|
(defmacro trace-http ()
|
|
|
|
'(setf drakma:*header-stream* *standard-output*))
|
|
|
|
|
2016-08-14 04:35:03 +02:00
|
|
|
; Telegram API methods, see https://core.telegram.org/bots/api
|
|
|
|
|
2017-07-10 20:56:04 +01:00
|
|
|
(defmacro with-ok-results ((unserialized results) &body body)
|
|
|
|
`(let ((,results (slot-value ,unserialized (find-json-symbol :result))))
|
|
|
|
(if (slot-value ,unserialized (find-json-symbol :ok))
|
|
|
|
(progn ,@body)
|
|
|
|
nil)))
|
|
|
|
|
2016-08-14 04:35:03 +02:00
|
|
|
(defun get-updates (b &key limit timeout)
|
|
|
|
"https://core.telegram.org/bots/api#getupdates"
|
2016-08-14 13:18:43 +03:00
|
|
|
(let* ((current-id (id b))
|
2017-05-17 13:17:58 +02:00
|
|
|
(request (decode (make-request b "getUpdates"
|
|
|
|
(list (cons :offset current-id)
|
|
|
|
(cons :limit limit)
|
|
|
|
(cons :timeout timeout))
|
|
|
|
:streamp t)))
|
2016-08-18 04:24:09 +02:00
|
|
|
(results (slot-value request (find-json-symbol :result))))
|
|
|
|
(when (eql (slot-value request (find-json-symbol :ok)) nil)
|
2016-08-14 04:35:03 +02:00
|
|
|
(error 'request-error :what request))
|
|
|
|
(when (> (length results) 0)
|
|
|
|
(let* ((last-update (elt results (- (length results) 1)))
|
2016-08-18 04:24:09 +02:00
|
|
|
(id (slot-value last-update (find-json-symbol :update--id))))
|
2016-08-14 04:35:03 +02:00
|
|
|
(when (= current-id 0)
|
2016-08-14 13:18:43 +03:00
|
|
|
(setf (id b) id))
|
|
|
|
(incf (id b))))
|
2016-08-14 04:35:03 +02:00
|
|
|
results))
|
|
|
|
|
|
|
|
(defun set-webhook (b &key url certificate)
|
|
|
|
"https://core.telegram.org/bots/api#setwebhook"
|
2016-08-18 04:24:09 +02:00
|
|
|
(let ((options '()))
|
|
|
|
(when url (nconc options `((:url . ,url))))
|
|
|
|
(when certificate (nconc options `((:certificate . ,certificate))))
|
|
|
|
(make-request b "setWebhook" options)))
|
2016-08-14 04:35:03 +02:00
|
|
|
|
2016-08-18 04:37:00 +02:00
|
|
|
(defun send-message (b chat-id text &key parse-mode disable-web-page-preview disable-notification reply)
|
2016-08-14 04:35:03 +02:00
|
|
|
"https://core.telegram.org/bots/api#sendmessage"
|
2016-08-18 04:24:09 +02:00
|
|
|
(let ((options
|
2017-05-17 13:17:58 +02:00
|
|
|
(list
|
2016-08-18 04:24:09 +02:00
|
|
|
(cons :chat_id chat-id)
|
|
|
|
(cons :text text))))
|
|
|
|
(when parse-mode (nconc options `((:parse_mode . ,parse-mode))))
|
|
|
|
(when disable-web-page-preview (nconc options `((:disable_web_page_preview . ,disable-web-page-preview))))
|
|
|
|
(when disable-notification (nconc options `((:disable_notification . ,disable-notification))))
|
2016-08-18 04:37:00 +02:00
|
|
|
(when reply (nconc options `((:reply_to_message_id . ,reply))))
|
2016-08-18 04:24:09 +02:00
|
|
|
(make-request b "sendMessage" options)))
|
2016-08-14 04:35:03 +02:00
|
|
|
|
|
|
|
(defun forward-message (b chat-id from-chat-id message-id &key disable-notification)
|
|
|
|
"https://core.telegram.org/bots/api#forwardmessage"
|
2016-08-18 04:24:09 +02:00
|
|
|
(let ((options
|
2017-05-17 13:17:58 +02:00
|
|
|
(list
|
2016-08-18 04:24:09 +02:00
|
|
|
(cons :chat_id chat-id)
|
|
|
|
(cons :from_chat_id from-chat-id)
|
|
|
|
(cons :message_id message-id))))
|
|
|
|
(when disable-notification (nconc options `((:disable_notification . ,disable-notification))))
|
|
|
|
(make-request b "forwardMessage" options)))
|
|
|
|
|
2016-08-18 04:37:00 +02:00
|
|
|
(defun send-photo (b chat-id photo &key caption disable-notification reply reply-markup)
|
2016-08-14 04:35:03 +02:00
|
|
|
"https://core.telegram.org/bots/api#sendphoto"
|
2016-08-18 04:24:09 +02:00
|
|
|
(let ((options
|
2017-05-17 13:17:58 +02:00
|
|
|
(list
|
2016-08-18 04:24:09 +02:00
|
|
|
(cons :chat_id chat-id)
|
|
|
|
(cons :photo photo))))
|
|
|
|
(when caption (nconc options `((:caption . ,caption))))
|
|
|
|
(when disable-notification (nconc options `((:disable_notification . ,disable-notification))))
|
2016-08-18 04:37:00 +02:00
|
|
|
(when reply (nconc options `((:reply_to_message_id . ,reply))))
|
2016-08-18 04:24:09 +02:00
|
|
|
(when reply-markup (nconc options `((:reply_markup . ,reply-markup))))
|
|
|
|
(make-request b "sendPhoto" options)))
|
|
|
|
|
2016-08-18 04:37:00 +02:00
|
|
|
(defun send-audio (b chat-id audio &key duration performer title disable-notification reply reply-markup)
|
2016-08-14 04:35:03 +02:00
|
|
|
"https://core.telegram.org/bots/api#sendaudio"
|
2016-08-18 04:24:09 +02:00
|
|
|
(let ((options
|
2017-05-17 13:17:58 +02:00
|
|
|
(list
|
2016-08-18 04:24:09 +02:00
|
|
|
(cons :chat_id chat-id)
|
|
|
|
(cons :audio audio))))
|
|
|
|
(when duration (nconc options `((:duration . ,duration))))
|
|
|
|
(when performer (nconc options `((:performer . ,performer))))
|
|
|
|
(when title (nconc options `((:title . ,title))))
|
|
|
|
(when disable-notification (nconc options `((:disable_notification . ,disable-notification))))
|
2016-08-18 04:37:00 +02:00
|
|
|
(when reply (nconc options `((:reply_to_message_id . ,reply))))
|
2016-08-18 04:24:09 +02:00
|
|
|
(when reply-markup (nconc options `((:reply_markup . ,reply-markup))))
|
|
|
|
(make-request b "sendAudio" options)))
|
|
|
|
|
2016-08-18 04:37:00 +02:00
|
|
|
(defun send-document (b chat-id document &key caption disable-notification reply reply-markup)
|
2016-08-14 04:35:03 +02:00
|
|
|
"https://core.telegram.org/bots/api#senddocument"
|
2016-08-18 04:24:09 +02:00
|
|
|
(let ((options
|
2017-05-17 13:17:58 +02:00
|
|
|
(list
|
2016-08-18 04:24:09 +02:00
|
|
|
(cons :chat_id chat-id)
|
|
|
|
(cons :document document))))
|
|
|
|
(when caption (nconc options `((:caption . ,caption))))
|
|
|
|
(when disable-notification (nconc options `((:disable_notification . ,disable-notification))))
|
2016-08-18 04:37:00 +02:00
|
|
|
(when reply (nconc options `((:reply_to_message_id . ,reply))))
|
2016-08-18 04:24:09 +02:00
|
|
|
(when reply-markup (nconc options `((:reply_markup . ,reply-markup))))
|
|
|
|
(make-request b "sendDocument" options)))
|
|
|
|
|
2016-08-18 04:37:00 +02:00
|
|
|
(defun send-sticker (b chat-id sticker &key disable-notification reply reply-markup)
|
2016-08-14 04:35:03 +02:00
|
|
|
"https://core.telegram.org/bots/api#sendsticker"
|
2016-08-18 04:24:09 +02:00
|
|
|
(let ((options
|
2017-05-17 13:17:58 +02:00
|
|
|
(list
|
2016-08-18 04:24:09 +02:00
|
|
|
(cons :chat_id chat-id)
|
|
|
|
(cons :sticker sticker))))
|
|
|
|
(when disable-notification (nconc options `((:disable_notification . ,disable-notification))))
|
2016-08-18 04:37:00 +02:00
|
|
|
(when reply (nconc options `((:reply_to_message_id . ,reply))))
|
2016-08-18 04:24:09 +02:00
|
|
|
(when reply-markup (nconc options `((:reply_markup . ,reply-markup))))
|
|
|
|
(make-request b "sendSticker" options)))
|
|
|
|
|
2016-08-18 04:37:00 +02:00
|
|
|
(defun send-video (b chat-id video &key duration width height caption disable-notification reply reply-markup)
|
2016-08-14 04:35:03 +02:00
|
|
|
"https://core.telegram.org/bots/api#sendvideo"
|
2016-08-18 04:24:09 +02:00
|
|
|
(let ((options
|
2017-05-17 13:17:58 +02:00
|
|
|
(list
|
2016-08-18 04:24:09 +02:00
|
|
|
(cons :chat_id chat-id)
|
|
|
|
(cons :video video))))
|
|
|
|
(when duration (nconc options `((:duration . ,duration))))
|
|
|
|
(when width (nconc options `((:width . ,width))))
|
|
|
|
(when height (nconc options `((:height . ,height))))
|
|
|
|
(when caption (nconc options `((:caption . ,caption))))
|
|
|
|
(when disable-notification (nconc options `((:disable_notification . ,disable-notification))))
|
2016-08-18 04:37:00 +02:00
|
|
|
(when reply (nconc options `((:reply_to_message_id . ,reply))))
|
2016-08-18 04:24:09 +02:00
|
|
|
(when reply-markup (nconc options `((:reply_markup . ,reply-markup))))
|
|
|
|
(make-request b "sendVideo" options)))
|
|
|
|
|
2016-08-18 04:37:00 +02:00
|
|
|
(defun send-voice (b chat-id voice &key duration disable-notification reply reply-markup)
|
2016-08-14 04:35:03 +02:00
|
|
|
"https://core.telegram.org/bots/api#sendvoice"
|
2016-08-18 04:24:09 +02:00
|
|
|
(let ((options
|
2017-05-17 13:17:58 +02:00
|
|
|
(list
|
2016-08-18 04:24:09 +02:00
|
|
|
(cons :chat_id chat-id)
|
|
|
|
(cons :voice voice))))
|
|
|
|
(when duration (nconc options `((:duration . ,duration))))
|
|
|
|
(when disable-notification (nconc options `((:disable_notification . ,disable-notification))))
|
2016-08-18 04:37:00 +02:00
|
|
|
(when reply (nconc options `((:reply_to_message_id . ,reply))))
|
2016-08-18 04:24:09 +02:00
|
|
|
(when reply-markup (nconc options `((:reply_markup . ,reply-markup))))
|
|
|
|
(make-request b "sendVoice" options)))
|
|
|
|
|
2016-08-18 04:37:00 +02:00
|
|
|
(defun send-location (b chat-id latitude longitude &key disable-notification reply reply-markup)
|
2016-08-14 04:35:03 +02:00
|
|
|
"https://core.telegram.org/bots/api#sendlocation"
|
2016-08-18 04:24:09 +02:00
|
|
|
(let ((options
|
2017-05-17 13:17:58 +02:00
|
|
|
(list
|
2016-08-18 04:24:09 +02:00
|
|
|
(cons :chat_id chat-id)
|
2016-08-14 04:35:03 +02:00
|
|
|
(cons :latitude latitude)
|
2016-08-18 04:24:09 +02:00
|
|
|
(cons :longitude longitude))))
|
|
|
|
(when disable-notification (nconc options `((:disable_notification . ,disable-notification))))
|
2016-08-18 04:37:00 +02:00
|
|
|
(when reply (nconc options `((:reply_to_message_id . ,reply))))
|
2016-08-18 04:24:09 +02:00
|
|
|
(when reply-markup (nconc options `((:reply_markup . ,reply-markup))))
|
|
|
|
(make-request b "sendLocation" options)))
|
2016-08-14 04:35:03 +02:00
|
|
|
|
2016-08-18 04:37:00 +02:00
|
|
|
(defun send-venue (b chat-id latitude longitude title address &key foursquare-id disable-notification reply reply-markup)
|
2016-08-14 04:35:03 +02:00
|
|
|
"https://core.telegram.org/bots/api#sendvenue"
|
2016-08-18 04:24:09 +02:00
|
|
|
(let ((options
|
2017-05-17 13:17:58 +02:00
|
|
|
(list
|
2016-08-18 04:24:09 +02:00
|
|
|
(cons :chat_id chat-id)
|
2016-08-14 04:35:03 +02:00
|
|
|
(cons :latitude latitude)
|
|
|
|
(cons :longitude longitude)
|
|
|
|
(cons :title title)
|
2016-08-18 04:24:09 +02:00
|
|
|
(cons :address address))))
|
|
|
|
(when foursquare-id (nconc options `((:foursquare_id . ,foursquare-id))))
|
|
|
|
(when disable-notification (nconc options `((:disable_notification . ,disable-notification))))
|
2016-08-18 04:37:00 +02:00
|
|
|
(when reply (nconc options `((:reply_to_message_id . ,reply))))
|
2016-08-18 04:24:09 +02:00
|
|
|
(when reply-markup (nconc options `((:reply_markup . ,reply-markup))))
|
|
|
|
(make-request b "sendVenue" options)))
|
|
|
|
|
2016-08-18 04:37:00 +02:00
|
|
|
(defun send-contact (b chat-id phone-number first-name &key last-name disable-notification reply reply-markup)
|
2016-08-14 04:35:03 +02:00
|
|
|
"https://core.telegram.org/bots/api#sendcontact"
|
2016-08-18 04:24:09 +02:00
|
|
|
(let ((options
|
2017-05-17 13:17:58 +02:00
|
|
|
(list
|
2016-08-18 04:24:09 +02:00
|
|
|
(cons :chat_id chat-id)
|
|
|
|
(cons :phone_number phone-number)
|
|
|
|
(cons :first_name first-name))))
|
|
|
|
(when last-name (nconc options `((:last_name . ,last-name))))
|
|
|
|
(when disable-notification (nconc options `((:disable_notification . ,disable-notification))))
|
2016-08-18 04:37:00 +02:00
|
|
|
(when reply (nconc options `((:reply_to_message_id . ,reply))))
|
2016-08-18 04:24:09 +02:00
|
|
|
(when reply-markup (nconc options `((:reply_markup . ,reply-markup))))
|
|
|
|
(make-request b "sendContact" options)))
|
2016-08-14 04:35:03 +02:00
|
|
|
|
|
|
|
(defun send-chat-action (b chat-id action)
|
|
|
|
"https://core.telegram.org/bots/api#sendchataction"
|
2016-08-18 04:24:09 +02:00
|
|
|
(let ((options
|
2017-05-17 13:17:58 +02:00
|
|
|
(list
|
2016-08-18 04:24:09 +02:00
|
|
|
(cons :chat_id chat-id)
|
2016-08-14 04:35:03 +02:00
|
|
|
(cons :action action))))
|
2016-08-18 04:24:09 +02:00
|
|
|
(make-request b "sendChatAction" options)))
|
2016-08-14 04:35:03 +02:00
|
|
|
|
|
|
|
(defun get-user-profile-photos (b user-id &key offset limit)
|
|
|
|
"https://core.telegram.org/bots/api#getuserprofilephotos"
|
2016-08-18 04:24:09 +02:00
|
|
|
(let ((options
|
2017-05-17 13:17:58 +02:00
|
|
|
(list
|
2016-08-18 04:24:09 +02:00
|
|
|
(cons :user_id user-id))))
|
|
|
|
(when offset (nconc options `((:offset . ,offset))))
|
|
|
|
(when limit (nconc options `((:limit . ,limit))))
|
|
|
|
(make-request b "getUserProfilePhotos" options)))
|
2016-08-14 04:35:03 +02:00
|
|
|
|
|
|
|
(defun get-file (b file-id)
|
|
|
|
"https://core.telegram.org/bots/api#getfile"
|
2016-08-18 04:24:09 +02:00
|
|
|
(let ((options
|
2017-05-17 13:17:58 +02:00
|
|
|
(list
|
2016-08-18 04:24:09 +02:00
|
|
|
(cons :file_id file-id))))
|
|
|
|
(make-request b "getFile" options)))
|
2016-08-14 04:35:03 +02:00
|
|
|
|
2017-07-10 20:56:04 +01:00
|
|
|
(defun download-file (b file-id)
|
2017-07-10 20:57:55 +01:00
|
|
|
"Get the path for a file from a file-id (see: get-file) and then
|
|
|
|
download it. Returns nil if the value of the http response code is
|
|
|
|
not success (200); otherwise it will returns three values: the
|
|
|
|
data, the http headers and the exension of the original file"
|
2017-07-10 20:56:04 +01:00
|
|
|
(with-package :cl-telegram-bot
|
|
|
|
(let* ((file-spec (decode (get-file b file-id))))
|
|
|
|
(with-ok-results (file-spec results)
|
|
|
|
(when-let* ((path (access results 'file--path))
|
|
|
|
(uri (concatenate 'string (file-endpoint b) path))
|
|
|
|
(extension (cl-ppcre:scan-to-strings "\\..*$" path)))
|
|
|
|
(multiple-value-bind (body code headers)
|
|
|
|
(drakma:http-request uri :method :get)
|
|
|
|
(when (= code +http-ok+)
|
|
|
|
(values body headers extension))))))))
|
|
|
|
|
2016-08-14 04:35:03 +02:00
|
|
|
(defun kick-chat-member (b chat-id user-id)
|
|
|
|
"https://core.telegram.org/bots/api#kickchatmember"
|
2016-08-18 04:24:09 +02:00
|
|
|
(let ((options
|
2017-05-17 13:17:58 +02:00
|
|
|
(list
|
2016-08-18 04:24:09 +02:00
|
|
|
(cons :chat_id chat-id)
|
|
|
|
(cons :user_id user-id))))
|
|
|
|
(make-request b "kickChatMember" options)))
|
2016-08-14 04:35:03 +02:00
|
|
|
|
|
|
|
(defun leave-chat (b chat-id)
|
|
|
|
"https://core.telegram.org/bots/api#leavechat"
|
2016-08-18 04:24:09 +02:00
|
|
|
(let ((options
|
2017-05-17 13:17:58 +02:00
|
|
|
(list
|
2016-08-18 04:24:09 +02:00
|
|
|
(cons :chat_id chat-id))))
|
|
|
|
(make-request b "leaveChat" options)))
|
2016-08-14 04:35:03 +02:00
|
|
|
|
|
|
|
(defun unban-chat-member (b chat-id user-id)
|
|
|
|
"https://core.telegram.org/bots/api#unbanchatmember"
|
2016-08-18 04:24:09 +02:00
|
|
|
(let ((options
|
2017-05-17 13:17:58 +02:00
|
|
|
(list
|
2016-08-18 04:24:09 +02:00
|
|
|
(cons :chat_id chat-id)
|
|
|
|
(cons :user_id user-id))))
|
|
|
|
(make-request b "unbanChatMember" options)))
|
2016-08-14 04:35:03 +02:00
|
|
|
|
|
|
|
(defun get-chat (b chat-id)
|
|
|
|
"https://core.telegram.org/bots/api#getchat"
|
2016-08-18 04:24:09 +02:00
|
|
|
(let ((options
|
2017-05-17 13:17:58 +02:00
|
|
|
(list
|
2016-08-18 04:24:09 +02:00
|
|
|
(cons :chat_id chat-id))))
|
|
|
|
(make-request b "getChat" options)))
|
2016-08-14 04:35:03 +02:00
|
|
|
|
|
|
|
(defun get-chat-administrators (b chat-id)
|
|
|
|
"https://core.telegram.org/bots/api#getchatadministrators"
|
2016-08-18 04:24:09 +02:00
|
|
|
(let ((options
|
2017-05-17 13:17:58 +02:00
|
|
|
(list
|
2016-08-18 04:24:09 +02:00
|
|
|
(cons :chat_id chat-id))))
|
|
|
|
(make-request b "getChatAdministrators" options)))
|
2016-08-14 04:35:03 +02:00
|
|
|
|
|
|
|
(defun get-chat-members-count (b chat-id)
|
|
|
|
"https://core.telegram.org/bots/api#getchatmemberscount"
|
2016-08-18 04:24:09 +02:00
|
|
|
(let ((options
|
2017-05-17 13:17:58 +02:00
|
|
|
(list
|
2016-08-18 04:24:09 +02:00
|
|
|
(cons :chat_id chat-id))))
|
|
|
|
(make-request b "getChatMembersCount" options)))
|
2016-08-14 04:35:03 +02:00
|
|
|
|
|
|
|
(defun get-chat-member (b chat-id user-id)
|
|
|
|
"https://core.telegram.org/bots/api#getchatmember"
|
2016-08-18 04:24:09 +02:00
|
|
|
(let ((options
|
2017-05-17 13:17:58 +02:00
|
|
|
(list
|
2016-08-18 04:24:09 +02:00
|
|
|
(cons :chat_id chat-id)
|
|
|
|
(cons :user_id user-id))))
|
|
|
|
(make-request b "getChatMember" options)))
|
2016-08-14 04:35:03 +02:00
|
|
|
|
|
|
|
(defun answer-callback-query (b callback-query-id &key text show-alert)
|
|
|
|
"https://core.telegram.org/bots/api#answercallbackquery"
|
2016-08-18 04:24:09 +02:00
|
|
|
(let ((options
|
2017-05-17 13:17:58 +02:00
|
|
|
(list
|
2016-08-18 04:24:09 +02:00
|
|
|
(cons :callback_query_id callback-query-id))))
|
|
|
|
(when text (nconc options `((:text . ,text))))
|
|
|
|
(when show-alert (nconc options `((:show_alert . ,show-alert))))
|
|
|
|
(make-request b "answerCallbackQuery" options)))
|
2016-08-14 04:35:03 +02:00
|
|
|
|
|
|
|
(defun edit-message-text (b chat-id message-id inline-message-id text &key parse-mode disable-web-page-preview reply-markup)
|
|
|
|
"https://core.telegram.org/bots/api#editmessagetext"
|
2016-08-18 04:24:09 +02:00
|
|
|
(let ((options
|
2017-05-17 13:17:58 +02:00
|
|
|
(list
|
2016-08-18 04:24:09 +02:00
|
|
|
(cons :chat_id chat-id)
|
|
|
|
(cons :message_id message-id)
|
|
|
|
(cons :inline_message_id inline-message-id)
|
|
|
|
(cons :text text))))
|
|
|
|
(when parse-mode (nconc options `((:parse_mode . ,parse-mode))))
|
|
|
|
(when disable-web-page-preview (nconc options `((:disable_web_page_preview . ,disable-web-page-preview))))
|
|
|
|
(when reply-markup (nconc options `((:reply_markup . ,reply-markup))))
|
|
|
|
(make-request b "editMessageText" options)))
|
2016-08-14 04:35:03 +02:00
|
|
|
|
|
|
|
(defun edit-message-caption (b chat-id message-id inline-message-id &key caption reply-markup)
|
|
|
|
"https://core.telegram.org/bots/api#editmessagecaption"
|
2016-08-18 04:24:09 +02:00
|
|
|
(let ((options
|
2017-05-17 13:17:58 +02:00
|
|
|
(list
|
2016-08-18 04:24:09 +02:00
|
|
|
(cons :chat_id chat-id)
|
|
|
|
(cons :message_id message-id)
|
|
|
|
(cons :inline_message_id inline-message-id))))
|
|
|
|
(when caption (nconc options `((:caption . ,caption))))
|
|
|
|
(when reply-markup (nconc options `((:reply_markup . ,reply-markup))))
|
|
|
|
(make-request b "editMessageCaption" options)))
|
2016-08-14 04:35:03 +02:00
|
|
|
|
|
|
|
(defun edit-message-reply-markup (b chat-id message-id inline-message-id &key reply-markup)
|
|
|
|
"https://core.telegram.org/bots/api#editmessagereplymarkup"
|
2016-08-18 04:24:09 +02:00
|
|
|
(let ((options
|
2017-05-17 13:17:58 +02:00
|
|
|
(list
|
2016-08-18 04:24:09 +02:00
|
|
|
(cons :chat_id chat-id)
|
|
|
|
(cons :message_id message-id)
|
|
|
|
(cons :inline_message_id inline-message-id))))
|
|
|
|
(when reply-markup (nconc options `((:reply_markup . ,reply-markup))))
|
|
|
|
(make-request b "editMessageReplyMarkup" options)))
|
2016-08-14 04:35:03 +02:00
|
|
|
|
|
|
|
(defun answer-inline-query (b inline-query-id results &key cache-time is-personal next-offset switch-pm-text)
|
|
|
|
"https://core.telegram.org/bots/api#answerinlinequery"
|
2016-08-18 04:24:09 +02:00
|
|
|
(let ((options
|
2017-05-17 13:17:58 +02:00
|
|
|
(list
|
2016-08-18 04:24:09 +02:00
|
|
|
(cons :inline_query_id inline-query-id)
|
|
|
|
(cons :results results))))
|
|
|
|
(when cache-time (nconc options `((:cache_time . ,cache-time))))
|
|
|
|
(when is-personal (nconc options `((:is_personal . ,is-personal))))
|
|
|
|
(when next-offset (nconc options `((:next_offset . ,next-offset))))
|
|
|
|
(when switch-pm-text (nconc options `((:switch_pm_text . ,switch-pm-text))))
|
|
|
|
(make-request b "answerInlineQuery" options)))
|