Este commit está contenido en:
Your Name
2020-05-28 10:44:39 +00:00
padre 86ffefc449
commit bc2b938771
Se han modificado 13 ficheros con 4977 adiciones y 0 borrados

Ver fichero

@@ -0,0 +1,24 @@
version: '2.3'
services:
hatbot:
build: ./hatbot
restart: always
hostname: hatbot
container_name: hatbot
entrypoint:
- /bin/bash
- entrypoint.sh
volumes:
- ./hatbot:/hatbot
networks:
mynet:
ipv4_address: 172.56.0.101
networks:
mynet:
# enable_ipv6: false
driver: bridge
ipam:
config:
- subnet: 172.56.0.0/24

103
testing/hatbot/fonts.conf Archivo normal
Ver fichero

@@ -0,0 +1,103 @@
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<!-- /etc/fonts/fonts.conf file to configure system font access -->
<fontconfig>
<!--
DO NOT EDIT THIS FILE.
IT WILL BE REPLACED WHEN FONTCONFIG IS UPDATED.
LOCAL CHANGES BELONG IN 'local.conf'.
The intent of this standard configuration file is to be adequate for
most environments. If you have a reasonably normal environment and
have found problems with this configuration, they are probably
things that others will also want fixed. Please submit any
problems to the fontconfig bugzilla system located at fontconfig.org
Note that the normal 'make install' procedure for fontconfig is to
replace any existing fonts.conf file with the new version. Place
any local customizations in local.conf which this file references.
Keith Packard
-->
<!-- Font directory list -->
<dir>/usr/share/fonts</dir>
<dir>/usr/X11R6/lib/X11/fonts</dir> <dir>/usr/local/share/fonts</dir>
<dir prefix="xdg">fonts</dir>
<!-- the following element will be removed in the future -->
<dir>~/.fonts</dir>
<!--
Accept deprecated 'mono' alias, replacing it with 'monospace'
-->
<match target="pattern">
<test qual="any" name="family">
<string>mono</string>
</test>
<edit name="family" mode="assign" binding="same">
<string>monospace</string>
</edit>
</match>
<!--
Accept alternate 'sans serif' spelling, replacing it with 'sans-serif'
-->
<match target="pattern">
<test qual="any" name="family">
<string>sans serif</string>
</test>
<edit name="family" mode="assign" binding="same">
<string>sans-serif</string>
</edit>
</match>
<!--
Accept deprecated 'sans' alias, replacing it with 'sans-serif'
-->
<match target="pattern">
<test qual="any" name="family">
<string>sans</string>
</test>
<edit name="family" mode="assign" binding="same">
<string>sans-serif</string>
</edit>
</match>
<!--
Ignore dpkg temporary files created in fonts directories
-->
<selectfont>
<rejectfont>
<glob>*.dpkg-tmp</glob>
</rejectfont>
</selectfont>
<selectfont>
<rejectfont>
<glob>*.dpkg-new</glob>
</rejectfont>
</selectfont>
<!--
Load local system customization file
-->
<include ignore_missing="yes">conf.d</include>
<!-- Font cache directory list -->
<cachedir>/var/cache/fontconfig</cachedir>
<cachedir prefix="xdg">fontconfig</cachedir>
<!-- the following element will be removed in the future -->
<cachedir>~/.fontconfig</cachedir>
<config>
<!--
Rescan configuration every 30 seconds when FcFontSetList is called
-->
<rescan>
<int>30</int>
</rescan>
</config>
</fontconfig>

Ver fichero

@@ -0,0 +1,31 @@
FROM node:12-slim
RUN apt -o Acquire::ForceIPv4=true update && apt -y -o Acquire::ForceIPv4=true upgrade && apt -y install -o Acquire::ForceIPv4=true \
git \
ttf-freefont \
fontconfig \
libx11-xcb1 \
libxcomposite1 \
libxcursor1 \
libxdamage1 \
libxi6 \
libxtst6 \
libglib2.0 \
libnss3 \
libcups2 \
libxss1 \
libxrandr2 \
libasound2 \
libatk1.0-0 \
libatk-bridge2.0-0 \
libpangocairo-1.0-0 \
libgtk-3-0 \
libx11-xcb1 \
libxtst6 \
libnss3 \
libxss1 \
libasound2 \
libatk-bridge2.0-0 \
&& apt clean
RUN npm i pm2 -g
WORKDIR /hatbot
USER node

Ver fichero

