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:
annelin 2019-06-11 16:24:44 +03:00
parent 780dd6d6a1
commit da2de42645
4 changed files with 28 additions and 29 deletions

View file

@ -3,8 +3,8 @@ telegram:
api_id: '845316' # telegram API ID (my.telegram.org) #
api_hash: '27fe5224bc822bf3a45e015b4f9dfdb7' # telegram API HASH (my.telegram.org) #
verbosity: 2 # 1 = no verbosity, 2 = moderate verbosity, 3 = network requests debug
useragent: 'Zhabogram XMPP Gateway' # client name
version: '1.0' # client version
useragent: 'Zhabogram' # client name
version: '1.2' # client version
use_test_dc: false # always use false
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
@ -16,7 +16,7 @@ xmpp:
debug: false
admins:
- '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
host: 'localhost' # XMPP server
port: 8888 # component port

View file

@ -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::UserStatus) do |update| self.status_update_handler(update) end # register status handler
@client.connect()
return true
end
# disconnect and destroy telegram client #
@ -339,11 +340,10 @@ class TelegramClient
# handling replies #
reply_to = 0
if text[0] == '>' then
if text[0] == '>' and text.match(Regexp.new /^>( )?[0-9]{10,20}/) then
text = text.split("\n")
reply_to = text[0].scan(/\d/).to_i
reply_to = 0 if reply_to < 10000
text = splitted.drop(1).join("\n") if reply_to != 0
reply_to = text[0].scan(/\d+/).first.to_i
text = text.drop(1).join("\n")
end
# handling files received from xmpp #
@ -377,6 +377,12 @@ class TelegramClient
return @cache[:users][user_id] if @cache[:users].key? user_id
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
def process_status_update(user_id, status, immed = true)
@logger.debug "Processing status update for user id %s.." % user_id.to_s

View file

@ -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
@sessions = {}
@presence_que = {}
@db = SQLite3::Database.new(params['db_path'] || 'users.db')
@db.execute("CREATE TABLE IF NOT EXISTS users(jid varchar(256), login varchar(256), PRIMARY KEY(jid) );")
@db.results_as_hash = true
@db = params['db_path'] || 'users.dat'
self.load_db()
end
# load sessions from db #
def load_db(jid = nil)
@logger.info "Initializing database.."
query = (jid.nil?) ? "SELECT * FROM users" : "SELECT * FROM users where jid = '%s';" % jid
@logger.debug(query)
@db.execute(query) do |session| @sessions[session['jid']] = TelegramClient.new(self, session['jid'], session['login']) end
def load_db()
@logger.info "Loading sessions..."
File.open( @db, 'r' ) {|f| YAML.load(f).each do |jid,login| @sessions[jid] = TelegramClient.new(self, jid, login) end }
end
# store session to db #
def update_db(jid, delete = false, register = false)
login = (not register and @sessions.key? jid) ? @sessions[jid].login.to_s : register
return if not login
@logger.info "Writing database [%s].." % jid.to_s
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]
@logger.debug query
@db.execute(query)
def save_db()
@logger.info "Saving sessions..."
sessions_store = []
@sessions.each do |jid,session| store << {jid: jid, login: session.login} end
File.open( @db, 'w' ) {|f| f.write(YAML.dump(sessions_store)) }
end
# connecting to XMPP server #
@ -97,7 +91,7 @@ class XMPPComponent
return -11
rescue Exception => e
@logger.error 'Connection failed: %s' % e
@db.close
self.save_db()
exit -8
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(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.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 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 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() || @sessions[prsnc.from.bare.to_s].sync_status(); return; end # connect if we have session
end
# 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].connect()
self.request_tz(from)
self.update_db(from.bare.to_s)
self.save_db()
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
when '/connect' # go online
@ -239,7 +233,7 @@ class XMPPComponent
@sessions[from.bare.to_s].connect() if @sessions.key? from.bare.to_s
when '/logout' # go offline and destroy session
@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)
when '/info' # show some debug information
return if not @config[:admins].include? from.bare.to_s

View file

@ -5,7 +5,6 @@ require 'xmpp4r'
require 'xmpp4r/discovery'
require 'digest'
require 'base64'
require 'sqlite3'
require 'fileutils'
require 'tdlib-ruby'
require_relative 'inc/telegramclient'