diff --git a/package.json b/package.json index 3f9d903..8f241f6 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "author": "Flummi & jkhsjdhjs", "license": "WTFPL", "dependencies": { - "cuffeo": "^1.0.5", + "cuffeo": "^1.0.5-2", "flumm-fetch-cookies": "^1.3.4-1", "pg": "^7.14.0", "stringify-object": "^3.3.0" diff --git a/src/bot.mjs b/src/bot.mjs index 2c99ade..37fbb60 100644 --- a/src/bot.mjs +++ b/src/bot.mjs @@ -2,11 +2,13 @@ import _fs from "fs"; import cuffeo from "cuffeo"; import config from "../cfg/config.json"; import logger from "./inc/log.mjs"; +import user from "./inc/user.mjs"; const fs = _fs.promises; const timeout = 1000; (async () => { + await user.initUser(); const self = { _trigger: new Map(), trigger: function trigger(args) { diff --git a/src/inc/events/info.mjs b/src/inc/events/info.mjs index 7c6e490..8776a59 100644 --- a/src/inc/events/info.mjs +++ b/src/inc/events/info.mjs @@ -8,5 +8,11 @@ export default async bot => { f: e => { logger.debug(e); } + }, { + name: "debug", + listener: "debug", + f: e => { + logger.debug(e); + } }]; }; diff --git a/src/inc/trigger/debug.mjs b/src/inc/trigger/debug.mjs index 9f313c4..5b20c4d 100644 --- a/src/inc/trigger/debug.mjs +++ b/src/inc/trigger/debug.mjs @@ -1,5 +1,6 @@ import { getLevel } from "../admin.mjs"; import fetch from "flumm-fetch-cookies"; +import user from "../user.mjs"; import vm from "vm"; @@ -9,6 +10,7 @@ let context = vm.createContext({ bot: null, admins: null, fetch: fetch, + user: user, console: console }); diff --git a/src/inc/trigger/freewar.mjs b/src/inc/trigger/freewar.mjs new file mode 100644 index 0000000..eba1bf7 --- /dev/null +++ b/src/inc/trigger/freewar.mjs @@ -0,0 +1,35 @@ +import fetch from "flumm-fetch-cookies"; + +const regex = /
(
.*<\/div>)?(?.*)<\/div><\/td>(?.*)<\/td>.*(?.*)<\/b>/gm; + +export default async bot => { + + return [{ + name: "fw_shops", + call: /^(\.|\/)fwshop/i, + active: true, + f: async e => { + const shopsite = await (await fetch("https://freewar.zocker.eu/")).text(); + + const shops = [...shopsite.matchAll(regex)].map(e => { + const [ name, tmp ] = e.groups.name.split(/\<.*\>/); + const [ x, y ] = tmp.split("/"); + + return { + region: e.groups.region.replace(/\<.*/m, ""), + name: name, + coords: { + x: +x, + y: +y + }, + percent: e.groups.percent + }; + }); + + e.reply([ + "Die besten drei Shops:", + JSON.stringify(shops.slice(0, 3)) + ]); + } + }]; +}; diff --git a/src/inc/trigger/lastfm.mjs b/src/inc/trigger/lastfm.mjs index e942702..24b2226 100644 --- a/src/inc/trigger/lastfm.mjs +++ b/src/inc/trigger/lastfm.mjs @@ -1,5 +1,6 @@ import fetch from "flumm-fetch-cookies"; import config from "../../../cfg/config.json"; +import user from "../user.mjs"; const api = `http://ws.audioscrobbler.com/2.0/?method=user.getRecentTracks&limit=1&api_key=${config.apis.lastfm.key}&format=json&user=`; @@ -14,9 +15,19 @@ export default async bot => { usage: "[b].np[/b] [i][/i]" },*/ f: async e => { - const nick = e.args[0] || e.user.nick; + if(e.args.length > 0 && e.args[0].charAt(0) === "=") { + const tmp = e.args[0].slice(1); + await user.set(e.user.prefix, { lastfm: tmp }); + return e.reply(`lastfm account set to: [b]${tmp}[/b]`); + } - let res = await (await fetch(`${api}${nick}`)).json(); + if(!user.has(e.user.prefix)) + return e.reply("nope"); + const u = user.get(e.user.prefix); + if(u.lastfm === null || u.lastfm === "") + return e.reply("nope"); + + let res = await (await fetch(`${api}${u.lastfm}`)).json(); if(res.error) return e.reply("User not found"); diff --git a/src/inc/trigger/lib/serialize.mjs b/src/inc/trigger/lib/serialize.mjs new file mode 100644 index 0000000..877bf18 --- /dev/null +++ b/src/inc/trigger/lib/serialize.mjs @@ -0,0 +1,76 @@ +export default new class serialize { + FUNCFLAG = "_$$ND_FUNC$$_"; + CIRCULARFLAG = "_$$ND_CC$$_"; + KEYPATHSEPARATOR = "_$$.$$_"; + + getKeyPath(obj, path) { + let currentObj = obj; + path.split(this.KEYPATHSEPARATOR).forEach((p, index) => { + if (index) + currentObj = currentObj[p]; + }); + return currentObj; + } + serialize(obj, outputObj, cache, path) { + path = path || "$"; + cache = cache || {}; + cache[path] = obj; + outputObj = outputObj || {}; + + if(Array.isArray(obj)) + return JSON.stringify(obj); + + for(let key in obj) { + if(obj.hasOwnProperty(key)) { + if(Array.isArray(obj[key])) + outputObj[key] = obj[key]; + else if(typeof obj[key] === "object" && obj[key] !== null) { + let found = false; + for(let subKey in cache) { + if (cache.hasOwnProperty(subKey)) { + if (cache[subKey] === obj[key]) { + outputObj[key] = this.CIRCULARFLAG + subKey; + found = true; + } + } + } + if (!found) + outputObj[key] = this.serialize(obj[key], outputObj[key], cache, path + this.KEYPATHSEPARATOR + key); + } + else if(typeof obj[key] === "function") + outputObj[key] = this.FUNCFLAG + obj[key].toString(); + else + outputObj[key] = obj[key]; + } + } + return (path === "$") ? JSON.stringify(outputObj) : outputObj; + } + unserialize(obj, originObj) { + let isIndex; + if (typeof obj === "string") { + obj = JSON.parse(obj); + isIndex = true; + } + originObj = originObj || obj; + + let circularTasks = []; + for(let key in obj) { + if(obj.hasOwnProperty(key)) { + if(typeof obj[key] === "object") + obj[key] = this.unserialize(obj[key], originObj); + else if(typeof obj[key] === "string") { + if(obj[key].indexOf(this.FUNCFLAG) === 0) + obj[key] = eval("(" + obj[key].substring(this.FUNCFLAG.length) + ")"); + else if(obj[key].indexOf(this.CIRCULARFLAG) === 0) { + obj[key] = obj[key].substring(this.CIRCULARFLAG.length); + circularTasks.push({obj: obj, key: key}); + } + } + } + } + + if (isIndex) + circularTasks.forEach(task => task.obj[task.key] = this.getKeyPath(originObj, task.obj[task.key])); + return obj; + } +}; diff --git a/src/inc/trigger/rape.mjs b/src/inc/trigger/rape.mjs index bed54f0..8bfaa94 100644 --- a/src/inc/trigger/rape.mjs +++ b/src/inc/trigger/rape.mjs @@ -1,4 +1,5 @@ import sql from "../sql.mjs"; +import user from "../user.mjs"; export default async bot => { @@ -6,14 +7,17 @@ export default async bot => { name: "rape", call: /^(\.|\/)rape/i, set: "nxy", - active: false, + active: true, help: { text: "Rapes a nick and eventually charge for it", usage: "[b].rape[/b] [i]()[/i]" }, - f: e => { - const nick = e.args[0] || e.user.nick; + f: async e => { + const nick = (e.args[0] || (e.type === "tg" ? e.user.username || e.user.nick : e.user.nick)).split("@").join(""); + return e.replyAction(`rapes [b]${nick}[/b].`); + const rand = Math.round(Math.random()); + //const u = user.get(new RegExp(`${nick}!.*@${e.network}`, "i")) || { fines: 0 }; if(rand !== 1) e.replyAction(`rapes [b]${nick}[/b].`) @@ -22,13 +26,15 @@ export default async bot => { const fined = [e.user.nick, nick][rand]; const reason = ["raping", "being too lewd and getting raped"][rand]; - sql.query("insert into nxy_users (nick, fines) values (lower($1), $2) on conflict (nick) do update set fines = nxy_users.fines + excluded.fines returning fines", [fined, fine]) + await user.set(e.user.prefix, { fines: u.fines += fine }) + + /*sql.query("insert into nxy_users (nick, fines) values (lower($1), $2) on conflict (nick) do update set fines = nxy_users.fines + excluded.fines returning fines", [fined, fine]) .then(rows => { e.replyAction(`fines [b]${nick}[/b] [b]$${fine}[/b] for ${reason}. You owe: [b]$${rows[0].fines}[/b].`); }) .catch(err => { console.log(err); - }); + });*/ } } }, { diff --git a/src/inc/trigger/sandbox.mjs b/src/inc/trigger/sandbox.mjs index 62a3f03..5a0a8de 100644 --- a/src/inc/trigger/sandbox.mjs +++ b/src/inc/trigger/sandbox.mjs @@ -1,46 +1,43 @@ -import sql from "../sql.mjs"; import { maxoutput, sandbox, bfgen } from "./lib/sandbox.mjs"; +import user from "../user.mjs"; import vm from "vm"; +import util from "util"; import fetch from "flumm-fetch-cookies"; -import stringify from "stringify-object"; +import serialize from "./lib/serialize.mjs"; let _contexts = new Map(); export default async bot => { - sql.query("select prefix, sandbox from nxy_users where sandbox != 'NULL'") - .then(rows => rows.forEach(row => eval(`_contexts.set(row.prefix, ${JSON.parse(row.sandbox)});`))) - .catch(err => console.log("nichts vorhanden lol", err)); + if(user.size > 0) + user.forEach((v, prefix) => eval(`_contexts.set(prefix, serialize.unserialize(v.sandbox));`)); return [{ name: "sandbox_js", call: /^(\.|\/)js (.*)/i, set: "uwe", - f: e => { + f: async e => { const args = e.message.trim().substring(4); + if (!_contexts.has(e.user.prefix)) _contexts.set(e.user.prefix, vm.createContext({ })); if (args.match(/^reset$/)) { _contexts.set(e.user.prefix, vm.createContext({ })); + await user.set(e.user.prefix, { sandbox: "{}" }); return e.reply("Sandbox resetted!"); } let context = vm.createContext(_contexts.get(e.user.prefix)); + try { let output = vm.runInContext(args, context, { timeout: 2000 }); if (typeof output !== undefined && output) { - output = JSON.stringify(output); + output = util.inspect(output); if (output.length > maxoutput) return e.reply(`${e.user.nick}: holy fuck, Ausgabe wäre viel zu lang! (${output.length} Zeichen :DDDDDD)`); else { _contexts.set(e.user.prefix, context); - let tmp = JSON.stringify(stringify(_contexts.get(e.user.prefix)) - .replace(/\n/g, "") - .replace(/\t/g, "") - .split("[native code]").join("")); - sql.query("insert into nxy_users (nick, prefix, sandbox) values (lower($1), $3, $2) on conflict (prefix) do update set sandbox = $2, nick = lower($1)", [ - (e.type === "tg" ? e.user.username || e.user.nick : e.user.nick), tmp, e.user.prefix - ]).then(() => e.reply(e.user.nick + ": " + output)) - .catch(err => console.log(err)); + await user.set(e.user.prefix, { sandbox: serialize.serialize(_contexts.get(e.user.prefix)) }); + e.reply(`${e.user.nick}: ${output}`); } } else diff --git a/src/inc/trigger/useless_nxy.mjs b/src/inc/trigger/useless_nxy.mjs index 5de5618..81b148b 100644 --- a/src/inc/trigger/useless_nxy.mjs +++ b/src/inc/trigger/useless_nxy.mjs @@ -1,4 +1,5 @@ import sql from "../sql.mjs"; +import user from "../user.mjs"; import fetch from "flumm-fetch-cookies"; const data = { @@ -167,33 +168,22 @@ export default async bot => { name: "waifu_husbando", call: /^(\.|\/)(waifu|husbando)/i, set: "nxy", - f: e => { - let nick = e.args[0] || (e.type === "tg"?e.user.username || e.user.nick:e.user.nick) - let mode = e.cmd; - nick = nick.split("@").join(""); + f: async e => { + const nick = (e.args[0] || (e.type === "tg" ? e.user.username || e.user.nick : e.user.nick)).split("@").join(""); + const mode = e.cmd; if(e.args.length > 0 && e.args[0].charAt(0) === "=") { let tmp = e.args[0].slice(1); - sql.any( - `insert into nxy_users (prefix, nick, ${mode}) values ($1, lower($2), $3) on conflict (prefix) do update set ${mode} = excluded.${mode}, nick = $2`, [ - e.user.prefix, - (e.type === "tg"?e.user.username || e.user.nick:e.user.nick), - tmp - ]) - .then(rows => { - e.reply(`${mode.charAt(0).toUpperCase()+mode.slice(1)} set to: [b]${tmp}[/b]`) - }) - .catch(err => console.log(err)); - } - else { - sql.any(`select ${mode} from nxy_users where lower(nick) = lower($1) limit 1`, [nick]) - .then(rows => { - if(!rows[0]) - return e.reply(`[b]${mode.charAt(0).toUpperCase() + mode.slice(1)}[/b]: none`); - e.reply(`${mode.charAt(0).toUpperCase() + mode.slice(1)}: [b]${rows[0][mode]}[/b]`); - }) - .catch(err => console.log(err)); + await user.set(e.user.prefix, { [mode]: tmp }); + return e.reply(`${mode.charAt(0).toUpperCase() + mode.slice(1)} set to: [b]${tmp}[/b]`); } + + let tmp, ret; + if(!(tmp = user.get(new RegExp(`${nick}!.*@${e.network}`, "i")))) + ret = "none"; + else + ret = tmp[mode] === null || tmp[mode] === "" ? "none" : tmp[mode]; + return e.reply(`[b]${mode.charAt(0).toUpperCase() + mode.slice(1)}[/b]: ${ret}`); } }, { name: "asshole", diff --git a/src/inc/trigger/useless_uwe.mjs b/src/inc/trigger/useless_uwe.mjs index db8e115..fafcb62 100644 --- a/src/inc/trigger/useless_uwe.mjs +++ b/src/inc/trigger/useless_uwe.mjs @@ -186,6 +186,13 @@ export default async bot => { f: e => { e.reply("[b]GET HYPER![/b]"); } + }, { + name: "F", + call: /^f$/i, + set: "uwe", + f: e => { + e.reply(e.message); + } }, { name: "bark", call: /^(\.|\/)bark$/i, diff --git a/src/inc/user.mjs b/src/inc/user.mjs new file mode 100644 index 0000000..e3920ca --- /dev/null +++ b/src/inc/user.mjs @@ -0,0 +1,60 @@ +import sql from "./sql.mjs"; + +export default new class user { + constructor() { + this.user = new Map(); + } + + async initUser() { + const users = await sql.query("select * from nxy_users"); + if(users.rowCount === 0) + return false; + + users.rows.forEach(user => this.user.set(user.prefix, user)); + return true; + } + + async load(prefix) { + let user = await sql.query("select * from nxy_users where prefix = $1", [ prefix ]); + if(user.rowCount === 0) { + await sql.query("insert into nxy_users (prefix) values ($1)", [ prefix ]); + user = await sql.query("select * from nxy_users where prefix = $1", [ prefix ]); + this.user.set(prefix, user.rows[0]); + } + return user.rows[0]; + } + + async set(prefix, data) { + const keys = Object.keys(data); + const values = keys.map((e, i) => `$${i + 2}`).join(", "); + let query = `insert into nxy_users (prefix, ${keys.join(", ")}) values ($1, ${values}) on conflict (prefix) do update set `; + query += keys.map((e, i) => `${e} = $${i + 2}`).join(", "); + await sql.query(query, [ prefix, ...Object.values(data) ]); + this.user.delete(prefix); + this.user.set(prefix, await this.load(prefix)); + return this.user.get(prefix); + } + + get(user) { + if(typeof user === "object") { // regex + for(let [k, v] of this.user.entries()) + if(user.test(k)) + return v; + } + else + return this.user.get(user); + return false; + } + has(...args) { + return this.user.has(...args); + } + + + forEach(...args) { + return this.user.forEach(...args); + } + get size() { + return this.user.size; + } + +};