@@ -0,0 +1,23 @@
module.exports = {
url : 'https://duckduckgo.com/',
headers : {
'dnt': '1',
// 'accept-encoding': 'gzip, deflate, sdch, br',
'x-requested-with': 'XMLHttpRequest',
'accept-language': 'en-GB,en-US;q=0.8,en;q=0.6,ms;q=0.4',
'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36',
'accept': 'application/json, text/javascript, */*; q=0.01',
'referer': 'https://duckduckgo.com/',
'authority': 'duckduckgo.com',
},
max_iter : 2,
max_retries : 2,
params_template :{
l: "wt-wt",
o: "json",
q: null,
vqd: null,
f: ",,,",
p: null
}
}

Archivo binario no mostrado.

Después

Anchura:  |  Altura:  |  Tamaño: 132 KiB

Ver fichero

@@ -0,0 +1,210 @@
const Masto = require('masto').Masto,
fs = require('fs'),
requestsync = require('sync-request'),
CanvasRenderService = require('chartjs-node-canvas').CanvasRenderService,
osmsm = require('osm-static-maps'),
id = '46174';
(async () => {
const masto = await Masto.login({
uri: 'https://mastodon.hatthieves.es',
accessToken: 'KylPfsSfzi5tqbmNMW8PM7QixnwtPSS63AYJ6kJL_GQ'
}),
stream = await masto.streamPublicTimeline(),
arrayRandomColor = () => {
return 'rgba(' + Math.floor(Math.random() * 256) + ',' + Math.floor(Math.random() * 256) + ',' + Math.floor(Math.random() * 256) + ',1)'
},
chart = (status, country, days) => {
const dates = [],
day = days ? days : 10
for (let n = 0; n < day; n++) {
const date = new Date(Date.now()),
newdate = new Date(date.setDate(date.getDate() - n))
dates.push((1 + newdate.getMonth()) + '-' + newdate.getDate() + '-' + newdate.getFullYear())
}
const data = [],
today = dates.shift()
dates.map(date => {
const body = JSON.parse(requestsync('GET', 'https://covid19.mathdro.id/api/daily/' + date).getBody()),
countries = JSON.parse(requestsync('GET', 'https://covid19.mathdro.id/api/countries').getBody())
let total = {
confirmed: 0,
deaths: 0,
recovered: 0
}
if (country) {
body.map(c => {
if (country === c.countryRegion) {
total.confirmed += parseInt(c.confirmed)
total.deaths += parseInt(c.deaths)
total.recovered += parseInt(c.recovered)
}
})
} else {
body.map(c => {
total.confirmed += parseInt(c.confirmed)
total.deaths += parseInt(c.deaths)
total.recovered += parseInt(c.recovered)
})
}
data.push({
confirmed: total.confirmed,
deaths: total.deaths,
recovered: total.recovered
})
})
dates.splice(0, 0, today)
let body
if (country) {
body = JSON.parse(requestsync('GET', 'https://covid19.mathdro.id/api/countries/' + country).getBody())
} else {
body = JSON.parse(requestsync('GET', 'https://covid19.mathdro.id/api').getBody())
}
data.splice(0, 0, {
confirmed: parseInt(body.confirmed.value),
deaths: parseInt(body.deaths.value),
recovered: parseInt(body.recovered.value)
})
dates.reverse()
data.reverse()
const width = 500,
height = 300,
type = 'line',
configuration = {
type: type,
data: {
labels: dates,
datasets: [{
label: 'Confirmed',
data: data.map(d => d.confirmed),
backgroundColor: arrayRandomColor(),
borderColor: arrayRandomColor(),
borderWidth: 3,
order: 3
},
{
label: 'Deaths',
data: data.map(d => d.deaths),
backgroundColor: arrayRandomColor(),
borderColor: arrayRandomColor(),
borderWidth: 3,
order: 1
},
{
label: 'Recovered',
data: data.map(d => d.recovered),
backgroundColor: arrayRandomColor(),
borderColor: arrayRandomColor(),
borderWidth: 3,
order: 2
}]
},
options: {
legend: {
display: true
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
},
chartCallback = (ChartJS) => {
ChartJS.defaults.global.elements.rectangle.borderWidth = 1
ChartJS.plugins.register({
beforeDraw: (chart, options) => {
const ctx = chart.ctx
ctx.fillStyle = '#FFFFFF'
ctx.fillRect(0, 0, width, height)
}
})
},
canvasRenderService = new CanvasRenderService(width, height, chartCallback),
crs = canvasRenderService.renderToStream(configuration)
crs.pipe(fs.createWriteStream(__dirname + '/covid19.png'))
crs.on('end', async () => {
const attachment = await masto.uploadMediaAttachment({
file: fs.createReadStream(__dirname + '/covid19.png'),
description: status ? '@' + status.account.acct + ' #COVID19 Status ' + country : '#COVID19 Status Global'
})
if (attachment.id) {
await masto.createStatus({
in_reply_to_id: status ? status.id : null,
status: status ? '@' + status.account.acct + ' #COVID19 Status ' + country : '#COVID19 Status Global',
visibility: 'public',
media_ids: [attachment.id]
}).then((newStatus) => {
// console.log(newStatus)
})
}
})
},
map = (status, min) => {
const confirmed = JSON.parse(requestsync('GET', 'https://covid19.mathdro.id/api/confirmed').getBody()),
geojson = {
geojson: {
type: 'FeatureCollection',
features: []
},
zoom: 2
}
confirmed.map(country => {
const m = min ? min : 0
if (country.confirmed > m) {
geojson.geojson.features.push({
type: 'Feature',
properties: {
title: country.countryRegion,
description: 'Confirmed: ' + country.confirmed + '\nRecovered: ' + country.recovered + '\nDeaths: ' + country.deaths + '\nActive: ' + country.active
},
geometry: {
type: 'Point',
coordinates: [country.long, country.lat]
}
})
}
})
osmsm(geojson)
.then(async imageBinaryBuffer => {
fs.writeFileSync(__dirname + '/covid19-map.png', imageBinaryBuffer)
const attachment = await masto.uploadMediaAttachment({
file: fs.createReadStream(__dirname + '/covid19-map.png'),
description: min ? '@' + status.account.acct + '#COVID19 Status Map more ' + min + ' confirmed' : '@' + status.account.acct + '#COVID19 Status Map'
})
if (attachment.id) {
await masto.createStatus({
in_reply_to_id: status.id,
status: min ? '@' + status.account.acct + ' #COVID19 Status Map more ' + min + ' confirmed' : '@' + status.account.acct + '#COVID19 Status Map',
visibility: 'public',
media_ids: attachment.id ? [attachment.id] : null
}).then((newStatus) => {
// console.log(newStatus)
})
}
}).catch(error => console.error)
},
startChart = () => {
chart()
setTimeout(() => { startChart() }, 6 * 60 * 60 * 1000)
}
startChart()
stream.on('update', status => {
if (status.mentions.some(mention => mention.id === id)) {
const content = status.content.replace(/<[^>]*>?/gm, ''),
clean = content.split(/ +/).filter(token => !token.startsWith('@'))
if (clean[0] === 'map' && clean.length === 1) {
map(status)
} else if (clean[0] === 'map' && clean.length === 2) {
clean.shift()
map(status, parseInt(clean[0]))
} else if (clean.length === 1) {
chart(status, clean[0])
} else if (clean.length === 2 && parseInt(clean[1])) {
chart(status, clean[0], clean[1])
}
}
})
})()

Archivo binario no mostrado.

Después

Anchura:  |  Altura:  |  Tamaño: 34 KiB

Ver fichero

@@ -0,0 +1,7 @@
#!/bin/bash
yarn
cp /hatbot/constants.js /hatbot/node_modules/duckduckgo-images-api/src/constants.js
#pm2 start index.js
pm2 start whatsapp.js
#pm2 start covid19.js
/bin/sleep infinity

BIN
testing/hatbot/hatbot/file.png Archivo normal

Archivo binario no mostrado.

Después

Anchura:  |  Altura:  |  Tamaño: 26 KiB

264
testing/hatbot/hatbot/index.js Archivo normal
Ver fichero

@@ -0,0 +1,264 @@
const Masto = require('masto').Masto,
wikiquote = require('wikiquote'),
http = require('http'),
cheerio = require('cheerio'),
request = require('request'),
ddgimage = require('duckduckgo-images-api'),
googleNewsAPI = require('google-news-json'),
ytsr = require('ytsr'),
CanvasRenderService = require('chartjs-node-canvas').CanvasRenderService,
TelegramBot = require('node-telegram-bot-api'),
fs = require('fs'),
token = '868884053:AAGrNoJYbBGLDxhGqeOx2ViJxt5D7KQIaas',
botId = -1001360688090,
id = '56179',
accounts = [],
requested = [];
(async () => {
let following = false
const masto = await Masto.login({
uri: 'https://mastodon.madrid',
accessToken: '-cF4rFvw4FVb2KSJAwLr33oHrOpIvDjFKvSfaxRIWRc'
}),
bot = new TelegramBot(token, { polling: true }),
stream = await masto.streamPublicTimeline(),
sendStatus = async (replyId, status, attachmentId) => {
await masto.createStatus({
in_reply_to_id: replyId,
status: status,
visibility: 'public',
media_ids: attachmentId ? [attachmentId] : null
}).then((newStatus) => {
// console.log(newStatus)
})
bot.sendMessage(botId, status)
},
followed = async (id) => {
following = true
accounts.splice(0, accounts.length)
for await (const account of masto.fetchAccountFollowing(id)) {
account.map(account => accounts.push(account))
console.log('LOADED ACCOUNTS: ' + accounts.length)
}
// chart()
following = false
},
arrayRandomColor = (n) => {
const colors = []
for (c = 0; c < n; c++) {
colors.push('rgba(' + Math.floor(Math.random() * 256) + ',' + Math.floor(Math.random() * 256) + ',' + Math.floor(Math.random() * 256) + ',1)')
}
return colors
},
chart = () => {
const dates = []
for (let n = 0; n < 10; n++) {
const date = new Date(Date.now()),
newdate = new Date(date.setDate(date.getDate() - n))
dates.push(newdate.getFullYear() + '-' + (newdate.getMonth() < 10 ? '0' : '') + (1 + newdate.getMonth()) + '-' + (newdate.getDate() < 10 ? '0' : '') + newdate.getDate())
}
const data = new Array(dates.length)
data.fill(0)
accounts.map(account => {
if (dates.indexOf(account.last_status_at) !== -1) {
data[dates.indexOf(account.last_status_at)]++
}
})
dates.reverse()
data.reverse()
const width = 500,
height = 300,
type = Math.floor(Math.random() * 2) ? 'bar' : 'line',
configuration = {
type: type,
data: {
labels: dates,
datasets: [{
label: 'Last Status Accounts',
data: data,
backgroundColor: type === 'bar' ? arrayRandomColor(data.length) : arrayRandomColor(data.length)[0],
borderColor: type === 'bar' ? arrayRandomColor(data.length) : arrayRandomColor(data.length)[0],
borderWidth: type === 'bar' ? 1 : 3
}]
},
options: {
legend: {
display: false
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
},
chartCallback = (ChartJS) => {
ChartJS.defaults.global.elements.rectangle.borderWidth = 1
ChartJS.plugins.register({
beforeDraw: (chart, options) => {
const ctx = chart.ctx
ctx.fillStyle = '#FDF6E3'
ctx.fillRect(0, 0, width, height)
}
})
},
canvasRenderService = new CanvasRenderService(width, height, chartCallback),
crs = canvasRenderService.renderToStream(configuration)
crs.pipe(fs.createWriteStream(__dirname + '/file.png'))
crs.on('end', async () => {
const attachment = await masto.uploadMediaAttachment({
file: fs.createReadStream(__dirname + '/file.png'),
description: 'Last Statuses #Chart'
})
if (attachment.id) {
sendStatus(null, 'Last Statuses #Chart 🎩 following ' + accounts.length + ' accounts', attachment.id)
bot.sendPhoto(botId, fs.createReadStream(__dirname + '/file.png'))
}
})
},
startChart = () => {
setTimeout(() => {
startFollowed(id)
startChart()
}, 6 * 60 * 60 * 1000)
},
startFollowed = id => {
followed(id).catch(error => {
console.log('ERROR: ' + error.message)
startFollowed(id)
})
}
bot.onText(/(.+)/, async (msg, match) => {
await masto.createStatus({
status: msg.from.first_name + ': ' + msg.text,
visibility: 'public'
}).then((newStatus) => {
// console.log(newStatus)
})
})
startFollowed(id)
// startChart()
stream.on('update', async status => {
if (!accounts.some(account => account.id === status.account.id)
&& !requested.some(account => account.id === status.account.id)
&& id !== status.account.id
&& !status.account.note.replace(/<[^>]*>?/gm, '').match(/#nobots?/im) && !following) {
await masto.followAccount(status.account.id, { reblogs: false }).then(relation => {
if (relation.requested && !relation.following) {
requested.push(status.account)
}
}).catch(console.error)
accounts.push(status.account)
console.log('Following: ' + status.account.acct)
}
if (status.mentions.some(mention => mention.id === id)) {
const content = status.content.replace(/<[^>]*>?/gm, ''),
clean = content.split(/ +/).filter(token => !token.startsWith('@'))
bot.sendMessage(botId, '@' + status.account.acct + ' ' + clean.join(' '))
if (clean.length > 0) {
if (clean[0] === 'chiste' || clean[0] === 'chistes') {
const req = http.get('http://www.chistes.com/chistealazar.asp?n=3', res => {
const bodyChunks = []
res.on('data', chunk => {
bodyChunks.push(chunk)
}).on('end', () => {
const buf = Buffer.concat(bodyChunks),
$ = cheerio.load(buf.toString('binary'))
sendStatus(status.id, '@' + status.account.acct + ' 🎩 \n' + $('div.chiste').text())
}).on('error', error => {
console.log('ERROR: ' + error.message)
})
})
req.on('error', error => {
console.log('ERROR: ' + error.message)
})
} else if (clean[0] === 'video' && clean.length > 1) {
clean.shift()
ytsr(clean.join(' '), { limit: 1 }, (error, result) => {
if (error) {
console.log('ERROR: ' + error.message)
} else {
sendStatus(status.id, '@' + status.account.acct + ' 🎩 \n' + result.items[0].title + ' - ' + result.items[0].duration + '\n' + result.items[0].link + '\n' + result.items[0].description)
}
})
} else if (clean[0] === 'imagen' && clean.length > 1) {
clean.shift()
ddgimage.image_search({
query: clean.join(' '),
moderate: false,
iterations: 2,
retries: 10
}).then(async result => {
const attachment = await masto.uploadMediaAttachment({
file: request.get(result[0].image),
description: clean.join(' ')
})
if (attachment.id) {
sendStatus(status.id, '@' + status.account.acct + ' 🎩 ' + clean.map(token => '#' + token).join(' '), attachment.id)
bot.sendPhoto(botId, request.get(result[0].image))
}
})
} else if (clean[0] === 'noticias' && clean.length > 1) {
clean.shift()
googleNewsAPI.getNews(googleNewsAPI.SEARCH, clean.join(' '), "es-ES", (err, response) => {
if (err) {
console.log('ERROR: ' + err.message)
} else {
let text = '@' + status.account.acct + ' 🎩 \n'
response.items.map((news, index) => {
if (index < 3) {
text += news.title + ' - ' + news.link + '\n'
}
})
sendStatus(status.id, text)
}
})
} else if (clean[0] === 'noticias' && clean.length === 1) {
googleNewsAPI.getNews(googleNewsAPI.TOP_NEWS, null, "es-ES", (err, response) => {
if (err) {
console.log('ERROR: ' + err.message)
} else {
let text = '@' + status.account.acct + ' 🎩 \n'
response.items.map((news, index) => {
if (index < 3) {
text += news.title + ' - ' + news.link + '\n'
}
})
sendStatus(status.id, text)
}
})
} else if (clean[0] === 'stats' && clean.length === 1) {
request('https://top.hatthieves.es/api/3/all', {
json: true,
auth: {
user: 'docker',
pass: 'docker',
sendImmediately: true
}
}, (err, res, data) => {
if (err) {
console.log('ERROR: ' + err.message)
} else {
sendStatus(status.id, `Cloud System Stats\n\nCPU: ${data.quicklook.cpu_name} - ${Math.round(data.quicklook.cpu_hz_current / 1000000) / 1000}GHz\nCPU Cores: ${data.load.cpucore}\nCPU Load: ${data.load.min1}\nCPU used: ${data.cpu.total}%\nMem used: ${data.mem.percent}%\nSwap used: ${data.memswap.percent}%\nSSD space: ${data.fs[0].percent}%\nProcess: ${data.processcount.total}\nThreads: ${data.processcount.thread}\nContainers: ${data.docker.containers.length}\nDocker: ${data.docker.version.Version}\nUptime: ${data.uptime}\n\nby #HatThieves`)
}
})
} else {
wikiquote.search(clean.join(' '), { language: 'es' })
.then(pages => {
if (pages.length > 0) {
return wikiquote.getRandomQuote(pages[0].title, { language: 'es' })
} else {
return 'no he encontrado nada...'
}
}).then(quote => sendStatus(status.id, '@' + status.account.acct + ' 🎩 ' + quote.replace(/\[[^\]]*\]?/gm, '')))
}
}
}
}).on('error', error => {
console.log('ERROR: ' + error.message)
})
})()

Ver fichero

@@ -0,0 +1,27 @@
{
"name": "hatbot",
"version": "1.0.0",
"description": "One bot with a 🎩",
"main": "index.js",
"private": true,
"author": "ale",
"license": "MIT",
"dependencies": {
"chart.js": "*",
"chartjs-node-canvas": "*",
"cheerio": "*",
"duckduckgo-images-api": "*",
"es6-promisify": "*",
"google-news-json": "*",
"masto": "*",
"mime-types": "*",
"node-telegram-bot-api": "*",
"osm-static-maps": "*",
"qrcode-terminal": "*",
"request": "*",
"sync-request": "*",
"whatsapp-web.js": "^1.5.1",
"wikiquote": "*",
"ytsr": "*"
}
}

Ver fichero

@@ -0,0 +1,354 @@
const { Client, MessageMedia } = require('whatsapp-web.js'),
client = new Client({ puppeteer: { args: ['--no-sandbox', '--disable-setuid-sandbox'] } }),
http = require('http'),
ddgimage = require('duckduckgo-images-api'),
request = require('request'),
mime = require('mime-types'),
googleNewsAPI = require('google-news-json'),
ytsr = require('ytsr'),
wikiquote = require('wikiquote'),
cheerio = require('cheerio'),
qrcode = require('qrcode-terminal'),
idChan = '34652383768-1574607114@g.us',
count = { messages: 0 },
fs = require('fs'),
requestsync = require('sync-request'),
CanvasRenderService = require('chartjs-node-canvas').CanvasRenderService,
osmsm = require('osm-static-maps'),
arrayRandomColor = (n) => {
const colors = []
for (c = 0; c < n; c++) {
colors.push('rgba(' + Math.floor(Math.random() * 256) + ',' + Math.floor(Math.random() * 256) + ',' + Math.floor(Math.random() * 256) + ',1)')
}
return colors
},
chart = async (msg, country, days) => {
const dates = [],
day = days ? days : 10
for (let n = 0; n < day; n++) {
const date = new Date(Date.now()),
newdate = new Date(date.setDate(date.getDate() - n))
dates.push((1 + newdate.getMonth()) + '-' + newdate.getDate() + '-' + newdate.getFullYear())
}
const data = [],
today = dates.shift(),
countries = JSON.parse(requestsync('GET', 'https://covid19.mathdro.id/api/countries').getBody())
dates.map(date => {
const body = JSON.parse(requestsync('GET', 'https://covid19.mathdro.id/api/daily/' + date).getBody())
let total = {
confirmed: 0,
deaths: 0,
recovered: 0
}
if (country) {
body.map(c => {
if (country === c.countryRegion) {
total.confirmed += parseInt(c.confirmed)
total.deaths += parseInt(c.deaths)
total.recovered += parseInt(c.recovered)
}
})
} else {
body.map(c => {
total.confirmed += parseInt(c.confirmed)
total.deaths += parseInt(c.deaths)
total.recovered += parseInt(c.recovered)
})
}
data.push({
confirmed: total.confirmed,
deaths: total.deaths,
recovered: total.recovered
})
})
dates.splice(0, 0, today)
let body
if (country) {
body = JSON.parse(requestsync('GET', 'https://covid19.mathdro.id/api/countries/' + country).getBody())
} else {
body = JSON.parse(requestsync('GET', 'https://covid19.mathdro.id/api').getBody())
}
data.splice(0, 0, {
confirmed: parseInt(body.confirmed.value),
deaths: parseInt(body.deaths.value),
recovered: parseInt(body.recovered.value)
})
dates.reverse()
data.reverse()
const width = 500,
height = 300,
type = 'line',
configuration = {
type: type,
data: {
labels: dates,
datasets: [{
label: 'Confirmed',
data: data.map(d => d.confirmed),
backgroundColor: type === 'bar' ? arrayRandomColor(data.length) : arrayRandomColor(data.length)[0],
borderColor: type === 'bar' ? arrayRandomColor(data.length) : arrayRandomColor(data.length)[0],
borderWidth: type === 'bar' ? 1 : 3,
order: 3
},
{
label: 'Deaths',
data: data.map(d => d.deaths),
backgroundColor: type === 'bar' ? arrayRandomColor(data.length) : arrayRandomColor(data.length)[0],
borderColor: type === 'bar' ? arrayRandomColor(data.length) : arrayRandomColor(data.length)[0],
borderWidth: type === 'bar' ? 1 : 3,
order: 1
},
{
label: 'Recovered',
data: data.map(d => d.recovered),
backgroundColor: type === 'bar' ? arrayRandomColor(data.length) : arrayRandomColor(data.length)[0],
borderColor: type === 'bar' ? arrayRandomColor(data.length) : arrayRandomColor(data.length)[0],
borderWidth: type === 'bar' ? 1 : 3,
order: 2
}]
},
options: {
legend: {
display: true
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
},
chartCallback = (ChartJS) => {
ChartJS.defaults.global.elements.rectangle.borderWidth = 1
ChartJS.plugins.register({
beforeDraw: (chart, options) => {
const ctx = chart.ctx
ctx.fillStyle = '#FFFFFF'
ctx.fillRect(0, 0, width, height)
}
})
},
canvasRenderService = new CanvasRenderService(width, height, chartCallback),
crs = await canvasRenderService.renderToBufferSync(configuration)
const mm = new MessageMedia('image/png', crs.toString('base64'))
await msg.reply(mm)
},
map = (msg, min) => {
const confirmed = JSON.parse(requestsync('GET', 'https://covid19.mathdro.id/api/confirmed').getBody()),
geojson = {
geojson: {
type: 'FeatureCollection',
features: []
},
zoom: 2
}
confirmed.map(country => {
const m = min ? min : 0
if (country.confirmed > m) {
geojson.geojson.features.push({
type: 'Feature',
properties: {
title: country.countryRegion,
description: 'Confirmed: ' + country.confirmed + '\nRecovered: ' + country.recovered + '\nDeaths: ' + country.deaths + '\nActive: ' + country.active
},
geometry: {
type: 'Point',
coordinates: [country.long, country.lat]
}
})
}
})
osmsm(geojson)
.then(async imageBinaryBuffer => {
const mm = new MessageMedia('image/png', imageBinaryBuffer.toString('base64'))
await msg.reply(mm)
}).catch(error => console.error)
}
client.on('qr', qr => {
qrcode.generate(qr, qrc => {
console.log(qrc)
})
})
client.on('ready', () => {
console.log('Client is ready!')
})
client.on('message_create', async msg => {
if (msg.type === 'chat') { // && msg.from === idChan) {
count.messages++
const clean = msg.body.split(' ')
if (clean[0] === '.count') {
msg.reply('He recibido ' + count.messages + ' chats en total')
} else if (clean[0] === '.imagen' && clean.length > 1) {
clean.shift()
ddgimage.image_search({
query: clean.join(' '),
moderate: false,
iterations: 2,
retries: 10
}).then(result => {
request.get(result[0].image, { encoding: null }, async (err, res, data) => {
if (err) {
console.error(err.message)
} else {
const mm = new MessageMedia(mime.lookup(result[0].image), Buffer.from(data).toString('base64'))
await msg.reply(mm)
}
})
})
} else if (clean[0] === '.video' && clean.length > 1) {
clean.shift()
ytsr(clean.join(' '), { limit: 1 }, async (err, result) => {
if (err) {
console.error(err.message)
} else {
await msg.reply(result.items[0].title + ' - ' + result.items[0].duration + '\n' + result.items[0].link + '\n' + result.items[0].description)
}
})
} else if (clean[0] === '.wiki' && clean.length > 1) {
clean.shift()
wikiquote.search(clean.join(' '), { language: 'es' })
.then(pages => {
if (pages.length > 0) {
return wikiquote.getRandomQuote(pages[0].title, { language: 'es' })
} else {
return 'no he encontrado nada...'
}
}).then(async quote => await msg.reply(quote.replace(/\[[^\]]*\]?/gm, '')))
} else if (clean[0] === '.stats' && clean.length === 1) {
request('https://top.hatthieves.es/api/3/all', {
json: true,
auth: {
user: 'docker',
pass: 'docker',
sendImmediately: true
}
}, async (err, res, data) => {
if (err) {
console.error(err.message)
} else {
await msg.reply(`Cloud System Stats\n\nCPU: ${data.quicklook.cpu_name} - ${Math.round(data.quicklook.cpu_hz_current / 1000000) / 1000}GHz\nCPU Cores: ${data.load.cpucore}\nCPU Load: ${data.load.min1}\nCPU used: ${data.cpu.total}%\nMem used: ${data.mem.percent}%\nSwap used: ${data.memswap.percent}%\nSSD space: ${data.fs[0].percent}%\nProcess: ${data.processcount.total}\nThreads: ${data.processcount.thread}\nContainers: ${data.docker.containers.length}\nDocker: ${data.docker.version.Version}\nUptime: ${data.uptime}\n\nby #HatThieves`)
}
})
} else if (clean[0] === '.chiste' || clean[0] === '.chistes') {
const req = http.get('http://www.chistes.com/chistealazar.asp?n=3', res => {
const bodyChunks = []
res.on('data', chunk => {
bodyChunks.push(chunk)
}).on('end', async () => {
const buf = Buffer.concat(bodyChunks),
$ = cheerio.load(buf.toString('binary'))
await msg.reply($('div.chiste').text())
}).on('error', error => {
console.log('ERROR: ' + error.message)
})
})
req.on('error', error => {
console.log('ERROR: ' + error.message)
})
} else if (clean[0] === '.noticias' && clean.length > 1) {
clean.shift()
googleNewsAPI.getNews(googleNewsAPI.SEARCH, clean.join(' '), "es-ES", async (err, response) => {
if (err) {
console.log('ERROR: ' + err.message)
} else {
let text = ''
response.items.map((news, index) => {
if (index < 3) {
text += news.title + ' - ' + news.link + '\n'
}
})
await msg.reply(text)
}
})
} else if (clean[0] === '.noticias' && clean.length === 1) {
googleNewsAPI.getNews(googleNewsAPI.TOP_NEWS, null, "es-ES", async (err, response) => {
if (err) {
console.log('ERROR: ' + err.message)
} else {
let text = ''
response.items.map((news, index) => {
if (index < 3) {
text += news.title + ' - ' + news.link + '\n'
}
})
await msg.reply(text)
}
})
} else if (clean[0] === '.p' && clean.length > 1) {
clean.shift()
request.post('https://www.pandorabots.com/pandora/talk?botid=b8d616e35e36e881', {
form: {
botcust2: 'd7d0de702e8987ba',
message: clean.join(' ')
}
}, async (err, request, body) => {
if (err) console.error
else {
const $ = cheerio.load(body)
await msg.reply(decodeURIComponent($('body').html().split('<')[$('body').html().split('<').length - 2].replace(/^\/b> /, '').trim()))
}
})
} else if (clean[0] === '.virus' && clean.length === 1) {
chart(msg)
} else if (clean[0] === '.virus' && clean.length > 1) {
clean.shift()
chart(msg, clean[0], clean[1])
} else if (clean[0] === '.map' && clean.length === 1) {
map(msg)
} else if (clean[0] === '.map' && clean.length > 1) {
clean.shift()
map(msg, parseInt(clean[0]))
} else if (clean[0] === '.ranking' && clean.length === 1) {
const body = JSON.parse(requestsync('GET', 'https://covid19.mathdro.id/api/confirmed').getBody())
body.sort((a, b) => parseInt(b.confirmed) - parseInt(a.confirmed))
let confirmed = body.map((country, index) => {
if (index < 10) {
return country.countryRegion + ': ' + country.confirmed
}
})
body.sort((a, b) => parseInt(b.deaths) - parseInt(a.deaths))
let deaths = body.map((country, index) => {
if (index < 10) {
return country.countryRegion + ': ' + country.deaths
}
})
body.sort((a, b) => parseInt(b.recovered) - parseInt(a.recovered))
let recovered = body.map((country, index) => {
if (index < 10) {
return country.countryRegion + ': ' + country.recovered
}
})
let output = 'Confirmed\n_________\n\n' + confirmed.join('\n').trim() + '\n\n\nDeaths\n_________\n\n' + deaths.join('\n').trim() + '\n\n\nRecovered\n_________\n\n' + recovered.join('\n').trim()
await msg.reply(output)
} else if (clean[0] === '.ranking' && clean.length > 1 && parseInt(clean[1])) {
const body = JSON.parse(requestsync('GET', 'https://covid19.mathdro.id/api/confirmed').getBody())
body.sort((a, b) => parseInt(b.confirmed) - parseInt(a.confirmed))
let confirmed = body.map((country, index) => {
if (index < clean[1]) {
return country.countryRegion + ': ' + country.confirmed
}
})
body.sort((a, b) => parseInt(b.deaths) - parseInt(a.deaths))
let deaths = body.map((country, index) => {
if (index < clean[1]) {
return country.countryRegion + ': ' + country.deaths
}
})
body.sort((a, b) => parseInt(b.recovered) - parseInt(a.recovered))
let recovered = body.map((country, index) => {
if (index < clean[1]) {
return country.countryRegion + ': ' + country.recovered
}
})
let output = 'Confirmed\n_________\n\n' + confirmed.join('\n').trim() + '\n\n\nDeaths\n_________\n\n' + deaths.join('\n').trim() + '\n\n\nRecovered\n_________\n\n' + recovered.join('\n').trim()
await msg.reply(output)
}
}
})
client.initialize()

3934
testing/hatbot/hatbot/yarn.lock Archivo normal

La diferencia del archivo ha sido suprimido porque es demasiado grande Cargar Diff