Release 0.5

[NEW] Now using local Jabber timezone
This commit is contained in:
annelin 2019-04-14 05:56:29 +03:00
parent 04b8097a6f
commit a799c1244b
2 changed files with 90 additions and 33 deletions

View file

@ -145,11 +145,11 @@ class TelegramClient
@client.download_file(file.id) if file # download it if already not @client.download_file(file.id) if file # download it if already not
# forwards, replies and message id.. # 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 = "| fwd %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 text = "| fwd %s(%s) | %s" % [self.format_chatname(update.message.forward_info.chat_id), update.message.forward_info.author_signature.to_s, text] if update.message.forward_info.instance_of? TD::Types::MessageForwardInfo::MessageForwardedPost # fwd from chat
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 = "| reply %s | %s" % [self.format_reply(update.message.chat_id, update.message.reply_to_message_id), 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 text = "%s | %s | %s" % [update.message.id.to_s, self.format_username(update.message.sender_user_id), text] # username/id
# send and add message id to unreads # send and add message id to unreads
@cache[:unread_msg][update.message.chat_id] = update.message.id @cache[:unread_msg][update.message.chat_id] = update.message.id
@xmpp.incoming_message(update.message.chat_id.to_s, text) @xmpp.incoming_message(update.message.chat_id.to_s, text)
@ -184,7 +184,7 @@ class TelegramClient
@logger.debug 'Got MessageDeleted update' @logger.debug 'Got MessageDeleted update'
@logger.debug update.to_json @logger.debug update.to_json
return if not update.is_permanent return if not update.is_permanent
text = "[MSG ID %s DELETE]" % update.message_ids.join(',') text = "[MSG %s DELETE]" % update.message_ids.join(',')
@xmpp.incoming_message(update.chat_id.to_s, text) @xmpp.incoming_message(update.chat_id.to_s, text)
end end
@ -265,6 +265,8 @@ class TelegramClient
@client.search_chat_messages(chat_id, 0, 1, sender_user_id: @me.id, filter: TD::Types::SearchMessagesFilter::Empty.new).then {|msgs| @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) @client.delete_messages(chat_id, [msgs.messages[0].id], true)
}.wait }.wait
when '/dump'
response = @cache[:chats][chat_id].to_json
else else
response = 'Unknown command. response = 'Unknown command.
@ -315,15 +317,15 @@ class TelegramClient
end end
# update users information and save it to cache # # update users information and save it to cache #
def process_chat_info(chat_id) def process_chat_info(chat_id, no_subscription = false)
@logger.debug 'Updating chat id %s..' % chat_id.to_s @logger.debug 'Updating chat id %s..' % chat_id.to_s
# fullfil cache.. pasha durov, privet. # # fullfil cache.. pasha durov, privet. #
@client.get_chat(chat_id).then { |chat| @client.get_chat(chat_id).then { |chat|
@cache[:chats][chat_id] = chat # cache chat @cache[:chats][chat_id] = chat # cache chat
@client.download_file(chat.photo.small.id) if chat.photo # download userpic @client.download_file(chat.photo.small.id) if chat.photo # download userpic
@xmpp.presence(chat_id.to_s, :subscribe, nil, nil, @cache[:chats][chat_id].title.to_s) # send subscription request @xmpp.presence(chat_id.to_s, :subscribe, nil, nil, @cache[:chats][chat_id].title.to_s) if not no_subscription # send subscription request
@xmpp.presence(chat_id.to_s, nil, :chat, nil, @cache[:chats][chat_id].title.to_s) if chat.type.instance_of? TD::Types::ChatType::BasicGroup or chat.type.instance_of? TD::Types::ChatType::Supergroup # send :chat status if its group/supergroup @xmpp.presence(chat_id.to_s, nil, :chat, @cache[:chats][chat_id].title.to_s) if chat.type.instance_of? TD::Types::ChatType::BasicGroup or chat.type.instance_of? TD::Types::ChatType::Supergroup # send :chat status if its group/supergroup
self.process_user_info(chat.type.user_id) if chat.type.instance_of? TD::Types::ChatType::Private # process user if its a private chat self.process_user_info(chat.type.user_id) if chat.type.instance_of? TD::Types::ChatType::Private # process user if its a private chat
}.wait }.wait
end end
@ -350,7 +352,7 @@ class TelegramClient
xmpp_status = "Online" xmpp_status = "Online"
when TD::Types::UserStatus::Offline when TD::Types::UserStatus::Offline
xmpp_show = (Time.now.getutc.to_i - status.was_online.to_i < 3600) ? :away : :xa 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") xmpp_status = DateTime.strptime((status.was_online+Time.now.getlocal(@xmpp.timezone).utc_offset).to_s,'%s').strftime("Last seen at %H:%M %d/%m/%Y")
when TD::Types::UserStatus::Recently when TD::Types::UserStatus::Recently
xmpp_show = :dnd xmpp_show = :dnd
xmpp_status = "Last seen recently" xmpp_status = "Last seen recently"
@ -390,6 +392,12 @@ class TelegramClient
return title, username, firstname, lastname, phone, bio, userpic return title, username, firstname, lastname, phone, bio, userpic
end end
# roster status sync #
def sync_status()
@logger.debug "Syncing statuses.."
@cache[:users].each_value do |user| process_status_update(user.id, user.status) end
end
# graceful disconnect # graceful disconnect
def disconnect(logout) def disconnect(logout)
@logger.info 'Disconnect request received..' @logger.info 'Disconnect request received..'
@ -404,12 +412,30 @@ class TelegramClient
# format tg user name # # format tg user name #
def format_username(user_id) def format_username(user_id)
if not @cache[:users].key? user_id then self.process_user_info(user_id) end user_id = @me.id if user_id == 0 # @me
id = (@cache[:users][user_id].username == '') ? user_id : @cache[:users][user_id].username if not @cache[:users].key? user_id then self.process_user_info(user_id) end # update cache
name = '%s %s (@%s)' % [@cache[:users][user_id].first_name, @cache[:users][user_id].last_name, id] if not @cache[:users].key? user_id then return user_id end # return id if not found anything about this user
name.sub! ' ]', ']' id = (@cache[:users][user_id].username == '') ? user_id : @cache[:users][user_id].username # username or user id
name = @cache[:users][user_id].first_name # firstname
name = name + ' ' + @cache[:users][user_id].last_name if @cache[:users][user_id].last_name != '' # lastname
return "%s (@%s)" % [name, id]
end
# format tg chat name #
def format_chatname(chat_id)
if not @cache[:chats].key? chat_id then self.process_chat_info(chat_id, true) end
if not @cache[:chats].key? chat_id then return chat_id end
name = '%s (%s)' % [@cache[:chats][chat_id].title, chat_id]
return name return name
end end
# format reply#
def format_reply(chat_id, message_id)
text = ''
@client.get_message(chat_id, message_id).then { |message| text = "%s" % message.content.text.text.to_s }.wait
text = (text.lines.count > 1) ? "%s..." % text.split("\n")[0] : text
return "MSG %s (%s..)" % [message_id.to_s, text]
end
# format content link # # format content link #
def format_content_link(file_id, fname, local = false) def format_content_link(file_id, fname, local = false)
@ -417,4 +443,5 @@ class TelegramClient
path = "%s/%s%s" % [prefix, Digest::SHA256.hexdigest(file_id), File.extname(fname)] path = "%s/%s%s" % [prefix, Digest::SHA256.hexdigest(file_id), File.extname(fname)]
return path return path
end end
end end

