Release 0.6
[NEW] broadcasting vcard photo update [NEW] new commands: /secret, /group, /supergroup, /channel, /search, /history (send /help to any contact) [UPD] improved formatting
This commit is contained in:
parent
f9c5a1da8d
commit
d20414617a
|
@ -33,7 +33,7 @@ class TelegramClient
|
|||
@logger = Logger.new(STDOUT); @logger.level = @@loglevel; @logger.progname = '[TelegramClient: %s/%s]' % [xmpp.user_jid, login] # create logger
|
||||
@xmpp = xmpp # our XMPP user session. we will send messages back to Jabber through this instance.
|
||||
@login = login # store tg login
|
||||
@cache = {chats: {}, users: {}, users_fi: {}, unread_msg: {} } # we will store our cache here
|
||||
@cache = {chats: {}, users: {}, users_fi: {}, userpics: {}, unread_msg: {} } # we will store our cache here
|
||||
@files_dir = File.dirname(__FILE__) + '/../sessions/' + @xmpp.user_jid + '/files/'
|
||||
|
||||
# spawn telegram client and specify callback handlers
|
||||
|
@ -91,7 +91,7 @@ class TelegramClient
|
|||
end
|
||||
|
||||
# message from telegram network handler #
|
||||
def message_handler(update)
|
||||
def message_handler(update, show_date = false)
|
||||
@logger.debug 'Got NewMessage update'
|
||||
@logger.debug update.message.to_json
|
||||
|
||||
|
@ -100,6 +100,7 @@ class TelegramClient
|
|||
|
||||
# media? #
|
||||
file = nil
|
||||
prefix = ''
|
||||
text = ''
|
||||
case update.message.content
|
||||
when TD::Types::MessageContent::Photo # photos
|
||||
|
@ -145,10 +146,14 @@ class TelegramClient
|
|||
@client.download_file(file.id) if file # download it if already not
|
||||
|
||||
# forwards, replies and message id..
|
||||
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 = "| 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 %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 = "%s | %s | %s" % [update.message.id.to_s, self.format_username(update.message.sender_user_id), text] # username/id
|
||||
prefix += "[%s]" % DateTime.strptime((update.message.date+Time.now.getlocal(@xmpp.timezone).utc_offset).to_s,'%s').strftime("[%d %b %Y %H:%M:%S]") if show_date
|
||||
prefix += "fwd from %s | " % self.format_username(update.message.forward_info.sender_user_id) if update.message.forward_info.instance_of? TD::Types::MessageForwardInfo::MessageForwardedFromUser # fwd from user
|
||||
prefix += "fwd from %s | " % self.format_chatname(update.message.forward_info.chat_id) if update.message.forward_info.instance_of? TD::Types::MessageForwardInfo::MessageForwardedPost # fwd from chat
|
||||
prefix += "reply to %s | " % self.format_reply(update.message.chat_id, update.message.reply_to_message_id) if update.message.reply_to_message_id.to_i != 0 # reply to
|
||||
|
||||
# text formatting
|
||||
text = "%s | %s | %s\n%s" % [update.message.id, self.format_username(update.message.sender_user_id), prefix, text] if update.message.chat_id < 0 # groupchats
|
||||
text = "%s %s | %s%s" % [(update.message.is_outgoing ? '→' : '←'), update.message.id.to_s, prefix, text] if update.message.chat_id > 0 # private chats
|
||||
|
||||
# send and add message id to unreads
|
||||
@cache[:unread_msg][update.message.chat_id] = update.message.id
|
||||
|
@ -175,7 +180,7 @@ class TelegramClient
|
|||
@logger.debug update.to_json
|
||||
|
||||
# formatting
|
||||
text = "[MSG %s EDIT] %s" % [update.message_id.to_s, update.new_content.text.text.to_s]
|
||||
text = "| %s edit | %s" % [update.message_id.to_s, update.new_content.text.text.to_s]
|
||||
@xmpp.incoming_message(update.chat_id.to_s, text)
|
||||
end
|
||||
|
||||
|
@ -184,7 +189,7 @@ class TelegramClient
|
|||
@logger.debug 'Got MessageDeleted update'
|
||||
@logger.debug update.to_json
|
||||
return if not update.is_permanent
|
||||
text = "[MSG %s DELETE]" % update.message_ids.join(',')
|
||||
text = "| %s del |" % update.message_ids.join(',')
|
||||
@xmpp.incoming_message(update.chat_id.to_s, text)
|
||||
end
|
||||
|
||||
|
@ -236,6 +241,14 @@ class TelegramClient
|
|||
when '/join' # join group/supergroup by invite link or by id
|
||||
chat = (resolved) ? resolved.id : splitted[1]
|
||||
chat.to_s[0..3] == "http" ? @client.join_chat_by_invite_link(chat).wait : @client.join_chat(chat.to_i).wait
|
||||
when '/secret' # create new secret chat
|
||||
@client.create_new_secret_chat(resolved.id) if resolved
|
||||
when '/group' # create new group with @user_id
|
||||
@client.create_new_basic_group_chat([resolved.id], splitted[2]) if resolved and splitted[2]
|
||||
when '/supergroup' # create new supergroup
|
||||
@client.create_new_supergroup_chat(splitted[1], splitted[2]) if splitted[2]
|
||||
when '/channel' # create new channel
|
||||
@client.create_new_supergroup_chat(splitted[1], splitted[2], is_channel: true) if splitted[2]
|
||||
when '/invite' # invite user to chat
|
||||
@client.add_chat_member(chat_id, resolved.id).wait if resolved
|
||||
when '/kick' # removes user from chat
|
||||
|
@ -250,6 +263,7 @@ class TelegramClient
|
|||
when '/leave', '/delete' # delete / leave chat
|
||||
@client.close_chat(chat_id).wait
|
||||
@client.leave_chat(chat_id).wait
|
||||
@client.close_secret_chat(chat_id).wait
|
||||
@client.delete_chat_history(chat_id, true).wait
|
||||
@xmpp.presence(chat_id, :unsubscribed)
|
||||
@xmpp.presence(chat_id, :unavailable)
|
||||
|
@ -262,24 +276,41 @@ class TelegramClient
|
|||
@client.edit_message_text(chat_id, msgs.messages[0].id, TD::Types::InputMessageContent::Text.new(:text => { :text => edited, :entities => []}, :disable_web_page_preview => false, :clear_draft => true )) if edited != original
|
||||
}.wait
|
||||
when '/d' # delete last message
|
||||
@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)
|
||||
}.wait
|
||||
id = splitted[1].to_i
|
||||
@client.search_chat_messages(chat_id, 0, 1, sender_user_id: @me.id, filter: TD::Types::SearchMessagesFilter::Empty.new).then {|msgs| id = msgs.messages[0].id }.wait if not id or id == 0
|
||||
@client.delete_messages(chat_id, [id], true)
|
||||
when '/dump'
|
||||
response = @cache[:chats][chat_id].to_json
|
||||
when '/search'
|
||||
count = (splitted[1]) ? splitted[1].to_i : 10
|
||||
query = (splitted[2]) ? splitted[2] : nil
|
||||
@client.search_chat_messages(chat_id, 0, count, query: query, filter: TD::Types::SearchMessagesFilter::Empty.new).then {|msgs|
|
||||
msgs.messages.reverse.each do |msg| self.message_handler(TD::Types::Update::NewMessage.new(message: msg, disable_notification: false, contains_mention: false), true) end
|
||||
}.wait
|
||||
when '/history'
|
||||
count = (splitted[1]) ? splitted[1].to_i : 10
|
||||
@client.get_chat_history(chat_id, 0, 0, count).then {|msgs|
|
||||
msgs.messages.reverse.each do |msg| self.message_handler(TD::Types::Update::NewMessage.new(message: msg, disable_notification: false, contains_mention: false), true) end
|
||||
}.wait
|
||||
else
|
||||
response = 'Unknown command.
|
||||
|
||||
/s/mitsake/mistake/ — Edit last message
|
||||
/d — Delete last message
|
||||
|
||||
/add @username or id — Creates conversation with specified user
|
||||
/join chat_link or id — Joins chat by its link or id
|
||||
/invite @username — Invites @username to current chat
|
||||
/kick @username — Removes @username from current chat
|
||||
/ban @username [hours] — Bans @username in current chat for [hours] hrs or forever if [hours] not specified
|
||||
/block — Blacklists current user
|
||||
/unblock — Removes current user from blacklist
|
||||
/add @username or id — Create conversation with specified user or chat id
|
||||
/secret @username — Create "secret chat" with specified user
|
||||
/group @username groupname — Create group chat named groupname with @username
|
||||
/supergroup name description — Create supergroup chat
|
||||
/channel name description — Create channel
|
||||
/history count — Retrieve chat history
|
||||
/search count query — Search in chat history
|
||||
/join chat_link or id — Join chat by its link or id
|
||||
/invite @username — Invite @username to current chat
|
||||
/kick @username — Remove @username from current chat
|
||||
/ban @username [hours] — Ban @username in current chat for [hours] hrs or forever if [hours] not specified
|
||||
/block — Blacklistscurrent user
|
||||
/unblock — Remove current user from blacklist
|
||||
/leave — Leave current chat
|
||||
/delete — Delete current chat
|
||||
'
|
||||
|
@ -323,9 +354,10 @@ class TelegramClient
|
|||
# fullfil cache.. pasha durov, privet. #
|
||||
@client.get_chat(chat_id).then { |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).wait if chat.photo # download userpic
|
||||
@cache[:userpics][chat_id] = Digest::SHA1.hexdigest(IO.binread(self.format_content_link(chat.photo.small.remote.id, 'image.jpg', true))) if chat.photo and File.exist? self.format_content_link(chat.photo.small.remote.id, 'image.jpg', true) # cache userpic
|
||||
@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, @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, nil, @cache[:userpics][chat_id]) 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
|
||||
}.wait
|
||||
end
|
||||
|
@ -345,7 +377,7 @@ class TelegramClient
|
|||
# convert telegram status to XMPP one
|
||||
def process_status_update(user_id, status)
|
||||
@logger.debug "Processing status update for user id %s.." % user_id.to_s
|
||||
xmpp_show, xmpp_status = nil, ''
|
||||
xmpp_show, xmpp_status, xmpp_photo = nil
|
||||
case status
|
||||
when TD::Types::UserStatus::Online
|
||||
xmpp_show = nil
|
||||
|
@ -363,7 +395,8 @@ class TelegramClient
|
|||
xmpp_show = :unavailable
|
||||
xmpp_status = "Last seen last month"
|
||||
end
|
||||
@xmpp.presence(user_id.to_s, nil, xmpp_show, xmpp_status)
|
||||
xmpp_photo = @cache[:userpics][user_id] if @cache[:userpics].key? user_id
|
||||
@xmpp.presence(user_id.to_s, nil, xmpp_show, xmpp_status, nil, xmpp_photo)
|
||||
end
|
||||
|
||||
# get contact information (for vcard).
|
||||
|
@ -385,7 +418,7 @@ class TelegramClient
|
|||
# userpic #
|
||||
if @cache[:chats][chat_id].photo then # we have userpic
|
||||
userpic = self.format_content_link(@cache[:chats][chat_id].photo.small.remote.id, 'image.jpg', true)
|
||||
userpic = Base64.encode64(IO.binread(userpic)) if File.exist? userpic
|
||||
userpic = (File.exist? userpic) ? Base64.encode64(IO.binread(userpic)) : nil
|
||||
end
|
||||
|
||||
# ..
|
||||
|
@ -393,9 +426,10 @@ class TelegramClient
|
|||
end
|
||||
|
||||
# roster status sync #
|
||||
def sync_status()
|
||||
def sync_status(user_id = nil)
|
||||
@logger.debug "Syncing statuses.."
|
||||
@cache[:users].each_value do |user| process_status_update(user.id, user.status) end
|
||||
if user_id and @cache[:users].key? user_id then return process_status_update(@cache[:users][user_id].id, @cache[:users][user_id].status) end # sync single contact #
|
||||
@cache[:users].each_value do |user| process_status_update(user.id, user.status) end # sync everyone #
|
||||
end
|
||||
|
||||
# graceful disconnect
|
||||
|
@ -412,7 +446,7 @@ class TelegramClient
|
|||
|
||||
# format tg user name #
|
||||
def format_username(user_id)
|
||||
user_id = @me.id if user_id == 0 # @me
|
||||
return if user_id == 0 # @me
|
||||
if not @cache[:users].key? user_id then self.process_user_info(user_id) end # update cache
|
||||
if not @cache[:users].key? user_id then return user_id end # return id if not found anything about this user
|
||||
id = (@cache[:users][user_id].username == '') ? user_id : @cache[:users][user_id].username # username or user id
|
||||
|
@ -434,7 +468,7 @@ class TelegramClient
|
|||
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]
|
||||
return "%s (%s..)" % [message_id.to_s, text]
|
||||
end
|
||||
|
||||
# format content link #
|
||||
|
|
|
@ -107,11 +107,13 @@ class XMPPComponent
|
|||
# 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].tg_contact_vcard(iq.to.to_s)
|
||||
reply = iq.answer
|
||||
reply.type = :result
|
||||
reply.elements["vCard"] = vcard
|
||||
@@transport.send(reply)
|
||||
@sessions[iq.from.bare.to_s].tg_sync_roster(iq.to.to_s) # re-sync status
|
||||
|
||||
# time response #
|
||||
elsif iq.type == :result and iq.elements["time"] and @sessions.key? iq.from.bare.to_s then
|
||||
@logger.debug "Got Timezone response"
|
||||
|
@ -203,7 +205,7 @@ class XMPPSession < XMPPComponent
|
|||
end
|
||||
|
||||
# presence update #
|
||||
def presence(from, type = nil, show = nil, status = nil, nickname = nil)
|
||||
def presence(from, type = nil, show = nil, status = nil, nickname = nil, photo = nil)
|
||||
@logger.debug "Presence update request from %s.." %from.to_s
|
||||
req = Jabber::Presence.new()
|
||||
req.from = from.nil? ? @@transport.jid : from.to_s+'@'+@@transport.jid.to_s # presence <from>
|
||||
|
@ -212,6 +214,7 @@ class XMPPSession < XMPPComponent
|
|||
req.show = show unless show.nil? # presence <show>
|
||||
req.status = status unless status.nil? # presence message
|
||||
req.add_element('nick', {'xmlns' => 'http://jabber.org/protocol/nick'} ).add_text(nickname) unless nickname.nil? # nickname
|
||||
req.add_element('x', {'xmlns' => 'vcard-temp:x:update'} ).add_element("photo").add_text(photo) unless photo.nil? # nickname
|
||||
@logger.debug req
|
||||
@@transport.send(req)
|
||||
end
|
||||
|
@ -231,8 +234,15 @@ class XMPPSession < XMPPComponent
|
|||
@telegram.process_auth(typ, data)
|
||||
end
|
||||
|
||||
# sync roster #
|
||||
def tg_sync_roster(to = nil)
|
||||
@logger.debug "Sync Telegram contact status with roster.. %s" % to.to_s
|
||||
to = (to) ? to.split('@')[0].to_i : nil
|
||||
@telegram.sync_status(to)
|
||||
end
|
||||
|
||||
# make vcard from telegram contact #
|
||||
def make_vcard(to)
|
||||
def tg_contact_vcard(to)
|
||||
@logger.debug "Requesting information to make a VCard for Telegram contact..." # title, username, firstname, lastname, phone, bio, userpic
|
||||
fn, nickname, given, family, phone, desc, photo = @telegram.get_contact_info(to.split('@')[0].to_i)
|
||||
vcard = Jabber::Vcard::IqVcard.new()
|
||||
|
@ -255,6 +265,7 @@ class XMPPSession < XMPPComponent
|
|||
return vcard
|
||||
end
|
||||
|
||||
###########################################
|
||||
## timezones ##
|
||||
def request_tz(jid)
|
||||
@logger.debug "Request timezone from JID %s" % jid.to_s
|
||||
|
@ -272,7 +283,7 @@ class XMPPSession < XMPPComponent
|
|||
@logger.debug "Set TZ to %s" % timezone
|
||||
@timezone = timezone
|
||||
@logger.debug "Resyncing contact list.."
|
||||
@telegram.sync_status()
|
||||
self.tg_sync_roster()
|
||||
end
|
||||
|
||||
###########################################
|
||||
|
|
Reference in a new issue