2019-04-06 06:12:54 +00:00
require 'tdlib-ruby'
2019-04-07 11:58:07 +00:00
require 'digest'
2019-04-06 07:29:48 +00:00
2019-04-06 06:12:54 +00:00
class TelegramClient
# tdlib configuration, shared within all instances #
def self . configure ( params )
2019-04-07 11:58:07 +00:00
@@loglevel = params [ 'loglevel' ] || Logger :: DEBUG
@@content_path = params [ 'content_path' ] || '/tmp'
@@content_link = params [ 'content_link' ] || 'https://localhost/tg_media'
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
@@content_upload_prefix = params [ " content_upload_prefix " ] || 'https://localhost/upload/'
2019-04-06 06:12:54 +00:00
TD . configure do | config |
2019-04-07 11:58:07 +00:00
config . lib_path = params [ 'path' ] || 'lib/' # we hope it's here
config . client . api_id = params [ 'api_id' ] || '17349' # desktop telegram app
config . client . api_hash = params [ 'api_hash' ] || '344583e45741c457fe1862106095a5eb' # desktop telegram app
config . client . device_model = params [ 'useragent' ] || 'Zhabogram XMPP Gateway'
config . client . application_version = params [ 'version' ] || '-1.0' # hmm...
config . client . use_test_dc = params [ 'use_test_dc' ] || false
config . client . system_version = '42' # I think I have permission to hardcode The Ultimate Question of Life, the Universe, and Everything?..
2019-04-06 06:12:54 +00:00
end
2019-04-07 11:58:07 +00:00
TD :: Api . set_log_verbosity_level ( params [ 'verbosity' ] || 1 )
2019-04-06 06:12:54 +00:00
end
# instance initialization #
def initialize ( xmpp , login )
2019-04-07 11:58:07 +00:00
return if not @@loglevel # call .configure() first
2019-04-06 06:12:54 +00:00
2019-04-07 11:58:07 +00:00
@logger = Logger . new ( STDOUT ) ; @logger . level = @@loglevel ; @logger . progname = '[TelegramClient: %s/%s]' % [ xmpp . user_jid , login ] # create logger
2019-04-06 08:23:14 +00:00
@xmpp = xmpp # our XMPP user session. we will send messages back to Jabber through this instance.
@login = login # store tg login
2019-04-08 22:28:26 +00:00
@cache = { chats : { } , users : { } , unread_msg : { } } # we will store our cache here
2019-04-07 11:58:07 +00:00
@files_dir = File . dirname ( __FILE__ ) + '/../sessions/' + @xmpp . user_jid + '/files/'
2019-04-06 06:12:54 +00:00
2019-04-06 08:23:14 +00:00
# spawn telegram client and specify callback handlers
2019-04-09 06:42:42 +00:00
@logger . info 'Connecting to Telegram network..'
2019-04-07 11:58:07 +00:00
@client = TD :: Client . new ( database_directory : 'sessions/' + @xmpp . user_jid , files_directory : 'sessions/' + @xmpp . user_jid + '/files/' ) # create telegram client instance
2019-04-06 06:12:54 +00:00
@client . on ( TD :: Types :: Update :: AuthorizationState ) do | update | self . auth_handler ( update ) end # register auth update handler
@client . on ( TD :: Types :: Update :: NewMessage ) do | update | self . message_handler ( update ) end # register new message update handler
2019-04-07 11:58:07 +00:00
@client . on ( TD :: Types :: Update :: MessageContent ) do | update | self . message_edited_handler ( update ) end # register msg edited handler
@client . on ( TD :: Types :: Update :: DeleteMessages ) do | update | self . message_deleted_handler ( update ) end # register msg del handler
@client . on ( TD :: Types :: Update :: File ) do | update | self . file_handler ( update ) end # register file handler
@client . on ( TD :: Types :: Update :: NewChat ) do | update | self . new_chat_handler ( update ) end # register new chat handler
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
@client . on ( TD :: Types :: Update :: User ) do | update | self . user_handler ( update ) end # new user update?
2019-04-07 11:58:07 +00:00
@client . on ( TD :: Types :: Update :: UserStatus ) do | update | self . status_update_handler ( update ) end # register status handler
2019-04-06 06:12:54 +00:00
@client . connect #
2019-04-06 08:23:14 +00:00
# we will check for outgoing messages in a queue and/or auth data from XMPP thread while XMPP indicates that service is online #
2019-04-06 07:29:48 +00:00
begin
2019-04-06 07:46:29 +00:00
while not @xmpp . online? === false do
2019-04-06 06:12:54 +00:00
self . process_outgoing_msg ( @xmpp . message_queue . pop ) unless @xmpp . message_queue . empty? # found something in message queue
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
self . process_auth ( @xmpp . auth_data . shift ) unless @xmpp . auth_data . empty? # found something in auth queue
2019-04-09 06:42:42 +00:00
sleep 0 . 1
2019-04-06 06:12:54 +00:00
end
2019-04-07 11:58:07 +00:00
rescue Exception = > e
@logger . error 'Unexcepted exception! %s' % e . to_s
2019-04-06 07:29:48 +00:00
ensure
@logger . info 'Exitting gracefully...'
@client . dispose
end
2019-04-06 06:12:54 +00:00
end
2019-04-06 07:29:48 +00:00
###########################################
## Callback handlers #####################
###########################################
2019-04-06 06:12:54 +00:00
# authorization handler #
def auth_handler ( update )
2019-04-06 07:29:48 +00:00
@logger . debug 'Authorization state changed: %s' % update . authorization_state
2019-04-06 06:12:54 +00:00
2019-04-06 07:29:48 +00:00
case update . authorization_state
2019-04-06 06:12:54 +00:00
# auth stage 0: specify login #
when TD :: Types :: AuthorizationState :: WaitPhoneNumber
2019-04-06 07:29:48 +00:00
@logger . info 'Logging in..'
2019-04-06 06:12:54 +00:00
@client . set_authentication_phone_number ( @login )
# auth stage 1: wait for authorization code #
when TD :: Types :: AuthorizationState :: WaitCode
2019-04-06 07:29:48 +00:00
@logger . info 'Waiting for authorization code..'
2019-04-06 06:12:54 +00:00
@xmpp . send_message ( nil , 'Please, enter authorization code via /code 12345' )
# auth stage 2: wait for 2fa passphrase #
when TD :: Types :: AuthorizationState :: WaitPassword
2019-04-06 07:29:48 +00:00
@logger . info 'Waiting for 2FA password..'
2019-04-06 06:12:54 +00:00
@xmpp . send_message ( nil , 'Please, enter 2FA passphrase via /password 12345' )
2019-04-07 11:58:07 +00:00
# authorization successful -- indicate that client is online and retrieve contact list #
2019-04-06 06:12:54 +00:00
when TD :: Types :: AuthorizationState :: Ready
2019-04-06 07:29:48 +00:00
@logger . info 'Authorization successful!'
2019-04-06 07:46:29 +00:00
@xmpp . online!
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
@client . get_me ( ) . then { | user | @me = user } . wait
@client . get_chats ( limit = 9999 ) . wait
2019-04-07 11:58:07 +00:00
@logger . info " Contact list updating finished "
self . sync_roster ( )
when TD :: Types :: AuthorizationState :: Closed
@logger . info 'Session closed.'
@xmpp . offline!
2019-04-06 06:12:54 +00:00
end
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-04-06 06:12:54 +00:00
# message from telegram network handler #
def message_handler ( update )
2019-04-09 06:42:42 +00:00
@logger . debug 'Got NewMessage update'
2019-04-07 11:58:07 +00:00
@logger . debug update . message . to_json
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
return if not @cache [ :chats ] . key? update . message . chat_id # we do not know about this chat, ignore it
return if update . message . is_outgoing and update . message . sending_state . instance_of? TD :: Types :: MessageSendingState :: Pending # ignore self outgoing messages
2019-04-07 11:58:07 +00:00
# media? #
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
file = nil
text = ''
case update . message . content
when TD :: Types :: MessageContent :: Photo # photos
file = update . message . content . photo . sizes [ - 1 ] . photo
text = " %s.jpg (image/jpeg), %d bytes | %s | %s " % [ update . message . content . photo . id . to_s , file . size . to_i , self . format_content_link ( file . remote . id , 'image.jpg' ) , update . message . content . caption . text . to_s ]
when TD :: Types :: MessageContent :: Animation # "gif" (mp4) animations
file = update . message . content . animation . animation
text = " gif: %s | %s " % [ update . message . content . animation . file_name , self . format_content_link ( file . remote . id , 'video.mp4' ) ]
when TD :: Types :: MessageContent :: Sticker # stickers
file = update . message . content . sticker . sticker
text = " sticker: %s | %s " % [ update . message . content . sticker . emoji . to_s , self . format_content_link ( file . remote . id , 'sticker.webp' ) ]
when TD :: Types :: MessageContent :: Audio # music files
file = update . message . content . audio . audio
text = " %s (%s), %d bytes | %s | %s " % [ update . message . content . audio . file_name . to_s , update . message . content . audio . mime_type . to_s , file . size . to_i , self . format_content_link ( file . remote . id , update . message . content . audio . file_name . to_s ) , update . message . content . caption . text . to_s ]
when TD :: Types :: MessageContent :: Video # video files
file = update . message . content . video . video
text = " %s (%s), %d bytes | %s | %s " % [ update . message . content . video . file_name . to_s , update . message . content . video . mime_type . to_s , file . size . to_i , self . format_content_link ( file . remote . id , update . message . content . video . file_name . to_s ) , update . message . content . caption . text . to_s ]
when TD :: Types :: MessageContent :: VoiceNote # voice messages
file = update . message . content . voice_note . voice
text = " voice message (%i s.) | %s " % [ update . message . content . voice_note . duration , self . format_content_link ( file . remote . id , 'voice.oga' ) ]
when TD :: Types :: MessageContent :: Document # documents
file = update . message . content . document . document
text = " %s (%s), %d bytes | %s | %s " % [ update . message . content . document . file_name . to_s , update . message . content . document . mime_type . to_s , file . size . to_i , self . format_content_link ( file . remote . id , update . message . content . document . file_name . to_s ) , update . message . content . caption . text . to_s ]
when TD :: Types :: MessageContent :: ChatJoinByLink # joined member
text = " joined "
when TD :: Types :: MessageContent :: ChatAddMembers # add members
text = " added "
update . message . content . member_user_ids . each do | member | text = text + self . format_username ( member ) + ' ' end
when TD :: Types :: MessageContent :: ChatDeleteMember # kicked member
text = " removed %s " % self . format_username ( update . message . content . user_id )
when TD :: Types :: MessageContent :: PinMessage # pinned message
@client . get_message ( update . message . chat_id , update . message . content . message_id ) . then { | message | text = " pinned message: %s " % message . content . text . text . to_s } . wait
when TD :: Types :: MessageContent :: ChatChangeTitle # changed chat title
text = " chat title set to: %s " % update . message . content . title . to_s
when TD :: Types :: MessageContent :: Location # location
location = " %s,%s " % [ update . message . content . location . latitude . to_s , update . message . content . location . longitude . to_s ]
text = " coordinates: %s | https://www.google.com/maps/search/%s/ " % [ location , location ]
when TD :: Types :: MessageContent :: Text # plain text
text = update . message . content . text . text . to_s
else
text = " unknown message type %s " % update . message . content . class
2019-04-07 11:58:07 +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
@client . download_file ( file . id ) if file # download it if already not
2019-04-07 11:58:07 +00:00
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
# forwards, replies and message id..
text = " [Forward from %s] %s " % [ self . format_username ( update . message . forward_info . sender_user_id ) , text ] if update . message . forward_info . instance_of? TD :: Types :: MessageForwardInfo :: MessageForwardedFromUser # fwd from user
text = " [Forward from channel %s (%s)] %s " % [ update . message . forward_info . chat_id . to_s , update . message . forward_info . author_signature . to_s , text ] if update . message . forward_info . instance_of? TD :: Types :: MessageForwardInfo :: MessageForwardedPost # fwd from chat
2019-04-07 11:58:07 +00:00
text = " [Reply to MSG %s] %s " % [ update . message . reply_to_message_id . to_s , text ] if update . message . reply_to_message_id . to_i != 0 # reply
text = " [MSG %s] [%s] %s " % [ update . message . id . to_s , self . format_username ( update . message . sender_user_id ) , text ] # username/id
2019-04-08 22:28:26 +00:00
# send and add message id to unreads
@cache [ :unread_msg ] [ update . message . chat_id ] = update . message . id
2019-04-07 11:58:07 +00:00
@xmpp . send_message ( update . message . chat_id . to_s , text )
end
# new chat update -- when tg client discovers new chat #
def new_chat_handler ( update )
2019-04-09 06:42:42 +00:00
@logger . debug 'Got NewChat update'
2019-04-07 11:58:07 +00:00
@logger . debug update . to_json
self . process_chat_info ( update . chat . id )
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
# user -- something changed in user data #
def user_handler ( update )
@logger . debug 'Got User update'
@logger . debug update . to_json
self . process_user_info ( update . user . id )
end
2019-04-07 11:58:07 +00:00
# edited msg #
def message_edited_handler ( update )
2019-04-09 06:42:42 +00:00
@logger . debug 'Got MessageEdited update'
2019-04-07 11:58:07 +00:00
@logger . debug update . to_json
# formatting
text = " [MSG %s EDIT] %s " % [ update . message_id . to_s , update . new_content . text . text . to_s ]
@xmpp . send_message ( update . chat_id . to_s , text )
2019-04-06 06:12:54 +00:00
end
2019-04-07 11:58:07 +00:00
# deleted msg #
def message_deleted_handler ( update )
2019-04-09 06:42:42 +00:00
@logger . debug 'Got MessageDeleted update'
2019-04-07 11:58:07 +00:00
@logger . debug update . to_json
return if not update . is_permanent
text = " [MSG ID %s DELETE] " % update . message_ids . join ( ',' )
@xmpp . send_message ( update . chat_id . to_s , text )
end
# file msg -- symlink to download path #
def file_handler ( update )
2019-04-09 06:42:42 +00:00
@logger . debug 'Got File update'
2019-04-07 11:58:07 +00:00
@logger . debug update . to_json
if update . file . local . is_downloading_completed then
fname = update . file . local . path . to_s
2019-04-08 20:46:16 +00:00
target = " %s/%s%s " % [ @@content_path , Digest :: SHA256 . hexdigest ( " Current user = %s, File ID = %s " % [ @tg_login . to_s , update . file . remote . id ] ) , File . extname ( fname ) ]
2019-04-07 11:58:07 +00:00
@logger . debug 'Downloading of <%s> completed! Link to <%s>' % [ fname , target ]
File . symlink ( fname , target )
end
end
# status update handler #
def status_update_handler ( update )
2019-04-09 06:42:42 +00:00
@logger . debug 'Got new StatusUpdate'
2019-04-07 11:58:07 +00:00
@logger . debug update . to_json
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
return if update . user_id == @me . id # ignore self statuses
self . process_status_update ( update . user_id , update . status )
2019-04-07 11:58:07 +00:00
end
2019-04-06 06:12:54 +00:00
2019-04-06 07:29:48 +00:00
###########################################
## LooP handlers #########################
###########################################
2019-04-06 06:12:54 +00:00
# processing authorization #
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
def process_auth ( auth_data )
@logger . debug 'check_authorization :%s..' % auth_data [ 0 ]
@client . check_authentication_code ( auth_data [ 1 ] ) if auth_data [ 0 ] == :code
@client . check_authentication_password ( auth_data [ 1 ] ) if auth_data [ 0 ] == :password
end
# /command #
def process_command ( chat_id , text )
splitted = text . split # splitted[0] = command, splitted[1] = argument
splitted = [ '/sed' , text [ 3 .. - 1 ] ] if text [ 0 .. 2 ] == '/s/' # sed-like edit
resolved = nil ; response = nil
# if second argument starts with @, try to resolve it
@client . search_public_chat ( splitted [ 1 ] [ 1 .. - 1 ] ) . then { | chat | resolved = chat } . wait if splitted [ 1 ] and splitted [ 1 ] [ 0 ] == '@'
case splitted [ 0 ]
when '/info' # retrieve some information by link, @username or username
response = " Contact id: %s \n Contact name: %s \n Contact type: %s " % [ resolved . id . to_s , resolved . title . to_s , resolved . type . class . to_s ] if resolved
when '/add' # open new private chat by its id
chat = ( resolved ) ? resolved . id : splitted [ 1 ] . to_i
@client . create_private_chat ( chat ) . wait
self . process_chat_info ( chat )
when '/join' # join group/supergroup by invite link or by id
chat = splitted [ 1 ]
chat . start_with? " http " ? @client . join_chat_by_invite_link ( chat ) . wait : @client . join_chat ( chat . to_i ) . wait
when '/invite' # invite user to chat
@client . add_chat_member ( chat_id , response . id ) . wait if resolved
when '/kick' # removes user from chat
@client . set_chat_member_status ( chat_id , response . id , TD :: Types :: ChatMemberStatus :: Left . new ( ) ) . wait if resolved
when '/ban' # removes user from chat. argument = hours to ban.
until_date = ( splitted [ 1 ] ) ? Time . now . getutc . to_i + splitted [ 1 ] . to_i * 3600 : 0
@client . set_chat_member_status ( chat_id , response . id , TD :: Types :: ChatMemberStatus :: Banned . new ( banned_until_date : until_date ) ) . wait if resolved
when '/block' # add user to blacklist
@client . block_user ( chat_id )
when '/unblock' # add user to blacklist
@client . unblock_user ( chat_id )
when '/leave' , '/delete' # delete / leave chat
@client . close_chat ( chat_id ) . wait
@client . leave_chat ( chat_id ) . wait
@client . delete_chat_history ( chat_id , true ) . wait
@xmpp . presence_update ( chat_id , :unsubscribed )
@xmpp . presence_update ( chat_id , :unavailable )
@cache [ :chats ] . delete ( chat_id )
when '/sed' # sed-like edit
sed = splitted [ 1 ] . split ( '/' )
@client . search_chat_messages ( chat_id , 0 , 1 , sender_user_id : @me . id , filter : TD :: Types :: SearchMessagesFilter :: Empty . new ) . then { | msgs |
original = msgs . messages [ 0 ] . content . text . text . to_s
edited = ( sed [ 0 ] != '' ) ? original . gsub ( Regexp . new ( sed [ 0 ] ) , sed [ 1 ] ) : sed [ 1 ]
@client . edit_message_text ( chat_id , msgs . messages [ 0 ] . id , TD :: Types :: InputMessageContent :: Text . new ( :text = > { :text = > edited , :entities = > [ ] } , :disable_web_page_preview = > false , :clear_draft = > true ) ) if edited != original
} . wait
when '/d' # delete last message
@client . search_chat_messages ( chat_id , 0 , 1 , sender_user_id : @me . id , filter : TD :: Types :: SearchMessagesFilter :: Empty . new ) . then { | msgs |
@client . delete_messages ( chat_id , [ msgs . messages [ 0 ] . id ] , true )
} . wait
else
response = ' Unknown command .
/ s /mi tsake / mistake / — Edit last message
/ d — Delete last message
/ info @username — Search public chat or user
/ add @username or id — Creates conversation with specified user
/ join chat_link or id — Joins chat by its link or id
/ invite @username — Invites @username to current chat
/ kick @username — Removes @username from current chat
/ ban @username [hours] — Bans @username in current chat for [hours] hrs or forever if [hours] not specified
/ block — Blacklists current user
/ unblock — Removes current user from blacklist
/ leave — Leave current chat
/ delete — Delete current chat
'
end
@xmpp . send_message ( chat_id , response ) if response
2019-04-06 06:12:54 +00:00
end
# processing outgoing message from queue #
def process_outgoing_msg ( msg )
2019-04-09 06:42:42 +00:00
@logger . debug 'Sending message to user/chat <%s> within Telegram network..' % msg [ :to ]
2019-04-08 22:28:26 +00:00
chat_id , text , reply_to = msg [ :to ] . to_i , msg [ :text ] , 0
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
# processing /commands #
return self . process_command ( chat_id , text ) if text [ 0 ] == '/'
2019-04-08 22:28:26 +00:00
# handling replies #
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
if text [ 0 ] == '>' then
splitted = text . split ( " \n " )
reply_to = splitted [ 0 ] . scan ( / \ d / ) . join ( '' ) || 0
2019-04-08 22:28:26 +00:00
text = splitted . drop ( 1 ) . join ( " \n " ) if reply_to != 0
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
# handling files received from xmpp #
if text . start_with? @@content_upload_prefix then
message = TD :: Types :: InputMessageContent :: Document . new ( document : TD :: Types :: InputFile :: Remote . new ( id : text ) , caption : { :text = > '' , :entities = > [ ] } )
else
message = TD :: Types :: InputMessageContent :: Text . new ( :text = > { :text = > text , :entities = > [ ] } , :disable_web_page_preview = > false , :clear_draft = > true )
end
2019-04-08 22:28:26 +00:00
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
# send message and mark chat as read #
2019-04-08 22:28:26 +00:00
@client . send_message ( chat_id , message , reply_to_message_id : reply_to )
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
@client . view_messages ( chat_id , [ @cache [ :unread_msg ] . delete ( chat_id ) ] , force_read : true ) if @cache [ :unread_msg ] [ chat_id ]
2019-04-06 06:12:54 +00:00
end
2019-04-07 11:58:07 +00:00
# update users information and save it to cache #
def process_chat_info ( chat_id )
2019-04-09 06:42:42 +00:00
@logger . debug 'Updating chat id %s..' % chat_id . to_s
2019-04-07 11:58:07 +00:00
# fullfil cache.. pasha durov, privet. #
@client . get_chat ( chat_id ) . then { | chat |
@cache [ :chats ] [ chat_id ] = chat # cache chat
self . process_user_info ( chat . type . user_id ) if chat . type . instance_of? TD :: Types :: ChatType :: Private # cache user if it is private chat
} . wait
# send to roster #
if @cache [ :chats ] . key? chat_id
2019-04-09 06:42:42 +00:00
@logger . debug " Sending presence to roster.. "
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
@xmpp . presence_update ( chat_id . to_s , :subscribe , nil , nil , @cache [ :chats ] [ chat_id ] . title . to_s ) # send subscription request
@xmpp . presence_update ( chat_id . to_s , nil , :chat , nil , @cache [ :chats ] [ chat_id ] . title . to_s ) if chat_id < 0 # send :chat status if its group/supergroup
2019-04-07 11:58:07 +00:00
end
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
# update user info in cache and sync status to roster if needed #
2019-04-07 11:58:07 +00:00
def process_user_info ( user_id )
2019-04-09 06:42:42 +00:00
@logger . debug 'Updating user id %s..' % user_id . to_s
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
@client . get_user ( user_id ) . then { | user |
@cache [ :users ] [ user_id ] = user # add to cache
self . process_status_update ( user_id , user . status ) # status update
} . wait
2019-04-07 11:58:07 +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-04-07 11:58:07 +00:00
# convert telegram status to XMPP one
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
def process_status_update ( user_id , status )
@logger . debug " Processing status update for user id %s.. " % user_id . to_s
xmpp_show , xmpp_status = nil , ''
2019-04-07 11:58:07 +00:00
case status
when TD :: Types :: UserStatus :: Online
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
xmpp_show = nil
xmpp_status = " Online "
2019-04-07 11:58:07 +00:00
when TD :: Types :: UserStatus :: Offline
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
xmpp_show = ( Time . now . getutc . to_i - status . was_online . to_i < 3600 ) ? :away : :xa
xmpp_status = DateTime . strptime ( status . was_online . to_s , '%s' ) . strftime ( " Last seen at %H:%M %d/%m/%Y " )
2019-04-07 11:58:07 +00:00
when TD :: Types :: UserStatus :: Recently
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
xmpp_show = :dnd
xmpp_status = " Last seen recently "
2019-04-07 11:58:07 +00:00
when TD :: Types :: UserStatus :: LastWeek
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
xmpp_show = :unavailable
xmpp_status = " Last seen last week "
2019-04-07 11:58:07 +00:00
when TD :: Types :: UserStatus :: LastMonth
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
xmpp_show = :unavailable
xmpp_status = " Last seen last month "
2019-04-07 11:58:07 +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
@xmpp . presence_update ( user_id . to_s , nil , xmpp_show , xmpp_status )
2019-04-07 11:58:07 +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
###########################################
## Format functions #######################
###########################################
2019-04-07 11:58:07 +00:00
# format tg user name #
def format_username ( user_id )
if not @cache [ :users ] . key? user_id then self . process_user_info ( user_id ) end
2019-04-08 22:28:26 +00:00
id = ( @cache [ :users ] [ user_id ] . username == '' ) ? user_id : @cache [ :users ] [ user_id ] . username
2019-04-09 06:42:42 +00:00
name = '%s %s (@%s)' % [ @cache [ :users ] [ user_id ] . first_name , @cache [ :users ] [ user_id ] . last_name , id ]
2019-04-07 11:58:07 +00:00
name . sub! ' ]' , ']'
return name
end
# format content link #
def format_content_link ( file_id , fname )
path = " %s/%s%s " % [ @@content_link , Digest :: SHA256 . hexdigest ( " Current user = %s, File ID = %s " % [ @tg_login . to_s , file_id . to_s ] ) . to_s , File . extname ( fname ) ]
return path
end
2019-04-06 06:12:54 +00:00
end