const Discord = require("discord.js"); const fs = require('fs'); const request = require('request'); const rp = require('request-promise-native'); const sqlite = require('sqlite3'); const crypto = require('crypto'); class Lewd { constructor() { this.matches = [ "tits", "ass", "booty", "thicc", "2d", "furry", "sexy", "reddimg", "dick", "cock", "penis", "milf", "fuck", "sex", "degenerate", "milkers", "goth", "btgg" ]; try { this.db = new sqlite.Database('./db/pr0n.db'); this.db.run('CREATE TABLE IF NOT EXISTS pr0n(id PRIMARY KEY, url, subreddit, author, title, reddit_ratio, discord_ratio, post_id, channel_id, guild_id)'); this.db.close(); } catch (e) { console.log('Failed to open SQlite db for Lewd module! Data logging will not function.'); } this.setReactionCollectors(); } async setReactionCollectors() { try { const db = new sqlite.Database('./db/pr0n.db'); const results = db.all('SELECT post_id, channel_id, guild_id FROM pr0n', [], (err, rows) => { if (err) { throw err; } rows.forEach((r) => { console.log(r.post_id); }); }); db.close(); } catch (e) { console.log('Failed to open SQlite db for Lewd module! Data logging will not function.'); db.close(); } } async fixOldEntries() { try { const db = new sqlite.Database('./db/pr0n.db'); const results = db.all('SELECT id, post_id, channel_id, guild_id, discord_ratio FROM pr0n WHERE discord_ratio=0.0', [], (err, rows) => { if (err) { throw err; } rows.forEach((r) => { console.log(r); }); }); db.close(); } catch (e) { console.log('Failed to open SQlite db for Lewd module! Data logging will not function.'); db.close(); } } async loadSubreddit(name, desired_entries=400) { let entries = 0; let entryData = []; let subredditData = await rp(`https://www.reddit.com/r/${name}/new/.json?limit=100`); // access if cached try { let stats = fs.statSync(`cache/${name}.txt`); let time_diff = (new Date().getTime() - new Date(stats.mtime).getTime()) / 1000; if (time_diff > 21600) { throw new Error('Need to update cache!'); } let entryText = fs.readFileSync(`cache/${name}.txt`); entryData = JSON.parse(entryText); console.log(`Loading cached data for ${name}`); return entryData; } catch (e) { console.log(`${name} not cached...`); } try { let sJson = JSON.parse(subredditData); entryData = entryData.concat(sJson.data.children); entries += sJson.data.children.length; while (entries <= desired_entries) { let after_tag = sJson.data.after; subredditData = await rp(`https://www.reddit.com/r/${name}/new/.json?limit=100&after=${after_tag}`); sJson = JSON.parse(subredditData); entryData = entryData.concat(sJson.data.children); entries += sJson.data.children.length; } console.log(`Writing ${name} data to cache...`); fs.writeFileSync(`cache/${name}.txt`, JSON.stringify(entryData)); return entryData; } catch (e) { console.log("Invalid JSON!"); return ""; } } async getRandomEntry(subreddit) { let srData = await this.loadSubreddit(subreddit); let count = srData.length; console.log(`Got ${count} items`); for(let i = 0; i < 10; i++) { let selection = Math.floor(Math.random() * count); let url = srData[selection].data.url; let selectionData = srData[selection].data; let infoBundle = { url: selectionData.url, subreddit: selectionData.subreddit, author: selectionData.author, title: selectionData.title, upvote_ratio: selectionData.upvote_ratio }; if(url.endsWith('.jpg') || url.endsWith('.gif') || url.endsWith('.png') || url.endsWith('.jpeg') || url.includes('gfycat.com') ) { //return url.toString(); console.log(infoBundle); return infoBundle; } } return -1; } async getRandomRedditImg(sub) { let rEmbed = new Discord.MessageEmbed(); let img = await this.getRandomEntry(sub); console.log(img.url); if(img.url.includes('gfycat.com')) { return img.url; } else { rEmbed.setImage(img.url); } return rEmbed; } async sendAndLog(chan, sub) { const db = new sqlite.Database('./db/pr0n.db'); const shasum = crypto.createHash('sha256'); let rEmbed = new Discord.MessageEmbed(); let imgInfo = await this.getRandomEntry(sub); shasum.update(imgInfo.url); const shaHash = shasum.digest('hex').slice(0,9); if(imgInfo.url.includes('gfycat.com')) { rEmbed = imgInfo.url; } else { rEmbed.setImage(imgInfo.url); } const sentMsg = await chan.send(rEmbed); await sentMsg.react('\uD83D\uDC4D'); await sentMsg.react('\uD83D\uDC4E'); try { db.run('INSERT INTO pr0n(id, url, subreddit, author, title, reddit_ratio, discord_ratio, post_id, channel_id, guild_id) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', [ shaHash, imgInfo.url, imgInfo.subreddit, imgInfo.author, imgInfo.title, imgInfo.upvote_ratio, '0.0', sentMsg.id, sentMsg.channel.id, sentMsg.guild.id ]); } catch (e) { console.log(e); } db.close(); } async updateRating(messageID, new_ratio) { const db = new sqlite.Database('./db/pr0n.db'); try { db.run('UPDATE pr0n SET discord_ratio = ? WHERE post_id = ?', [ new_ratio, messageID ]); } catch (e) { console.log(e); } db.close(); } async action(msg) { let chan = msg.channel; if(msg.content.startsWith('!tits')) { await sendAndLog(chan,'homegrowntits+BigBoobsGW+Boobies+hugehangers+biggerthanyouthought+udders+tittydrop'); } else if (msg.content.startsWith('!booty') || msg.content.startsWith('!ass')) { await this.sendAndLog(chan,'bigasses+pawg+slightcellulite'); } else if (msg.content.startsWith('!thicc')) { await this.sendAndLog(chan,'thickthighs+voluptuous+breedingmaterial+thickchixx+plumper+gonewildplus+thickchixxx+bbw_chubby'); } else if (msg.content.startsWith('!2d')) { await this.sendAndLog(chan,'hentai+rule34'); } else if (msg.content.startsWith('!furry')) { await this.sendAndLog(chan,'furry+yiff'); } else if (msg.content.startsWith('!sexy')) { await this.sendAndLog(chan,'lingerie+gonemild'); } else if (msg.content.startsWith('!reddimg')) { let contentArr = msg.content.split(" "); if(contentArr.length < 2) return; await this.sendAndLog(chan,contentArr[1]); } else if (msg.content.startsWith('!dick') || msg.content.startsWith('!cock') || msg.content.startsWith('!penis')) { await this.sendAndLog(chan,'penis+massivecock+ratemycock+sizecomparison+averagepenis+naturalpenis+smallpenis'); } else if (msg.content.startsWith('!milf')) { await this.sendAndLog(chan,'milf+wifesharing+gonewild30plus+milfie'); } else if (msg.content.startsWith('!fuck') || msg.content.startsWith('!sex')) { await this.sendAndLog(chan,'gonewildcouples+nsfw_gif+besthqporngifs+60fpsporn+girlsfinishingthejob+lipsthatgrip+amateurgirlsbigcocks+shelikesitrough'); } else if (msg.content.startsWith('!degenerate')) { await this.sendAndLog(chan,'yiff+cuckold+hotwife+bondage+bdsm+bdsmgw+forcedorgasms+rule34+furry+dominated+teenbdsm+bondageblowjobs+fetish+cumsluts+vore'); } else if (msg.content.startsWith('!milkers')) { await this.sendAndLog(chan,'udders+hugehangers+bigboobsgw+hugeboobs+hugetits+hugeboobgifs'); } else if (msg.content.startsWith('!goth')) { await this.sendAndLog(chan,'gothsluts+bigtiddygothgf+snowwhites+altgonewild'); } else if (msg.content.startsWith('!btgg')) { await this.sendAndLog(chan, 'bigtiddygothgf'); } } async react(reaction, user) { console.log("***REACTION CAUGHT***"); const emojis = reaction.message.reactions.cache; //console.log(emojis); if(!emojis.has('\uD83D\uDC4D') || !emojis.has('\uD83D\uDC4E')) { return; } const upCount = emojis.get('\uD83D\uDC4D').count; const downCount = emojis.get('\uD83D\uDC4E').count; console.log("Message ID" + reaction.message.id); console.log("Upvotes: " + upCount); console.log("Downvotes: " + downCount); if (upCount+downCount > 2) { await this.updateRating(reaction.message.id, upCount/(upCount+downCount)); } } } module.exports = Lewd;