diff --git a/.gitignore b/.gitignore index 8741f7e..d621574 100644 --- a/.gitignore +++ b/.gitignore @@ -1,13 +1,5 @@ -.cache/ node_modules -environment -hubot.lua -.DS_Store* .hubot_history -run.sh -run_telegram.sh -*.pub +matrix-data config/ coverage/ -.telegram/ -telegram.config diff --git a/Procfile b/Procfile deleted file mode 100644 index 9c85565..0000000 --- a/Procfile +++ /dev/null @@ -1 +0,0 @@ -web: bin/hubot -a campfire diff --git a/asjon-testing.coffee b/asjon-testing.coffee index 6eb895e..d26cdf6 100644 --- a/asjon-testing.coffee +++ b/asjon-testing.coffee @@ -11,7 +11,7 @@ before = (done) -> robot = new Robot null, "mock-adapter", no, 'asjon' robot.adapter.on 'connected', -> # Initialize mocked environment - user = robot.brain.userForId "1", { name: 'mocha', room: '#mocha' } + user = robot.brain.userForId "1", { name: 'mocha', room: name: 'mocha', id: '#mocha' } adapter = robot.adapter send = (s) -> robot.adapter.receive new TextMessage user, s receive = (f) -> robot.adapter.on 'send', f diff --git a/bin/hubot b/bin/hubot index e48be9b..0de4001 100755 --- a/bin/hubot +++ b/bin/hubot @@ -2,6 +2,5 @@ set -e export PATH="node_modules/.bin:node_modules/hubot/node_modules/.bin:$PATH" export DEBUG=nightmare -export PYTHON=python2 node_modules/.bin/hubot --name "asjon" --alias "assa" "$@" diff --git a/bin/hubot.cmd b/bin/hubot.cmd deleted file mode 100644 index bbda95e..0000000 --- a/bin/hubot.cmd +++ /dev/null @@ -1,3 +0,0 @@ -@echo off - -npm install && node_modules\.bin\hubot.cmd --name "asjon" %* \ No newline at end of file diff --git a/package.json b/package.json index 6fb7d53..fe696a0 100644 --- a/package.json +++ b/package.json @@ -26,8 +26,9 @@ "hubot-rules": "^0.1.0", "hubot-scripts": "^2.5.16", "hubot-shipit": "^0.2.0", - "hubot-tg": "rnhmjoj/hubot-tg", + "hubot-tg": "davidar/hubot-matrix", "hubot-youtube": "^0.1.2", + "mocha": "^3.2.0", "moment": "^2.10.2", "needle": "^0.10.0", "nock": "^1.7.1", diff --git a/scripts/blacklist.coffee b/scripts/blacklist.coffee index e123ea6..5da5486 100644 --- a/scripts/blacklist.coffee +++ b/scripts/blacklist.coffee @@ -22,13 +22,13 @@ module.exports = (robot) -> 'ne sei certo?', 'direi che è meglio di no'] notFound = ['non so chi sia', 'sicuro? non lo trovo', 'boh, chi è?', 'mai sentito, hai scritto giusto?', 'boh, non lo trovo'] - noPermit = ['BZBZ 403-NOT-AUTHORIZED', 'BZBZ DOES-NOT-COMPUTE', + noPermit = ['BZBZ 403-NOT-AUTHORIZED', 'BZBZ DOES-NOT-COMPUTE', 'BZBZ ADMIN-NOT-DETECTED', 'BZBZ IS-NOT-AUTHORIZED', 'BZBZ ACCESS-DENIED'] isFromAdmin = (res) -> res.robot.adapterName is 'shell' or - res.message.room is process.env.ADMIN_ROOM + res.message.room.id is process.env.ADMIN_ROOM # find closest match with levenshtein metric @@ -63,7 +63,7 @@ module.exports = (robot) -> else robot.logger.info "no known user matches #{name}" res.send res.random notFound - + robot.respond /ascolta (.+)/i, (res) -> if not isFromAdmin res diff --git a/scripts/matrix.coffee b/scripts/matrix.coffee new file mode 100644 index 0000000..eb8ab40 --- /dev/null +++ b/scripts/matrix.coffee @@ -0,0 +1,205 @@ +# 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}" + diff --git a/scripts/memoria.coffee b/scripts/memoria.coffee index dc86538..08f9354 100644 --- a/scripts/memoria.coffee +++ b/scripts/memoria.coffee @@ -66,11 +66,6 @@ module.exports = (robot) -> # Estrazione argomento della query arg = (res.match[3] or res.match[2] or res.match[1]).toLowerCase().replace('?','') arg = arg.replace('tuo','mio').replace('tuoi','miei') - # Se l'argomento è una richiesta di circolari skippo - # console.log query, arg - if arg.match /^le (?:ultime )?(?:\d+ )?circolari(?:\?)?$/i - # non rispondo - return # Controllo se l'argomento è data data = toDate arg if data.isValid() and arg.match(/^(il |l')/i) and (query is 'quand' or query is 'cos') diff --git a/scripts/meta.coffee b/scripts/meta.coffee index 5fdca51..560dc44 100644 --- a/scripts/meta.coffee +++ b/scripts/meta.coffee @@ -34,7 +34,7 @@ module.exports = (robot) -> # allow direct talk in user chat or campfire unless message.done or (true in results) - if message.room == message.user.id or message.user.id is 1 + if robot.adapterName is 'shell' or message.room.private message.text = robot.name + ' ' + message.text results.push listeners()... diff --git a/scripts/misc.coffee b/scripts/misc.coffee index 7741f0e..426ac3e 100644 --- a/scripts/misc.coffee +++ b/scripts/misc.coffee @@ -37,13 +37,12 @@ module.exports = (robot) -> thank = ['prego :)', "non c'è di che", 'faccio solo il mio lavoro', 'no problemo amigo', 'non fate complimenti ;)'] - sender = (res) -> - res.message.user.name.replace /_/g, ' ' + sender = (res) -> res.message.user.name welcome = (res) -> current = robot.brain.get 'ringraziato' robot.brain.set 'ringraziato', (current or 0) + 1 - res.send res.random thank + res.send res.random thank # thank asjon robot.hear /(?:grazie|bravo) (?:asjon|assa|assion(?:i|e))/i, welcome @@ -78,7 +77,7 @@ module.exports = (robot) -> # memes robot.respond /teq/i, (res) -> - res.send 'http://i3.kym-cdn.com/photos/images/newsfeed/000/353/279/e31.jpg' + res.send 'http://i3.kym-cdn.com/photos/images/newsfeed/000/353/279/e31.jpg' # other robot.respond /saluta (.+)$/i, (res) -> @@ -112,10 +111,9 @@ module.exports = (robot) -> res.send "sto parlando in #{res.message.room}, #{sender res}" robot.respond /ti amo/i, (res) -> - res.send 'anche io ti amo ' + sender res + res.send "anche io ti amo #{sender res}" robot.respond /ti odio/i, (res) -> - res.message.user.name = "Michele_Guerini_Rocco" res.send "ma cosa ti ho fatto di male #{sender res}? :(" robot.hear /(?:ehi|ciao|we|(?:bella(?: li)?)) (?:asjon|assa|assion(?:i|e))/i, (res) -> @@ -123,5 +121,8 @@ module.exports = (robot) -> 'dimmi', 'weeee', 'ehilà'] res.send "#{res.random greet} #{sender res}" - robot.respond /(ci sei)?\?/i, (res) -> - res.send res.random confirm + robot.respond /ci sei\?/i, (res) -> + res.send res.random confirm + + robot.hear /assa\?/, (res) -> + res.send res.random confirm diff --git a/scripts/scuola.coffee b/scripts/scuola.coffee deleted file mode 100644 index 8862b94..0000000 --- a/scripts/scuola.coffee +++ /dev/null @@ -1,86 +0,0 @@ -# Description: -# utilità per orario scolastico e interrogazioni -# -# Dependencies: -# "moment": "2.10.2" -# -# Configuration: -# None -# -# Commands: -# hubot orario/cosa abbiamo domani/oggi? - mostra l'orario per la 5IA -# hubot lista degli interrogati - lista completa degli interrogati nella 5IA -# hubot interrogati (di) oggi/domani/il ... - mostra la lista degli interrogati nella 5IA -# -# Author: -# Enrico Fasoli (fazo96) - -moment = require 'moment' -fs = require 'fs' - -moment.locale 'it' - -interr = undefined -orario = undefined - -dateformats = ['YYYY-MM-DD','DD-MM-YYYY',"DD MMMM YYYY", "DD MMMM","DD"] - -fs.readFile './config/orario.json', (err, data) -> - try - orario = JSON.parse data - catch e - orario = undefined - -fs.readFile './config/interrogazioni.json', (err, data) -> - try - interr = JSON.parse data - catch e - interr = undefined - if interr?.sort?.call? - interr.sort (a,b) -> - if moment(a.day,'YYYY-MM-DD').isBefore(b.day,'day') - return -1 - if moment(a.day,'YYYY-MM-DD').isAfter(b.day,'day') - return 1 - return 0 - -module.exports = (robot) -> - robot.respond /(?:che )?cosa abbiamo (?:per )?(domani|oggi)(?:\?)?/i, (res) -> - if res.match[1] is 'domani' - index = moment().add(1, 'days').weekday() - else index = moment().weekday() - if orario?[index]? - res.send orario[index].join ', ' - else res.send 'non ho informazioni per domani' - - robot.respond /(?:dimmi )?(?:l\')?orario(?: scolastico)?/i, (res) -> - unless orario?.push? - return res.send 'non conosco l\'orario scolastico :(' - ris = orario.map (x,i) -> - moment().weekday(i).format('dddd')+': '+x.join(', ') - res.send 'Orario scolastico della 5IA\n'+ris.join('\n') - - robot.respond /interrogat(?:o|i) (?:di )?(oggi|domani|il (.+))(?:\?)?/i, (res) -> - unless interr?.push? - return res.send 'non conosco gli interrogati :(' - if res.match[1] is 'domani' - day = moment().add(1, 'days') - else if res.match[1] is 'oggi' - day = moment() - else - q = res.match[1].replace(/il|\?/i, '') - day = moment q, dateformats - ris = interr.filter (x) -> - moment(x.day).isSame day, 'day' - ris = ris.map (x) -> - '('+x.day+') '+x.materia+': '+x.list.join(', ') - res.send ris.join('\n') or 'nessun interrogato' - - robot.respond /(?:lista )?(?:degli )?interrogati$/i, (res) -> - unless interr?.push? - res.send 'non conosco gli interrogati :(' - ris = interr.map (x) -> - gg = moment(x.day, 'YYYY-MM-DD') - s = gg.format('dddd Do MMMM YYYY')+' - '+gg.fromNow() - '('+s+') '+x.materia+': '+x.list.join(', ') - res.send ris.join('\n') or 'nessun interrogato' diff --git a/scripts/shell.coffee b/scripts/shell.coffee index de5e059..a7a86f8 100644 --- a/scripts/shell.coffee +++ b/scripts/shell.coffee @@ -12,13 +12,13 @@ cp = require 'child_process' -nope = ['BZBZ 400-BAD-REQUEST', 'BZBZ DOES-NOT-COMPUTE', +nope = ['BZBZ 400-BAD-REQUEST', 'BZBZ DOES-NOT-COMPUTE', 'BZBZ ADMIN-NOT-DETECTED', 'BZBZ IS-NOT-AUTHORIZED', 'BZBZ ACCESS-DENIED'] isFromAdmin = (res) -> res.robot.adapterName is 'shell' or - res.message.room is process.env.ADMIN_ROOM + res.message.room.id is process.env.ADMIN_ROOM runCmd = (cmd,res,cb) -> @@ -44,31 +44,31 @@ module.exports = (robot) -> runCmd 'npm test', dest if process.env.AUTO_INFORM_ON_START - r = room: process.env.AUTO_INFORM_ON_START - robot.send r, 'asjon avviato e operativo!' + room = id: process.env.AUTO_INFORM_ON_START + robot.messageRoom room, 'asjon avviato e operativo!' robot.respond /aggiornati|scarica (?:gli )?aggiornamenti/i, (res) -> - return res.send res.random nope unless isFromAdmin(res) + return res.send res.random nope unless isFromAdmin res runCmd 'git pull && npm install', res robot.respond /(?:controlla gli )?aggiornamenti/i, (res) -> - return res.send res.random nope unless isFromAdmin(res) + return res.send res.random nope unless isFromAdmin res runCmd 'git fetch && git status', res robot.respond /(?:installa (?:le )?)?dipendenze/i, (res) -> - return res.send res.random nope unless isFromAdmin(res) + return res.send res.random nope unless isFromAdmin res runCmd 'npm install', res robot.respond /(?:esegui (?:i )?)?test/i, (res) -> - return res.send res.random nope unless isFromAdmin(res) + return res.send res.random nope unless isFromAdmin res runCmd 'npm test', res robot.respond /secret-kill-code/i, (res) -> - return res.send res.random nope unless isFromAdmin(res) + return res.send res.random nope unless isFromAdmin res process.exit 0 robot.respond /(emergency|reverse) shell|phone home/i, (res) -> - return res.send res.random nope unless isFromAdmin(res) + return res.send res.random nope unless isFromAdmin res rhost = process.env.REV_REMOTE_HOST rport = process.env.REV_REMOTE_PORT || 22 rtport = process.env.REV_REMOTE_TUNNEL_PORT || 2200 @@ -78,7 +78,7 @@ module.exports = (robot) -> return res.send 'non è impostato nessun host' unless rhost? return res.send 'manca una chiave ssh' unless key? - ssh = "ssh -R #{rtport}:#{host}:#{port} -i #{key} -p #{rport} #{rhost}" + ssh = "ssh -R #{rtport}:#{host}:#{port} -i #{key} -p #{rport} #{rhost}" res.send "ok, apro una reverse shell #{rhost}:#{rtport} -> #{host}:#{port}" res.send "connettiti entro 10s" diff --git a/scripts/shortener.coffee b/scripts/shortener.coffee index fc5d8fc..451d5cb 100644 --- a/scripts/shortener.coffee +++ b/scripts/shortener.coffee @@ -1,5 +1,5 @@ # Description: -# Accorcia un link usando l'api di breve.xyz +# Accorcia un link usando l'api di brve.bit # # Dependencies: # valid-url @@ -25,7 +25,8 @@ module.exports = (robot) -> robot.respond /breve|accorcia (.+)$/i, (res) -> url = res.match[1] if is_web_uri url - ne.post 'https://breve.xyz/api', url: url, (err, resp, body) => + ne.post 'https://brve.bit/api', url: url, {rejectUnauthorized: false}, (err, resp, body) => + return res.send "c'è qualche problema: #{err}" if err res.send (res.random valid) + body.link else - res.send res.random invalid \ No newline at end of file + res.send res.random invalid diff --git a/scripts/telegram.coffee b/scripts/telegram.coffee deleted file mode 100644 index 3e1d952..0000000 --- a/scripts/telegram.coffee +++ /dev/null @@ -1,270 +0,0 @@ -# Description: -# funzioni speciali per telegram-cli -# -# Requires: -# "fast-levenshtein": "1.0.6" -# -# Configuration: -# Uses hubot-tg enviroment variables -# -# 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 gruppi sei / dove scrivi - chiedi a hubot dove chatta -# hubot invita/aggiungi - chiedi ad hubot di invitare qualcuno nel gruppo attuale -# hubot (mi inviti / invitami) (nel gruppo / in) - chiedi ad hubot di invitardi in un gruppo -# hubot (aggiungi[mi] / crea) (il mio / [tra]i contatto/i) [telefono] - chiedi ad hubot di creare il tuo contatto -# hubot banna - chiedi di bannare un utente dal gruppo attuale (solo se hubot l'ha invitato) -# hubot bannalo - chiedi ad hubot di bannare l'ultimo utente ad aver scritto un messaggio dal gruppo -# -# Author: -# Michele Guerini Rocco (rnhmjoj) -# - -net = require 'net' -lev = require 'fast-levenshtein' - -module.exports = (robot) -> - # 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'] - banned = [', ora non sarai più un problema', ' terminato', - ' non farti più vedere', ', questa è la tua fine' - ' sparito per sempre'] - - # find closest match with levenshtein metric - find_closest = (target, list) -> - dists = [].concat.apply [], ( - for str in list - for word in [str].concat str.split ' ' - [(lev.get target, word), str] ) - [dist, name] = dists.reduce (x, y) -> - if x[0] < y[0] then x else y - return if dist < 4 then name else null - - # format a name as telegram-cli likes it - norm = (x) -> x.replace /\ /g, '_' - - # return a list of every match for a regex - match_all = (regex, str) -> - matches = [] - str.replace regex, -> - arr = [].slice.call arguments, 0 - extras = arr.splice -2 - arr.index = extras[0] - arr.input = extras[1] - matches.push arr - matches - - # directly run a command in telegram-cli and return its output - # (a list of strings) - run_command = (command, callback) -> - client = net.connect robot.adapter.port, robot.adapter.host, -> - client.write command+'\n' - client.setEncoding 'utf8' - client.on 'data', (reply) -> - if callback? - res = (reply.split '\n')[1..-3] - [..., err] = res[0].split ' ' - callback res, err - client.end() - - # return an object with the known chat information - chat_info = (name, callback) -> - run_command "chat_info #{norm name}", (data) -> - match = data[0].match /// - Chat\ (\w+(\ ?\w+)*) # chat name - \ \(id\ (\d+)\) # chat id - /// - chat = - name: match[1] - id: 'chat#'+match[3] - members: data[1..].map (i) -> (i.split ' invited')[0].replace /\t/g, '' - robot.logger.info 'parsed chat data: ' + JSON.stringify chat, null, 2 - callback chat - - # return an object with the known user information - user_info = (name, callback) -> - run_command "user_info #{norm name}", (data) -> - match = (data.join '\n').match /// - User\ (\w+(\ ?\w+)*) # contact name - (\ @(\w+))? # telegram username - (\ \(\#(\d+)\))? # telegram id - [\s\S]+phone:\ (\d+)? # phone number - /// - user = - name: match[1] - username: match[4] - id: 'user#'+match[6] - phone: match[7] - robot.logger.info 'parsed user data: ' + JSON.stringify user, null, 2 - callback user - - # get hubot telegram profile information - robot_info = (callback) -> - run_command 'get_self', (data) -> - match = (data.join '\n').match /// - User\ (\w+(\ ?\w+)*) # contact name - (\ @(\w+))? # telegram username - (\ \(\#(\d+)\))? # telegram id - [\s\S]+phone:\ (\d+)? # phone number - /// - user = - name: match[1] - username: match[4] - id: 'user#'+match[6] - phone: match[7] - robot.logger.info 'parsed robot data: ' + JSON.stringify user, null, 2 - callback user - - # return the list of active chat groups - chat_list = (callback) -> - run_command 'dialog_list', (list) -> - chats = list.filter (item) -> not item.lastIndexOf 'Chat', 0 - chats = chats.map (chat) -> (chat.match /Chat (.+):/)[1] - robot.logger.info 'parsed bot chats list: ' + JSON.stringify chats, null, 2 - callback chats - - # return the list of contacts (names only) - contact_list = (callback) -> - run_command 'contact_list', callback - - # add a user to the contact list - add_contact = (name, phone, callback) -> - robot.logger.info "create contact for user #{name}" - user_info name, (user) -> - [first, last...] = user.name.split ' ' - phone = phone or user.phone - if not phone? - return callback 'serve per forza il tuo numero' - run_command "add_contact #{phone} '#{first}' '#{last.join ' '}'", (reply) -> - robot.logger.info 'result: ' + reply - reply = reply[0].split ' ' - if reply[0] is 'FAIL:' - return callback reply[1..] - callback() - - # get the messages history for a chat group - get_history = (chat, size, callback) -> - regex = /\[(.+)\] (.+) [>«»]+ ((?:(?!\n(\[|\d))[\s\S])+)/g - parse_line = (x) -> - date: x[1] - peer: x[2].replace(chat, '').trim() - text: x[3].trim().replace '\n', ' ' - run_command "history #{norm chat} #{size}", (lines) -> - callback ((match_all regex, lines.join '\n').map parse_line) - - # ban user from a group chat - delete_user = (user, chat, res) -> - run_command "chat_del_user #{chat.id} #{user.id}", (reply, err) -> - robot.logger.info "delete user #{user.name} from chat #{chat.name}" - robot.logger.info 'result: ' + reply[0] - if err is 'SUCCESS' - robot.logger.info 'user deleted' - res.send user.name + res.random banned - else if err is 'CHAT_ADMIN_REQUIRED' - robot.logger.warning 'cannot delete user: not authorized' - res.send res.random failed - else - robot.logger.error 'error:\n' + reply.join '\n' - res.send error - - # add user to a group chat - add_user = (user, chat, res) -> - run_command "chat_add_user #{chat.id} #{user.id}", (reply, err) -> - robot.logger.info "add user #{user.name} to chat #{chat.name}" - robot.logger.info 'result: ' + reply[0] - if err is 'SUCCESS' - robot.messageRoom chat.id, res.random done - else if err is 'USER_NOT_MUTUAL_CONTACT' - robot.logger.warning 'cannot add user: not authorized' - res.send 'ah, non posso: ho bisogno del contatto' - else if err is 'USER_ALREADY_PARTICIPANT' - robot.logger.warning 'cannot add user: user already present' - res.send 'ma è già qui!' - else if err is 'CHAT_ADMIN_REQUIRED' - robot.logger.warning 'cannot add user: not authorized' - res.send res.random failed - else - robot.logger.error 'error:\n' + reply.join '\n' - res.send error - - robot.respond /chi sei/, (res) -> - robot_info (user) -> - username = if user.username? then " noto anche come #{user.username}" else '' - phone = if user.phone? then " chiamatemi al #{user.phone}. " else '. ' - id = "il mio id di telegram è #{user.id}" - res.send "sono #{user.name}#{username},#{phone}#{id}" - - robot.respond /(cosa sai di me|chi sono)/i, (res) -> - user_info res.message.user.name, (user) -> - username = if user.username? then " ma ti chiamano anche #{user.username}" else '' - phone = if user.phone? then " so il tuo numero: #{user.phone} e " else ' ' - id = "il tuo id di telegram è #{user.id}" - res.send "so che sei #{user.name}#{username},#{phone}#{id}" - - robot.respond /(in che gruppi sei| dove scrivi)/, (res) -> - intro = ['scrivo in questi gruppi', 'chatto qui', 'sono attivo in'] - chat_list (list) -> - res.send (res.random intro) + ':\n' + (list.map (i) -> '* '+i).join '\n' - - robot.respond /(aggiungi(mi)?|crea) ((trai? (i )?contatti)|(il mio contatto))( (\d+))?/, (res) -> - add_contact res.message.user.name, res.match[8], (err) -> - if err? - res.send "c'è un problema: " + err - else - res.send "fatto!" - - robot.respond /(invita|aggiungi) (.+)/, (res) -> - name = res.match[2] - id = res.message.room - if id.match /^user/ - return res.send 'non è un gruppo questo' - contact_list (contacts) -> - name = find_closest(name, contacts) - if not name? - return res.send res.random unknown - res.send res.random success - user_info name, (user) -> - chat_info id, (chat) -> - add_user user, chat, res - - robot.respond /(mi )?invit(i|ami) (in|nel gruppo) ([^?]+)\??/, (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 - name = res.match[4] - admin_id = process.env['ADMIN_ROOM'] - chat_list (list) -> - if not (name in list) - return res.send res.random failed - chat_info name, (chat) -> - if chat.id is admin_id - return res.send res.random denied - if user.name in chat.members - return res.send 'ma sei già nel gruppo... [facepalm]' - res.send res.random success - add_user user, chat, res - - robot.respond /banna(l(o|a)| (.+))/, (res) -> - if res.message.room.match /^user/ - return res.send 'non è un gruppo questo' - chat_info res.message.room, (chat) -> - get_history chat.name, 2, (history) -> - robot_info (self) -> - target = res.match[3] - if not target? - name = history[0].peer - else - name = find_closest(target, chat.members) - if not name? - return res.send res.random unknown - if name in [res.message.user.name, self.name] - return res.send 'ma sei scemo o cosa?' - user_info name, (user) -> delete_user user, chat, res diff --git a/test/memoria-test.coffee b/test/memoria-test.coffee index 64063a0..b06af06 100644 --- a/test/memoria-test.coffee +++ b/test/memoria-test.coffee @@ -71,9 +71,3 @@ describe 'modulo memoria', -> done() asjon.send 'asjon memory-dump' - it 'non interferisce con "circolari"', (done) -> - # se done() viene chiamato piu di 1 volta il test fallisce - asjon.receive (e,l) -> done() - asjon.send 'asjon cosa sono a?' - asjon.send 'asjon cosa sono le circolari' -