Merge pull request #28 from rnhmjoj/matrix

Matrix
This commit is contained in:
Michele Guerini Rocco 2017-02-25 19:05:24 +01:00 committed by GitHub
commit 89594cbb03
16 changed files with 237 additions and 409 deletions

10
.gitignore vendored
View File

@ -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

View File

@ -1 +0,0 @@
web: bin/hubot -a campfire

View File

@ -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

View File

@ -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" "$@"

View File

@ -1,3 +0,0 @@
@echo off
npm install && node_modules\.bin\hubot.cmd --name "asjon" %*

View File

@ -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",

View File

@ -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

205
scripts/matrix.coffee Normal file
View File

@ -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) <stanza> - chiedi ad hubot di invitardi in una stanza
# hubot invita/aggiungi <nome> - chiedi ad hubot di invitare qualcuno nel stanza attuale
# hubot kicka <nome> - 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}"

View File

@ -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')

View File

@ -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()...

View File

@ -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

View File

@ -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'

View File

@ -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"

View File

@ -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
res.send res.random invalid

View File

@ -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 <nome> - chiedi ad hubot di invitare qualcuno nel gruppo attuale
# hubot (mi inviti / invitami) (nel gruppo / in) <gruppo> - 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 <nome> - 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

View File

@ -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'