1
1
mirror of https://github.com/leon-ai/leon.git synced 2024-11-27 08:06:03 +03:00

refactor(skill/have_i_been_pwned): from module to skill

This commit is contained in:
louistiti 2022-02-20 23:55:21 +08:00
parent 3fea149497
commit 9d5ceb03cb
No known key found for this signature in database
GPG Key ID: 7ECA3DD523793FE6
15 changed files with 238 additions and 25 deletions

View File

@ -65,6 +65,11 @@
],
"entitiesType": "trim"
},
{
"method": "GET",
"route": "/api/action/utilities/have_i_been_pwned/run",
"params": []
},
{
"method": "POST",
"route": "/api/action/utilities/is_it_down/run",

View File

@ -25,7 +25,7 @@
]
},
"haveibeenpwned": {
"no-pwnage": [
"no_pwnage": [
"Great news, \"%email%\" hasn't been compromised in a data breach.",
"\"%email%\" looks good to me!"
],
@ -41,7 +41,7 @@
"I'm checking for a compromised email...",
"Trying to verify pwnage status..."
],
"no-email": [
"no_email": [
"Please provide one or more email addresses you need me to check."
],
"errors": [

View File

@ -25,7 +25,7 @@
]
},
"haveibeenpwned": {
"no-pwnage": [
"no_pwnage": [
"Bonne nouvelle, %email% n'a pas été compromis par une violation de données.",
"%email% cela me semble correct!"
],
@ -38,7 +38,7 @@
"Je cherche un email compromis.",
"Essayer de vérifier le statut de pwnage."
],
"no-email": [
"no_email": [
"Veuillez fournir une ou plusieurs adresses électroniques que vous devez vérifier..."
],
"errors": [

View File

@ -22,7 +22,7 @@ def run(string, entities):
emails = utils.config('emails')
if not emails:
return utils.output('end', 'no-email', utils.translate('no-email'))
return utils.output('end', 'no_email', utils.translate('no_email'))
utils.output('inter', 'checking', utils.translate('checking'))
@ -38,9 +38,9 @@ def run(string, entities):
return utils.output('end', 'blocked', utils.translate('unavailable', { 'website_name': 'Have I Been Pwned' }))
elif not breached:
if isLastEmail:
return utils.output('end', 'no-pwnage', utils.translate('no-pwnage', data))
return utils.output('end', 'no_pwnage', utils.translate('no_pwnage', data))
else:
utils.output('inter', 'no-pwnage', utils.translate('no-pwnage', data))
utils.output('inter', 'no_pwnage', utils.translate('no_pwnage', data))
else:
data['result'] = ''

View File

@ -6,6 +6,6 @@ describe('checker:haveibeenpwned', () => {
const [obj] = global.nlu.brain.execute.mock.calls
await global.brain.execute(obj[0])
expect(global.brain.finalOutput.codes).toIncludeSameMembers(['no-email'])
expect(global.brain.finalOutput.codes).toIncludeSameMembers(['no_email'])
})
})

View File

@ -192,31 +192,41 @@ class Brain {
// Read output
this.process.stdout.on('data', (data) => {
const obj = JSON.parse(data.toString())
const executionTimeEnd = Date.now()
const executionTime = executionTimeEnd - executionTimeStart
if (typeof obj === 'object') {
if (obj.output.type === 'inter') {
log.title(`${skillFriendlyName} skill`)
log.info(data.toString())
try {
const obj = JSON.parse(data.toString())
this.interOutput = obj.output
if (typeof obj === 'object') {
if (obj.output.type === 'inter') {
log.title(`${skillFriendlyName} skill`)
log.info(data.toString())
const speech = obj.output.speech.toString()
if (!opts.mute) {
this.talk(speech)
this.interOutput = obj.output
const speech = obj.output.speech.toString()
if (!opts.mute) {
this.talk(speech)
}
speeches.push(speech)
} else {
output += data
}
speeches.push(speech)
} else {
output += data
/* istanbul ignore next */
reject({
type: 'warning',
obj: new Error(`The "${skillFriendlyName}" skill from the "${domainFriendlyName}" domain is not well configured. Check the configuration file.`),
speeches,
executionTime
})
}
} else {
const executionTimeEnd = Date.now()
const executionTime = executionTimeEnd - executionTimeStart
} catch (e) {
/* istanbul ignore next */
reject({
type: 'warning',
obj: new Error(`The ${skillFriendlyName} skill from the ${domainFriendlyName} domain is not well configured. Check the configuration file.`),
type: 'error',
obj: new Error(`The "${skillFriendlyName}" skill from the "${domainFriendlyName}" domain isn't returning JSON format.`),
speeches,
executionTime
})

View File

@ -0,0 +1,53 @@
{
"actions": {
"run": {
"utterance_samples": [
"Has iifeoluwa.ao@gmail.com been pwned?",
"Has iifeoluwa.ao@gmail.com been compromised?",
"Has iifeoluwa.ao@gmail.com been exposed in a breach?",
"Is iifeoluwa.ao@gmail.com still uncompromised?",
"Is iifeoluwa.ao@gmail.com compromised?",
"Have my email address been pwned?",
"Check that iifeoluwa.ao@gmail.com and louis.grenard@gmail.com haven't been compromised",
"Check that iifeoluwa.ao@gmail.com and louis.grenard@gmail.com haven't been pwned",
"Check that iifeoluwa.ao@gmail.com and louis.grenard@gmail.com haven't been exposed in a breach",
"Verify the pwnage status of iifeoluwa.ao@gmail.com",
"Verify the pwnage status of iifeoluwa.ao@gmail.com and louis.grenard@gmail.com"
]
}
},
"answers": {
"no_pwnage": [
"Great news, \"%email%\" hasn't been compromised in a data breach.",
"\"%email%\" looks good to me!"
],
"pwned": [
"Oops, looks like \"%email%\" has been compromised in at least one breach involving:<br><br><ul>%result%</ul>",
"Sadly, \"%email%\" was affected in the following breaches:<br><br><ul>%result%</ul>",
"Unfortunately, \"%email%\" has been exposed in a data breach affecting:<br><br><ul>%result%</ul>"
],
"list_element": [
"<li><a href=\"%url%\" target=\"_blank\">%name%</a> with a total of %total% accounts.</li>"
],
"checking": [
"I'm checking for a compromised email...",
"Trying to verify pwnage status..."
],
"no_email": [
"Please provide one or more email addresses you need me to check."
],
"errors": [
"I think %website_name% is down at the moment, please try again later.",
"I'm having trouble reaching %website_name%. Please check that your internet connection is active.",
"Bad news, %website_name% is not responding. Maybe try at a later time?"
],
"blocked": [
"There was an issue accessing %website_name%'s service.",
"Unfortunate news, %website_name% isn't granting me access to its service."
],
"unavailable": [
"It looks like Cloudflare is defending %website_name%, please retry in a few moments.",
"Unfortunately, Cloudflare is temporarily blocking your access to %website_name%, please retry in a while."
]
}
}

View File

@ -0,0 +1,48 @@
{
"actions": {
"run": {
"utterance_samples": [
"iifeoluwa.ao@gmail.com a-t-elle été pwned ?",
"iifeoluwa.ao@gmail.com a-t-elle été compromise ?",
"iifeoluwa.ao@gmail.com a-t-elle été exposée à une brèche ?",
"iifeoluwa.ao@gmail.com est-elle toujours non compromise ?",
"Est-ce que iifeoluwa.ao@gmail.com est compromise ?",
"Est-ce que mon adresse email a été compromise ?",
"Vérifie que iifeoluwa.ao@gmail.com et louis.grenard@gmail.com n'ont pas été compromise",
"Vérifie que iifeoluwa.ao@gmail.com et louis.grenard@gmail.com n'ont pas été pwned",
"Vérifie que iifeoluwa.ao@gmail.com et louis.grenard@gmail.com n'ont pas été exposées à une brèche"
]
}
},
"answers": {
"no_pwnage": [
"Bonne nouvelle, %email% n'a pas été compromis par une violation de données.",
"%email% cela me semble correct!"
],
"pwned": [
"Oups, on dirait que %email% a été compromis par une infraction impliquant %breach%.",
"%breach% a été impliqué dans une brèche. Malheureusement, %email% a été touché.",
"Malheureusement, %email% a été exposé à une violation de données affectant %breach%."
],
"checking": [
"Je cherche un email compromis.",
"Essayer de vérifier le statut de pwnage."
],
"no_email": [
"Veuillez fournir une ou plusieurs adresses électroniques que vous devez vérifier..."
],
"errors": [
"Je pense que %website_name% est en panne pour le moment, veuillez réessayer plus tard.",
"J'ai du mal à joindre %website_name%. Veuillez vérifier que votre connexion Internet est active.",
"Mauvaise nouvelle, %website_name% ne répond pas. Peut-être essayer plus tard?"
],
"blocked": [
"Il y avait un problème d'accès au service de %website_name%.",
"Malheureusement, %website_name% ne me donne pas accès à son service."
],
"unavailable": [
"Il semblerait que Cloudflare protège %website_name%, veuillez réessayer dans un petit instant.",
"Malheureusement, Cloudflare a temporairement bloqué votre accès à %website_name%, merci de retenter dans un moment."
]
}
}

View File

@ -0,0 +1,11 @@
{
"name": "Have I Been Pwned",
"bridge": "python",
"version": "1.0.0",
"description": "Verify if one or several email addresses have been pwned (thanks to haveibeenpwned.com).",
"author": {
"name": "Louis Grenard",
"email": "louis.grenard@gmail.com",
"url": "https://github.com/louistiti"
}
}

View File

@ -0,0 +1,76 @@
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import utils
from time import sleep
from urllib import parse
from requests import codes, exceptions
# Developer token
api_key = utils.config('credentials')['api_key']
def run(string, entities):
"""Verify if one or several email addresses have been pwned"""
emails = []
for item in entities:
if item['entity'] == 'email':
emails.append(item['resolution']['value'])
if not emails:
emails = utils.config('options')['emails']
if not emails:
return utils.output('end', 'no_email', utils.translate('no_email'))
utils.output('inter', 'checking', utils.translate('checking'))
for index, email in enumerate(emails):
is_last_email = index == len(emails) - 1
breached = check_for_breach(email)
data = { 'email': email }
# Have I Been Pwned API returns a 403 when accessed by unauthorized/banned clients
if breached == 403:
return utils.output('end', 'blocked', utils.translate('blocked', { 'website_name': 'Have I Been Pwned' }))
elif breached == 503:
return utils.output('end', 'blocked', utils.translate('unavailable', { 'website_name': 'Have I Been Pwned' }))
elif not breached:
if is_last_email:
return utils.output('end', 'no_pwnage', utils.translate('no_pwnage', data))
else:
utils.output('inter', 'no_pwnage', utils.translate('no_pwnage', data))
else:
data['result'] = ''
for index, b in enumerate(breached):
data['result'] += utils.translate('list_element', {
'url': 'http://' + b['Domain'],
'name': b['Name'],
'total': b['PwnCount']
}
)
if is_last_email:
return utils.output('end', 'pwned', utils.translate('pwned', data))
else:
utils.output('inter', 'pwned', utils.translate('pwned', data))
def check_for_breach(email):
# Delay for 2 seconds before making request to accomodate API usage policy
sleep(2)
truncate = '?truncateResponse=true'
url = 'https://haveibeenpwned.com/api/v3/breachedaccount/' + parse.quote_plus(email)
try:
response = utils.http('GET', url, { 'hibp-api-key': api_key })
if response.status_code == 404:
return None
elif response.status_code == 200:
return response.json()
return response.status_code
except exceptions.RequestException as e:
return utils.output('end', 'down', utils.translate('errors', { 'website_name': 'Have I Been Pwned' }))

View File

@ -0,0 +1,10 @@
{
"configurations": {
"options": {
"emails": []
},
"credentials": {
"api_key": "YOUR_API_KEY"
}
}
}