2019-04-06 06:12:54 +00:00
require 'xmpp4r'
2019-04-06 07:29:48 +00:00
### Some constants #########
:: HELP_MESSAGE = " Unknown command. \n \n Please, use /login <phonenumber> to try log in. ☺ "
2019-04-06 06:12:54 +00:00
#############################
## XMPP Transport Class #####
#############################
class XMPPComponent
2019-04-06 07:29:48 +00:00
def initialize ( )
@logger = Logger . new ( STDOUT ) ; @logger . progname = '[XMPPComponent]'
end
2019-04-06 06:12:54 +00:00
# transport initialization & connecting to XMPP server #
def connect ( params ) # :jid => transport_jid, :host => xmpp_server, :port => xmpp_component_port, :secret => xmpp_component_secret
2019-04-06 07:29:48 +00:00
@logger . info " Connecting.. "
2019-04-06 06:12:54 +00:00
begin
@@transport = Jabber :: Component . new ( params [ :jid ] )
@@transport . connect ( params [ :host ] , params [ :port ] )
@@transport . auth ( params [ :secret ] )
@@transport . add_message_callback do | msg | msg . first_element_text ( 'body' ) ? self . message_handler ( msg ) : nil end
@sessions = { }
2019-04-06 07:29:48 +00:00
@logger . info " Connection established "
2019-04-06 06:12:54 +00:00
Thread . stop ( )
rescue Exception = > e
2019-04-06 07:29:48 +00:00
@logger . info 'Connection failed: %s' % e
2019-04-06 06:12:54 +00:00
exit 1
end
end
# new message to XMPP component #
def message_handler ( msg )
2019-04-06 07:29:48 +00:00
@logger . info 'New message from [%s] to [%s]' % [ msg . from , msg . to ]
2019-04-06 06:12:54 +00:00
return self . process_internal_command ( msg . from . bare , msg . first_element_text ( 'body' ) ) if msg . to == @@transport . jid # treat message as internal command if received as transport jid
2019-04-06 07:29:48 +00:00
return @sessions [ msg . from . bare ] . queue_message ( msg . to . to_s , msg . first_element_text ( 'body' ) ) if @sessions . key? msg . from . bare # queue message for processing session is active for jid from
2019-04-06 06:12:54 +00:00
end
# process internal /command #
def process_internal_command ( jfrom , body )
case body . split [ 0 ] # /command argument = [command, argument]
2019-04-06 07:29:48 +00:00
when '/login'
# we will try to create new user session for JID <jfrom> and try to start telegram client for login <body.split[1]>
2019-04-06 06:12:54 +00:00
@sessions [ jfrom ] = XMPPSession . new ( jfrom , body . split [ 1 ] )
2019-04-06 07:29:48 +00:00
when '/code' , '/password'
# we will pass auth data to user session if this session exists.
@sessions [ jfrom ] . enter_auth_data ( body . split [ 0 ] [ 1 .. 8 ] , body . split [ 1 ] ) if @sessions . key? jfrom
else # unknown command -- we will display sort of help message.
reply = Jabber :: Message . new ; reply . from , reply . to , reply . body , reply . type = @@transport . jid , jfrom , :: HELP_MESSAGE , :chat
2019-04-06 06:12:54 +00:00
@@transport . send ( reply )
end
end
end
#############################
## XMPP Session Class #######
#############################
class XMPPSession < XMPPComponent
attr_accessor :user_jid , :tg_login , :tg_auth_data , :message_queue
# start XMPP user session and Telegram client instance #
def initialize ( jid , tg_login )
2019-04-06 07:29:48 +00:00
@logger = Logger . new ( STDOUT ) ; @logger . progname = '[XMPPSession: %s/%s]' % [ jid , tg_login ]
@logger . info " Starting Telegram session "
2019-04-06 06:12:54 +00:00
@user_jid , @tg_login , @tg_auth_data , @message_queue = jid , tg_login , { code : nil , password : nil } , Queue . new ( )
2019-04-06 07:29:48 +00:00
@tg_client = Thread . new { TelegramClient . new ( self , tg_login ) }
2019-04-06 06:12:54 +00:00
end
# send message to XMPP #
def send_message ( from = nil , body = '' )
2019-04-06 07:29:48 +00:00
@logger . info " Incoming message from Telegram network <- %s " % from . to_s
2019-04-06 06:12:54 +00:00
from = from . nil? ? @@transport . jid : from . to_s + '@' + @@transport . jid . to_s
reply = Jabber :: Message . new ; reply . from , reply . to , reply . body , reply . type = from , @user_jid , body , :chat
@@transport . send ( reply )
end
# queue message (we will share this queue within :message_queue to Telegram client thread) #
def queue_message ( to , text = '' )
2019-04-06 07:29:48 +00:00
@logger . info " Queuing message to be sent to Telegram network user -> " % to
2019-04-06 06:12:54 +00:00
@message_queue << { to : to . split ( '@' ) [ 0 ] , text : text }
2019-04-06 07:29:48 +00:00
puts @message_queue
2019-04-06 06:12:54 +00:00
end
# enter auth data (we will share this data within :tg_auth_data to Telegram client thread ) #
def enter_auth_data ( typ , data )
2019-04-06 07:29:48 +00:00
logger . info " Authorizing in Telegram network with :%s " % typ
@tg_auth_data [ typ . to_sym ] = data
2019-04-06 06:12:54 +00:00
end
end