From 2a2f379939738aafebbc864ecd53fef67ce65375 Mon Sep 17 00:00:00 2001 From: Flummi Date: Tue, 23 Aug 2016 11:23:25 +0000 Subject: [PATCH] test --- package.json | 3 +- src/lib.js | 164 ++++++++++++++++++++++ src/main.js | 313 ++++++------------------------------------ src/trigger/del.js | 37 +++-- src/trigger/level.js | 14 ++ src/trigger/parser.js | 55 ++++++++ 6 files changed, 293 insertions(+), 293 deletions(-) create mode 100644 src/lib.js create mode 100644 src/trigger/level.js create mode 100644 src/trigger/parser.js diff --git a/package.json b/package.json index 3548dfd..dd428d0 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,8 @@ "mysql": "^2.11.1", "repl": "^0.1.3", "swig": "^1.4.2", - "uuid": "^2.0.2" + "uuid": "^2.0.2", + "node-ffprobe": "^1.2.2" }, "repository": { "type": "git", diff --git a/src/lib.js b/src/lib.js new file mode 100644 index 0000000..d7137d6 --- /dev/null +++ b/src/lib.js @@ -0,0 +1,164 @@ +var fs = require('fs-extra'); +var http = require('http'); +var https = require('https'); +var exec = require('child_process').exec; +var probe = require('node-ffprobe'); +var uuid = require('uuid'); +var crypto = require('crypto'); +var path = require('path'); + +var bot, sql, cfg; +var debug = true; + +module.exports = Lib; +function Lib(tbot, tsql, tcfg) { + this.bot = bot = tbot; + this.sql = sql = tsql; + this.cfg = cfg = tcfg; + this.admins = []; +} + +Lib.prototype.getUser = (u, n, cbgu) => { + bot.write('WHOIS '+u, n, () => { + bot.once('data', (err, msg) => { + var params; + var map = []; + map.push(u); + if(msg.command == 'RPL_WHOISUSER') { + params = msg.params.split(' '); + map[u] = map[u] || {}; + map[u].nick = u; + map[u].username = params[2]; + map[u].hostname = params[3]; + map[u].realname = msg.trailing; + } + if(typeof(map[u]) === 'object') + cbgu(map[u]); + }); + }); +}; +Lib.prototype.getUserlevel = (e, tmp_channel, cb) => { + Lib.prototype.getUser(e.user.getNick(), e.network, (cbgu) => { + var host = cbgu.username+'@'+cbgu.hostname; + var lvl_channel = (cbgu.nick in tmp_channel)? cfg.level[ tmp_channel[cbgu.nick] ] : 0; + var lvl_db = 0; + if(host in this.admins) + lvl_db = (this.admins[host].server == e.network)? this.admins[host].level : 0; + cb({ + 'channel': lvl_channel, + 'db': lvl_db, + 'level': Math.max(lvl_channel, lvl_db) + }); + }); +}; +Lib.prototype.loadUser = (cb) => { + this.admins = []; + sql.query("select * from `f0ck`.`user`", (err, rows, fields) => { + rows.forEach((e,i,a) => { + this.admins.push(e.nick); + this.admins[e.vhost] = { + 'id': e.id, + 'nick': e.nick, + 'vhost': e.vhost, + 'level': e.level, + 'server': e.server + }; + }); + cb(true); + }).on('error', () => { + cb(false); + }); +} +Lib.prototype.checkRepost = (url, cbcr) => { + sql.query("select count(*) as count from `f0ck`.`items` where `src` = ?", url, (err, rows, fields) => { + cbcr((rows[0].count == 0)?true:false); + }); +}; +Lib.prototype.checkRepostCheckSum = (cs, cbcrcs) => { + sql.query("select count(*) as count from `f0ck`.`items` where `checksum` = ?", cs, (err, rows, fields) => { + cbcrcs((rows[0].count == 0)?true:false); + }); +}; +Lib.prototype.formatSize = (size) => { + var i = Math.floor(Math.log(size) / Math.log(1024)); + return (size / Math.pow(1024, i)).toFixed(2) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i]; +}; +Lib.prototype.getCheckSum = (file, cbcs) => { + var sha256sum = crypto.createHash('sha256'); + var s = fs.ReadStream(file); + s.on('data', (d) => { + sha256sum.update(d); + }); + s.on('end', () => { + cbcs(sha256sum.digest('hex')); + }); +}; +Lib.prototype.dl = (url, dest, cb) => { + var request = (url.match(/^https/)?https:http).get(url, (response) => { // type:1=post,type:2=stfu + console.log(response.headers['content-type']); + if(cfg.allowedMimes.hasOwnProperty(response.headers['content-type'])) { + if(response.headers['content-length'] <= cfg.maxFileSize) { + checkRepost(url, (cbcr) => { + if(cbcr) { + var file = fs.createWriteStream(dest+"."+cfg.allowedMimes[response.headers['content-type']]); + response.pipe(file); + file.on('finish', () => { + file.close(); + probe(dest+"."+cfg.allowedMimes[response.headers['content-type']], (err, probeData) => { + if(probeData.streams[0].height !== undefined || probeData.streams[0].width !== undefined) { + if(probeData.streams[0].height <= cfg.minRes || probeData.streams[0].width <= cfg.minRes) + cb({'status':false, 'msg':'f0ck! your shitpost is too small ('+probeData.streams[0].width+' x '+probeData.streams[0].height+'), min '+cfg.minRes+' x '+cfg.minRes+' required', 'type':1}); + else + cb({'status':true, 'msg':'downloaded '+dest, 'type':1, 'infos':{'mime':response.headers['content-type'], 'size':response.headers['content-length'], 'ext':cfg.allowedMimes[response.headers['content-type']]}}); + } + else + cb({'status':true, 'msg':'downloaded '+dest, 'type':1, 'infos':{'mime':response.headers['content-type'], 'size':response.headers['content-length'], 'ext':cfg.allowedMimes[response.headers['content-type']]}}); + }); + }); + file.on('error', (err) => { + fs.unlink(dest+"."+cfg.allowedMimes[response.headers['content-type']]); + file.close(); + cb({'status':false, 'msg':err.message, 'type':1}); + }); + } + else + cb({'status':false, 'msg':'repost motherf0cker', 'type':1}); + }); + } + else + cb({'status':false, 'msg':'f0ck! your file is too big (~'+formatSize(response.headers['content-length'])+'), max '+formatSize(cfg.maxFileSize)+' allowed', 'type':1}); + } + else + cb({'status':false, 'msg':'f0ck you', 'type':2}); + }).on('error', (msg) => { + cb({'status':false, 'msg':msg, 'type':2}); + }); +}; +Lib.prototype.generateThumbs = () => { + var outdir = './t/'; + sql.query("select * from `f0ck`.`items`", (err, rows, fields) => { + rows.forEach((e,i,a) => { + var thumbnail = outdir+e.id+'.png'; + if(!fs.existsSync(thumbnail)) { + exec('ffmpegthumbnailer -i'+e.dest+' -s256 -o'+thumbnail, (error) => { + if(error) { + log('failed thumbnail for '+e.id+' ('+e.mime+') 1'); + fs.copySync('./s/mp3.png', thumbnail); // copy standardthumbnail + } + else { + exec('convert '+thumbnail+' -resize "128x128^" -gravity center -crop 128x128+0+0 +repage '+thumbnail, (error) => { + if(error) + log('failed thumbnail for '+e.id+' ('+e.mime+') 2'); + else + log("generated thumbnail for "+e.id+" ("+e.mime+")"); + }); + } + }); + } + }); + }); +}; +Lib.prototype.log = (msg) => { + if(debug) + bot.send("#f0ck", msg, 'n0xy'); +}; \ No newline at end of file diff --git a/src/main.js b/src/main.js index f1abb7f..3f17486 100644 --- a/src/main.js +++ b/src/main.js @@ -4,24 +4,24 @@ var http = require('http'); var https = require('https'); var mysql = require('mysql'); var bot = require('coffea')(); -var uuid = require('uuid'); var crypto = require('crypto'); var path = require('path'); var exec = require('child_process').exec; var probe = require('node-ffprobe'); +var Lib = require('./lib.js'); var swig = require('swig'); + var templates = {}; var debug = false; -var upload = true; -var admins = []; + var sql; var haDC = () => { sql = mysql.createConnection(cfg.mysql); sql.connect((err) => { - if(err) setTimeout(haDC,2000); + if(err) setTimeout(haDC, 2000); }); sql.on('error', (err) => { if(err.code === 'PROTOCOL_CONNECTION_LOST') haDC(); @@ -29,6 +29,8 @@ var haDC = () => { }; haDC(); +var lib = new Lib(bot, sql, cfg); + cfg.server.forEach((e,i,a) => { bot.add({ "name": e.name, @@ -44,254 +46,21 @@ cfg.server.forEach((e,i,a) => { console.log("Server "+e.name+" wurde geladen"); }); -var log = (msg) => { - if(debug) - bot.send("#f0ck", msg, 'n0xy'); -}; - bot.on('motd', (e) => { console.log("motd von "+e.network+" erhalten"); + bot.join("#kbot-dev"); // tmp bot.write('MODE f0ck +B', e.network, (c)=>{}); // Botflag }); bot.on('message', (e) => { var orig = e.message; - if(orig.match(/https?:\/\/[\w-]+(\.[\w-]+)+\.?(:\d+)?(\/\S*)?/gi) && e.channel.getName() == "#f0ck" && upload) { // shitpostcatcher - if(!orig.match(/\!ignore$/)) { - var tmp = orig.match(/https?:\/\/[\w-]+(\.[\w-]+)+\.?(:\d+)?(\/\S*)?/gi); // get links - tmp.forEach((entry,i,a) => { - var tmpdest = uuid.v1().split('-')[0]; - dl(entry, "./b/"+tmpdest, (cb) => { // download item - if(cb.status === true) { - getUser(e.user.getNick(), e.network, (cbgu) => { - getCheckSum("./b/"+tmpdest+"."+cb.infos.ext, (cbcs) => { - checkRepostCheckSum(cbcs, (cbcrcs) => { - if(cbcrcs) { - sql.query("insert into `f0ck`.`items` (`src`,`dest`,`mime`,`size`,`checksum`,`username`,`userchannel`,`usernetwork`,`stamp`,`active`) values (?,?,?,?,?,?,?,?,?,?)", [ - entry, - "./b/"+tmpdest+"."+cb.infos.ext, - cb.infos.mime, - cb.infos.size, - cbcs, - cbgu['nick'], - e.channel.getName(), - e.network, - Math.floor(new Date() / 1000), - 0 - ]).on('result', (result) => { - generateThumbs(); - e.reply("https://f0ck.me/"+result.insertId+" - "+path.parse(entry).base+" ("+cb.infos.mime+", ~"+formatSize(cb.infos.size)+") from "+cbgu['nick']+" ("+cbgu['username']+"@"+cbgu['hostname']+")"); - }).on('error', (msg) => { - e.reply(msg); - }); - } - else { - fs.unlink("./b/"+tmpdest+"."+cb.infos.ext); // delete repost - e.reply("repost motherf0cker"); - } - }); - }); - }); - } - else - if(cb.type == 1) - e.reply(cb.msg); - }); - }); + trigger.trigger.forEach((entry,i,a) => { + if(orig.match(new RegExp(entry.call, "gi"))) { + entry.func(e); } - } - else if(orig.match(/^\.user/)) { // (debug) get userinfos - getUser(e.user.getNick(), e.network, (cbgu) => { - e.reply(cbgu); - }); - } - else if(orig.match(/^\!reload tpl$/)) { - getTpls(); - e.reply("templates reloaded"); - } - else if(orig.match(/^\!toggle debug$/)) { - if(debug) { - debug = false; - e.reply("debugmessages deactivated"); - } - else { - debug = true; - e.reply("debugmessages activated"); - } - } - else if(orig.match(/^\!toggle catcher$/)) { - if(upload) { - upload = false; - e.reply("catcher deactivated"); - } - else { - upload = true; - e.reply("catcher activated"); - } - } - else if(orig.match(/^\!load user$/)) { - loadUser((cb) => { - //e.reply(admins); - }); - } - else if(orig.match(/^\!level$/)) { - var tmp_channel = bot.getChannel(e.channel.getName(), e.network).names; - getUserlevel(e, tmp_channel, (cb) => { - e.reply("level from "+e.user.getNick()+": "+cb.level+" (Channel: "+cb.channel+" DB: "+cb.db+")"); - }); - } - else if(orig.match(/^\!del (\d+)$/i)) { - var tmp_channel = bot.getChannel(e.channel.getName(), e.network).names; - getUserlevel(e, tmp_channel, (cb) => { - if(cb.level >= 100) { - var id = orig.split(' ')[1]; - sql.query("delete from `f0ck`.`items` where `id` = ?", id).on('end', () => { - e.reply("f0ck "+id+" deleted"); - }); - } - else - e.reply("no permission"); - }); - } - else if(orig.match(/^\!thumbs$/i)) { - var tmp_channel = bot.getChannel(e.channel.getName(), e.network).names; - getUserlevel(e, tmp_channel, (cb) => { - if(cb.level >= 100) { - //exec('rm ./t/*.png', (error) => { - e.reply("generating Thumbnails..."); - generateThumbs(); - //}); - } - else - e.reply("no permission"); - }); - } + }); }); -var getUser = (u, n, cbgu) => { - bot.write('WHOIS '+u, n, () => { - bot.once('data', (err, msg) => { - var params; - var map = []; - map.push(u); - if(msg.command == 'RPL_WHOISUSER') { - params = msg.params.split(' '); - map[u] = map[u] || {}; - map[u].nick = u; - map[u].username = params[2]; - map[u].hostname = params[3]; - map[u].realname = msg.trailing; - } - if(typeof(map[u]) === 'object') - cbgu(map[u]); - }); - }); -}; - -var getUserlevel = (e, tmp_channel, cb) => { - getUser(e.user.getNick(), e.network, (cbgu) => { - var host = cbgu.username+'@'+cbgu.hostname; - var lvl_channel = (cbgu.nick in tmp_channel)? cfg.level[ tmp_channel[cbgu.nick] ] : 0; - var lvl_db = 0; - if(host in admins) - lvl_db = (admins[host].server == e.network)? admins[host].level : 0; - cb({ - 'channel': lvl_channel, - 'db': lvl_db, - 'level': Math.max(lvl_channel, lvl_db) - }); - }); -}; - -var loadUser = (cb) => { - admins = []; - sql.query("select * from `f0ck`.`user`", (err, rows, fields) => { - rows.forEach((e,i,a) => { - admins.push(e.nick); - admins[e.vhost] = { - 'id': e.id, - 'nick': e.nick, - 'vhost': e.vhost, - 'level': e.level, - 'server': e.server - }; - }); - cb(true); - }).on('error', () => { - cb(false); - });; -}; - -var dl = (url, dest, cb) => { - var request = (url.match(/^https/)?https:http).get(url, (response) => { // type:1=post,type:2=stfu - console.log(response.headers['content-type']); - if(cfg.allowedMimes.hasOwnProperty(response.headers['content-type'])) { - if(response.headers['content-length'] <= cfg.maxFileSize) { - checkRepost(url, (cbcr) => { - if(cbcr) { - var file = fs.createWriteStream(dest+"."+cfg.allowedMimes[response.headers['content-type']]); - response.pipe(file); - file.on('finish', () => { - file.close(); - probe(dest+"."+cfg.allowedMimes[response.headers['content-type']], (err, probeData) => { - if(probeData.streams[0].height !== undefined || probeData.streams[0].width !== undefined) { - if(probeData.streams[0].height <= cfg.minRes || probeData.streams[0].width <= cfg.minRes) - cb({'status':false, 'msg':'f0ck! your shitpost is too small ('+probeData.streams[0].width+' x '+probeData.streams[0].height+'), min '+cfg.minRes+' x '+cfg.minRes+' required', 'type':1}); - else - cb({'status':true, 'msg':'downloaded '+dest, 'type':1, 'infos':{'mime':response.headers['content-type'], 'size':response.headers['content-length'], 'ext':cfg.allowedMimes[response.headers['content-type']]}}); - } - else - cb({'status':true, 'msg':'downloaded '+dest, 'type':1, 'infos':{'mime':response.headers['content-type'], 'size':response.headers['content-length'], 'ext':cfg.allowedMimes[response.headers['content-type']]}}); - }); - }); - file.on('error', (err) => { - fs.unlink(dest+"."+cfg.allowedMimes[response.headers['content-type']]); - file.close(); - cb({'status':false, 'msg':err.message, 'type':1}); - }); - } - else - cb({'status':false, 'msg':'repost motherf0cker', 'type':1}); - }); - } - else - cb({'status':false, 'msg':'f0ck! your file is too big (~'+formatSize(response.headers['content-length'])+'), max '+formatSize(cfg.maxFileSize)+' allowed', 'type':1}); - } - else - cb({'status':false, 'msg':'f0ck you', 'type':2}); - }).on('error', (msg) => { - cb({'status':false, 'msg':msg, 'type':2}); - }); -}; - -var checkRepost = (url, cbcr) => { - sql.query("select count(*) as count from `f0ck`.`items` where `src` = ?", url, (err, rows, fields) => { - cbcr((rows[0].count == 0)?true:false); - }); -}; -var checkRepostCheckSum = (cs, cbcrcs) => { - sql.query("select count(*) as count from `f0ck`.`items` where `checksum` = ?", cs, (err, rows, fields) => { - cbcrcs((rows[0].count == 0)?true:false); - }); -}; - -var formatSize = (size) => { - var i = Math.floor(Math.log(size) / Math.log(1024)); - return (size / Math.pow(1024, i)).toFixed(2) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i]; -}; - -var getCheckSum = (file, cbcs) => { - var sha256sum = crypto.createHash('sha256'); - var s = fs.ReadStream(file); - s.on('data', (d) => { - sha256sum.update(d); - }); - s.on('end', () => { - cbcs(sha256sum.digest('hex')); - }); -}; - - // Webserver http.createServer((req, res) => { if(cfg.wlip.hasOwnProperty(req.connection.remoteAddress)) { @@ -488,36 +257,34 @@ var getTpls = () => { }; }; -var generateThumbs = () => { - var outdir = './t/'; - sql.query("select * from `f0ck`.`items`", (err, rows, fields) => { - rows.forEach((e,i,a) => { - var thumbnail = outdir+e.id+'.png'; - if(!fs.existsSync(thumbnail)) { - exec('ffmpegthumbnailer -i'+e.dest+' -s256 -o'+thumbnail, (error) => { - if(error) { - log('failed thumbnail for '+e.id+' ('+e.mime+') 1'); - //fs.unlink(thumbnail); - fs.copySync('./s/mp3.png', thumbnail); // copy standardthumbnail - } - else { - exec('convert '+thumbnail+' -resize "128x128^" -gravity center -crop 128x128+0+0 +repage '+thumbnail, (error) => { - if(error) { - log('failed thumbnail for '+e.id+' ('+e.mime+') 2'); - //fs.unlink(thumbnail); - } - else { - log("generated thumbnail for "+e.id+" ("+e.mime+")"); - } - }); - } - }); - } - }); - }); -}; - -loadUser((cb)=>{ +lib.loadUser((cb)=>{ console.log((cb)?"Admins wurden geladen":"Admins konnten nicht geladen werden"); }); -getTpls(); \ No newline at end of file +getTpls(); + +var trigger = { + trigger: [], + add: (args) => { + trigger.trigger.push({ + call: args.call, + func: args.func, + desc: args.desc, + level: args.level + }); + } +}; + +var loadPlugins = function() { + var files = fs.readdirSync(__dirname+'/trigger/'); + files.forEach(function (file) { + if(file.substr(-3, 3) === '.js') { + console.log('Loading plugin', file); + require(__dirname+'/trigger/' + file)(bot, trigger, lib); + } + }); +}; +var use = function(fn) { + fn(this); + return this; +}; +loadPlugins(); \ No newline at end of file diff --git a/src/trigger/del.js b/src/trigger/del.js index c6dfdc6..86406a7 100644 --- a/src/trigger/del.js +++ b/src/trigger/del.js @@ -1,22 +1,21 @@ -module.exports = (bot) => { - var del = (e, args) => { - var tmp_channel = bot.getChannel(e.channel.getName(), e.network).names; - getUserlevel(e, e.user.getNick(), tmp_channel, (cb) => { - if(cb.level >= 100) { - var id = orig.split(' ')[1]; - sql.query("delete from `f0ck`.`items` where `id` = ?", id).on('end', () => { - e.reply("f0ck "+id+" deleted"); - }); - } - else - e.reply("no permission"); - }); - }; - - bot.addCmd({ - name: 'spec', +module.exports = (bot, trigger, lib) => { + trigger.add({ + name: 'delete', + call: '^\!del (\d+)$', level: 100, - func: spec, - desc: 'delete f0rk' + func: (e) => { + var tmp_channel = bot.getChannel(e.channel.getName(), e.network).names; + lib.getUserlevel(e, e.user.getNick(), tmp_channel, (cb) => { + if(cb.level >= 100) { + var id = orig.split(' ')[1]; + sql.query("delete from `f0ck`.`items` where `id` = ?", id).on('end', () => { + e.reply("f0ck "+id+" deleted"); + }); + } + else + e.reply("no permission"); + }); + }, + desc: 'delete f0ck' }); }; \ No newline at end of file diff --git a/src/trigger/level.js b/src/trigger/level.js new file mode 100644 index 0000000..af573ce --- /dev/null +++ b/src/trigger/level.js @@ -0,0 +1,14 @@ +module.exports = (bot, trigger, lib) => { + trigger.add({ + name: 'level', + call: '^\!level$', + level: 0, + func: (e) => { + var tmp_channel = bot.getChannel(e.channel.getName(), e.network).names; + lib.getUserlevel(e, tmp_channel, (cb) => { + e.reply("level from "+e.user.getNick()+": "+cb.level+" (Channel: "+cb.channel+" DB: "+cb.db+")"); + }); + }, + desc: 'get Userlevel' + }); +}; \ No newline at end of file diff --git a/src/trigger/parser.js b/src/trigger/parser.js new file mode 100644 index 0000000..3ff8cd9 --- /dev/null +++ b/src/trigger/parser.js @@ -0,0 +1,55 @@ +var fs = require('fs-extra'); +var uuid = require('uuid'); + +module.exports = (bot, trigger, lib) => { + trigger.add({ + name: 'parser', + call: 'https?:\/\/[\w-]+(\.[\w-]+)+\.?(:\d+)?(\/\S*)?', + level: 0, + func: (e) => { + if(!e.message.match(/\!ignore$/)) { + var tmp = e.message.match(/https?:\/\/[\w-]+(\.[\w-]+)+\.?(:\d+)?(\/\S*)?/gi); // get links + tmp.forEach((entry,i,a) => { + var tmpdest = uuid.v1().split('-')[0]; + lib.dl(entry, "./b/"+tmpdest, (cb) => { // download item + if(cb.status === true) { + lib.getUser(e.user.getNick(), e.network, (cbgu) => { + lib.getCheckSum("./b/"+tmpdest+"."+cb.infos.ext, (cbcs) => { + lib.checkRepostCheckSum(cbcs, (cbcrcs) => { + if(cbcrcs) { + lib.sql.query("insert into `f0ck`.`items` (`src`,`dest`,`mime`,`size`,`checksum`,`username`,`userchannel`,`usernetwork`,`stamp`,`active`) values (?,?,?,?,?,?,?,?,?,?)", [ + entry, + "./b/"+tmpdest+"."+cb.infos.ext, + cb.infos.mime, + cb.infos.size, + cbcs, + cbgu['nick'], + e.channel.getName(), + e.network, + Math.floor(new Date() / 1000), + 0 + ]).on('result', (result) => { + generateThumbs(); + e.reply("https://f0ck.me/"+result.insertId+" - "+path.parse(entry).base+" ("+cb.infos.mime+", ~"+formatSize(cb.infos.size)+") from "+cbgu['nick']+" ("+cbgu['username']+"@"+cbgu['hostname']+")"); + }).on('error', (msg) => { + e.reply(msg); + }); + } + else { + fs.unlink("./b/"+tmpdest+"."+cb.infos.ext); // delete repost + e.reply("repost motherf0cker"); + } + }); + }); + }); + } + else + if(cb.type == 1) + e.reply(cb.msg); + }); + }); + } + }, + desc: 'muh' + }); +}; \ No newline at end of file