Warning! It is beta software and it has not been tested thoroughly.
[UPD] Code restructurization. Removed unneccessary XMPPSession class.
[UPD] Recuded memory consumption.
[UPD] Seems like memory leaks fixed too, need test a bit longer
[UPD] Now running in forever-loop, use double Ctrl+C to quit
[ADD] Admin commands /sessions, /debug and /restart
[ADD] New config parameters: xmpp->debug to print XML stream and xmpp->admins[] to give access to above mentioned /commands
[ADD] We can now use memory profiler to get detailed memory usage information: run application with --profiler key (and also gem install memprof2) (yes, fucking leaks...)
[FIX] Fixed secret chat closing (I hope so...)
* tdlib-ruby == 2.0 with pre-compiled _libtdjson.so_
* memprof2 == 0.1.2 (optional, if running with --profiler key to detailed memory usage information)
There is pre-compiled _libtdjson.so_ for Debian Stretch x64 in repository.
For any other distro you need to manually compile [**tdlib**](https://github.com/tdlib/td) and place _libtdjson.so_ to relative **lib/** directory (or **LD_LIBRARY_PATH**).
prefix+="fwd from %s | "%self.format_username(update.message.forward_info.sender_user_id)ifupdate.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)ifupdate.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)ifupdate.message.reply_to_message_id.to_i!=0# reply to
@xmpp.presence(chat_id.to_s,nil,:chat,@cache[:chats][chat_id].title.to_s,nil,@cache[:userpics][chat_id])ifchat.type.instance_of?TD::Types::ChatType::BasicGrouporchat.type.instance_of?TD::Types::ChatType::Supergroup# send :chat status if its group/supergroup
@xmpp.presence(@jid,chat_id.to_s,nil,:chat,@cache[:chats][chat_id].title.to_s,nil,@cache[:userpics][chat_id])ifchat.type.instance_of?TD::Types::ChatType::BasicGrouporchat.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
ifuser_idand@cache[:users].key?user_idthenreturnprocess_status_update(@cache[:users][user_id].id,@cache[:users][user_id].status)end# sync single contact #
query=(delete)?"DELETE FROM users where jid = '%s';"%jid.to_s:"INSERT OR REPLACE INTO users(jid, tg_login) VALUES('%s', '%s');"%[jid.to_s,@sessions[jid].tg_login.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,@sessions[jid].login.to_s]
@logger.debugquery
@db.execute(query)
end
# transport initialization & connecting to XMPP server #
@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.debugiq.to_s
@@transport.send(iq)
end
#############################
#### Callback handlers #####
#############################
@ -107,36 +139,49 @@ class XMPPComponent
# new message to XMPP component #
defmessage_handler(msg)
returnifmsg.type==:error
@logger.info'New message from [%s] to [%s]'%[msg.from,msg.to]
returnself.process_internal_command(msg.from,msg.first_element_text('body'))ifmsg.to==@@transport.jid# treat message as internal command if received as transport jid
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
defpresence_handler(presence)
@logger.debug"New presence iq received"
@logger.debug(presence)
ifpresence.type==:subscribethenreply=presence.answer(false);reply.type=:subscribed;@@transport.send(reply);end# send "subscribed" reply to "subscribe" presence
ifpresence.to==@@transport.jidand@sessions.key?presence.from.bare.to_sandpresence.type==:unavailablethen@sessions[presence.from.bare.to_s].disconnect();return;end# go offline when received offline presence from jabber user
ifpresence.to==@@transport.jidand@sessions.key?presence.from.bare.to_sthen@sessions[presence.from.bare.to_s].request_tz(presence.from);@sessions[presence.from.bare.to_s].connect();return;end# connect if we have session
@logger.info'Received message from <%s> to <%s>'%[msg.from,msg.to]
ifmsg.to==@@transport.jidthenself.process_command(msg.from,msg.first_element_text('body'));return;end# treat message as internal command if received as transport jid
if@sessions.key?msg.from.bare.to_sthenself.request_tz(msg.from)ifnot@sessions[msg.from.bare.to_s].tz_set?;@sessions[msg.from.bare.to_s].process_outgoing_msg(msg.to.to_s.split('@')[0].to_i,msg.first_element_text('body'));return;end#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
# new presence to XMPP component #
defpresence_handler(prsnc)
@logger.info"New presence received"
@logger.debug(prsnc)
ifprsnc.type==:subscribethenreply=prsnc.answer(false);reply.type=:subscribed;@@transport.send(reply);end# send "subscribed" reply to "subscribe" presence
ifprsnc.to==@@transport.jidand@sessions.key?prsnc.from.bare.to_sandprsnc.type==:unavailablethen@sessions[prsnc.from.bare.to_s].disconnect();return;end# go offline when received offline presence from jabber user
ifprsnc.to==@@transport.jidand@sessions.key?prsnc.from.bare.to_sthenself.request_tz(prsnc.from);@sessions[prsnc.from.bare.to_s].connect();return;end# connect if we have session
@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.debugiq.to_s
@@transport.send(iq)
end
defset_tz(timezone)
@logger.debug"Set TZ to %s"%timezone
@timezone=timezone
# @logger.debug "Resyncing contact list.."
# self.tg_sync_status()
end
###########################################
# session status #
defonline?()@onlineend
defonline!()@logger.info"Connection established";@online=true;self.presence(nil,:subscribe);self.presence(nil,nil,nil,"Logged in as "+@tg_login.to_s)end