Release 1.2
[!] Using YAML serilaization instead of sqlite3. You may convert your SQLite db to YAML format using this: (echo "---"; sqlite3 users.db 'select jid,login from users'|sed "s/|/: \'/g;s/$/\'/g") > users.dat [FIX] Fixed repllies [UPD] Sending presence probe after disconnect received — maybe there are another XMPP resource? ☺ [UPD] When XMPP user goes online if Telegram session already established -- resync statuses with Telegram network to get all contacts online immediately
This commit is contained in:
parent
780dd6d6a1
commit
da2de42645
|
@ -3,8 +3,8 @@ telegram:
|
||||||
api_id: '845316' # telegram API ID (my.telegram.org) #
|
api_id: '845316' # telegram API ID (my.telegram.org) #
|
||||||
api_hash: '27fe5224bc822bf3a45e015b4f9dfdb7' # telegram API HASH (my.telegram.org) #
|
api_hash: '27fe5224bc822bf3a45e015b4f9dfdb7' # telegram API HASH (my.telegram.org) #
|
||||||
verbosity: 2 # 1 = no verbosity, 2 = moderate verbosity, 3 = network requests debug
|
verbosity: 2 # 1 = no verbosity, 2 = moderate verbosity, 3 = network requests debug
|
||||||
useragent: 'Zhabogram XMPP Gateway' # client name
|
useragent: 'Zhabogram' # client name
|
||||||
version: '1.0' # client version
|
version: '1.2' # client version
|
||||||
use_test_dc: false # always use false
|
use_test_dc: false # always use false
|
||||||
loglevel: 0 # 0 = debug, 1 = info, 2 = warn, 3 = err, 4 = fatal, 5 = unknown (ruby logger class)
|
loglevel: 0 # 0 = debug, 1 = info, 2 = warn, 3 = err, 4 = fatal, 5 = unknown (ruby logger class)
|
||||||
content_path: '/var/zhabogram/content' # we will move (symlink) downloaded content here — you must setup web server that serve this directry
|
content_path: '/var/zhabogram/content' # we will move (symlink) downloaded content here — you must setup web server that serve this directry
|
||||||
|
@ -16,7 +16,7 @@ xmpp:
|
||||||
debug: false
|
debug: false
|
||||||
admins:
|
admins:
|
||||||
- 'root@localhost'
|
- 'root@localhost'
|
||||||
db_path: 'users.db' # sqlite3 users (JID:Telegram Login) database
|
db_path: 'users.dat' # users store (JID:Telegram Login)
|
||||||
jid: 'tlgrm.localhost' # component JID
|
jid: 'tlgrm.localhost' # component JID
|
||||||
host: 'localhost' # XMPP server
|
host: 'localhost' # XMPP server
|
||||||
port: 8888 # component port
|
port: 8888 # component port
|
||||||
|
|
|
@ -54,6 +54,7 @@ class TelegramClient
|
||||||
@client.on(TD::Types::Update::User) do |update| self.user_handler(update) end # new user update?
|
@client.on(TD::Types::Update::User) do |update| self.user_handler(update) end # new user update?
|
||||||
@client.on(TD::Types::Update::UserStatus) do |update| self.status_update_handler(update) end # register status handler
|
@client.on(TD::Types::Update::UserStatus) do |update| self.status_update_handler(update) end # register status handler
|
||||||
@client.connect()
|
@client.connect()
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
# disconnect and destroy telegram client #
|
# disconnect and destroy telegram client #
|
||||||
|
@ -339,11 +340,10 @@ class TelegramClient
|
||||||
|
|
||||||
# handling replies #
|
# handling replies #
|
||||||
reply_to = 0
|
reply_to = 0
|
||||||
if text[0] == '>' then
|
if text[0] == '>' and text.match(Regexp.new /^>( )?[0-9]{10,20}/) then
|
||||||
text = text.split("\n")
|
text = text.split("\n")
|
||||||
reply_to = text[0].scan(/\d/).to_i
|
reply_to = text[0].scan(/\d+/).first.to_i
|
||||||
reply_to = 0 if reply_to < 10000
|
text = text.drop(1).join("\n")
|
||||||
text = splitted.drop(1).join("\n") if reply_to != 0
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# handling files received from xmpp #
|
# handling files received from xmpp #
|
||||||
|
@ -377,6 +377,12 @@ class TelegramClient
|
||||||
return @cache[:users][user_id] if @cache[:users].key? user_id
|
return @cache[:users][user_id] if @cache[:users].key? user_id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# sync statuses with XMPP roster
|
||||||
|
def sync_status()
|
||||||
|
@logger.debug "Syncing statuses with roster.."
|
||||||
|
@cache[:chats].each do |chat| self.process_status_update(chat.id, (@cache[:users].include? chat.id ? @cache[:users][chat.id].status : chat.title.to_s), true) end
|
||||||
|
end
|
||||||
|
|
||||||
# convert telegram status to XMPP one
|
# convert telegram status to XMPP one
|
||||||
def process_status_update(user_id, status, immed = true)
|
def process_status_update(user_id, status, immed = true)
|
||||||
@logger.debug "Processing status update for user id %s.." % user_id.to_s
|
@logger.debug "Processing status update for user id %s.." % user_id.to_s
|
||||||
|
|
|
@ -32,28 +32,22 @@ class XMPPComponent
|
||||||
@config = { host: params["host"] || 'localhost', port: params["port"] || 8899, jid: params["jid"] || 'tlgrm.localhost', secret: params['password'] || '', admins: params['admins'] || [], debug: params['debug'] } # default config
|
@config = { host: params["host"] || 'localhost', port: params["port"] || 8899, jid: params["jid"] || 'tlgrm.localhost', secret: params['password'] || '', admins: params['admins'] || [], debug: params['debug'] } # default config
|
||||||
@sessions = {}
|
@sessions = {}
|
||||||
@presence_que = {}
|
@presence_que = {}
|
||||||
@db = SQLite3::Database.new(params['db_path'] || 'users.db')
|
@db = params['db_path'] || 'users.dat'
|
||||||
@db.execute("CREATE TABLE IF NOT EXISTS users(jid varchar(256), login varchar(256), PRIMARY KEY(jid) );")
|
|
||||||
@db.results_as_hash = true
|
|
||||||
self.load_db()
|
self.load_db()
|
||||||
end
|
end
|
||||||
|
|
||||||
# load sessions from db #
|
# load sessions from db #
|
||||||
def load_db(jid = nil)
|
def load_db()
|
||||||
@logger.info "Initializing database.."
|
@logger.info "Loading sessions..."
|
||||||
query = (jid.nil?) ? "SELECT * FROM users" : "SELECT * FROM users where jid = '%s';" % jid
|
File.open( @db, 'r' ) {|f| YAML.load(f).each do |jid,login| @sessions[jid] = TelegramClient.new(self, jid, login) end }
|
||||||
@logger.debug(query)
|
|
||||||
@db.execute(query) do |session| @sessions[session['jid']] = TelegramClient.new(self, session['jid'], session['login']) end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# store session to db #
|
# store session to db #
|
||||||
def update_db(jid, delete = false, register = false)
|
def save_db()
|
||||||
login = (not register and @sessions.key? jid) ? @sessions[jid].login.to_s : register
|
@logger.info "Saving sessions..."
|
||||||
return if not login
|
sessions_store = []
|
||||||
@logger.info "Writing database [%s].." % jid.to_s
|
@sessions.each do |jid,session| store << {jid: jid, login: session.login} end
|
||||||
query = (delete) ? "DELETE FROM users where jid = '%s';" % jid.to_s : "INSERT OR REPLACE INTO users(jid, login) VALUES('%s', '%s');" % [jid.to_s, login]
|
File.open( @db, 'w' ) {|f| f.write(YAML.dump(sessions_store)) }
|
||||||
@logger.debug query
|
|
||||||
@db.execute(query)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# connecting to XMPP server #
|
# connecting to XMPP server #
|
||||||
|
@ -97,7 +91,7 @@ class XMPPComponent
|
||||||
return -11
|
return -11
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
@logger.error 'Connection failed: %s' % e
|
@logger.error 'Connection failed: %s' % e
|
||||||
@db.close
|
self.save_db()
|
||||||
exit -8
|
exit -8
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -174,8 +168,8 @@ class XMPPComponent
|
||||||
@logger.debug "Received presence :%s from <%s> to <%s>" % [prsnc.type.to_s, prsnc.from.to_s, prsnc.to.to_s]
|
@logger.debug "Received presence :%s from <%s> to <%s>" % [prsnc.type.to_s, prsnc.from.to_s, prsnc.to.to_s]
|
||||||
@logger.debug(prsnc.to_s)
|
@logger.debug(prsnc.to_s)
|
||||||
if prsnc.type == :subscribe then reply = prsnc.answer(false); reply.type = :subscribed; @component.send(reply); end # send "subscribed" reply to "subscribe" presence
|
if prsnc.type == :subscribe then reply = prsnc.answer(false); reply.type = :subscribed; @component.send(reply); end # send "subscribed" reply to "subscribe" presence
|
||||||
if prsnc.to == @component.jid and @sessions.key? prsnc.from.bare.to_s and prsnc.type == :unavailable then @sessions[prsnc.from.bare.to_s].disconnect(); return; end # go offline when received offline presence from jabber user
|
if prsnc.to == @component.jid and @sessions.key? prsnc.from.bare.to_s and prsnc.type == :unavailable then @sessions[prsnc.from.bare.to_s].disconnect(); self.presence(prsnc.from, nil, :subscribe) ; return; end # go offline when received offline presence from jabber user
|
||||||
if prsnc.to == @component.jid and @sessions.key? prsnc.from.bare.to_s then self.request_tz(prsnc.from); @sessions[prsnc.from.bare.to_s].connect(); return; end # connect if we have session
|
if prsnc.to == @component.jid and @sessions.key? prsnc.from.bare.to_s then self.request_tz(prsnc.from); @sessions[prsnc.from.bare.to_s].connect() || @sessions[prsnc.from.bare.to_s].sync_status(); return; end # connect if we have session
|
||||||
end
|
end
|
||||||
|
|
||||||
# new iq (vcard/tz) request to XMPP component #
|
# new iq (vcard/tz) request to XMPP component #
|
||||||
|
@ -226,7 +220,7 @@ class XMPPComponent
|
||||||
@sessions[from.bare.to_s] = TelegramClient.new(self, from.bare.to_s, body.split[1]) if not (@sessions.key? from.bare.to_s and @sessions[from.bare.to_s].online?)
|
@sessions[from.bare.to_s] = TelegramClient.new(self, from.bare.to_s, body.split[1]) if not (@sessions.key? from.bare.to_s and @sessions[from.bare.to_s].online?)
|
||||||
@sessions[from.bare.to_s].connect()
|
@sessions[from.bare.to_s].connect()
|
||||||
self.request_tz(from)
|
self.request_tz(from)
|
||||||
self.update_db(from.bare.to_s)
|
self.save_db()
|
||||||
when '/code', '/password' # pass auth data to telegram
|
when '/code', '/password' # pass auth data to telegram
|
||||||
@sessions[from.bare.to_s].process_auth(body.split[0], body.split[1]) if @sessions.key? from.bare.to_s
|
@sessions[from.bare.to_s].process_auth(body.split[0], body.split[1]) if @sessions.key? from.bare.to_s
|
||||||
when '/connect' # go online
|
when '/connect' # go online
|
||||||
|
@ -239,7 +233,7 @@ class XMPPComponent
|
||||||
@sessions[from.bare.to_s].connect() if @sessions.key? from.bare.to_s
|
@sessions[from.bare.to_s].connect() if @sessions.key? from.bare.to_s
|
||||||
when '/logout' # go offline and destroy session
|
when '/logout' # go offline and destroy session
|
||||||
@sessions[from.bare.to_s].disconnect(true) if @sessions.key? from.bare.to_s
|
@sessions[from.bare.to_s].disconnect(true) if @sessions.key? from.bare.to_s
|
||||||
self.update_db(from.bare.to_s, true)
|
self.save_db()
|
||||||
@sessions.delete(from.bare.to_s)
|
@sessions.delete(from.bare.to_s)
|
||||||
when '/info' # show some debug information
|
when '/info' # show some debug information
|
||||||
return if not @config[:admins].include? from.bare.to_s
|
return if not @config[:admins].include? from.bare.to_s
|
||||||
|
|
|
@ -5,7 +5,6 @@ require 'xmpp4r'
|
||||||
require 'xmpp4r/discovery'
|
require 'xmpp4r/discovery'
|
||||||
require 'digest'
|
require 'digest'
|
||||||
require 'base64'
|
require 'base64'
|
||||||
require 'sqlite3'
|
|
||||||
require 'fileutils'
|
require 'fileutils'
|
||||||
require 'tdlib-ruby'
|
require 'tdlib-ruby'
|
||||||
require_relative 'inc/telegramclient'
|
require_relative 'inc/telegramclient'
|
||||||
|
|
Reference in a new issue