Initial release
Implemented authorization and simple messages
This commit is contained in:
commit
854b61ada0
12
inc/logger.rb
Normal file
12
inc/logger.rb
Normal file
|
@ -0,0 +1,12 @@
|
|||
require 'logger'
|
||||
|
||||
class Logging
|
||||
def self.log
|
||||
if @logger.nil?
|
||||
@logger = Logger.new STDOUT
|
||||
@logger.level = Logger::DEBUG
|
||||
@logger.datetime_format = '%Y-%m-%d %H:%M:%S '
|
||||
end
|
||||
@logger
|
||||
end
|
||||
end
|
90
inc/telegram.rb
Normal file
90
inc/telegram.rb
Normal file
|
@ -0,0 +1,90 @@
|
|||
require 'tdlib-ruby'
|
||||
|
||||
class TelegramClient
|
||||
|
||||
# tdlib configuration, shared within all instances #
|
||||
def self.configure(params)
|
||||
TD.configure do |config|
|
||||
config.lib_path = params[:lib_path] || 'lib/'
|
||||
config.client.api_id = params[:api_id] || 430850
|
||||
config.client.api_hash = params[:api_hash] || '3d3cfcbd30d0805f757c5fc521004861'
|
||||
end
|
||||
TD::Api.set_log_verbosity_level(params[:verbose] || 1)
|
||||
end
|
||||
|
||||
# instance initialization #
|
||||
def initialize(xmpp, login)
|
||||
|
||||
@xmpp = xmpp
|
||||
@login = login
|
||||
|
||||
Logging.log.info '[TelegramClient] [%s] Initializing..' % @login
|
||||
|
||||
@client = TD::Client.new(database_directory: 'sessions/' + @login, files_directory: 'sessions/' + @login + '/files/') # create telegram client instance
|
||||
@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
|
||||
@client.connect #
|
||||
|
||||
# we will check new messages in queue and auth data in forever loop #
|
||||
#begin
|
||||
loop do
|
||||
self.process_outgoing_msg(@xmpp.message_queue.pop) unless @xmpp.message_queue.empty? # found something in message queue
|
||||
self.process_auth(:code, @xmpp.tg_auth_data[:code]) unless @xmpp.tg_auth_data[:code].nil? # found code in auth queue
|
||||
self.process_auth(:password, @xmpp.tg_auth_data[:password]) unless @xmpp.tg_auth_data[:password].nil? # found 2fa password in auth queue
|
||||
sleep 0.5
|
||||
end
|
||||
#ensure
|
||||
#Logging.log.info '[TelegramClient] Exitting gracefully...'
|
||||
#@client.dispose
|
||||
#end
|
||||
end
|
||||
|
||||
# authorization handler #
|
||||
def auth_handler(update)
|
||||
Logging.log.debug '[TelegramClient] [%s] Authorization state changed: %s' % [@login, update.authorization_state]
|
||||
case update.authorization_state
|
||||
|
||||
# auth stage 0: specify login #
|
||||
when TD::Types::AuthorizationState::WaitPhoneNumber
|
||||
Logging.log.debug '[TelegramClient] [%s] Logging in..' % @login
|
||||
@client.set_authentication_phone_number(@login)
|
||||
# auth stage 1: wait for authorization code #
|
||||
when TD::Types::AuthorizationState::WaitCode
|
||||
@xmpp.send_message(nil, 'Please, enter authorization code via /code 12345')
|
||||
Logging.log.debug '[TelegramClient] [%s] Waiting for Authorization code..' % @login
|
||||
# auth stage 2: wait for 2fa passphrase #
|
||||
when TD::Types::AuthorizationState::WaitPassword
|
||||
@xmpp.send_message(nil, 'Please, enter 2FA passphrase via /password 12345')
|
||||
Logging.log.debug '[TelegramClient] [%s] Waiting for 2FA password..' % @login
|
||||
# authorizatio successful #
|
||||
when TD::Types::AuthorizationState::Ready
|
||||
@xmpp.send_message(nil, 'Authorization successful.')
|
||||
Logging.log.debug '[TelegramClient] [%s] Authorization successful.' % @login
|
||||
end
|
||||
end
|
||||
|
||||
# message from telegram network handler #
|
||||
def message_handler(update)
|
||||
Logging.log.debug '[TelegramClient] [%s] Got NewMessage update <%s>' % [@login, update.message]
|
||||
from = update.message.chat_id
|
||||
text = update.message.content.text.text
|
||||
@xmpp.send_message(from, text) if not update.message.is_outgoing
|
||||
end
|
||||
|
||||
##################################################
|
||||
|
||||
# processing authorization #
|
||||
def process_auth(typ, data)
|
||||
Logging.log.debug '[TelegramClient] [%s] Authorizing with <%s> in Telegram...' % [@login, typ.to_s]
|
||||
@client.check_authentication_code(data) if typ == :code
|
||||
@client.check_authentication_password(data) if typ == :password
|
||||
@xmpp.tg_auth = {} # unset it to prevent extracting 2fa password from memory
|
||||
end
|
||||
|
||||
# processing outgoing message from queue #
|
||||
def process_outgoing_msg(msg)
|
||||
Logging.log.debug '[TelegramClient] [%s] Sending message to user/chat <%s> within Telegram network..' % [@login, msg[:to]]
|
||||
message = TD::Types::InputMessageContent::Text.new(:text => { :text => msg[:text], :entities => []}, :disable_web_page_preview => false, :clear_draft => false )
|
||||
@client.send_message(msg[:to].to_i, message)
|
||||
end
|
||||
end
|
86
inc/xmpp.rb
Normal file
86
inc/xmpp.rb
Normal file
|
@ -0,0 +1,86 @@
|
|||
require 'xmpp4r'
|
||||
|
||||
#############################
|
||||
## XMPP Transport Class #####
|
||||
#############################
|
||||
class XMPPComponent
|
||||
attr_accessor :jid
|
||||
|
||||
# transport initialization & connecting to XMPP server #
|
||||
def connect(params) # :jid => transport_jid, :host => xmpp_server, :port => xmpp_component_port, :secret => xmpp_component_secret
|
||||
Logging.log.info '[XMPP] Connecting...'
|
||||
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 = {}
|
||||
Logging.log.info '[XMPP] Connection established'
|
||||
Thread.stop()
|
||||
rescue Exception => e
|
||||
Logging.log.info '[XMPP] Connection failed (%s)' % e
|
||||
exit 1
|
||||
end
|
||||
end
|
||||
|
||||
# new message to XMPP component #
|
||||
def message_handler(msg)
|
||||
Logging.log.debug '[XMPP] New message from [%s] to [%s]' % [msg.from, msg.to]
|
||||
|
||||
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
|
||||
return @sessions[msg.from.bare].queue_message(msg.to, msg.first_element_text('body')) if @sessions.key? msg.from.bare # queue message for processing session is active for jid from
|
||||
end
|
||||
|
||||
# process internal /command #
|
||||
def process_internal_command(jfrom, body)
|
||||
case body.split[0] # /command argument = [command, argument]
|
||||
when '/help' #
|
||||
when '/login' # Create new session
|
||||
@sessions[jfrom] = XMPPSession.new(jfrom, body.split[1])
|
||||
when '/code', '/password' # Enter auth code / 2fa password
|
||||
@sessions[jfrom].enter_auth_data(body.split[0], body.split[1])
|
||||
else # Unknown command
|
||||
reply = Jabber::Message.new; reply.from, reply.to, reply.body, reply.type = @@transport.jid, jfrom, 'Unknown command', :chat
|
||||
@@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)
|
||||
Logging.log.info "[XMPPSession] [%s] Starting Telegram session as [%s]" % [jid, tg_login]
|
||||
@user_jid, @tg_login, @tg_auth_data, @message_queue = jid, tg_login, {code: nil, password: nil}, Queue.new()
|
||||
@tg_thread = Thread.new{ TelegramClient.new(self, tg_login) }
|
||||
end
|
||||
|
||||
# send message to XMPP #
|
||||
def send_message(from = nil, body = '')
|
||||
Logging.log.info "[XMPPSession] [%s] Incoming message from Telegram network <- [%s].." % [@user_jid, from.to_s]
|
||||
puts 1
|
||||
from = from.nil? ? @@transport.jid : from.to_s+'@'+@@transport.jid.to_s
|
||||
puts 2
|
||||
reply = Jabber::Message.new; reply.from, reply.to, reply.body, reply.type = from, @user_jid, body, :chat
|
||||
puts reply
|
||||
@@transport.send(reply)
|
||||
end
|
||||
|
||||
# queue message (we will share this queue within :message_queue to Telegram client thread) #
|
||||
def queue_message(to, text = '')
|
||||
Logging.log.info "[XMPPSession] [%s] Queuying message to Telegram network -> [%s].." % [@user_jid, to]
|
||||
@message_queue << {to: to.split('@')[0], text: text}
|
||||
end
|
||||
|
||||
# enter auth data (we will share this data within :tg_auth_data to Telegram client thread ) #
|
||||
def enter_auth_data(typ, data)
|
||||
Logging.log.info "[XMPPSession] [%s] Authorizing in Telegram with [%s]" % [@user_jid, typ]
|
||||
@tg_auth_data[typ[1..8].to_sym] = data
|
||||
end
|
||||
|
||||
end
|
7
main.rb
Normal file
7
main.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
require_relative 'inc/logger'
|
||||
require_relative 'inc/telegram'
|
||||
require_relative 'inc/xmpp'
|
||||
|
||||
Logging.log.info '[MAIN] Starting Zhabogram v0.o1...'
|
||||
TelegramClient.configure(verbose: 2)
|
||||
XMPPComponent.new().connect(host: 'localhost', port: '8899', jid: 'tlgrm2.rxtx.us', secret: '')
|
Reference in a new issue