2020-03-09 17:56:13 +00:00
DEFAULTS = {
lib_path : 'lib/' ,
verbosity : 2 ,
loglevel : :debug ,
client : { api_id : 50322 , api_hash : '9ff1a639196c0779c86dd661af8522ba' , use_chat_info_database : false } ,
content : { path : '' , link : '' , upload : '' }
}
PERMISSIONS = {
admin : { can_be_edited : true , can_change_info : true , can_post_messages : true , can_edit_messages : true , can_delete_messages : true , can_invite_users : true , can_restrict_members : true , can_pin_messages : true , can_promote_members : false } ,
member : TD :: Types :: ChatPermissions . new ( can_send_messages : true , can_send_media_messages : true , can_send_polls : true , can_send_other_messages : true , can_add_web_page_previews : true , can_change_info : true , can_invite_users : true , can_pin_messages : true ) ,
readonly : TD :: Types :: ChatPermissions . new ( can_send_messages : false , can_send_media_messages : false , can_send_polls : false , can_send_other_messages : false , can_add_web_page_previews : false , can_change_info : false , can_invite_users : false , can_pin_messages : false ) ,
2020-04-12 18:47:21 +00:00
login : TD :: Types :: PhoneNumberAuthenticationSettings . new ( allow_flash_call : false , is_current_phone_number : false , allow_sms_retriever_api : false ) ,
2020-03-09 17:56:13 +00:00
}
2019-08-21 12:43:07 +00:00
HELP_GATE_CMD = %q{ Available commands:
/ login phone — sign in
/ logout — sign out
/ code — check one-time code
/ password — check 2fa password
/ setusername username — update @username
/ setname first last — update name
/ setbio — update about
/ setpassword [old] [new] — set or remove password
/ config [param] [value] — view or update configuration options
2020-03-09 07:04:24 +00:00
2019-08-21 12:43:07 +00:00
Configuration options
2020-03-09 07:04:24 +00:00
timezone < timezone > — adjust timezone for Telegram user statuses ( example : + 02 : 00 )
keeponline < bool > — always keep telegram session online and rely on jabber offline messages ( example : true )
2020-09-26 08:03:01 +00:00
rawmessages < bool > — do not add additional info ( message id , origin etc . ) to incoming messages ( example : true )
2019-08-21 12:43:07 +00:00
}
HELP_CHAT_CMD = %q{ Available commands:
/ d [n] — delete your last message(s)
2020-03-09 11:56:52 +00:00
/ s edited message — edit your last message
2019-08-21 12:43:07 +00:00
/ add @username — add @username to your chat list
/ join https: / / t . me / invite_link — join to chat via invite link
/ group title — create groupchat «title» with current user
/ supergroup title description — create new supergroup «title» with «description»
/ channel title description — create new channel «title» with «description»
/ secret — create secretchat with current user
/ block — blacklist current user
/ unblock — unblacklist current user
/ invite id or @username — add user to current chat
2020-03-09 17:56:13 +00:00
/ link — get invite link for current chat
2019-08-21 12:43:07 +00:00
/ kick id or @username — remove user from current chat
2020-03-09 17:56:13 +00:00
/ mute id or @username [hours] — mute user in current chat
/ unmute id or @username — unrestrict user from current chat
/ ban id or @username [hours] — restrict @username from current chat
/ unban id or @username — unbans @username in current chat (and devotes from admins)
/ promote id or @username — promote user to admin in current chat
2019-08-21 12:43:07 +00:00
/ leave — leave current chat
2020-03-09 17:56:13 +00:00
/ leave! — leave current chat (for owners)
2020-09-26 08:13:58 +00:00
/ ttl — set secret chat messages TTL before self-destroying (in seconds)
2019-08-21 12:43:07 +00:00
/ close — close current secret chat
/ delete — delete current chat from chat list
/ members [query] — search members [by optional query] in current chat (requires admin rights)
2020-03-09 11:56:52 +00:00
/ search string [limit] — search <string> in current chat
2019-08-21 12:43:07 +00:00
}
2019-08-08 10:51:33 +00:00
2019-04-06 06:12:54 +00:00
class TelegramClient
2020-04-12 18:47:21 +00:00
attr_reader :session
2019-04-06 06:12:54 +00:00
2019-08-08 10:51:33 +00:00
## configure tdlib (when valid tdlib params specified) or zhabogram
def self . configure ( ** config )
2020-04-12 18:47:21 +00:00
@@config = config
2019-08-21 12:43:07 +00:00
TD . config . update ( config [ :tdlib ] )
2020-04-12 18:47:21 +00:00
TD :: Api . set_log_verbosity_level ( config [ :tdlib_verbosity ] )
2019-04-06 06:12:54 +00:00
end
2019-08-08 10:51:33 +00:00
## initialize telegram client instance (xmpp = XMPP stream, jid = user's jid , login = user's telegram login (for now, it is phone number)
def initialize ( xmpp , jid , ** session )
2020-03-09 17:56:13 +00:00
return unless @@config
2019-08-08 10:51:33 +00:00
@logger = Logger . new ( STDOUT , level : @@config [ :loglevel ] , progname : 'TelegramClient: %s | %s' % [ jid , session [ :login ] ] )
2020-09-20 11:03:02 +00:00
@resource = @@config [ :tdlib ] [ :client ] [ :device_model ] || 'zhabogram'
2019-08-08 10:51:33 +00:00
@xmpp = xmpp
@jid = jid
@session = session
2020-03-09 07:04:24 +00:00
@resources = Set . new
2020-04-22 19:50:38 +00:00
@cache = { chats : { nil = > [ ] } , users : { } , status : { } }
2020-03-09 07:04:24 +00:00
self . connect ( ) if @session [ :keeponline ] == 'true'
2019-05-04 22:42:59 +00:00
end
2019-08-08 10:51:33 +00:00
## connect telegram client
2020-03-09 00:55:50 +00:00
def connect ( resource = nil )
2020-03-09 07:04:24 +00:00
return self . roster ( resource ) if self . online? # already connected
2019-08-08 10:51:33 +00:00
@logger . warn 'Connecting to Telegram network..'
@telegram = TD :: Client . new ( database_directory : 'sessions/' + @jid , files_directory : 'sessions/' + @jid + '/files/' )
@telegram . on ( TD :: Types :: Update :: AuthorizationState ) do | u | @logger . debug ( u ) ; self . update_authorizationstate ( u ) end
@telegram . on ( TD :: Types :: Update :: User ) do | u | @logger . debug ( u ) ; self . update_user ( u ) end
@telegram . on ( TD :: Types :: Update :: UserStatus ) do | u | @logger . debug ( u ) ; self . update_userstatus ( u ) end
@telegram . on ( TD :: Types :: Update :: NewChat ) do | u | @logger . debug ( u ) ; self . update_newchat ( u ) end
@telegram . on ( TD :: Types :: Update :: NewMessage ) do | u | @logger . debug ( u ) ; self . update_newmessage ( u ) end
@telegram . on ( TD :: Types :: Update :: MessageContent ) do | u | @logger . debug ( u ) ; self . update_messagecontent ( u ) end
@telegram . on ( TD :: Types :: Update :: DeleteMessages ) do | u | @logger . debug ( u ) ; self . update_deletemessages ( u ) end
@telegram . on ( TD :: Types :: Update :: File ) do | u | @logger . debug ( u ) ; self . update_file ( u ) end
2020-04-12 18:47:21 +00:00
@telegram . connect ( )
2020-03-09 00:55:50 +00:00
@resources << resource
2019-05-04 20:17:29 +00:00
end
2019-08-08 10:51:33 +00:00
## disconnect telegram client
2020-03-09 07:04:24 +00:00
def disconnect ( resource = nil , quit = false )
@resources . delete ( resource )
2020-04-12 18:47:21 +00:00
return if ( ( @resources . count > 0 || @session [ :keeponline ] == 'true' ) && ! quit )
2020-04-22 19:50:38 +00:00
return if not self . online?
2019-08-08 10:51:33 +00:00
@logger . warn 'Disconnecting from Telegram network..'
2020-03-09 07:04:24 +00:00
@cache [ :chats ] . each_key do | chat | @xmpp . send_presence ( @jid , chat , :unavailable ) end
2020-04-12 18:47:21 +00:00
@telegram . dispose ( )
2020-04-22 19:50:38 +00:00
@telegram = nil
2019-05-04 20:17:29 +00:00
end
2020-03-09 00:55:50 +00:00
2020-03-09 07:04:24 +00:00
## resend statuses to (to another resource for example)
def roster ( resource = nil )
return if @resources . include? resource # we know it
@logger . warn 'Sending roster for %s' % resource
@cache [ :chats ] . each_key do | chat | self . process_status_update ( chat ) end
@xmpp . send_presence ( @jid , nil , nil , nil , " Logged in as: %s " % @session [ :login ] )
2020-03-09 00:55:50 +00:00
@resources << resource
end
2019-05-04 20:17:29 +00:00
2019-08-08 10:51:33 +00:00
## online?
def online?
2020-03-09 07:04:24 +00:00
@telegram and @telegram . alive?
2020-03-09 00:55:50 +00:00
end
2019-08-08 10:51:33 +00:00
#########################################################################
# telegram updates handlers #############################################
#########################################################################
## authorization state change
def update_authorizationstate ( update )
2019-04-06 07:29:48 +00:00
case update . authorization_state
2019-08-08 10:51:33 +00:00
when TD :: Types :: AuthorizationState :: WaitPhoneNumber # stage 0: set login
@logger . warn 'Logging in..'
2020-04-12 18:47:21 +00:00
@telegram . set_authentication_phone_number ( @session [ :login ] , PERMISSIONS [ :login ] ) if @session [ :login ]
2019-08-08 10:51:33 +00:00
@xmpp . send_message ( @jid , nil , 'Please, enter your Telegram login via /login 12345' ) if not @session [ :login ]
when TD :: Types :: AuthorizationState :: WaitCode # stage 1: wait for auth code
@logger . warn 'Waiting for authorization code..'
@xmpp . send_message ( @jid , nil , 'Please, enter authorization code via /code 12345' )
when TD :: Types :: AuthorizationState :: WaitPassword # stage 2: wait for 2fa
@logger . warn 'Waiting for 2FA password..'
@xmpp . send_message ( @jid , nil , 'Please, enter 2FA passphrase via /password 12345' )
when TD :: Types :: AuthorizationState :: Ready # stage 3: auth completed
2019-08-21 12:43:07 +00:00
@session [ :login ] || = @me . phone_number
2019-08-08 10:51:33 +00:00
@logger . warn 'Authorization successful!'
@telegram . get_me . then { | me | @me = me } . wait
2020-03-09 11:56:52 +00:00
@telegram . get_chats ( TD :: Types :: ChatList :: Main . new , 9223372036854775807 , 0 , 999 ) . wait
2020-01-05 05:22:52 +00:00
@xmpp . send_presence ( @jid , nil , :subscribe , nil , nil )
@xmpp . send_presence ( @jid , nil , :subscribed , nil , nil )
2020-03-09 07:04:24 +00:00
@xmpp . send_presence ( @jid , nil , nil , nil , " Logged in as: %s " % @session [ :login ] )
2019-08-08 10:51:33 +00:00
end
2019-04-06 06:12:54 +00:00
end
Release v0.3
[UPD] more correct way to handle user/chat/auth updates
[UPD] removed successful login message, using presence instead
[NEW] config option `content_upload_prefix` that says which url prefixes will be treated as media and uploaded as file to telegram
[NEW] processing self outgoing messages that sent via another telegram instance
[NEW] added gif animations, locations, video, chat events support
[NEW] control commands implemented:
/s/old/new (edit), /d (delete), /info @username, /add @username or uid, /join invite.link or id, /invite @username, /kick @username, /ban @username [hours], /block, /unblock, /leave, /delete
2019-04-12 03:11:56 +00:00
2019-08-08 10:51:33 +00:00
## message received
2020-03-09 11:56:52 +00:00
def update_newmessage ( update )
2019-05-31 11:30:25 +00:00
return if update . message . is_outgoing and update . message . sending_state . instance_of? TD :: Types :: MessageSendingState :: Pending # ignore self outgoing messages
2019-08-08 10:51:33 +00:00
@logger . warn 'New message from chat %s' % update . message . chat_id
2019-05-31 11:30:25 +00:00
2019-08-08 10:51:33 +00:00
content , prefix = update . message . content , [ ]
text = case content # text
2020-05-14 17:24:52 +00:00
when TD :: Types :: MessageContent :: Text then content . text . text
2019-07-14 07:23:48 +00:00
when TD :: Types :: MessageContent :: Sticker then content . sticker . emoji
2020-05-14 17:24:52 +00:00
when TD :: Types :: MessageContent :: Animation , TD :: Types :: MessageContent :: Photo , TD :: Types :: MessageContent :: Audio , TD :: Types :: MessageContent :: Video , TD :: Types :: MessageContent :: Document then content . caption . text
when TD :: Types :: MessageContent :: Location then " coordinates: %{latitude},%{longitude} | https://www.google.com/maps/search/%{latitude},%{longitude}/ " % content . location . to_h
2020-05-15 13:32:06 +00:00
when TD :: Types :: MessageContent :: VoiceNote then 'voice note (%i s.)' % content . voice_note . duration
when TD :: Types :: MessageContent :: VideoNote then 'video note (%i s.)' % content . video_note . duration
2019-05-31 11:30:25 +00:00
when TD :: Types :: MessageContent :: BasicGroupChatCreate , TD :: Types :: MessageContent :: SupergroupChatCreate then " has created chat "
2020-05-14 17:24:52 +00:00
when TD :: Types :: MessageContent :: PinMessage then " pinned message: %s " % self . format_message ( update . message . chat_id , content . message_id )
2019-05-31 11:30:25 +00:00
when TD :: Types :: MessageContent :: ChatJoinByLink then " joined chat via invite link "
2019-05-31 22:35:03 +00:00
when TD :: Types :: MessageContent :: ChatAddMembers then " invited %s " % self . format_contact ( message . content . member_user_ids . first )
when TD :: Types :: MessageContent :: ChatDeleteMember then " kicked %s " % self . format_contact ( update . message . content . user_id )
2019-08-08 10:51:33 +00:00
when TD :: Types :: MessageContent :: ChatChangeTitle then " chat title set to: %s " % update . message . content . title
else " unknown message (%s) " % update . message . content . class
2019-05-31 11:30:25 +00:00
end
2019-08-08 10:51:33 +00:00
file = case content # file(s)
2020-05-14 17:24:52 +00:00
when TD :: Types :: MessageContent :: Sticker then content . sticker . sticker
when TD :: Types :: MessageContent :: VoiceNote then content . voice_note . voice
when TD :: Types :: MessageContent :: VideoNote then content . video_note . video
when TD :: Types :: MessageContent :: Animation then content . animation . animation
when TD :: Types :: MessageContent :: Photo then content . photo . sizes [ - 1 ] . photo
when TD :: Types :: MessageContent :: Audio then content . audio . audio
when TD :: Types :: MessageContent :: Video then content . video . video
when TD :: Types :: MessageContent :: Document then content . document . document
2019-08-08 10:51:33 +00:00
end
2020-05-14 17:24:52 +00:00
file = @telegram . download_file ( file . id , 1 , 0 , 0 , true ) . value if file # download file (if one)
2019-05-31 11:30:25 +00:00
prefix << ( update . message . is_outgoing ? '➡ ' : '⬅ ' ) + update . message . id . to_s # message direction
2019-08-08 10:51:33 +00:00
prefix << " %s " % self . format_contact ( update . message . sender_user_id ) if update . message . chat_id < 0 and update . message . sender_user_id # show sender in group chats
prefix << " reply: %s " % self . format_message ( update . message . chat_id , update . message . reply_to_message_id , true ) if update . message . reply_to_message_id . to_i != 0 # reply to
2020-03-09 11:56:52 +00:00
prefix << " fwd: %s " % self . format_forward ( update . message . forward_info ) if update . message . forward_info # forward
2020-05-14 17:24:52 +00:00
prefix << " file: %s " % self . format_file ( file ) if file # file
2019-05-31 22:35:03 +00:00
prefix = prefix . join ( ' | ' )
prefix += ( update . message . chat_id < 0 and text and text != " " ) ? " \n " : '' # \n if it is groupchat and message is not empty
prefix += ( update . message . chat_id > 0 and text and text != " " ) ? " | " : ''
2020-09-26 08:03:01 +00:00
text = prefix + text unless ( text . start_with? '?OTR' or @session [ :rawmessages ] == 'true' ) # OTR support (I do not know why would you need it, seriously)
2020-03-09 11:56:52 +00:00
@telegram . view_messages ( update . message . chat_id , [ update . message . id ] , true ) # mark message as read
2019-08-08 10:51:33 +00:00
@xmpp . send_message ( @jid , update . message . chat_id , text ) # forward message to XMPP
2019-04-07 11:58:07 +00:00
end
2019-08-08 10:51:33 +00:00
## message content updated
def update_messagecontent ( update )
text = " ✎ %s | %s " % [ update . message_id , update . new_content . text . text ]
@xmpp . send_message ( @jid , update . chat_id , text )
2019-04-06 06:12:54 +00:00
end
2019-04-07 11:58:07 +00:00
2019-08-08 10:51:33 +00:00
## message(s) deleted
def update_deletemessages ( update )
text = " ✗ %s " % update . message_ids . join ( ',' )
@xmpp . send_message ( @jid , update . chat_id , text ) if update . is_permanent
2019-04-07 11:58:07 +00:00
end
2019-08-08 10:51:33 +00:00
## new chat discovered
def update_newchat ( update )
2020-04-12 18:47:21 +00:00
puts update . to_json
@telegram . download_file ( update . chat . photo . small . id , 10 , 0 , 0 , false ) if update . chat . photo
2019-08-08 10:51:33 +00:00
@cache [ :chats ] [ update . chat . id ] = update . chat
@xmpp . send_presence ( @jid , update . chat . id , :subscribe , nil , nil , update . chat . title . to_s ) unless ( update . chat . type . instance_of? TD :: Types :: ChatType :: Supergroup and update . chat . type . is_channel and update . chat . last_read_inbox_message_id == 0 )
self . process_status_update ( update . chat . id , update . chat . title , :chat ) if update . chat . id < 0
2019-04-07 11:58:07 +00:00
end
2019-08-08 10:51:33 +00:00
## new user discovered
def update_user ( update )
@cache [ :users ] [ update . user . id ] = update . user
2020-04-22 19:50:38 +00:00
@cache [ :status ] [ update . user . id ] = update . user . status
2019-08-08 10:51:33 +00:00
self . process_status_update ( update . user . id , update . user . status )
Release v0.3
[UPD] more correct way to handle user/chat/auth updates
[UPD] removed successful login message, using presence instead
[NEW] config option `content_upload_prefix` that says which url prefixes will be treated as media and uploaded as file to telegram
[NEW] processing self outgoing messages that sent via another telegram instance
[NEW] added gif animations, locations, video, chat events support
[NEW] control commands implemented:
/s/old/new (edit), /d (delete), /info @username, /add @username or uid, /join invite.link or id, /invite @username, /kick @username, /ban @username [hours], /block, /unblock, /leave, /delete
2019-04-12 03:11:56 +00:00
end
2019-08-08 10:51:33 +00:00
## user status changed
def update_userstatus ( update )
2020-04-22 19:50:38 +00:00
@cache [ :status ] [ update . user_id ] = update . status
2019-08-08 10:51:33 +00:00
self . process_status_update ( update . user_id , update . status , nil , false )
2019-04-06 06:12:54 +00:00
end
2019-06-11 13:24:44 +00:00
2019-08-08 10:51:33 +00:00
## file downloaded
def update_file ( update )
return unless update . file . local . is_downloading_completed # not really
2019-04-06 06:12:54 +00:00
end
2019-04-07 11:58:07 +00:00
2019-08-08 10:51:33 +00:00
#########################################################################
# xmpp to telegram gateway functions ####################################
#########################################################################
## get user and chat information from cache (or try to retrieve it, if missing)
def get_contact ( id )
2020-03-09 07:04:24 +00:00
return unless self . online? && id # we're offline.
2019-08-08 10:51:33 +00:00
@telegram . search_public_chat ( id ) . then { | chat | id = chat . id } . wait if id [ 0 ] == '@'
@telegram . get_user ( id ) . wait if not @cache [ :users ] [ id ] and ( id > 0 )
@telegram . get_chat ( id ) . wait if not @cache [ :chats ] [ id ]
return @cache [ :chats ] [ id ] , @cache [ :users ] [ id ]
2019-04-07 11:58:07 +00:00
end
2020-03-09 11:56:52 +00:00
2020-03-09 17:56:13 +00:00
## get last messages from specified chat
2020-03-09 11:56:52 +00:00
def get_lastmessages ( id , query = nil , from = nil , count = 1 )
result = @telegram . search_chat_messages ( id , query . to_s , from . to_i , 0 , 0 , count . to_i , TD :: Types :: SearchMessagesFilter :: Empty . new ) . value
return ( result ) ? result . messages : [ ]
end
2019-08-08 10:51:33 +00:00
## set contact status
2020-03-09 11:56:52 +00:00
def process_status_update ( id , status = nil , show = nil , immed = true )
return unless self . online?
@logger . info " Status update for %s " % id
chat , user = self . get_contact ( id )
2019-08-08 10:51:33 +00:00
photo = Digest :: SHA1 . hexdigest ( IO . binread ( chat . photo . small . local . path ) ) if chat and chat . photo and File . exist? chat . photo . small . local . path
2020-04-22 19:50:38 +00:00
status || = @cache [ :status ] [ id ] if @cache [ :status ] [ id ]
2020-05-14 17:24:52 +00:00
status || = user . status if user and user . status
2019-08-08 10:51:33 +00:00
case status
when nil then show , status = :chat , chat ? chat . title : nil
when TD :: Types :: UserStatus :: Online then show , status = nil , " Online "
when TD :: Types :: UserStatus :: Recently then show , status = :dnd , " Last seen recently "
2020-09-16 03:52:08 +00:00
when TD :: Types :: UserStatus :: LastWeek then show , status = :xa , " Last seen last week "
when TD :: Types :: UserStatus :: LastMonth then show , status = :xa , " Last seen last month "
when TD :: Types :: UserStatus :: Empty then type , status = :unavailable , " Last seen a long time ago "
2019-08-08 10:51:33 +00:00
when TD :: Types :: UserStatus :: Offline then show , status = ( Time . now . getutc . to_i - status . was_online . to_i < 3600 ) ? :away : :xa ,
DateTime . strptime ( ( status . was_online + Time . now . getlocal ( @session [ :timezone ] ) . utc_offset ) . to_s , '%s' ) . strftime ( " Last seen at %H:%M %d/%m/%Y " )
2019-04-07 11:58:07 +00:00
end
2020-09-20 11:03:02 +00:00
return @xmpp . send_presence ( @jid , id , type , show , status , nil , photo , @resource , immed )
2019-04-13 14:42:56 +00:00
end
2019-08-08 10:51:33 +00:00
## send outgoing message to telegram user
2020-03-09 11:56:52 +00:00
def process_outgoing_message ( id , text )
return if self . process_command ( id , text . split . first , text . split [ 1 .. - 1 ] ) or not self . online? # try to execute commands
@logger . warn 'Sending message to chat %s' % id
2020-03-09 17:56:13 +00:00
reply = text . lines [ 0 ] . scan ( / \ d+ / ) . first . to_i if text . lines [ 0 ] =~ / ^> ?[0-9]{10} /
text = TD :: Types :: FormattedText . new ( text : ! reply ? text : text . lines [ 1 .. - 1 ] . join , entities : [ ] )
message = TD :: Types :: InputMessageContent :: Text . new ( text : text , disable_web_page_preview : false , clear_draft : false )
return ( id ) ? @telegram . send_message ( id , reply . to_i , nil , nil , message ) . rescue { | e | @xmpp . send_message ( @jid , id , " Not sent: %s " % e ) } : message
2019-08-08 10:51:33 +00:00
end
2019-04-13 14:42:56 +00:00
2019-08-08 10:51:33 +00:00
## /commands (some telegram actions)
2020-03-09 11:56:52 +00:00
def process_command ( id , cmd , args )
chat , user = self . get_contact ( id ) unless id == 0 # get chat information
if id == 0 then # transport commands
2019-08-08 10:51:33 +00:00
case cmd
2020-04-12 18:47:21 +00:00
when '/login' then @telegram . set_authentication_phone_number ( args [ 0 ] , PERMISSIONS [ :login ] ) . then { @session [ :login ] = args [ 0 ] } unless @session [ :login ] # sign in
when '/logout' then @telegram . log_out ( ) . then { @cache [ :chats ] . each_key do | chat | @xmpp . send_presence ( @jid , chat , :unsubscribed ) ; @session [ :login ] = nil end } # sign out
2019-08-08 10:51:33 +00:00
when '/code' then @telegram . check_authentication_code ( args [ 0 ] ) # check auth code
when '/password' then @telegram . check_authentication_password ( args [ 0 ] ) # chech auth password
when '/setusername' then @telegram . set_username ( args [ 0 ] || '' ) # set @username
when '/setname' then @telegram . set_name ( args [ 0 ] || '' , args [ 1 ] || '' ) # set My Name
when '/setbio' then @telegram . set_bio ( args [ 0 ] || '' ) # set About
when '/setpassword' then @telegram . set_password ( ( args [ 1 ] ? args [ 0 ] : '' ) , args [ 1 ] ) # set password
2019-08-21 12:43:07 +00:00
when '/config' then @xmpp . send_message ( @jid , nil , args [ 1 ] ? " %s set to %s " % [ args [ 0 ] , @session . store ( args [ 0 ] . to_sym , args [ 1 ] ) ] : @session . map { | attr | " %s is set to %s " % attr } . join ( " \n " ) )
2019-08-31 04:58:30 +00:00
when '/help' then @xmpp . send_message ( @jid , nil , HELP_GATE_CMD )
2019-08-08 10:51:33 +00:00
end
return true # stop executing
else # chat commands
case cmd
2020-03-09 11:56:52 +00:00
when '/d' then @telegram . delete_messages ( chat . id , self . get_lastmessages ( chat . id , nil , @me . id , args [ 0 ] || 1 ) . map ( & :id ) , true ) # delete message
2020-03-09 17:56:13 +00:00
when '/s' then @telegram . edit_message_text ( chat . id , self . get_lastmessages ( chat . id , nil , @me . id , 1 ) . first . id , nil , self . process_outgoing_message ( nil , args . join ( ' ' ) ) ) # edit message
2019-08-21 12:43:07 +00:00
when '/add' then @telegram . search_public_chat ( args [ 0 ] ) . then { | chat | @xmpp . send_presence ( @jid , chat . id , :subscribe ) } . wait # add @contact
when '/join' then @telegram . join_chat_by_invite_link ( args [ 0 ] ) # join https://t.me/publichat
2020-03-09 11:56:52 +00:00
when '/supergroup' then @telegram . create_new_supergroup_chat ( args [ 0 ] , false , args [ 1 .. - 1 ] . join ( ' ' ) , nil ) # create new supergroup
when '/channel' then @telegram . create_new_supergroup_chat ( args [ 0 ] , true , args [ 1 .. - 1 ] . join ( ' ' ) , nil ) # create new channel
2020-09-16 03:52:08 +00:00
when '/secret' then @telegram . create_new_secret_chat ( chat . id ) # create secret chat with current user
2020-03-09 11:56:52 +00:00
when '/group' then @telegram . create_new_basic_group_chat ( chat . id , args [ 0 ] ) # create group chat with current user
when '/block' then @telegram . block_user ( chat . id ) # blacklists current user
when '/unblock' then @telegram . unblock_user ( chat . id ) # unblacklists current user
when '/members' then @telegram . search_chat_members ( chat . id , args [ 0 ] , 9999 , TD :: Types :: ChatMembersFilter :: Members . new ) . then { | m | @xmpp . send_message ( @jid , chat . id , ( m . members . map do | u | " %s | role: %s " % [ self . format_contact ( u . user_id ) , u . status . class ] end ) . join ( " \n " ) ) } # chat members
2020-03-09 17:56:13 +00:00
when '/invite' then @telegram . add_chat_member ( chat . id , self . get_contact ( args [ 0 ] ) . first . id , 100 ) # invite @username to current groupchat
when '/link' then @telegram . generate_chat_invite_link ( chat . id ) . then { | link | @xmpp . send_message ( @jid , chat . id , link . invite_link ) } # get link to current chat
when '/kick' then @telegram . set_chat_member_status ( chat . id , self . get_contact ( args [ 0 ] ) . first . id , TD :: Types :: ChatMemberStatus :: Left . new ( ) ) # kick @username
when '/mute' then @telegram . set_chat_member_status ( chat . id , self . get_contact ( args [ 0 ] ) . first . id , TD :: Types :: ChatMemberStatus :: Restricted . new ( is_member : true , restricted_until_date : self . format_bantime ( args [ 0 ] ) , permissions : PERMISSIONS [ :readonly ] ) ) # mute @username [n hours]
when '/unmute' then @telegram . set_chat_member_status ( chat . id , self . get_contact ( args [ 0 ] ) . first . id , TD :: Types :: ChatMemberStatus :: Restricted . new ( is_member : true , restricted_until_date : 0 , permissions : PERMISSIONS [ :member ] ) ) # unmute @username
when '/ban' then @telegram . set_chat_member_status ( chat . id , self . get_contact ( args [ 0 ] ) . first . id , TD :: Types :: ChatMemberStatus :: Banned . new ( banned_until_date : self . format_bantime ( args [ 0 ] ) ) ) # ban @username [n hours]
when '/unban' then @telegram . set_chat_member_status ( chat . id , self . get_contact ( args [ 0 ] ) . first . id , TD :: Types :: ChatMemberStatus :: Member . new ( ) ) # unban @username
when '/promote' then @telegram . set_chat_member_status ( chat . id , self . get_contact ( args [ 0 ] ) . first . id , TD :: Types :: ChatMemberStatus :: Administrator . new ( custom_title : args [ 0 ] . to_s , ** PERMISSIONS [ :admin ] ) ) # promote @username to admin
when '/leave' then @telegram . leave_chat ( chat . id ) . then { @xmpp . send_presence ( @jid , chat . id , :unsubscribed ) } # leave current chat
when '/leave!' then @telegram . delete_supergroup ( chat . type . supergroup_id ) . then { @xmpp . send_presence ( @jid , chat . id , :unsubscribed ) } . rescue { | e | puts e . to_s } # leave current chat (for owners)
2020-09-26 08:13:58 +00:00
when '/ttl' then @telegram . send_chat_set_ttl_message ( chat . type . secret_chat_id , args [ 0 ] . to_i ) # close secret chat
2020-09-16 03:52:08 +00:00
when '/close' then @telegram . close_secret_chat ( chat . type . secret_chat_id ) . then { @xmpp . send_presence ( @jid , chat . id , :unsubscribed ) } # close secret chat
2020-03-09 17:56:13 +00:00
when '/delete' then @telegram . delete_chat_history ( chat . id , true , true ) . then { @xmpp . send_presence ( @jid , chat . id , :unsubscribed ) } # delete current chat
when '/search' then @telegram . get_messages ( chat . id , self . get_lastmessages ( chat . id , args [ 0 ] , 0 , args [ 1 ] || 100 ) . map ( & :id ) ) . value . messages . reverse . each { | msg | @xmpp . send_message ( @jid , chat . id , self . format_message ( chat . id , msg , false ) ) } # message search
2020-03-09 11:56:52 +00:00
when '/help' then @xmpp . send_message ( @jid , id , HELP_CHAT_CMD )
else return # continue
2019-08-08 10:51:33 +00:00
end
2020-03-09 11:56:52 +00:00
return true # stop
2019-08-08 10:51:33 +00:00
end
2019-04-13 14:42:56 +00:00
end
2019-08-08 10:51:33 +00:00
#########################################################################
# formatting functions #################################################
#########################################################################
2020-03-09 17:56:13 +00:00
2020-03-09 11:56:52 +00:00
def format_contact ( id )
return if not id or id == 0
chat , user = self . get_contact ( id )
str = id
2019-08-08 10:51:33 +00:00
str = " %s (%s) " % [ chat . title , chat . id ] if chat
str = " %s %s (%s) " % [ user . first_name , user . last_name , ( user . username . empty? ) ? user . id : user . username ] if user
str = str . gsub ( ' ' , ' ' )
return str
2019-04-14 02:56:29 +00:00
end
2019-05-31 11:30:25 +00:00
2020-05-14 17:24:52 +00:00
def format_file ( file )
return unless File . exist? file . local . path
src = file . local . path # source path
dest = " %s/%s " % [ @@config [ :content ] [ :path ] , file . remote . unique_id + File . extname ( file . local . path ) ] # destination path
link = " %s/%s " % [ @@config [ :content ] [ :link ] , File . basename ( dest ) ] # download link
File . rename ( src , dest )
return " %s (%d kbytes) | %s " % [ File . basename ( src ) , file . size / 1024 , link ]
end
2020-03-09 11:56:52 +00:00
def format_message ( id , message , preview = false )
message = ( message . instance_of? TD :: Types :: Message ) ? message : @telegram . get_message ( id , message ) . value
2019-08-08 10:51:33 +00:00
return unless message
2020-05-15 13:32:06 +00:00
str = " %s | %s | " % [ message . id , self . format_contact ( message . sender_user_id ) ] # add messageid and sender
str += DateTime . strptime ( ( message . date + Time . now . getlocal ( @session [ :timezone ] ) . utc_offset ) . to_s , '%s' ) . strftime ( " %d %b %Y %H:%M:%S | " ) unless preview # add date
str += ( not preview or message . content . text . text . lines . count < = 1 ) ? message . content . text . text : message . content . text . text . lines . first if message . content . respond_to? 'text' # text message
2020-05-19 14:42:27 +00:00
str += message . content . caption . text if message . content . respond_to? 'caption' # content caption
2019-08-08 10:51:33 +00:00
return str
2019-04-07 11:58:07 +00:00
end
2019-05-31 11:30:25 +00:00
2020-03-09 11:56:52 +00:00
def format_forward ( fwd )
str = case fwd . origin
2020-03-09 17:56:13 +00:00
when TD :: Types :: MessageForwardOrigin :: User then self . format_contact ( fwd . origin . sender_user_id )
when TD :: Types :: MessageForwardOrigin :: HiddenUser then fwd . origin . sender_name
when TD :: Types :: MessageForwardOrigin :: Channel then [ self . format_contact ( fwd . origin . chat_id ) , fwd . origin . author_signature ] . join ' '
2020-03-09 11:56:52 +00:00
end
return str
end
2020-03-09 17:56:13 +00:00
def format_bantime ( hours = 0 )
now = Time . now . getutc . to_i
till = now + hours . to_i * 3600
return ( hours . to_i > 0 ) ? till : 0
2020-03-09 11:56:52 +00:00
end
2019-04-06 06:12:54 +00:00
end