├── .Rbuildignore ├── inst ├── r_logo.webp ├── audio_test.mp3 └── voice_test.ogg ├── .travis.yml ├── man ├── getMe.Rd ├── getFile.Rd ├── getUpdates.Rd ├── stopPoll.Rd ├── sendDice.Rd ├── user_id.Rd ├── group_id.Rd ├── proxy.Rd ├── bot_token.Rd ├── getUserProfilePhotos.Rd ├── telegram.Rd ├── sendVideo.Rd ├── sendSticker.Rd ├── sendDocument.Rd ├── sendPhoto.Rd ├── forwardMessage.Rd ├── sendVoice.Rd ├── sendLocation.Rd ├── sendChatAction.Rd ├── sendAudio.Rd ├── sendMessage.Rd ├── sendPoll.Rd └── TGBot.Rd ├── NEWS ├── NAMESPACE ├── R ├── telegram_package.R ├── get_telegram_envvar.R └── TGBot.R ├── DESCRIPTION └── README.md /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^\.travis\.yml$ 2 | -------------------------------------------------------------------------------- /inst/r_logo.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lbraglia/telegram/HEAD/inst/r_logo.webp -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Sample .travis.yml for R projects 2 | 3 | language: r 4 | sudo: required 5 | -------------------------------------------------------------------------------- /inst/audio_test.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lbraglia/telegram/HEAD/inst/audio_test.mp3 -------------------------------------------------------------------------------- /inst/voice_test.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lbraglia/telegram/HEAD/inst/voice_test.ogg -------------------------------------------------------------------------------- /man/getMe.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/TGBot.R 3 | \name{getMe} 4 | \alias{getMe} 5 | \title{getMe} 6 | \usage{ 7 | getMe() 8 | } 9 | \description{ 10 | Test your bot's auth token 11 | } 12 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | Version 0.7 2 | ----------- 3 | 4 | * proxy setup using in TGBot call or using set_proxy method (both takes 5 | a list of parameters passed to httr::use_proxy 6 | * `group_id` utility function (it work the same as `bot_token` or 7 | `user_id`, by using the `R_TELEGRAM_GROUP_` prefix); 8 | * `sendDice` method; 9 | * `sendPoll` method; 10 | * `sendChatAction` method; 11 | * miscellaneous bugfixes. 12 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(TGBot) 4 | export(bot_token) 5 | export(group_id) 6 | export(proxy) 7 | export(user_id) 8 | importFrom(R6,R6Class) 9 | importFrom(curl,curl_download) 10 | importFrom(httr,POST) 11 | importFrom(httr,content) 12 | importFrom(httr,upload_file) 13 | importFrom(httr,warn_for_status) 14 | importFrom(jsonlite,fromJSON) 15 | importFrom(jsonlite,toJSON) 16 | importFrom(utils,menu) 17 | -------------------------------------------------------------------------------- /man/getFile.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/TGBot.R 3 | \name{getFile} 4 | \alias{getFile} 5 | \title{getFile} 6 | \usage{ 7 | getFile(file_id, destfile = NULL) 8 | } 9 | \arguments{ 10 | \item{file_id}{File identifier (required)} 11 | 12 | \item{destfile}{Destination path; if specified the file will be 13 | downloaded} 14 | } 15 | \description{ 16 | Get info about a file and download it 17 | } 18 | -------------------------------------------------------------------------------- /man/getUpdates.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/TGBot.R 3 | \name{getUpdates} 4 | \alias{getUpdates} 5 | \title{getUpdates} 6 | \usage{ 7 | getUpdates(offset = NULL, limit = NULL) 8 | } 9 | \arguments{ 10 | \item{offset}{Identifier of the first update to be returned.} 11 | 12 | \item{limit}{Limits the number of updates to be retrieved. Values 13 | between 1-100 are accepted. Defaults to 100} 14 | } 15 | \description{ 16 | Receive incoming updates 17 | } 18 | -------------------------------------------------------------------------------- /man/stopPoll.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/TGBot.R 3 | \name{stopPoll} 4 | \alias{stopPoll} 5 | \title{stopPoll} 6 | \usage{ 7 | stopPoll(message_id = NULL, chat_id = NULL) 8 | } 9 | \arguments{ 10 | \item{message_id}{Identifier of the original message with the poll} 11 | 12 | \item{chat_id}{Unique identifier for the target chat or username of 13 | the target channel (required)} 14 | } 15 | \description{ 16 | Use this method to stop a poll which was sent by the bot. 17 | } 18 | -------------------------------------------------------------------------------- /man/sendDice.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/TGBot.R 3 | \name{sendDice} 4 | \alias{sendDice} 5 | \title{sendDice} 6 | \usage{ 7 | sendDice(disable_notification = NULL, chat_id = NULL) 8 | } 9 | \arguments{ 10 | \item{disable_notification}{Sends the message silently. Users will 11 | receive a notification with no sound} 12 | 13 | \item{chat_id}{Unique identifier for the target chat or username of 14 | the target channel (required)} 15 | } 16 | \description{ 17 | Use this method to send a dice, which will have a random value from 18 | 1 to 6. 19 | } 20 | -------------------------------------------------------------------------------- /R/telegram_package.R: -------------------------------------------------------------------------------- 1 | #' telegram. 2 | #' 3 | #' Simple R wrapper around the Telegram Bot API 4 | #' (http://core.telegram.org/bots/api) to access Telegram's messaging 5 | #' facilities with ease (eg you send messages, images, files from R to 6 | #' your smartphone) 7 | #' 8 | #' @name telegram 9 | #' @docType package 10 | #' @importFrom R6 R6Class 11 | #' @importFrom httr POST 12 | #' @importFrom httr content 13 | #' @importFrom httr warn_for_status 14 | #' @importFrom httr upload_file 15 | #' @importFrom jsonlite fromJSON 16 | #' @importFrom jsonlite toJSON 17 | #' @importFrom curl curl_download 18 | #' @importFrom utils menu 19 | NULL 20 | -------------------------------------------------------------------------------- /man/user_id.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_telegram_envvar.R 3 | \name{user_id} 4 | \alias{user_id} 5 | \title{user_id} 6 | \usage{ 7 | user_id(x) 8 | } 9 | \arguments{ 10 | \item{x}{character of length 1 with the name of the user; if 11 | \code{NULL} a menu to choose between bot is displayed and the 12 | proper value returned} 13 | } 14 | \description{ 15 | Obtain telegram user id from system variables (in \code{Renviron}) set 16 | according to package naming conventions, that is 17 | \code{R_TELEGRAM_USER_X} where is the user's name . 18 | } 19 | \examples{ 20 | \dontrun{ user_id('me') } 21 | } 22 | -------------------------------------------------------------------------------- /man/group_id.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_telegram_envvar.R 3 | \name{group_id} 4 | \alias{group_id} 5 | \title{group_id} 6 | \usage{ 7 | group_id(x) 8 | } 9 | \arguments{ 10 | \item{x}{character of length 1 with the name of the user; if 11 | \code{NULL} a menu to choose between bot is displayed and the 12 | proper value returned} 13 | } 14 | \description{ 15 | Obtain telegram user id from system variables (in \code{Renviron}) set 16 | according to package naming conventions, that is 17 | \code{R_TELEGRAM_USER_X} where is the user's name . 18 | } 19 | \examples{ 20 | \dontrun{ group_id('test_group') } 21 | } 22 | -------------------------------------------------------------------------------- /man/proxy.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_telegram_envvar.R 3 | \name{proxy} 4 | \alias{proxy} 5 | \title{proxy} 6 | \usage{ 7 | proxy(x) 8 | } 9 | \arguments{ 10 | \item{x}{character of length 1 with the name of the proxy; if 11 | \code{NULL} a menu to choose between proxy is displayed and the 12 | proper value returned} 13 | } 14 | \description{ 15 | Obtain telegram proxy from system variables (in \code{Renviron}) set 16 | according to package naming conventions, that is 17 | \code{R_TELEGRAM_PROXY_X_Y} where X is the proxy's name and Y are the 18 | proxy parameters. 19 | } 20 | \examples{ 21 | \dontrun{ proxy('default') } 22 | } 23 | -------------------------------------------------------------------------------- /man/bot_token.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_telegram_envvar.R 3 | \name{bot_token} 4 | \alias{bot_token} 5 | \title{bot_token} 6 | \usage{ 7 | bot_token(x) 8 | } 9 | \arguments{ 10 | \item{x}{character of length 1 with the name of the bot; if 11 | \code{NULL} a menu to choose between bot is displayed and the 12 | proper value returned} 13 | } 14 | \description{ 15 | Obtain token from system variables (in \code{Renviron}) set 16 | according to package naming conventions, that is 17 | \code{R_TELEGRAM_BOT_} where \code{X} is bot's name (first question 18 | answered to the botfather). 19 | } 20 | \examples{ 21 | \dontrun{ bot_token('RBot') } 22 | } 23 | -------------------------------------------------------------------------------- /man/getUserProfilePhotos.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/TGBot.R 3 | \name{getUserProfilePhotos} 4 | \alias{getUserProfilePhotos} 5 | \title{getUserProfilePhotos} 6 | \usage{ 7 | getUserProfilePhotos(user_id = NULL, offset = NULL, limit = NULL) 8 | } 9 | \arguments{ 10 | \item{user_id}{Unique identifier of the target user (required)} 11 | 12 | \item{offset}{Sequential number of the first photo to be 13 | returned. By default, all photos are returned} 14 | 15 | \item{limit}{Limits the number of photos to be retrieved. Values 16 | between 1-100 are accepted. Defaults to 100} 17 | } 18 | \description{ 19 | Get a list of profile pictures for a user 20 | } 21 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: telegram 2 | Title: R Wrapper Around the Telegram Bot API 3 | Version: 0.7.1 4 | Authors@R: person("Luca", "Braglia", email = "lbraglia@gmail.com", role = c("aut", "cre")) 5 | Author: Luca Braglia [aut, cre] 6 | Maintainer: Luca Braglia 7 | Description: A simple wrapper around the Telegram Bot API () to access Telegram's messaging facilities with ease (e.g. you send messages, images, files from R to your smartphone). 8 | URL: https://github.com/lbraglia/telegram 9 | BugReports: https://github.com/lbraglia/telegram/issues 10 | Imports: R6, httr, jsonlite, curl, utils 11 | Depends: 12 | R (>= 3.2.3) 13 | License: GPL-3 14 | RoxygenNote: 7.3.2 15 | -------------------------------------------------------------------------------- /man/telegram.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/telegram_package.R 3 | \docType{package} 4 | \name{telegram} 5 | \alias{telegram-package} 6 | \alias{telegram} 7 | \title{telegram.} 8 | \description{ 9 | Simple R wrapper around the Telegram Bot API 10 | (http://core.telegram.org/bots/api) to access Telegram's messaging 11 | facilities with ease (eg you send messages, images, files from R to 12 | your smartphone) 13 | } 14 | \seealso{ 15 | Useful links: 16 | \itemize{ 17 | \item \url{https://github.com/lbraglia/telegram} 18 | \item Report bugs at \url{https://github.com/lbraglia/telegram/issues} 19 | } 20 | 21 | } 22 | \author{ 23 | \strong{Maintainer}: Luca Braglia \email{lbraglia@gmail.com} 24 | 25 | } 26 | -------------------------------------------------------------------------------- /man/sendVideo.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/TGBot.R 3 | \name{sendVideo} 4 | \alias{sendVideo} 5 | \title{sendVideo} 6 | \usage{ 7 | sendVideo( 8 | video = NULL, 9 | duration = NULL, 10 | caption = NULL, 11 | reply_to_message_id = NULL, 12 | chat_id = NULL 13 | ) 14 | } 15 | \arguments{ 16 | \item{video}{Video to send (required)} 17 | 18 | \item{duration}{Duration of sent video in seconds} 19 | 20 | \item{caption}{Video caption} 21 | 22 | \item{reply_to_message_id}{If the message is a reply, ID of the 23 | original message} 24 | 25 | \item{chat_id}{Unique identifier for the target chat or username of 26 | the target channel (required)} 27 | } 28 | \description{ 29 | Send \code{mp4} videos 30 | } 31 | -------------------------------------------------------------------------------- /man/sendSticker.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/TGBot.R 3 | \name{sendSticker} 4 | \alias{sendSticker} 5 | \title{sendSticker} 6 | \usage{ 7 | sendSticker( 8 | sticker = NULL, 9 | disable_notification = NULL, 10 | reply_to_message_id = NULL, 11 | chat_id = NULL 12 | ) 13 | } 14 | \arguments{ 15 | \item{sticker}{sticker to send (required)} 16 | 17 | \item{disable_notification}{Sends the message silently. Users will 18 | receive a notification with no sound} 19 | 20 | \item{reply_to_message_id}{If the message is a reply, ID of the 21 | original message} 22 | 23 | \item{chat_id}{Unique identifier for the target chat or username of 24 | the target channel (required)} 25 | } 26 | \description{ 27 | Send \code{.webp} stickers 28 | } 29 | -------------------------------------------------------------------------------- /man/sendDocument.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/TGBot.R 3 | \name{sendDocument} 4 | \alias{sendDocument} 5 | \title{sendDocument} 6 | \usage{ 7 | sendDocument( 8 | document = NULL, 9 | disable_notification = NULL, 10 | reply_to_message_id = NULL, 11 | chat_id = NULL 12 | ) 13 | } 14 | \arguments{ 15 | \item{document}{path to the file to send (required)} 16 | 17 | \item{disable_notification}{Sends the message silently. Users will 18 | receive a notification with no sound} 19 | 20 | \item{reply_to_message_id}{if the message is a reply, ID of the 21 | original message} 22 | 23 | \item{chat_id}{Unique identifier for the target chat or username of 24 | the target channel (required)} 25 | } 26 | \description{ 27 | Send general files 28 | } 29 | -------------------------------------------------------------------------------- /man/sendPhoto.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/TGBot.R 3 | \name{sendPhoto} 4 | \alias{sendPhoto} 5 | \title{sendPhoto} 6 | \usage{ 7 | sendPhoto( 8 | photo = NULL, 9 | caption = NULL, 10 | disable_notification = NULL, 11 | reply_to_message_id = NULL, 12 | chat_id = NULL 13 | ) 14 | } 15 | \arguments{ 16 | \item{photo}{photo to send (required)} 17 | 18 | \item{caption}{photo caption} 19 | 20 | \item{disable_notification}{Sends the message silently. Users will 21 | receive a notification with no sound} 22 | 23 | \item{reply_to_message_id}{If the message is a reply, ID of the 24 | original message} 25 | 26 | \item{chat_id}{Unique identifier for the target chat or username of 27 | the target channel (required)} 28 | } 29 | \description{ 30 | Send image files 31 | } 32 | -------------------------------------------------------------------------------- /man/forwardMessage.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/TGBot.R 3 | \name{forwardMessage} 4 | \alias{forwardMessage} 5 | \title{forwardMessage} 6 | \usage{ 7 | forwardMessage( 8 | from_chat_id = NULL, 9 | message_id = NULL, 10 | disable_notification = NULL, 11 | chat_id = NULL 12 | ) 13 | } 14 | \arguments{ 15 | \item{from_chat_id}{Unique identifier for the chat where the 16 | original message was sent (required)} 17 | 18 | \item{message_id}{Unique message identifier (required)} 19 | 20 | \item{disable_notification}{Sends the message silently. Users will 21 | receive a notification with no sound} 22 | 23 | \item{chat_id}{Unique identifier for the target chat or username of 24 | the target channel (required)} 25 | } 26 | \description{ 27 | Forward messages of any kind 28 | } 29 | -------------------------------------------------------------------------------- /man/sendVoice.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/TGBot.R 3 | \name{sendVoice} 4 | \alias{sendVoice} 5 | \title{sendVoice} 6 | \usage{ 7 | sendVoice( 8 | voice = NULL, 9 | duration = NULL, 10 | disable_notification = NULL, 11 | reply_to_message_id = NULL, 12 | chat_id = NULL 13 | ) 14 | } 15 | \arguments{ 16 | \item{voice}{Audio file to send (required)} 17 | 18 | \item{duration}{Duration of sent audio in seconds} 19 | 20 | \item{disable_notification}{Sends the message silently. Users will 21 | receive a notification with no sound} 22 | 23 | \item{reply_to_message_id}{If the message is a reply, ID of the 24 | original message} 25 | 26 | \item{chat_id}{Unique identifier for the target chat or username of 27 | the target channel (required)} 28 | } 29 | \description{ 30 | Send \code{.ogg} files encoded with OPUS 31 | } 32 | -------------------------------------------------------------------------------- /man/sendLocation.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/TGBot.R 3 | \name{sendLocation} 4 | \alias{sendLocation} 5 | \title{sendLocation} 6 | \usage{ 7 | sendLocation( 8 | latitude = NULL, 9 | longitude = NULL, 10 | disable_notification = NULL, 11 | reply_to_message_id = NULL, 12 | chat_id = NULL 13 | ) 14 | } 15 | \arguments{ 16 | \item{latitude}{Latitude of location (required)} 17 | 18 | \item{longitude}{Longitude of location (required)} 19 | 20 | \item{disable_notification}{Sends the message silently. Users will 21 | receive a notification with no sound} 22 | 23 | \item{reply_to_message_id}{If the message is a reply, ID of the 24 | original message} 25 | 26 | \item{chat_id}{Unique identifier for the target chat or username of 27 | the target channel (required)} 28 | } 29 | \description{ 30 | Send point on the map 31 | } 32 | -------------------------------------------------------------------------------- /man/sendChatAction.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/TGBot.R 3 | \name{sendChatAction} 4 | \alias{sendChatAction} 5 | \title{sendChatAction} 6 | \usage{ 7 | sendChatAction(action = NULL, chat_id = NULL) 8 | } 9 | \arguments{ 10 | \item{action}{type of action to broadcast. Choose one, depending on 11 | what the user is about to receive: "typing" for text messages, 12 | "upload_photo" for photos, "record_video" or "upload_video" for 13 | videos, "record_voice" or "upload_voice" for voice notes, 14 | "upload_document" for general files, "find_location" for 15 | location data, "record_video_note" or "upload_video_note" for 16 | video notes.} 17 | 18 | \item{chat_id}{Unique identifier for the target chat or username of 19 | the target channel (required)} 20 | } 21 | \description{ 22 | Tell the user that something is happening on the bot's side 23 | } 24 | -------------------------------------------------------------------------------- /man/sendAudio.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/TGBot.R 3 | \name{sendAudio} 4 | \alias{sendAudio} 5 | \title{sendAudio} 6 | \usage{ 7 | sendAudio( 8 | audio = NULL, 9 | caption = NULL, 10 | duration = NULL, 11 | performer = NULL, 12 | title = NULL, 13 | disable_notification = NULL, 14 | reply_to_message_id = NULL, 15 | chat_id = NULL 16 | ) 17 | } 18 | \arguments{ 19 | \item{audio}{path to audio file to send (required)} 20 | 21 | \item{caption}{audio caption} 22 | 23 | \item{duration}{duration of the audio in seconds} 24 | 25 | \item{performer}{performer} 26 | 27 | \item{title}{track name} 28 | 29 | \item{disable_notification}{Sends the message silently. Users will 30 | receive a notification with no sound} 31 | 32 | \item{reply_to_message_id}{If the message is a reply, ID of the 33 | original message} 34 | 35 | \item{chat_id}{Unique identifier for the target chat or username of 36 | the target channel (required)} 37 | } 38 | \description{ 39 | Send \code{mp3} files 40 | } 41 | -------------------------------------------------------------------------------- /man/sendMessage.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/TGBot.R 3 | \name{sendMessage} 4 | \alias{sendMessage} 5 | \title{sendMessage} 6 | \usage{ 7 | sendMessage( 8 | text = NULL, 9 | parse_mode = NULL, 10 | disable_web_page_preview = NULL, 11 | disable_notification = NULL, 12 | reply_to_message_id = NULL, 13 | chat_id = NULL 14 | ) 15 | } 16 | \arguments{ 17 | \item{text}{Text of the message to be sent (required)} 18 | 19 | \item{parse_mode}{send 'Markdown' if you want Telegram apps to show 20 | bold, italic and inline URLs in your bot's message} 21 | 22 | \item{disable_web_page_preview}{Disables link previews for links in 23 | this message} 24 | 25 | \item{disable_notification}{Sends the message silently. Users will 26 | receive a notification with no sound} 27 | 28 | \item{reply_to_message_id}{If the message is a reply, ID of the 29 | original message} 30 | 31 | \item{chat_id}{Unique identifier for the target chat or username of 32 | the target channel (required)} 33 | } 34 | \description{ 35 | Send text messages 36 | } 37 | -------------------------------------------------------------------------------- /man/sendPoll.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/TGBot.R 3 | \name{sendPoll} 4 | \alias{sendPoll} 5 | \title{sendPoll} 6 | \usage{ 7 | sendPoll( 8 | question = NULL, 9 | options = NULL, 10 | is_anonymous = TRUE, 11 | type = c("regular", "quiz"), 12 | allows_multiple_answers = FALSE, 13 | correct_option_id = NULL, 14 | is_closed = FALSE, 15 | disable_notification = NULL, 16 | reply_to_message_id = NULL, 17 | chat_id = NULL 18 | ) 19 | } 20 | \arguments{ 21 | \item{question}{Poll question, 1-255 characters} 22 | 23 | \item{options}{vector of possible answers: 2-10 strings 1-100 24 | characters each} 25 | 26 | \item{is_anonymous}{if TRUE (default) the poll needs to be 27 | anonymous} 28 | 29 | \item{type}{poll type, 'quiz' or 'regular', defaults to 'regular'} 30 | 31 | \item{allows_multiple_answers}{if TRUE the poll allows multiple 32 | answers (default to FALSE and ignored for polls in quiz mode)} 33 | 34 | \item{correct_option_id}{0-based identifier of the correct answer 35 | option, required for polls in quiz mode (eg 0 set the first 36 | answer as correct)} 37 | 38 | \item{is_closed}{if TRUE the poll needs to be immediately 39 | closed. This can be useful for poll preview. (default to FALSE)} 40 | 41 | \item{disable_notification}{Sends the message silently. Users will 42 | receive a notification with no sound} 43 | 44 | \item{reply_to_message_id}{If the message is a reply, ID of the 45 | original message} 46 | 47 | \item{chat_id}{Unique identifier for the target chat or username of 48 | the target channel (required)} 49 | } 50 | \description{ 51 | Use this method to send a native poll. 52 | } 53 | -------------------------------------------------------------------------------- /R/get_telegram_envvar.R: -------------------------------------------------------------------------------- 1 | get_telegram_envvar <- function(envvar_prefix){ 2 | 3 | f <- function(x){ 4 | envs <- as.list(Sys.getenv()) 5 | if (is.null(x)){ 6 | envs <- envs[grep(paste0("^", envvar_prefix) , names(envs))] 7 | if (length(envs) > 0L) { 8 | choices <- gsub(envvar_prefix, '', names(envs)) 9 | choice <- utils::menu(choices = choices, 10 | title = 'Choose one') 11 | return(envs[[choice]]) 12 | } else 13 | stop("I didn't found any system variable starting with ", 14 | envvar_prefix) 15 | } else if (is.character(x) && length(x) == 1L) { 16 | varname <- paste0(envvar_prefix, x) 17 | ## exact matching (for BOT, USER and GROUP) 18 | exact_match <- varname %in% names(envs) 19 | ## try list matching (for PROXY) 20 | vars_prefix <- paste0(varname, '_') 21 | list_match <- grep(paste0("^", vars_prefix), names(envs)) 22 | if (exact_match) { 23 | return(envs[[varname]]) 24 | } else if (any(list_match)) { 25 | ## extract the list 26 | select <- envs[list_match] 27 | ## remove name prefix 28 | names(select) <- gsub(vars_prefix, "", names(select)) 29 | return(select) 30 | } else 31 | stop(varname, ' (starting) environment variable (s) is (are) not available.') 32 | } else 33 | stop('x must be a length 1 char or NULL') 34 | } 35 | 36 | return(f) 37 | } 38 | 39 | #' bot_token 40 | #' 41 | #' Obtain token from system variables (in \code{Renviron}) set 42 | #' according to package naming conventions, that is 43 | #' \code{R_TELEGRAM_BOT_} where \code{X} is bot's name (first question 44 | #' answered to the botfather). 45 | #' 46 | #' @param x character of length 1 with the name of the bot; if 47 | #' \code{NULL} a menu to choose between bot is displayed and the 48 | #' proper value returned 49 | #' @examples \dontrun{ bot_token('RBot') } 50 | #' @export 51 | bot_token <- get_telegram_envvar('R_TELEGRAM_BOT_') 52 | 53 | #' user_id 54 | #' 55 | #' Obtain telegram user id from system variables (in \code{Renviron}) set 56 | #' according to package naming conventions, that is 57 | #' \code{R_TELEGRAM_USER_X} where is the user's name . 58 | #' 59 | #' @param x character of length 1 with the name of the user; if 60 | #' \code{NULL} a menu to choose between bot is displayed and the 61 | #' proper value returned 62 | #' @examples \dontrun{ user_id('me') } 63 | #' @export 64 | user_id <- get_telegram_envvar('R_TELEGRAM_USER_') 65 | 66 | #' group_id 67 | #' 68 | #' Obtain telegram user id from system variables (in \code{Renviron}) set 69 | #' according to package naming conventions, that is 70 | #' \code{R_TELEGRAM_USER_X} where is the user's name . 71 | #' 72 | #' @param x character of length 1 with the name of the user; if 73 | #' \code{NULL} a menu to choose between bot is displayed and the 74 | #' proper value returned 75 | #' @examples \dontrun{ group_id('test_group') } 76 | #' @export 77 | group_id <- get_telegram_envvar('R_TELEGRAM_GROUP_') 78 | 79 | 80 | #' proxy 81 | #' 82 | #' Obtain telegram proxy from system variables (in \code{Renviron}) set 83 | #' according to package naming conventions, that is 84 | #' \code{R_TELEGRAM_PROXY_X_Y} where X is the proxy's name and Y are the 85 | #' proxy parameters. 86 | #' 87 | #' @param x character of length 1 with the name of the proxy; if 88 | #' \code{NULL} a menu to choose between proxy is displayed and the 89 | #' proper value returned 90 | #' @examples \dontrun{ proxy('default') } 91 | #' @export 92 | proxy <- get_telegram_envvar('R_TELEGRAM_PROXY_') 93 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # telegram 2 | 3 | This package is a simple R wrapper around the 4 | [Telegram](https://telegram.org/) [Bot 5 | API](https://core.telegram.org/bots/api). 6 | 7 | It allows to send messages (text, Markdown, images, files) from R to 8 | your smartphone. 9 | 10 | More infos on telegram's bot api can be found 11 | [here](https://core.telegram.org/bots) and 12 | [here](https://core.telegram.org/bots/api). 13 | 14 | ## How to install the package? 15 | For the stable version: 16 | ```r 17 | install.packages('telegram') 18 | ``` 19 | For the development one: 20 | ```r 21 | devtools::install_github('lbraglia/telegram') 22 | ``` 23 | 24 | 25 | ## First time setup 26 | 27 | First you have to talk to the 28 | [botfather](https://telegram.me/botfather) to create a new bot; answer 29 | few questions regarding bot's name and you're ready to go. 30 | 31 | After you've done, the botfather returns a token (which has to be kept 32 | secret) that lets you handle your bot; we need this token when 33 | creating the bot object on the R side. Following [Hadley's API 34 | guidelines](https://github.com/r-lib/httr/blob/master/vignettes/api-packages.Rmd#appendix-api-key-best-practices) 35 | it's unsafe to type the token just in the R script. It's better to use 36 | enviroment variables set in `.Renviron` file. 37 | 38 | So let's say you have named your bot `RBot` (it's the first question 39 | you've answered to the botfather); then put the following line with 40 | your token in your `.Renviron`: 41 | ```bash 42 | R_TELEGRAM_BOT_RBot=123123:asdasdasd 43 | ``` 44 | If you follow the suggested `R_TELEGRAM_BOT_` prefix convention you'll be able 45 | to use the `bot_token` function (otherwise you'll have to get 46 | these variable from `Sys.getenv`). 47 | 48 | After you've finished these steps **restart R** in order to have 49 | working environment variables. 50 | 51 | 52 | ## How to connect R with Telegram 53 | 54 | Now you should be able to obtain a connection to your bot 55 | with these commands: 56 | ```r 57 | library(telegram) 58 | 59 | ## Create the bot object 60 | bot <- TGBot$new(token = bot_token('RBot')) 61 | 62 | ## Now check bot connection it should print some of your bot's data 63 | bot$getMe() 64 | 65 | ## Now, on the phone, find and say something to your bot to start a chat 66 | ## (and obtain a chat id). 67 | ## ... 68 | 69 | ## Here, check what you have inserted 70 | bot$getUpdates() 71 | 72 | ## You're interested in the message.chat.id variable: in order to set a 73 | ## default chat_id for the following commands (to ease typing) 74 | bot$set_default_chat_id(123456789) 75 | ``` 76 | 77 | After a bit using the package, you'll probably want to set the 78 | `chat_id` to your user id (or more generally, have something like an 79 | addressbook to store users' ids). If you put this in your `.Renviron`: 80 | ```bash 81 | R_TELEGRAM_USER_me=123456789 82 | ``` 83 | you'll be able to use the `user_id` function, eg like this: 84 | ```r 85 | bot$set_default_chat_id(user_id('me')) 86 | ``` 87 | Specularly if you need to interact frequently with a group, you may want 88 | to add this to your `.Renviron` (group chat id are negative integers): 89 | ```bash 90 | R_TELEGRAM_GROUP_fav_group=-123456789 91 | ``` 92 | you'll be able to use the `group_id` function, eg like this: 93 | ```r 94 | bot$set_default_chat_id(group_id('fav_group')) 95 | ``` 96 | 97 | ## How to connect using a proxy 98 | Proxy parameters are expected to be a named list (names as parameters 99 | passed to `httr::use_proxy`: 100 | 101 | ```r 102 | 103 | ## On initialization speci 104 | prx <- list('url' = '123.45.6.78', 105 | 'port' = 8080, 106 | 'username' = 'user', 107 | 'password' = 'password') 108 | bot <- TGBot$new(token = bot_token('RBot'), proxy = prx) 109 | 110 | ## .. or later (but before requests) ... 111 | bot <- TGBot$new(token = bot_token('RBot')) 112 | bot$set_proxy(proxy = prx) 113 | 114 | ## if you want to save default proxy values in .Renviron using the following 115 | ## schema 116 | ## 117 | ## R_TELEGRAM_PROXY_default_url=123.45.6.78 118 | ## R_TELEGRAM_PROXY_default_port=8080 119 | ## R_TELEGRAM_PROXY_default_username=user 120 | ## R_TELEGRAM_PROXY_default_password=password 121 | ## R_TELEGRAM_PROXY_default_auth=basic 122 | ## 123 | ## you can use the proxy utility function 124 | ## 125 | 126 | proxy('default') 127 | 128 | ## which should return 129 | ## 130 | ## $auth 131 | ## [1] "basic" 132 | ## 133 | ## $password 134 | ## [1] "password" 135 | ## 136 | ## $port 137 | ## [1] "8080" 138 | ## 139 | ## $url 140 | ## [1] "123.45.6.78" 141 | ## 142 | ## $username 143 | ## [1] "user" 144 | ## 145 | ## 146 | ## therefore, for a handy one-liner: 147 | 148 | bot <- TGBot$new(token = bot_token('RBot'), proxy = proxy('default')) 149 | ``` 150 | 151 | ## Examples of methods currently implemented 152 | Once you've followed the previous section, run the following commands 153 | and look at your phone. 154 | 155 | ```r 156 | ## ------------------ 157 | ## Send some messages 158 | ## ------------------ 159 | bot$sendMessage('This is plain text') 160 | 161 | ## Markdown support (version 2 via parse_mode = 'markdownv2') 162 | md <- " 163 | *bold* _italic_ [r-project](https://r-project.org) 164 | try `x <- rnorm(100)` at the console ... 165 | you can have 166 | ``` 167 | x <- runif(100) 168 | mean(x) 169 | ``` 170 | too 171 | " 172 | bot$sendMessage(md, parse_mode = 'markdown') 173 | ## HTML support (eg) 174 | html_message <- " 175 | bold, italic, underline, 176 | strikethrough, 177 | inline URL 178 | inline mention of a user 179 | inline fixed-width code 180 |
pre-formatted fixed-width code block
181 | " 182 | bot$sendMessage(html_message, parse_mode = 'html') 183 | 184 | ## ------------------- 185 | ## Send an image/photo 186 | ## ------------------- 187 | png('test.png') 188 | plot(rnorm(100)) 189 | dev.off() 190 | bot$sendPhoto('test.png', caption = 'This is my awesome graph') 191 | 192 | ## --------------------------------- 193 | ## Send a document (can be any file) 194 | ## --------------------------------- 195 | help(TGBot, help_type = 'pdf') 196 | bot$sendDocument('TGBot.pdf') 197 | 198 | ## --------------- 199 | ## Send a location 200 | ## --------------- 201 | bot$sendLocation(44.699, 10.6297) 202 | 203 | ## -------------- 204 | ## Send a sticker 205 | ## -------------- 206 | bot$sendSticker(system.file('r_logo.webp', package = 'telegram')) 207 | 208 | ## ------------ 209 | ## Send a video 210 | ## ------------ 211 | library(animation) 212 | saveVideo({ 213 | set.seed(1) 214 | nmax <- 10 215 | ani.options(interval = 0.4, nmax = nmax) 216 | x <- c() 217 | for (i in 1:nmax){ 218 | x <- c(x, rnorm(1)) 219 | plot(cumsum(x), lty = 2, xlim = c(1, nmax), ylim = c(-5, 5)) 220 | abline(h = 0, col = 'red') 221 | } 222 | }, video.name = 'animation.mp4') 223 | bot$sendVideo('animation.mp4') 224 | 225 | ## -------------------- 226 | ## Send mp3 audio files 227 | ## -------------------- 228 | bot$sendAudio(system.file('audio_test.mp3', package = 'telegram'), 229 | performer = 'espeak (https://espeak.sf.net)') 230 | 231 | ## ------------------------------------ 232 | ## Send voice (opus encoded .ogg files) 233 | ## ------------------------------------ 234 | bot$sendVoice(system.file('voice_test.ogg', package = 'telegram')) 235 | 236 | ## ----------------------------------------------------------------- 237 | ## Tell the user what's happening on the bot's side (for long tasks) 238 | ## ----------------------------------------------------------------- 239 | bot$sendChatAction('typing') 240 | bot$sendChatAction('upload_photo') 241 | bot$sendChatAction('record_video') 242 | bot$sendChatAction('upload_video') 243 | bot$sendChatAction('record_voice') 244 | bot$sendChatAction('upload_voice') 245 | bot$sendChatAction('upload_document') 246 | bot$sendChatAction('find_location') 247 | bot$sendChatAction('record_video_note') 248 | bot$sendChatAction('upload_video_note') 249 | 250 | ## ---------------------------------------------------------- 251 | ## Roll a dice (animation of a random number between 1 and 6) 252 | ## ---------------------------------------------------------- 253 | bot$sendDice() 254 | 255 | ## ------------ 256 | ## Start a poll 257 | ## ------------ 258 | bot$sendPoll(question = 'What is your gender?', 259 | options = c('Female', 'Male')) 260 | bot$sendPoll(question = "What was the color of Napoleon's horse?", 261 | options = c('black', 'yellow', 'white', 'green', 'pois'), 262 | is_anonymous = FALSE, 263 | type = 'quiz', 264 | correct_option_id = 2) ## it's 0 based so 2 is the third 265 | ## option (white) 266 | bot$sendPoll(question = "Which genres of music do you listen to the most?", 267 | options = c('blues', 'rock', 'metal', 'rnb', 'jazz', 'pop'), 268 | is_anonymous = FALSE, 269 | allows_multiple_answers = TRUE) 270 | 271 | ## ----------------- 272 | ## Forward a message 273 | ## ----------------- 274 | bot$forwardMessage(from_chat_id = 123456, 275 | chat_id = 123456, 276 | message_id = 35) 277 | 278 | ## --------------------------- 279 | ## Get info about user's photo 280 | ## --------------------------- 281 | bot$getUserProfilePhotos(user_id('me')) # <- alternatively, message.from.id variable in getUpdates 282 | 283 | ## ------------------------------------ 284 | ## Obtain files on the Telegram servers 285 | ## ------------------------------------ 286 | bot$getFile('asdasdasdqweqweqwe-UdYAAgI', # <- file_id from getUserProfilePhotos 287 | 'me_small.png') 288 | 289 | ``` 290 | -------------------------------------------------------------------------------- /man/TGBot.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/TGBot.R 3 | \docType{class} 4 | \name{TGBot} 5 | \alias{TGBot} 6 | \title{TGBot} 7 | \format{ 8 | An \code{\link[R6]{R6Class}} generator object. 9 | } 10 | \description{ 11 | Package main class (implementing the Telegram bot). 12 | } 13 | \section{API Methods}{ 14 | \describe{ 15 | \item{\code{\link{forwardMessage}}}{forward messages of any 16 | kind} \item{\code{\link{getFile}}}{get info about a file and 17 | download it} \item{\code{\link{getMe}}}{test your bot's auth 18 | token} \item{\code{\link{getUpdates}}}{receive incoming 19 | updates} \item{\code{\link{getUserProfilePhotos}}}{get a list 20 | of profile pictures for a user} 21 | \item{\code{\link{sendAudio}}}{send \code{mp3} files} 22 | \item{\code{\link{sendDocument}}}{send general files} 23 | \item{\code{\link{sendLocation}}}{send point on the map} 24 | \item{\code{\link{sendMessage}}}{send text messages} 25 | \item{\code{\link{sendPhoto}}}{send image files} 26 | \item{\code{\link{sendSticker}}}{send \code{.webp} stickers} 27 | \item{\code{\link{sendVideo}}}{send \code{mp4} videos} 28 | \item{\code{\link{sendVoice}}}{send ogg files encoded with 29 | OPUS} 30 | \item{\code{\link{sendPoll}}}{send a telegram poll} 31 | \item{\code{\link{stopPoll}}}{stop a telegram poll and obtain results} 32 | } 33 | } 34 | 35 | \examples{ 36 | \dontrun{ 37 | 38 | ## Without proxy 39 | bot <- TGBot$new(token = bot_token('RBot')) 40 | 41 | ## With a proxy ... 42 | prx <- list('url' = '123.45.6.78', 43 | 'port' = 8080, 44 | 'username' = 'user', 45 | 'password' = 'password') 46 | bot <- TGBot$new(token = bot_token('RBot'), proxy = prx) 47 | ## .. or 48 | bot <- TGBot$new(token = bot_token('RBot')) 49 | bot$set_proxy(proxy = prx) 50 | } 51 | } 52 | \references{ 53 | \href{http://core.telegram.org/bots}{Bots: An 54 | introduction for developers} and 55 | \href{http://core.telegram.org/bots/api}{Telegram Bot API} 56 | } 57 | \section{Methods}{ 58 | \subsection{Public methods}{ 59 | \itemize{ 60 | \item \href{#method-TGBot-new}{\code{TGBot$new()}} 61 | \item \href{#method-TGBot-set_token}{\code{TGBot$set_token()}} 62 | \item \href{#method-TGBot-set_proxy}{\code{TGBot$set_proxy()}} 63 | \item \href{#method-TGBot-set_default_chat_id}{\code{TGBot$set_default_chat_id()}} 64 | \item \href{#method-TGBot-req}{\code{TGBot$req()}} 65 | \item \href{#method-TGBot-last_request}{\code{TGBot$last_request()}} 66 | \item \href{#method-TGBot-print}{\code{TGBot$print()}} 67 | \item \href{#method-TGBot-forwardMessage}{\code{TGBot$forwardMessage()}} 68 | \item \href{#method-TGBot-getFile}{\code{TGBot$getFile()}} 69 | \item \href{#method-TGBot-getMe}{\code{TGBot$getMe()}} 70 | \item \href{#method-TGBot-getUpdates}{\code{TGBot$getUpdates()}} 71 | \item \href{#method-TGBot-getUserProfilePhotos}{\code{TGBot$getUserProfilePhotos()}} 72 | \item \href{#method-TGBot-sendAudio}{\code{TGBot$sendAudio()}} 73 | \item \href{#method-TGBot-sendChatAction}{\code{TGBot$sendChatAction()}} 74 | \item \href{#method-TGBot-sendDocument}{\code{TGBot$sendDocument()}} 75 | \item \href{#method-TGBot-sendLocation}{\code{TGBot$sendLocation()}} 76 | \item \href{#method-TGBot-sendMessage}{\code{TGBot$sendMessage()}} 77 | \item \href{#method-TGBot-sendPhoto}{\code{TGBot$sendPhoto()}} 78 | \item \href{#method-TGBot-sendSticker}{\code{TGBot$sendSticker()}} 79 | \item \href{#method-TGBot-sendVideo}{\code{TGBot$sendVideo()}} 80 | \item \href{#method-TGBot-sendVoice}{\code{TGBot$sendVoice()}} 81 | \item \href{#method-TGBot-sendDice}{\code{TGBot$sendDice()}} 82 | \item \href{#method-TGBot-sendPoll}{\code{TGBot$sendPoll()}} 83 | \item \href{#method-TGBot-stopPoll}{\code{TGBot$stopPoll()}} 84 | \item \href{#method-TGBot-clone}{\code{TGBot$clone()}} 85 | } 86 | } 87 | \if{html}{\out{
}} 88 | \if{html}{\out{}} 89 | \if{latex}{\out{\hypertarget{method-TGBot-new}{}}} 90 | \subsection{Method \code{new()}}{ 91 | \subsection{Usage}{ 92 | \if{html}{\out{
}}\preformatted{TGBot$new(token, proxy)}\if{html}{\out{
}} 93 | } 94 | 95 | } 96 | \if{html}{\out{
}} 97 | \if{html}{\out{}} 98 | \if{latex}{\out{\hypertarget{method-TGBot-set_token}{}}} 99 | \subsection{Method \code{set_token()}}{ 100 | \subsection{Usage}{ 101 | \if{html}{\out{
}}\preformatted{TGBot$set_token(token)}\if{html}{\out{
}} 102 | } 103 | 104 | } 105 | \if{html}{\out{
}} 106 | \if{html}{\out{}} 107 | \if{latex}{\out{\hypertarget{method-TGBot-set_proxy}{}}} 108 | \subsection{Method \code{set_proxy()}}{ 109 | \subsection{Usage}{ 110 | \if{html}{\out{
}}\preformatted{TGBot$set_proxy(proxy)}\if{html}{\out{
}} 111 | } 112 | 113 | } 114 | \if{html}{\out{
}} 115 | \if{html}{\out{}} 116 | \if{latex}{\out{\hypertarget{method-TGBot-set_default_chat_id}{}}} 117 | \subsection{Method \code{set_default_chat_id()}}{ 118 | \subsection{Usage}{ 119 | \if{html}{\out{
}}\preformatted{TGBot$set_default_chat_id(chat_id)}\if{html}{\out{
}} 120 | } 121 | 122 | } 123 | \if{html}{\out{
}} 124 | \if{html}{\out{}} 125 | \if{latex}{\out{\hypertarget{method-TGBot-req}{}}} 126 | \subsection{Method \code{req()}}{ 127 | \subsection{Usage}{ 128 | \if{html}{\out{
}}\preformatted{TGBot$req(method = NULL, body = NULL)}\if{html}{\out{
}} 129 | } 130 | 131 | } 132 | \if{html}{\out{
}} 133 | \if{html}{\out{}} 134 | \if{latex}{\out{\hypertarget{method-TGBot-last_request}{}}} 135 | \subsection{Method \code{last_request()}}{ 136 | \subsection{Usage}{ 137 | \if{html}{\out{
}}\preformatted{TGBot$last_request()}\if{html}{\out{
}} 138 | } 139 | 140 | } 141 | \if{html}{\out{
}} 142 | \if{html}{\out{}} 143 | \if{latex}{\out{\hypertarget{method-TGBot-print}{}}} 144 | \subsection{Method \code{print()}}{ 145 | \subsection{Usage}{ 146 | \if{html}{\out{
}}\preformatted{TGBot$print()}\if{html}{\out{
}} 147 | } 148 | 149 | } 150 | \if{html}{\out{
}} 151 | \if{html}{\out{}} 152 | \if{latex}{\out{\hypertarget{method-TGBot-forwardMessage}{}}} 153 | \subsection{Method \code{forwardMessage()}}{ 154 | \subsection{Usage}{ 155 | \if{html}{\out{
}}\preformatted{TGBot$forwardMessage( 156 | from_chat_id = NULL, 157 | message_id = NULL, 158 | disable_notification = NULL, 159 | chat_id = NULL 160 | )}\if{html}{\out{
}} 161 | } 162 | 163 | } 164 | \if{html}{\out{
}} 165 | \if{html}{\out{}} 166 | \if{latex}{\out{\hypertarget{method-TGBot-getFile}{}}} 167 | \subsection{Method \code{getFile()}}{ 168 | \subsection{Usage}{ 169 | \if{html}{\out{
}}\preformatted{TGBot$getFile(file_id, destfile = NULL)}\if{html}{\out{
}} 170 | } 171 | 172 | } 173 | \if{html}{\out{
}} 174 | \if{html}{\out{}} 175 | \if{latex}{\out{\hypertarget{method-TGBot-getMe}{}}} 176 | \subsection{Method \code{getMe()}}{ 177 | \subsection{Usage}{ 178 | \if{html}{\out{
}}\preformatted{TGBot$getMe()}\if{html}{\out{
}} 179 | } 180 | 181 | } 182 | \if{html}{\out{
}} 183 | \if{html}{\out{}} 184 | \if{latex}{\out{\hypertarget{method-TGBot-getUpdates}{}}} 185 | \subsection{Method \code{getUpdates()}}{ 186 | \subsection{Usage}{ 187 | \if{html}{\out{
}}\preformatted{TGBot$getUpdates(offset = NULL, limit = NULL)}\if{html}{\out{
}} 188 | } 189 | 190 | } 191 | \if{html}{\out{
}} 192 | \if{html}{\out{}} 193 | \if{latex}{\out{\hypertarget{method-TGBot-getUserProfilePhotos}{}}} 194 | \subsection{Method \code{getUserProfilePhotos()}}{ 195 | \subsection{Usage}{ 196 | \if{html}{\out{
}}\preformatted{TGBot$getUserProfilePhotos(user_id = NULL, offset = NULL, limit = NULL)}\if{html}{\out{
}} 197 | } 198 | 199 | } 200 | \if{html}{\out{
}} 201 | \if{html}{\out{}} 202 | \if{latex}{\out{\hypertarget{method-TGBot-sendAudio}{}}} 203 | \subsection{Method \code{sendAudio()}}{ 204 | \subsection{Usage}{ 205 | \if{html}{\out{
}}\preformatted{TGBot$sendAudio( 206 | audio = NULL, 207 | caption = NULL, 208 | duration = NULL, 209 | performer = NULL, 210 | title = NULL, 211 | disable_notification = NULL, 212 | reply_to_message_id = NULL, 213 | chat_id = NULL 214 | )}\if{html}{\out{
}} 215 | } 216 | 217 | } 218 | \if{html}{\out{
}} 219 | \if{html}{\out{}} 220 | \if{latex}{\out{\hypertarget{method-TGBot-sendChatAction}{}}} 221 | \subsection{Method \code{sendChatAction()}}{ 222 | \subsection{Usage}{ 223 | \if{html}{\out{
}}\preformatted{TGBot$sendChatAction(action = NULL, chat_id = NULL)}\if{html}{\out{
}} 224 | } 225 | 226 | } 227 | \if{html}{\out{
}} 228 | \if{html}{\out{}} 229 | \if{latex}{\out{\hypertarget{method-TGBot-sendDocument}{}}} 230 | \subsection{Method \code{sendDocument()}}{ 231 | \subsection{Usage}{ 232 | \if{html}{\out{
}}\preformatted{TGBot$sendDocument( 233 | document = NULL, 234 | disable_notification = NULL, 235 | reply_to_message_id = NULL, 236 | chat_id = NULL 237 | )}\if{html}{\out{
}} 238 | } 239 | 240 | } 241 | \if{html}{\out{
}} 242 | \if{html}{\out{}} 243 | \if{latex}{\out{\hypertarget{method-TGBot-sendLocation}{}}} 244 | \subsection{Method \code{sendLocation()}}{ 245 | \subsection{Usage}{ 246 | \if{html}{\out{
}}\preformatted{TGBot$sendLocation( 247 | latitude = NULL, 248 | longitude = NULL, 249 | disable_notification = NULL, 250 | reply_to_message_id = NULL, 251 | chat_id = NULL 252 | )}\if{html}{\out{
}} 253 | } 254 | 255 | } 256 | \if{html}{\out{
}} 257 | \if{html}{\out{}} 258 | \if{latex}{\out{\hypertarget{method-TGBot-sendMessage}{}}} 259 | \subsection{Method \code{sendMessage()}}{ 260 | \subsection{Usage}{ 261 | \if{html}{\out{
}}\preformatted{TGBot$sendMessage( 262 | text = NULL, 263 | parse_mode = NULL, 264 | disable_web_page_preview = NULL, 265 | disable_notification = NULL, 266 | reply_to_message_id = NULL, 267 | chat_id = NULL 268 | )}\if{html}{\out{
}} 269 | } 270 | 271 | } 272 | \if{html}{\out{
}} 273 | \if{html}{\out{}} 274 | \if{latex}{\out{\hypertarget{method-TGBot-sendPhoto}{}}} 275 | \subsection{Method \code{sendPhoto()}}{ 276 | \subsection{Usage}{ 277 | \if{html}{\out{
}}\preformatted{TGBot$sendPhoto( 278 | photo = NULL, 279 | caption = NULL, 280 | disable_notification = NULL, 281 | reply_to_message_id = NULL, 282 | chat_id = NULL 283 | )}\if{html}{\out{
}} 284 | } 285 | 286 | } 287 | \if{html}{\out{
}} 288 | \if{html}{\out{}} 289 | \if{latex}{\out{\hypertarget{method-TGBot-sendSticker}{}}} 290 | \subsection{Method \code{sendSticker()}}{ 291 | \subsection{Usage}{ 292 | \if{html}{\out{
}}\preformatted{TGBot$sendSticker( 293 | sticker = NULL, 294 | disable_notification = NULL, 295 | reply_to_message_id = NULL, 296 | chat_id = NULL 297 | )}\if{html}{\out{
}} 298 | } 299 | 300 | } 301 | \if{html}{\out{
}} 302 | \if{html}{\out{}} 303 | \if{latex}{\out{\hypertarget{method-TGBot-sendVideo}{}}} 304 | \subsection{Method \code{sendVideo()}}{ 305 | \subsection{Usage}{ 306 | \if{html}{\out{
}}\preformatted{TGBot$sendVideo( 307 | video = NULL, 308 | duration = NULL, 309 | caption = NULL, 310 | reply_to_message_id = NULL, 311 | chat_id = NULL 312 | )}\if{html}{\out{
}} 313 | } 314 | 315 | } 316 | \if{html}{\out{
}} 317 | \if{html}{\out{}} 318 | \if{latex}{\out{\hypertarget{method-TGBot-sendVoice}{}}} 319 | \subsection{Method \code{sendVoice()}}{ 320 | \subsection{Usage}{ 321 | \if{html}{\out{
}}\preformatted{TGBot$sendVoice( 322 | voice = NULL, 323 | duration = NULL, 324 | disable_notification = NULL, 325 | reply_to_message_id = NULL, 326 | chat_id = NULL 327 | )}\if{html}{\out{
}} 328 | } 329 | 330 | } 331 | \if{html}{\out{
}} 332 | \if{html}{\out{}} 333 | \if{latex}{\out{\hypertarget{method-TGBot-sendDice}{}}} 334 | \subsection{Method \code{sendDice()}}{ 335 | \subsection{Usage}{ 336 | \if{html}{\out{
}}\preformatted{TGBot$sendDice(disable_notification = NULL, chat_id = NULL)}\if{html}{\out{
}} 337 | } 338 | 339 | } 340 | \if{html}{\out{
}} 341 | \if{html}{\out{}} 342 | \if{latex}{\out{\hypertarget{method-TGBot-sendPoll}{}}} 343 | \subsection{Method \code{sendPoll()}}{ 344 | \subsection{Usage}{ 345 | \if{html}{\out{
}}\preformatted{TGBot$sendPoll( 346 | question = NULL, 347 | options = NULL, 348 | is_anonymous = TRUE, 349 | type = c("regular", "quiz"), 350 | allows_multiple_answers = FALSE, 351 | correct_option_id = NULL, 352 | is_closed = FALSE, 353 | disable_notification = NULL, 354 | reply_to_message_id = NULL, 355 | chat_id = NULL 356 | )}\if{html}{\out{
}} 357 | } 358 | 359 | } 360 | \if{html}{\out{
}} 361 | \if{html}{\out{}} 362 | \if{latex}{\out{\hypertarget{method-TGBot-stopPoll}{}}} 363 | \subsection{Method \code{stopPoll()}}{ 364 | \subsection{Usage}{ 365 | \if{html}{\out{
}}\preformatted{TGBot$stopPoll(message_id = NULL, chat_id = NULL)}\if{html}{\out{
}} 366 | } 367 | 368 | } 369 | \if{html}{\out{
}} 370 | \if{html}{\out{}} 371 | \if{latex}{\out{\hypertarget{method-TGBot-clone}{}}} 372 | \subsection{Method \code{clone()}}{ 373 | The objects of this class are cloneable with this method. 374 | \subsection{Usage}{ 375 | \if{html}{\out{
}}\preformatted{TGBot$clone(deep = FALSE)}\if{html}{\out{
}} 376 | } 377 | 378 | \subsection{Arguments}{ 379 | \if{html}{\out{
}} 380 | \describe{ 381 | \item{\code{deep}}{Whether to make a deep clone.} 382 | } 383 | \if{html}{\out{
}} 384 | } 385 | } 386 | } 387 | -------------------------------------------------------------------------------- /R/TGBot.R: -------------------------------------------------------------------------------- 1 | ## ------ 2 | ## UTILS 3 | ## ------ 4 | 5 | self <- 'shut up R CMD CHECK' 6 | private <- 'shut up R CMD CHECK' 7 | not_implemented <- function() stop('Currently not implemented') 8 | 9 | initialize <- function(token, proxy) { 10 | self$set_token(token) 11 | self$set_proxy(proxy) 12 | } 13 | 14 | set_token <- function(token){ 15 | if (!missing(token)) 16 | private$token <- token 17 | } 18 | 19 | set_proxy <- function(proxy){ 20 | if (!missing(proxy)){ 21 | if (is.list(proxy)){ 22 | private$proxy_url <- as.character(proxy$url) 23 | private$proxy_port <- as.integer(proxy$port) 24 | private$proxy_username <- as.character(proxy$username) 25 | private$proxy_password <- as.character(proxy$password) 26 | private$proxy_auth <- 27 | if ("auth" %in% names(proxy)) as.character(proxy$auth) 28 | else 'basic' 29 | private$proxy_set <- TRUE 30 | } else { 31 | private$proxy_set <- FALSE 32 | } 33 | } else { 34 | private$proxy_set <- FALSE 35 | } 36 | } 37 | 38 | 39 | set_default_chat_id <- function(chat_id){ 40 | if (!missing(chat_id)) 41 | private$default_chat_id <- as.character(chat_id) 42 | } 43 | 44 | make_body <- function(...){ 45 | body <- list(...) 46 | body <- body[!unlist(lapply(body, is.null))] 47 | body 48 | } 49 | 50 | request <- function(method = NULL, body = NULL){ 51 | if (is.null(method)) stop("method can't be null") 52 | api_url <- sprintf('https://api.telegram.org/bot%s/%s', 53 | private$token, 54 | method) 55 | private$lr_method <- method 56 | private$lr_body <- body 57 | private$lr_response <- r <- 58 | if (private$proxy_set) { 59 | ## use proxy 60 | httr::POST(url = api_url, 61 | body = body, 62 | httr::use_proxy( 63 | url = private$proxy_url, 64 | port = private$proxy_port, 65 | username = private$proxy_username, 66 | password = private$proxy_password, 67 | auth = private$proxy_auth)) 68 | } else { 69 | ## without proxy 70 | httr::POST(url = api_url, body = body) 71 | } 72 | httr::warn_for_status(r) 73 | r 74 | } 75 | 76 | last_request <- function(){ 77 | list('method' = private$lr_method, 78 | 'body' = private$lr_body, 79 | 'response' = private$lr_response) 80 | } 81 | 82 | ## pretty printer for methods 83 | make_methods_string <- function(meth, incipit){ 84 | wrap_at <- 72 85 | meth_string <- paste0(incipit, '\n', paste(meth, collapse = ", ")) 86 | paste0(paste(strwrap(meth_string, width = wrap_at), 87 | collapse = '\n'), 88 | '\n') 89 | } 90 | 91 | tgprint <- function(){ 92 | obj <- objects(self) 93 | api_methods <- c("getMe", 94 | "sendMessage", 95 | "forwardMessage", 96 | "sendPhoto", 97 | "sendAudio", 98 | "sendDocument", 99 | "sendSticker", 100 | "sendVideo", 101 | "sendVoice", 102 | 'sendPoll', 103 | "sendLocation", 104 | "sendChatAction", 105 | "getUserProfilePhotos", 106 | "getUpdates", 107 | ## "setWebhook", 108 | "getFile") 109 | dont_show <- c("clone", "initialize", "print") 110 | avail_methods <- sort(api_methods[api_methods %in% obj]) 111 | remaining_methods <- sort(obj[! obj %in% avail_methods]) 112 | remaining_methods <- remaining_methods[!(remaining_methods %in% dont_show)] 113 | api_string <- make_methods_string(avail_methods, "API methods: ") 114 | remaining_string <- make_methods_string(remaining_methods, 115 | "Other methods: ") 116 | cat("\n\n") 117 | if (!is.null(private$bot_first_name)) 118 | cat(sprintf('Bot name:\t%s\n', private$bot_first_name)) 119 | if (!is.null(private$bot_first_name)) 120 | cat(sprintf('Bot username:\t%s\n\n', private$bot_username)) 121 | cat(api_string, '\n') 122 | cat(remaining_string, '\n') 123 | } 124 | 125 | check_chat_id <- function(chat_id){ 126 | if (is.null(chat_id)){ 127 | if (is.null(private$default_chat_id)) 128 | stop("chat_id can't be missing") 129 | else 130 | return(private$default_chat_id) 131 | } else 132 | return(chat_id) 133 | } 134 | 135 | ## check for user insertion for a method 136 | ## - param is the insertion 137 | ## - type is data type 138 | ## - required is if the parameter is required for the method 139 | ## - if scalar is TRUE take only the first element (of the object, eg 140 | ## the vector) 141 | check_param <- function(param, type, required = FALSE, scalar = TRUE){ 142 | char_name <- deparse(substitute(char)) 143 | coerce <- c('char' = as.character, 144 | 'int' = as.integer, 145 | 'log' = as.logical, 146 | 'float' = as.numeric) 147 | if(is.null(param)){ 148 | if (required) stop(char_name, " can't be missing.") 149 | else NULL 150 | } else { 151 | ## scalar by default (but if set to false leave a vector of 152 | ## parameters (eg used in sendPoll for answers) 153 | rval <- coerce[[type]](param) 154 | if (scalar) rval <- rval[1] 155 | rval 156 | } 157 | } 158 | 159 | check_file <- function(path, required = FALSE){ 160 | if (file.exists(path)) 161 | path 162 | else { 163 | if (required) stop(path, 'is not a valid path') 164 | else NULL 165 | } 166 | } 167 | 168 | parsed_content <- function(x){ 169 | tx <- httr::content(x, as = 'text', encoding = 'UTF-8') 170 | rval <- jsonlite::fromJSON(tx)$result 171 | rval 172 | } 173 | 174 | 175 | ## ------ 176 | ## TG API 177 | ## ------ 178 | 179 | #' forwardMessage 180 | #' 181 | #' Forward messages of any kind 182 | #' 183 | #' @param from_chat_id Unique identifier for the chat where the 184 | #' original message was sent (required) 185 | #' @param message_id Unique message identifier (required) 186 | #' @param disable_notification Sends the message silently. Users will 187 | #' receive a notification with no sound 188 | #' @param chat_id Unique identifier for the target chat or username of 189 | #' the target channel (required) 190 | forwardMessage <- function(from_chat_id = NULL, 191 | message_id = NULL, 192 | disable_notification = NULL, 193 | chat_id = NULL) 194 | { 195 | ## params 196 | chat_id <- private$check_chat_id(chat_id = chat_id) 197 | from_chat_id <- check_param(from_chat_id, 'char', required = TRUE) 198 | message_id <- check_param(message_id, 'char', required = TRUE) 199 | disable_notification <- check_param(disable_notification, 'log') 200 | ## request body 201 | body <- make_body('chat_id' = chat_id, 202 | 'from_chat_id' = from_chat_id, 203 | 'disable_notification' = disable_notification, 204 | 'message_id' = message_id) 205 | ## request 206 | r <- private$request('forwardMessage', body = body) 207 | ## response handling 208 | invisible(r) 209 | } 210 | 211 | #' getFile 212 | #' 213 | #' Get info about a file and download it 214 | #' 215 | #' @param file_id File identifier (required) 216 | #' @param destfile Destination path; if specified the file will be 217 | #' downloaded 218 | getFile <- function(file_id, destfile = NULL) { 219 | file_id <- check_param(file_id, 'char', required = TRUE) 220 | ## request body 221 | body <- make_body('file_id' = file_id) 222 | ## request 223 | r <- private$request('getFile', body = body) 224 | ## response handling 225 | if (r$status == 200){ 226 | path <- parsed_content(r)$file_path 227 | dl_url <- sprintf('https://api.telegram.org/file/bot%s/%s', 228 | private$token, 229 | path) 230 | if (!is.null(destfile)) 231 | curl::curl_download(dl_url, destfile = destfile) 232 | invisible(dl_url) 233 | } else 234 | invisible(NULL) 235 | } 236 | 237 | #' getMe 238 | #' 239 | #' Test your bot's auth token 240 | getMe <- function() 241 | { 242 | r <- private$request('getMe') 243 | if (r$status == 200){ 244 | pc <- parsed_content(r) 245 | private$bot_first_name <- pc$first_name 246 | private$bot_username <- pc$username 247 | cat(sprintf('Bot name:\t%s\nBot username:\t%s\n', 248 | private$bot_first_name, 249 | private$bot_username)) 250 | } 251 | invisible(r) 252 | } 253 | 254 | #' getUpdates 255 | #' 256 | #' Receive incoming updates 257 | #' 258 | #' @param offset Identifier of the first update to be returned. 259 | #' @param limit Limits the number of updates to be retrieved. Values 260 | #' between 1-100 are accepted. Defaults to 100 261 | getUpdates <- function(offset = NULL, 262 | limit = NULL) 263 | { 264 | ## params 265 | offset <- check_param(offset, 'int') 266 | limit <- check_param(limit, 'int') 267 | ## request body 268 | body <- make_body('offset' = offset, 269 | 'limit' = limit) 270 | r <- private$request('getUpdates', body = body) 271 | if (r$status == 200){ 272 | rval <- parsed_content(r) 273 | return(rval) 274 | } 275 | else 276 | invisible(NULL) 277 | } 278 | 279 | #' getUserProfilePhotos 280 | #' 281 | #' Get a list of profile pictures for a user 282 | #' 283 | #' @param user_id Unique identifier of the target user (required) 284 | #' @param offset Sequential number of the first photo to be 285 | #' returned. By default, all photos are returned 286 | #' @param limit Limits the number of photos to be retrieved. Values 287 | #' between 1-100 are accepted. Defaults to 100 288 | getUserProfilePhotos <- function(user_id = NULL, 289 | offset = NULL, 290 | limit = NULL) 291 | { 292 | ## params 293 | user_id <- check_param(user_id, 'int', required = TRUE) 294 | offset <- check_param(offset, 'int') 295 | limit <- check_param(limit, 'int') 296 | ## request body 297 | body <- make_body('user_id' = user_id, 298 | 'offset' = offset, 299 | 'limit' = limit) 300 | ## request 301 | r <- private$request('getUserProfilePhotos', body = body) 302 | ## response handling 303 | if (r$status == 200){ 304 | file_id <- parsed_content(r)$photos 305 | rval <- do.call(rbind, file_id) 306 | return(rval) 307 | } else 308 | invisible(NULL) 309 | } 310 | 311 | 312 | 313 | #' sendAudio 314 | #' 315 | #' Send \code{mp3} files 316 | #' 317 | #' @param audio path to audio file to send (required) 318 | #' @param duration duration of the audio in seconds 319 | #' @param performer performer 320 | #' @param title track name 321 | #' @param caption audio caption 322 | #' @param disable_notification Sends the message silently. Users will 323 | #' receive a notification with no sound 324 | #' @param reply_to_message_id If the message is a reply, ID of the 325 | #' original message 326 | #' @param chat_id Unique identifier for the target chat or username of 327 | #' the target channel (required) 328 | sendAudio <- function(audio = NULL, 329 | caption = NULL, 330 | duration = NULL, 331 | performer = NULL, 332 | title = NULL, 333 | disable_notification = NULL, 334 | reply_to_message_id = NULL, 335 | chat_id = NULL) 336 | { 337 | ## params 338 | chat_id <- private$check_chat_id(chat_id = chat_id) 339 | caption <- check_param(caption, 'char') 340 | audio <- check_file(audio, required = TRUE) 341 | duration <- check_param(duration, 'int') 342 | performer <- check_param(performer, 'char') 343 | title <- check_param(title, 'char') 344 | disable_notification <- check_param(disable_notification, 'log') 345 | reply_to_message_id <- check_param(reply_to_message_id, 'int') 346 | ## request body 347 | body <- make_body('chat_id' = chat_id, 348 | 'audio' = httr::upload_file(audio), 349 | 'caption' = caption, 350 | 'duration' = duration, 351 | 'performer' = performer, 352 | 'title' = title, 353 | 'disable_notification' = disable_notification, 354 | 'reply_to_message_id' = reply_to_message_id) 355 | ## request 356 | r <- private$request('sendAudio', body = body) 357 | ## response handling 358 | invisible(r) 359 | } 360 | 361 | #' sendChatAction 362 | #' 363 | #' Tell the user that something is happening on the bot's side 364 | #' @param action type of action to broadcast. Choose one, depending on 365 | #' what the user is about to receive: "typing" for text messages, 366 | #' "upload_photo" for photos, "record_video" or "upload_video" for 367 | #' videos, "record_voice" or "upload_voice" for voice notes, 368 | #' "upload_document" for general files, "find_location" for 369 | #' location data, "record_video_note" or "upload_video_note" for 370 | #' video notes. 371 | #' @param chat_id Unique identifier for the target chat or username of 372 | #' the target channel (required) 373 | sendChatAction <- function(action = NULL, 374 | chat_id = NULL) 375 | { 376 | ## params 377 | chat_id <- private$check_chat_id(chat_id = chat_id) 378 | action <- check_param(action, 'char') 379 | ## request body 380 | body <- make_body('chat_id' = chat_id, 381 | 'action' = action) 382 | ## request 383 | r <- private$request('sendChatAction', body = body) 384 | ## response handling 385 | invisible(r) 386 | } 387 | 388 | #' sendDocument 389 | #' 390 | #' Send general files 391 | #' 392 | #' @param document path to the file to send (required) 393 | #' @param disable_notification Sends the message silently. Users will 394 | #' receive a notification with no sound 395 | #' @param reply_to_message_id if the message is a reply, ID of the 396 | #' original message 397 | #' @param chat_id Unique identifier for the target chat or username of 398 | #' the target channel (required) 399 | sendDocument <- function(document = NULL, 400 | disable_notification = NULL, 401 | reply_to_message_id = NULL, 402 | chat_id = NULL) 403 | { 404 | ## params 405 | chat_id <- private$check_chat_id(chat_id = chat_id) 406 | document <- check_file(document, required = TRUE) 407 | disable_notification <- check_param(disable_notification, 'log') 408 | reply_to_message_id <- check_param(reply_to_message_id, 'int') 409 | ## request body 410 | body <- make_body('chat_id' = chat_id, 411 | 'document' = httr::upload_file(document), 412 | 'disable_notification' = disable_notification, 413 | 'reply_to_message_id' = reply_to_message_id) 414 | ## request 415 | r <- private$request('sendDocument', body = body) 416 | ## response handling 417 | invisible(r) 418 | } 419 | 420 | #' sendLocation 421 | #' 422 | #' Send point on the map 423 | #' 424 | #' @param latitude Latitude of location (required) 425 | #' @param longitude Longitude of location (required) 426 | #' @param disable_notification Sends the message silently. Users will 427 | #' receive a notification with no sound 428 | #' @param reply_to_message_id If the message is a reply, ID of the 429 | #' original message 430 | #' @param chat_id Unique identifier for the target chat or username of 431 | #' the target channel (required) 432 | sendLocation <- function(latitude = NULL, 433 | longitude = NULL, 434 | disable_notification = NULL, 435 | reply_to_message_id = NULL, 436 | chat_id = NULL) 437 | { 438 | ## params 439 | chat_id <- private$check_chat_id(chat_id = chat_id) 440 | latitude <- check_param(latitude, 'float', required = TRUE) 441 | longitude <- check_param(longitude, 'float', required = TRUE) 442 | disable_notification <- check_param(disable_notification, 'log') 443 | reply_to_message_id <- check_param(reply_to_message_id, 'int') 444 | ## request body 445 | body <- make_body('chat_id' = chat_id, 446 | 'latitude' = latitude, 447 | 'longitude' = longitude, 448 | 'disable_notification' = disable_notification, 449 | 'reply_to_message_id' = reply_to_message_id) 450 | ## request 451 | r <- private$request('sendLocation', body = body) 452 | ## response handling 453 | invisible(r) 454 | } 455 | 456 | #' sendMessage 457 | #' 458 | #' Send text messages 459 | #' 460 | #' @param text Text of the message to be sent (required) 461 | #' @param parse_mode send 'Markdown' if you want Telegram apps to show 462 | #' bold, italic and inline URLs in your bot's message 463 | #' @param disable_web_page_preview Disables link previews for links in 464 | #' this message 465 | #' @param disable_notification Sends the message silently. Users will 466 | #' receive a notification with no sound 467 | #' @param reply_to_message_id If the message is a reply, ID of the 468 | #' original message 469 | #' @param chat_id Unique identifier for the target chat or username of 470 | #' the target channel (required) 471 | sendMessage <- function(text = NULL, 472 | parse_mode = NULL, 473 | disable_web_page_preview = NULL, 474 | disable_notification = NULL, 475 | reply_to_message_id = NULL, 476 | chat_id = NULL) 477 | { 478 | ## params 479 | chat_id <- private$check_chat_id(chat_id = chat_id) 480 | text <- check_param(text, 'char', required = TRUE) 481 | parse_mode <- check_param(parse_mode, 'char') 482 | disable_web_page_preview <- check_param(disable_web_page_preview, 'log') 483 | disable_notification <- check_param(disable_notification, 'log') 484 | reply_to_message_id <- check_param(reply_to_message_id, 'int') 485 | ## request body 486 | body <- make_body('chat_id' = chat_id, 487 | 'text' = as.character(text), 488 | 'parse_mode' = parse_mode, 489 | 'disable_web_page_preview' = disable_web_page_preview, 490 | 'disable_notification' = disable_notification, 491 | 'reply_to_message_id' = reply_to_message_id) 492 | ## request 493 | r <- private$request('sendMessage', body = body) 494 | ## response handling 495 | invisible(r) 496 | } 497 | 498 | #' sendPhoto 499 | #' 500 | #' Send image files 501 | #' 502 | #' @param photo photo to send (required) 503 | #' @param caption photo caption 504 | #' @param disable_notification Sends the message silently. Users will 505 | #' receive a notification with no sound 506 | #' @param reply_to_message_id If the message is a reply, ID of the 507 | #' original message 508 | #' @param chat_id Unique identifier for the target chat or username of 509 | #' the target channel (required) 510 | sendPhoto <- function(photo = NULL, 511 | caption = NULL, 512 | disable_notification = NULL, 513 | reply_to_message_id = NULL, 514 | chat_id = NULL) 515 | { 516 | ## params 517 | chat_id <- private$check_chat_id(chat_id = chat_id) 518 | photo <- check_file(photo, required = TRUE) 519 | caption <- check_param(caption, 'char') 520 | disable_notification <- check_param(disable_notification, 'log') 521 | reply_to_message_id <- check_param(reply_to_message_id, 'int') 522 | ## request body 523 | body <- make_body('chat_id' = chat_id, 524 | 'photo' = httr::upload_file(photo), 525 | 'caption' = caption, 526 | 'disable_notification' = disable_notification, 527 | 'reply_to_message_id' = reply_to_message_id) 528 | ## request 529 | r <- private$request('sendPhoto', body = body) 530 | ## response handling 531 | invisible(r) 532 | } 533 | 534 | #' sendSticker 535 | #' 536 | #' Send \code{.webp} stickers 537 | #' 538 | #' @param sticker sticker to send (required) 539 | #' @param disable_notification Sends the message silently. Users will 540 | #' receive a notification with no sound 541 | #' @param reply_to_message_id If the message is a reply, ID of the 542 | #' original message 543 | #' @param chat_id Unique identifier for the target chat or username of 544 | #' the target channel (required) 545 | sendSticker <- function(sticker = NULL, 546 | disable_notification = NULL, 547 | reply_to_message_id = NULL, 548 | chat_id = NULL) 549 | { 550 | ## params 551 | chat_id <- private$check_chat_id(chat_id = chat_id) 552 | sticker <- check_file(sticker, required = TRUE) 553 | disable_notification <- check_param(disable_notification, 'log') 554 | reply_to_message_id <- check_param(reply_to_message_id, 'int') 555 | ## request body 556 | body <- make_body('chat_id' = chat_id, 557 | 'sticker' = httr::upload_file(sticker), 558 | 'disable_notification' = disable_notification, 559 | 'reply_to_message_id' = reply_to_message_id) 560 | ## request 561 | r <- private$request('sendSticker', body = body) 562 | ## response handling 563 | invisible(r) 564 | } 565 | 566 | #' sendVideo 567 | #' 568 | #' Send \code{mp4} videos 569 | #' 570 | #' @param video Video to send (required) 571 | #' @param duration Duration of sent video in seconds 572 | #' @param caption Video caption 573 | #' @param reply_to_message_id If the message is a reply, ID of the 574 | #' original message 575 | #' @param chat_id Unique identifier for the target chat or username of 576 | #' the target channel (required) 577 | sendVideo <- function(video = NULL, 578 | duration = NULL, 579 | caption = NULL, 580 | reply_to_message_id = NULL, 581 | chat_id = NULL) 582 | { 583 | ## params 584 | chat_id <- private$check_chat_id(chat_id = chat_id) 585 | video <- check_file(video, required = TRUE) 586 | duration <- check_param(duration, 'int') 587 | caption <- check_param(caption, 'char') 588 | reply_to_message_id <- check_param(reply_to_message_id, 'int') 589 | ## request body 590 | body <- make_body('chat_id' = chat_id, 591 | 'video' = httr::upload_file(video), 592 | 'duration' = duration, 593 | 'caption' = caption, 594 | 'reply_to_message_id' = reply_to_message_id) 595 | ## request 596 | r <- private$request('sendVideo', body = body) 597 | ## response handling 598 | invisible(r) 599 | } 600 | 601 | #' sendVoice 602 | #' 603 | #' Send \code{.ogg} files encoded with OPUS 604 | #' 605 | #' @param voice Audio file to send (required) 606 | #' @param duration Duration of sent audio in seconds 607 | #' @param disable_notification Sends the message silently. Users will 608 | #' receive a notification with no sound 609 | #' @param reply_to_message_id If the message is a reply, ID of the 610 | #' original message 611 | #' @param chat_id Unique identifier for the target chat or username of 612 | #' the target channel (required) 613 | sendVoice <- function(voice = NULL, 614 | duration = NULL, 615 | disable_notification = NULL, 616 | reply_to_message_id = NULL, 617 | chat_id = NULL) 618 | { 619 | ## params 620 | chat_id <- private$check_chat_id(chat_id = chat_id) 621 | voice <- check_file(voice, required = TRUE) 622 | duration <- check_param(duration, 'int') 623 | disable_notification <- check_param(disable_notification, 'log') 624 | reply_to_message_id <- check_param(reply_to_message_id, 'int') 625 | ## request body 626 | body <- make_body('chat_id' = chat_id, 627 | 'voice' = httr::upload_file(voice), 628 | 'duration' = duration, 629 | 'disable_notification' = disable_notification, 630 | 'reply_to_message_id' = reply_to_message_id) 631 | ## request 632 | r <- private$request('sendVoice', body = body) 633 | ## response handling 634 | invisible(r) 635 | } 636 | 637 | #' sendDice 638 | #' 639 | #' Use this method to send a dice, which will have a random value from 640 | #' 1 to 6. 641 | #' 642 | #' @param disable_notification Sends the message silently. Users will 643 | #' receive a notification with no sound 644 | #' @param chat_id Unique identifier for the target chat or username of 645 | #' the target channel (required) 646 | sendDice <- function(disable_notification = NULL, 647 | chat_id = NULL) 648 | { 649 | ## params 650 | chat_id <- private$check_chat_id(chat_id = chat_id) 651 | disable_notification <- check_param(disable_notification, 'log') 652 | ## request body 653 | body <- make_body( 654 | 'chat_id' = chat_id, 655 | 'disable_notification' = disable_notification) 656 | ## request 657 | r <- private$request('sendDice', body = body) 658 | ## response handling 659 | invisible(r) 660 | } 661 | 662 | #' sendPoll 663 | #' 664 | #' Use this method to send a native poll. 665 | #' 666 | #' @param question Poll question, 1-255 characters 667 | #' @param options vector of possible answers: 2-10 strings 1-100 668 | #' characters each 669 | #' @param is_anonymous if TRUE (default) the poll needs to be 670 | #' anonymous 671 | #' @param type poll type, 'quiz' or 'regular', defaults to 'regular' 672 | #' @param allows_multiple_answers if TRUE the poll allows multiple 673 | #' answers (default to FALSE and ignored for polls in quiz mode) 674 | #' @param correct_option_id 0-based identifier of the correct answer 675 | #' option, required for polls in quiz mode (eg 0 set the first 676 | #' answer as correct) 677 | #' @param is_closed if TRUE the poll needs to be immediately 678 | #' closed. This can be useful for poll preview. (default to FALSE) 679 | #' @param disable_notification Sends the message silently. Users will 680 | #' receive a notification with no sound 681 | #' @param reply_to_message_id If the message is a reply, ID of the 682 | #' original message 683 | #' @param chat_id Unique identifier for the target chat or username of 684 | #' the target channel (required) 685 | #' 686 | sendPoll <- function(question = NULL, 687 | options = NULL, 688 | is_anonymous = TRUE, 689 | type = c('regular', 'quiz'), 690 | allows_multiple_answers = FALSE, 691 | correct_option_id = NULL, 692 | is_closed = FALSE, 693 | disable_notification = NULL, 694 | reply_to_message_id = NULL, 695 | chat_id = NULL) 696 | { 697 | ## params 698 | chat_id <- private$check_chat_id(chat_id = chat_id) 699 | question <- check_param(question, 'char') 700 | options <- check_param(options, 'char', scalar = FALSE) 701 | is_anonymous <- check_param(is_anonymous, 'log') 702 | type <- match.arg(type) 703 | allows_multiple_answers <- check_param(allows_multiple_answers, 'log') 704 | ## correct options is required only for quiz polls 705 | correct_option_id <- check_param( 706 | correct_option_id, 'int', required = type %in% 'quiz') 707 | is_closed <- check_param(is_closed, 'log') 708 | disable_notification <- check_param(disable_notification, 'log') 709 | reply_to_message_id <- check_param(reply_to_message_id, 'int') 710 | ## request body 711 | body <- make_body('chat_id' = chat_id, 712 | 'question' = question, 713 | 'options' = jsonlite::toJSON(options), 714 | 'is_anonymous' = is_anonymous, 715 | 'type' = type, 716 | 'allows_multiple_answers' = allows_multiple_answers, 717 | 'correct_option_id' = correct_option_id, 718 | 'disable_notification' = disable_notification, 719 | 'is_closed' = is_closed, 720 | 'reply_to_message_id' = reply_to_message_id) 721 | ## request 722 | r <- private$request('sendPoll', body = body) 723 | ## response handling 724 | invisible(r) 725 | } 726 | 727 | 728 | #' stopPoll 729 | #' 730 | #' Use this method to stop a poll which was sent by the bot. 731 | #' 732 | #' @param message_id Identifier of the original message with the poll 733 | #' @param chat_id Unique identifier for the target chat or username of 734 | #' the target channel (required) 735 | stopPoll <- function(message_id = NULL, 736 | chat_id = NULL) 737 | { 738 | ## params 739 | chat_id <- private$check_chat_id(chat_id = chat_id) 740 | ## message_id <- check_param(message_id, 'int', required = TRUE) 741 | 742 | ## request body 743 | body <- make_body('chat_id' = chat_id, 744 | 'message_id' = message_id) 745 | ## request 746 | r <- private$request('stopPoll', body = body) 747 | ## response handling 748 | invisible(r) 749 | } 750 | 751 | 752 | ## setWebhook <- function() not_implemented() 753 | 754 | 755 | #' TGBot 756 | #' 757 | #' Package main class (implementing the Telegram bot). 758 | #' 759 | #' @docType class 760 | #' @format An \code{\link[R6]{R6Class}} generator object. 761 | #' @section API Methods: \describe{ 762 | #' \item{\code{\link{forwardMessage}}}{forward messages of any 763 | #' kind} \item{\code{\link{getFile}}}{get info about a file and 764 | #' download it} \item{\code{\link{getMe}}}{test your bot's auth 765 | #' token} \item{\code{\link{getUpdates}}}{receive incoming 766 | #' updates} \item{\code{\link{getUserProfilePhotos}}}{get a list 767 | #' of profile pictures for a user} 768 | #' \item{\code{\link{sendAudio}}}{send \code{mp3} files} 769 | #' \item{\code{\link{sendDocument}}}{send general files} 770 | #' \item{\code{\link{sendLocation}}}{send point on the map} 771 | #' \item{\code{\link{sendMessage}}}{send text messages} 772 | #' \item{\code{\link{sendPhoto}}}{send image files} 773 | #' \item{\code{\link{sendSticker}}}{send \code{.webp} stickers} 774 | #' \item{\code{\link{sendVideo}}}{send \code{mp4} videos} 775 | #' \item{\code{\link{sendVoice}}}{send ogg files encoded with 776 | #' OPUS} 777 | #' \item{\code{\link{sendPoll}}}{send a telegram poll} 778 | #' \item{\code{\link{stopPoll}}}{stop a telegram poll and obtain results} 779 | #' } 780 | #' @references \href{http://core.telegram.org/bots}{Bots: An 781 | #' introduction for developers} and 782 | #' \href{http://core.telegram.org/bots/api}{Telegram Bot API} 783 | #' @examples \dontrun{ 784 | #' 785 | #' ## Without proxy 786 | #' bot <- TGBot$new(token = bot_token('RBot')) 787 | #' 788 | #' ## With a proxy ... 789 | #' prx <- list('url' = '123.45.6.78', 790 | #' 'port' = 8080, 791 | #' 'username' = 'user', 792 | #' 'password' = 'password') 793 | #' bot <- TGBot$new(token = bot_token('RBot'), proxy = prx) 794 | #' ## .. or 795 | #' bot <- TGBot$new(token = bot_token('RBot')) 796 | #' bot$set_proxy(proxy = prx) 797 | #' } 798 | #' @export 799 | TGBot <- R6::R6Class("TGBot", 800 | public = list( 801 | ## --------------------- 802 | ## methods - class utils 803 | ## --------------------- 804 | initialize = initialize, 805 | set_token = set_token, 806 | set_proxy = set_proxy, 807 | set_default_chat_id = set_default_chat_id, 808 | print = tgprint, 809 | 810 | ## This is for development/debug only, comment on release! 811 | req = request, 812 | last_request = last_request, 813 | 814 | ## --------------------- 815 | ## methods - TG api 816 | ## --------------------- 817 | 818 | ## later or never 819 | ## -------------- 820 | ## sendAnimation 821 | ## sendMediaGroup 822 | ## sendVideoNote 823 | ## **LiveLocation 824 | ## sendChatAction 825 | ## sendVenue 826 | ## sendContact 827 | ## **Chat* 828 | ## answerCallbackQuery 829 | ## setMyCommands 830 | ## other **Sticker** stuff 831 | 832 | forwardMessage = forwardMessage, 833 | getFile = getFile, 834 | getMe = getMe, 835 | getUpdates = getUpdates, 836 | getUserProfilePhotos = getUserProfilePhotos, 837 | sendAudio = sendAudio, 838 | sendChatAction = sendChatAction, 839 | sendDice = sendDice, 840 | sendDocument = sendDocument, 841 | sendLocation = sendLocation, 842 | sendMessage = sendMessage, 843 | sendPhoto = sendPhoto, 844 | sendPoll = sendPoll, 845 | sendSticker = sendSticker, 846 | sendVideo = sendVideo, 847 | sendVoice = sendVoice, 848 | ## setWebhook = setWebhook, 849 | stopPoll = stopPoll 850 | 851 | ), 852 | private = list( 853 | ## --------------------- 854 | ## members 855 | ## --------------------- 856 | token = NULL, 857 | default_chat_id = NULL, 858 | bot_first_name = NULL, 859 | bot_username = NULL, 860 | ## proxy data 861 | proxy_set = NULL, 862 | proxy_url = NULL, 863 | proxy_port = NULL, 864 | proxy_username = NULL, 865 | proxy_password = NULL, 866 | proxy_auth = NULL, 867 | ## last request (LR) infos 868 | lr_method = NULL, ## method 869 | lr_body = NULL, ## body 870 | lr_response = NULL, ## response 871 | ## --------------------- 872 | ## methods 873 | ## --------------------- 874 | request = request, ## make the request 875 | check_chat_id = check_chat_id 876 | ) 877 | ) 878 | --------------------------------------------------------------------------------