View file

@ -88,8 +88,8 @@ class XMPPComponent
# new message to XMPP component # # new message to XMPP component #
def message_handler(msg) def message_handler(msg)
@logger.info 'New message from [%s] to [%s]' % [msg.from, msg.to] @logger.info 'New message from [%s] to [%s]' % [msg.from, msg.to]
return self.process_internal_command(msg.from.bare.to_s, msg.first_element_text('body') ) if msg.to == @@transport.jid # treat message as internal command if received as transport jid return self.process_internal_command(msg.from, 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.to_s].tg_outgoing(msg.to.to_s, msg.first_element_text('body')) #if @sessions.key? msg.from.bare.to_s and @sessions[msg.from.bare.to_s].online? # queue message for processing session is active for jid from return @sessions[msg.from.bare.to_s].tg_outgoing(msg.from, msg.to.to_s, msg.first_element_text('body')) #if @sessions.key? msg.from.bare.to_s and @sessions[msg.from.bare.to_s].online? # queue message for processing session is active for jid from
end end
def presence_handler(presence) def presence_handler(presence)
@ -97,20 +97,27 @@ class XMPPComponent
@logger.debug(presence) @logger.debug(presence)
if presence.type == :subscribe then reply = presence.answer(false); reply.type = :subscribed; @@transport.send(reply); end # send "subscribed" reply to "subscribe" presence if presence.type == :subscribe then reply = presence.answer(false); reply.type = :subscribed; @@transport.send(reply); end # send "subscribed" reply to "subscribe" presence
if presence.to == @@transport.jid and @sessions.key? presence.from.bare.to_s and presence.type == :unavailable then @sessions[presence.from.bare.to_s].disconnect(); return; end # go offline when received offline presence from jabber user if presence.to == @@transport.jid and @sessions.key? presence.from.bare.to_s and presence.type == :unavailable then @sessions[presence.from.bare.to_s].disconnect(); return; end # go offline when received offline presence from jabber user
if presence.to == @@transport.jid and @sessions.key? presence.from.bare.to_s then @sessions[presence.from.bare.to_s].connect(); return; end # connect if we have session if presence.to == @@transport.jid and @sessions.key? presence.from.bare.to_s then @sessions[presence.from.bare.to_s].request_tz(presence.from); @sessions[presence.from.bare.to_s].connect(); return; end # connect if we have session
end end
def iq_handler(iq) def iq_handler(iq)
@logger.debug "New iq received" @logger.debug "New iq received"
@logger.debug(iq.to_s) @logger.debug(iq.to_s)
if iq.vcard and @sessions.key? iq.from.bare.to_s then # vcard request #
if iq.type == :get and iq.vcard and @sessions.key? iq.from.bare.to_s then
@logger.debug "Got VCard request"
vcard = @sessions[iq.from.bare.to_s].make_vcard(iq.to.to_s) vcard = @sessions[iq.from.bare.to_s].make_vcard(iq.to.to_s)
reply = iq.answer reply = iq.answer
reply.type = :result reply.type = :result
reply.elements["vCard"] = vcard reply.elements["vCard"] = vcard
@@transport.send(reply) @@transport.send(reply)
else # time response #
elsif iq.type == :result and iq.elements["time"] and @sessions.key? iq.from.bare.to_s then
@logger.debug "Got Timezone response"
timezone = iq.elements["time"].elements["tzo"].text
@sessions[iq.from.bare.to_s].set_tz(timezone)
elsif iq.type == :get then
reply = iq.answer reply = iq.answer
reply.type = :error reply.type = :error
end end
@ -122,26 +129,27 @@ class XMPPComponent
############################# #############################
# process internal /command # # process internal /command #
def process_internal_command(jfrom, body) def process_internal_command(from, body)
case body.split[0] # /command argument = [command, argument] case body.split[0] # /command argument = [command, argument]
when '/login' # creating new session if not exists and connect if user already has session when '/login' # creating new session if not exists and connect if user already has session
@sessions[jfrom] = XMPPSession.new(jfrom, body.split[1]) if not @sessions.key? jfrom @sessions[from.bare.to_s] = XMPPSession.new(from.bare.to_s, body.split[1]) if not @sessions.key? from.bare.to_s
@sessions[jfrom].connect() @sessions[from.bare.to_s].request_tz(from)
self.update_db(jfrom) @sessions[from.bare.to_s].connect()
self.update_db(from.bare.to_s)
when '/code', '/password' # pass auth data if we have session when '/code', '/password' # pass auth data if we have session
@sessions[jfrom].tg_auth(body.split[0], body.split[1]) if @sessions.key? jfrom @sessions[from.bare.to_s].tg_auth(body.split[0], body.split[1]) if @sessions.key? from.bare.to_s
when '/connect' # going online when '/connect' # going online
@sessions[jfrom].connect() if @sessions.key? jfrom @sessions[from.bare.to_s].connect() if @sessions.key? from.bare.to_s
when '/disconnect' # going offline without destroying a session when '/disconnect' # going offline without destroying a session
@sessions[jfrom].disconnect() if @sessions.key? jfrom @sessions[from.bare.to_s].disconnect() if @sessions.key? from.bare.to_s
when '/logout' # destroying session when '/logout' # destroying session
@sessions[jfrom].disconnect(true) if @sessions.key? jfrom @sessions[from.bare.to_s].disconnect(true) if @sessions.key? from.bare.to_s
self.update_db(jfrom, true) self.update_db(from.bare.to_s, true)
@sessions.delete(jfrom) @sessions.delete(from.bare.to_s)
else # unknown command -- display help # else # unknown command -- display help #
msg = Jabber::Message.new msg = Jabber::Message.new
msg.from = @@transport.jid msg.from = @@transport.jid
msg.to = jfrom msg.to = from.bare.to_s
msg.body = ::HELP_MESSAGE msg.body = ::HELP_MESSAGE
msg.type = :chat msg.type = :chat
@@transport.send(msg) @@transport.send(msg)
@ -154,7 +162,7 @@ end
## XMPP Session Class ####### ## XMPP Session Class #######
############################# #############################
class XMPPSession < XMPPComponent class XMPPSession < XMPPComponent
attr_reader :user_jid, :tg_login attr_reader :user_jid, :tg_login, :timezone
attr_accessor :online attr_accessor :online
# start XMPP user session and Telegram client instance # # start XMPP user session and Telegram client instance #
@ -162,6 +170,7 @@ class XMPPSession < XMPPComponent
@logger = Logger.new(STDOUT); @logger.level = @@loglevel; @logger.progname = '[XMPPSession: %s/%s]' % [jid, tg_login] # init logger @logger = Logger.new(STDOUT); @logger.level = @@loglevel; @logger.progname = '[XMPPSession: %s/%s]' % [jid, tg_login] # init logger
@logger.info "Initializing new session.." @logger.info "Initializing new session.."
@user_jid, @tg_login = jid, tg_login @user_jid, @tg_login = jid, tg_login
@timezone = '-00:00'
end end
# connect to tg # # connect to tg #
@ -210,8 +219,9 @@ class XMPPSession < XMPPComponent
########################################### ###########################################
# queue message (we will share this queue within :message_queue to Telegram client thread) # # queue message (we will share this queue within :message_queue to Telegram client thread) #
def tg_outgoing(to, text = '') def tg_outgoing(from, to, text = '')
@logger.debug "Sending message to be sent to Telegram network user -> " % to @logger.debug "Sending message to be sent to Telegram network user -> " % to
self.request_tz(from) if not self.tz_set?
@telegram.process_outgoing_msg(to.split('@')[0].to_i, text) @telegram.process_outgoing_msg(to.split('@')[0].to_i, text)
end end
@ -245,6 +255,25 @@ class XMPPSession < XMPPComponent
return vcard return vcard
end end
## timezones ##
def request_tz(jid)
@logger.debug "Request timezone from JID %s" % jid.to_s
iq = Jabber::Iq.new
iq.type = :get
iq.to = jid
iq.from = @@transport.jid
iq.id = 'time_req_1'
iq.add_element("time", {"xmlns" => "urn:xmpp:time"})
@logger.debug iq.to_s
@@transport.send(iq)
end
def set_tz(timezone)
@logger.debug "Set TZ to %s" % timezone
@timezone = timezone
@logger.debug "Resyncing contact list.."
@telegram.sync_status()
end
########################################### ###########################################
@ -252,4 +281,5 @@ class XMPPSession < XMPPComponent
def online?() @online end def online?() @online end
def online!() @logger.info "Connection established"; @online = true; self.presence(nil, :subscribe); self.presence(nil, nil, nil, "Logged in as " + @tg_login.to_s) end def online!() @logger.info "Connection established"; @online = true; self.presence(nil, :subscribe); self.presence(nil, nil, nil, "Logged in as " + @tg_login.to_s) end
def offline!() @online = false; self.presence(nil, :unavailable, nil, "Logged out"); @telegram = nil; end def offline!() @online = false; self.presence(nil, :unavailable, nil, "Logged out"); @telegram = nil; end
def tz_set?() return @timezone != '-00:00' end
end end