# Description: # integrazione con il protocollo matrix # # Requires: # "fast-levenshtein": "1.0.6" # # Commands # hubot chi sei - chiedi a hubot di identificarsi # hubot chi sono / cosa sai di me - mostra il tuo contatto nel registro di hubot # hubot in che stanze sei / dove scrivi - chiedi a hubot dove chatta # hubot (mi inviti / invitami) (nel stanza / in) - chiedi ad hubot di invitardi in una stanza # hubot invita/aggiungi - chiedi ad hubot di invitare qualcuno nel stanza attuale # hubot kicka - chiedi di bannare un utente dal stanza attuale # hubot kickalo - chiedi ad hubot di bannare l'ultimo utente ad aver scritto un messaggio # hubot esci / lasciaci un (minuto / attimo) - chiedi ad hubot di lasciare la stanza # # Author: # Michele Guerini Rocco (rnhmjoj) # lev = require 'fast-levenshtein' module.exports = (robot) -> matrix = robot.adapter.client return unless robot.adapterName is 'matrix' and matrix? # messages error = 'oh no: c\'è stato un errore, non so' done = ['fatto', 'ecco qui', 'ecco fatto'] success = ['provvedo subito', 'ok', 'certo', 'va bene'] unknown = ['non so chi sia', 'chi?', 'mai sentito', 'sicuro? non lo trovo'] failed = ['eh, mi piacerebbe molto ma non posso', 'i have no powers here', 'nope, non l\'ho invitato io', 'non sono admin qui, sorry'] # find closest match with levenshtein metric find_closest = (target, list, compare) -> return null if list.length is 0 compare = compare || ((x) -> x) dists = [].concat.apply [], ( for obj in list str = compare obj for word in [str].concat str.split ' ' [(lev.get target, word), obj]) [dist, best] = dists.reduce (x, y) -> if x[0] < y[0] then x else y return if dist < 4 then best else null # get hubot telegram profile information robot_info = -> self = robot.brain.userForId robot.adapter.user_id # return the list of chat rooms room_list = -> matrix.getRooms().map (room) -> create_user = (user) -> id: user.userId name: user.name avatar: user.getAvatarUrl matrix.baseUrl, 120, 120, allowDefault: false id: room.roomId name: room.name private: room.getJoinedMembers().length == 2 members: room.getJoinedMembers().map create_user invitees: room.getMembersWithMembership("invite").map create_user # return the list of contacts contact_list = -> matrix.getUsers().map (user) -> id: user.userId name: user.displayName avatar: user.avatarUrl # get the messages history for a chat room get_history = (room, size, callback) -> room = matrix.getRoom room.id matrix.scrollback room, size, (err, res) -> return callback err, null if err? return callback 1, null unless res.chunk? callback null, res.chunk.map (event) -> type: event.content.msgtype sender: robot.brain.userForId event.sender content: event.content.body # kick user from a chat room kick_user = (user, room, reason, callback) -> matrix.kick user.id, room.id, -> callback() if callback? # add user to a group chat invite_user = (user, room, callback) -> matrix.invite room.id, user.id, -> callback() if callback? robot.respond /chi sei/, (res) -> matrix = robot_info() res.send "sono #{robot.name} ma puoi anche chiamarmi #{robot.alias}", "se ti serve qualcosa chiedi: il mio id è #{matrix.id}" robot.respond /(cosa sai di me|chi sono)/i, (res) -> user = res.message.user id = "il tuo id matrix è #{user.id}" name = if user.name? then " ma preferisci che ti chiamino #{user.name}" else '' avatar = if user.avatar? then [ "il tuo avatar è", user.avatar ] else [] res.send ([ "so che #{id}#{name}" ].concat avatar)... robot.respond /(in che stanze sei| dove scrivi)/, (res) -> intro = ['scrivo in queste stanze', 'chatto qui', 'sono attivo in'] rooms = room_list().filter (room) -> not room.private res.send (res.random intro) + ':\n' + (rooms.map (i) -> '* '+i.name).join '\n' robot.respond /(invita|aggiungi) (.+)/, (res) -> name = res.match[2] room = res.message.room users = contact_list() user = find_closest name, users, (x) -> x.name if not user? return res.send res.random unknown if user.id is res.message.user.id return res.send 'intendi te stesso?' if user.id is robot_info().id return res.send 'io? mi sembra di esserci già' if user.id in (room.members.map (x) -> x.id) return res.send 'è già in questa stanza...', '[facepalm]' if user.id in (room.invitees.map (x) -> x.id) return res.send 'già invitato: deve solo accettare' res.send res.random success -> invite_user user, room -> res.send res.random done robot.logger.info "invited user #{user.id} to #{room.id}" robot.respond /(mi )?invit(i|ami) (in|nella stanza) ([^?]+)\??/, (res) -> denied = ['BZBZ ADMIN-NOT-DETECTED', 'BZBZ IS-NOT-AUTHORIZED', 'BZBZ ACCESS-DENIED'] failed = ['ahahah NO', 'mai sentito questo', 'invita anche me magari', 'che?'] user = res.message.user room = find_closest res.match[4], room_list(), (x) -> x.name admin_id = process.env['ADMIN_ROOM'] if room.id is admin_id or room.private return res.send res.random denied if not room? return res.send res.random failed if user.id in (room.members.map (x) -> x.id) return res.send 'ma sei già nella stanza...', '[facepalm]' if user.id in (room.invitees.map (x) -> x.id) return res.send 'lo sei già: devi solo accettare' invite_user user, room, -> res.send res.random success res.messageRoom room, "#{user.name}: benvenuto in #{room.name}!" robot.logger.info "invited user #{user.id} to #{room.id}" robot.respond /kicka(l(o|a)| (.+))/, (res) -> withdrew = ['invito revocato', 'ho annullato l\'invito'] room = res.message.room target = res.match[3] if not target? get_history room, 1, (err, history) -> return if err is 1 return res.send "errore nel leggere la history: #{err}" if err? user = history[0].sender if user.id in [res.message.user.id, robot_info().id] return res.send 'ma sei scemo o cosa?' kick_user room, user, "ordini di #{res.message.user.name}. niente di personale" else user = find_closest target, room.members, (x) -> x.name if not user? user = find_closest target, room.invitees, (x) -> x.name if not user? return res.send res.random unknown return kick_user room, user, "", -> res.send res.random withdrew robot.logger.info "withdraw invitee #{user.id} from #{room.id}" if user.id in [res.message.user.id, robot_info().id] return res.send 'ma sei scemo o cosa?' kick_user room, user, "ordini di #{res.message.user.name}. niente di personale" robot.logger.info "kicked user #{user.id} from #{room.id}" robot.respond /esci|lasciaci un (minuto|attimo)|dobbiamo parlare in privato/, (res) -> leave = [ 'come vuoi, vado', 'ok, esco', 'esco dalla stanza', 'me ne vado'] res.send (res.random leave), -> matrix.leave res.message.room.id, -> matrix.forget res.message.room.id robot.logger.info "left room #{res.message.room.id}"