From d83a1fb2b94cb1dabc6132a0e42ae211087d847e Mon Sep 17 00:00:00 2001 From: lilyissillyyy Date: Tue, 17 Feb 2026 17:38:40 -0500 Subject: [PATCH] Remove NSFWJS --- README.md | 4 +-- Xiao.js | 8 ------ assets/json/xiao-fact.json | 1 - commands/analyze/nsfw-image.js | 45 ---------------------------------- commands/analyze/screenshot.js | 4 --- commands/search/wikipedia.js | 7 +----- package.json | 3 +-- structures/Tensorflow.js | 24 ------------------ 8 files changed, 3 insertions(+), 93 deletions(-) delete mode 100644 commands/analyze/nsfw-image.js diff --git a/README.md b/README.md index d1bb14b9..11bdb884 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,7 @@ Only if you want to use the DECTalk command. 18. Start Xiao up! ## Commands -Total: 516 +Total: 515 ### Utility: @@ -327,7 +327,6 @@ Total: 516 * **is-it-down:** Determines if a website is down or not. * **levenshtein:** Determines the levenshtein distance between two strings. * **name-gender:** Determines the gender of a name. -* **nsfw-image:** Determines if an image is NSFW. * **nsfw-url:** Determines if a URL is NSFW. * **parse-time:** Analyzes the time duration you provide and gives the result. * **read-qr-code:** Reads a QR Code. @@ -728,7 +727,6 @@ Total: 516 * [moment-timezone](https://www.npmjs.com/package/moment-timezone) * [neopet-image-finder](https://www.npmjs.com/package/neopet-image-finder) * [node-superfetch](https://www.npmjs.com/package/node-superfetch) -* [nsfwjs](https://www.npmjs.com/package/nsfwjs) * [ntcjs](https://www.npmjs.com/package/ntcjs) * [parse-domain](https://www.npmjs.com/package/parse-domain) * [pokersolver](https://www.npmjs.com/package/pokersolver) diff --git a/Xiao.js b/Xiao.js index abd79d43..e324766b 100644 --- a/Xiao.js +++ b/Xiao.js @@ -256,14 +256,6 @@ client.on('clientReady', async () => { client.logger.error(`[ADULT SITES] Failed to fetch list\n${err.stack}`); } - // Set up nsfwjs - try { - await client.tensorflow.loadNSFWJS(); - client.logger.info('[NSFWJS] Loaded NSFWJS.'); - } catch (err) { - client.logger.error(`[NSFWJS] Failed to load NSFWJS\n${err.stack}`); - } - // Set up face detection try { await client.tensorflow.loadFaceDetector(); diff --git a/assets/json/xiao-fact.json b/assets/json/xiao-fact.json index 0bb429ea..f47263df 100644 --- a/assets/json/xiao-fact.json +++ b/assets/json/xiao-fact.json @@ -44,7 +44,6 @@ "The `horse-race` command contains several references: real horse names, My Little Pony characters, and various pop culture jokes. Even a few Xiao jokes are snuck in there!", "In `horse-race`, you will occasionally encounter horses named \"Donald Trump\" and \"Lily is Silly\". Be careful, as these aren't horses, their times are based on the actual human running the race!", "Numerous commands use a massive 2,000,000 entry array to check for adult sites. Some _still_ fall through the cracks.", - "Numerous commands use an AI powered by Tensorflow to check for NSFW content. It is about 93% accurate.", "The `ship` command will call you a narcissist if you test yourself with yourself.", "Whenever Lily gets a real fortune cookie, she adds the fortune to the `fortune` command.", "The `whos-that-pokemon` command will play a sound effect and the Pokémon's cry if both you and the bot are in a voice channel when the command is used.", diff --git a/commands/analyze/nsfw-image.js b/commands/analyze/nsfw-image.js deleted file mode 100644 index b2900f24..00000000 --- a/commands/analyze/nsfw-image.js +++ /dev/null @@ -1,45 +0,0 @@ -const Command = require('../../framework/Command'); -const request = require('node-superfetch'); -const { stripIndents } = require('common-tags'); -const displayNames = { - Drawing: 'SFW (Drawing)', - Neutral: 'SFW', - Porn: 'NSFW', - Hentai: 'NSFW (Drawing)', - Sexy: 'Suggestive' -}; - -module.exports = class NsfwImageCommand extends Command { - constructor(client) { - super(client, { - name: 'nsfw-image', - aliases: ['nsfw', 'nsfw-img', 'img-nsfw', 'image-nsfw'], - group: 'analyze', - description: 'Determines if an image is NSFW.', - throttling: { - usages: 2, - duration: 30 - }, - args: [ - { - key: 'image', - type: 'image-or-avatar', - avatarSize: 256 - } - ] - }); - } - - async run(msg, { image }) { - const { body } = await request.get(image); - const predictions = await this.client.tensorflow.isImageNSFW(body, false); - const formatted = predictions.map(result => { - const percentage = Math.round(result.probability * 100); - return `${percentage}% ${displayNames[result.className]}`; - }); - return msg.reply(stripIndents` - **This image gives the following results:** - ${formatted.join('\n')} - `); - } -}; diff --git a/commands/analyze/screenshot.js b/commands/analyze/screenshot.js index 2a4655fb..06888ea2 100644 --- a/commands/analyze/screenshot.js +++ b/commands/analyze/screenshot.js @@ -39,10 +39,6 @@ module.exports = class ScreenshotCommand extends Command { if (nsfw) return msg.reply('This site is NSFW.'); } const { body } = await request.get(`https://image.thum.io/get/width/1920/crop/675/noanimate/${url.href}`); - if (!msg.channel.nsfw) { - const aiDetect = await this.client.tensorflow.isImageNSFW(body); - if (aiDetect) return msg.reply('This site isn\'t NSFW, but the resulting image was.'); - } return msg.say({ files: [{ attachment: body, name: 'screenshot.png' }] }); } catch (err) { if (err.status === 404) return msg.say('Could not find any results. Invalid URL?'); diff --git a/commands/search/wikipedia.js b/commands/search/wikipedia.js index 00fa3365..957f4361 100644 --- a/commands/search/wikipedia.js +++ b/commands/search/wikipedia.js @@ -46,12 +46,7 @@ module.exports = class WikipediaCommand extends Command { }); const data = body.query.pages[0]; if (data.missing) return msg.say('Could not find any results.'); - let thumbnail = data.thumbnail ? data.thumbnail.source : null; - if (!msg.channel.nsfw && thumbnail) { - const img = await request.get(thumbnail); - const nsfw = await this.client.tensorflow.isImageNSFW(img.body); - if (nsfw) thumbnail = null; - } + const thumbnail = data.thumbnail ? data.thumbnail.source : null; let fact = data.extract; if (fact.length > 200) { const facts = fact.split('.'); diff --git a/package.json b/package.json index 0391f6f5..ad3bd83b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "xiao", - "version": "159.4.3", + "version": "160.0.0", "description": "Your personal server companion.", "main": "Xiao.js", "scripts": { @@ -67,7 +67,6 @@ "moment-timezone": "^0.6.0", "neopet-image-finder": "^5.0.3", "node-superfetch": "^0.3.5", - "nsfwjs": "^4.2.1", "ntcjs": "^1.1.3", "parse-domain": "^8.2.2", "pokersolver": "^2.1.4", diff --git a/structures/Tensorflow.js b/structures/Tensorflow.js index 1c7acc25..598c2af3 100644 --- a/structures/Tensorflow.js +++ b/structures/Tensorflow.js @@ -1,5 +1,4 @@ const tf = require('@tensorflow/tfjs-node'); -const nsfw = require('nsfwjs'); const faceDetection = require('@tensorflow-models/face-detection'); const faceModel = faceDetection.SupportedModels.MediaPipeFaceDetector; const path = require('path'); @@ -9,18 +8,11 @@ module.exports = class Tensorflow { constructor(client) { Object.defineProperty(this, 'client', { value: client }); - this.nsfwjs = null; this.faceDetector = null; this.styleModel = null; this.transformerModel = null; } - async loadNSFWJS() { - const nsfwjs = await nsfw.load('MobileNetV2'); - this.nsfwjs = nsfwjs; - return this.nsfwjs; - } - async loadFaceDetector() { const faceDetector = await faceDetection.createDetector(faceModel, { runtime: 'tfjs', maxFaces: 10 }); this.faceDetector = faceDetector; @@ -55,22 +47,6 @@ module.exports = class Tensorflow { return faces; } - async isImageNSFW(image, bool = true) { - const img = await tf.node.decodeImage(image, 3); - const predictions = await this.nsfwjs.classify(img); - img.dispose(); - if (bool) { - const results = []; - results.push(predictions[0]); - for (const result of predictions) { - if (result.className === predictions[0].className) continue; - if (result.probability >= predictions[0].probability - 0.1) results.push(result); - } - return results.some(result => result.className !== 'Drawing' && result.className !== 'Neutral'); - } - return predictions; - } - async stylizeImage(image, styleImg) { const imageTensor = await tf.node.decodeImage(image, 3); const [originalHeight, originalWidth] = imageTensor.shape.slice(0, 2);