182 lines
6.7 KiB
TypeScript
182 lines
6.7 KiB
TypeScript
|
import {
|
||
|
MatrixClient,
|
||
|
SimpleFsStorageProvider,
|
||
|
AutojoinRoomsMixin,
|
||
|
} from "matrix-bot-sdk";
|
||
|
|
||
|
const http = require("http");
|
||
|
|
||
|
// probably the worst code you have seen in your life
|
||
|
|
||
|
const bannedKeywords = [
|
||
|
['Sus', 'thigh high'],
|
||
|
['Amogus!!', 'amogus', 'among us'],
|
||
|
|
||
|
['LGBTQQIAAP++ propaganda',
|
||
|
|
||
|
'transgender', 'trans rights',
|
||
|
|
||
|
[
|
||
|
'thigh', 'sock', 'computer'
|
||
|
],
|
||
|
|
||
|
'transhumanist evolution', 'pride parade', 'pride flag', 'gay pride'
|
||
|
|
||
|
],
|
||
|
|
||
|
['Chinese cartoons', 'anime', 'manga', 'loli', 'azur lane', 'mihoyo', 'kancolle', 'neko', 'touhou', 'foxgirl', 'wolf girl', 'ayanamikodon', 'hatsune miku', 'vocaloid', 'mikudayo', 'kyoto animation'],
|
||
|
|
||
|
['Furries', 'fursona', 'fursuit', 'e621', 'furry fandom', 'furry art'],
|
||
|
|
||
|
['Gore', ' gore ', ' guro ', ' gory '],
|
||
|
];
|
||
|
|
||
|
// This will be the URL where clients can reach your homeserver. Note that this might be different
|
||
|
// from where the web/chat interface is hosted. The server must support password registration without
|
||
|
// captcha or terms of service (public servers typically won't work).
|
||
|
const homeserverUrl = "https://trygve.me";
|
||
|
|
||
|
// Use the access token you got from login or registration above.
|
||
|
const accessToken = "your token";
|
||
|
|
||
|
// In order to make sure the bot doesn't lose its state between restarts, we'll give it a place to cache
|
||
|
// any information it needs to. You can implement your own storage provider if you like, but a JSON file
|
||
|
// will work fine for this example.
|
||
|
const storage = new SimpleFsStorageProvider("hello-bot.json");
|
||
|
|
||
|
// Finally, let's create the client and set it to autojoin rooms. Autojoining is typical of bots to ensure
|
||
|
// they can be easily added to any room.
|
||
|
const client = new MatrixClient(homeserverUrl, accessToken, storage);
|
||
|
AutojoinRoomsMixin.setupOnClient(client);
|
||
|
|
||
|
// Before we start the bot, register our command handler
|
||
|
client.on("room.event", handleCommand);
|
||
|
|
||
|
// Now that everything is set up, start the bot. This will start the sync loop and run until killed.
|
||
|
client.start().then(() => console.log("Bot started!"));
|
||
|
|
||
|
// This is the command handler we registered a few lines up
|
||
|
async function handleCommand(roomId: string, event: any) {
|
||
|
let expression = '';
|
||
|
let image_url = '';
|
||
|
if (
|
||
|
event['content']?.['msgtype'] == 'm.image'
|
||
|
) {
|
||
|
image_url = homeserverUrl + "/_matrix/media/r0/download/" + (event['content']?.['url']).slice(6);
|
||
|
expression = 'image';
|
||
|
}
|
||
|
if (
|
||
|
event["content"]["avatar_url"]
|
||
|
) {
|
||
|
image_url = homeserverUrl + "/_matrix/media/r0/download/" + (event['content']?.['avatar_url']).slice(6);
|
||
|
expression = 'pfp';
|
||
|
}
|
||
|
|
||
|
if (event['sender'] === await client.getUserId()) return;
|
||
|
if (image_url == '') return;
|
||
|
|
||
|
console.log('New image received, analyzing...');
|
||
|
analyze_image(image_url, function(degenerate, degenerateKeywords, fullDegenerateKeywords, response) {
|
||
|
if (degenerate) {
|
||
|
console.log('====Degeneracy Detected!====');
|
||
|
console.log('User: ' + event['sender'] + ' sent image with url: ' + image_url);
|
||
|
console.log("Full keywords: " + fullDegenerateKeywords);
|
||
|
console.log("Sent keywords: " + degenerateKeywords);
|
||
|
console.log(response);
|
||
|
console.log('https://matrix.to/#/' + roomId + '/' + event['event_id'] + '?via=willy.club&via=trygve.me&via=matrix.org');
|
||
|
console.log('============================');
|
||
|
// determine what type of event it was
|
||
|
if (expression == 'image') {
|
||
|
client.redactEvent(roomId, event['event_id']);
|
||
|
client.sendText(roomId, 'Woah! Please refrain from posting images containing: "' + degenerateKeywords + '".');
|
||
|
} else {
|
||
|
client.kickUser(event['sender'], roomId, 'Please change your profile picture');
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
console.log('=======Nothing found========');
|
||
|
console.log('User: ' + event['sender'] + ' sent image with url: ' + image_url);
|
||
|
console.log(response);
|
||
|
console.log('https://matrix.to/#/' + roomId + '/' + event['event_id'] + '?via=willy.club&via=trygve.me&via=matrix.org');
|
||
|
console.log('============================');
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function analyze_image(image_url, callback) {
|
||
|
http.get(`http://localhost:5000/?image_url=` + image_url, resp => {
|
||
|
let data = "";
|
||
|
|
||
|
// A chunk of data has been recieved.
|
||
|
resp.on("data", chunk => {
|
||
|
data += chunk;
|
||
|
});
|
||
|
|
||
|
// The whole response has been received. Print out the result.
|
||
|
resp.on("end", () => {
|
||
|
let response = JSON.parse(data).message;
|
||
|
let responseWithoutComma = response.replace(',', ' ');
|
||
|
|
||
|
let degenerate = false;
|
||
|
let degenerateKeywords = '';
|
||
|
let fullDegenerateKeywords = '';
|
||
|
bannedKeywords.forEach(keyword => {
|
||
|
if (Array.isArray(keyword)) {
|
||
|
let alreadyAddedKeywordForThisGroup = false;
|
||
|
let skippedFirstIterationBecauseItsTheTitle = false;
|
||
|
keyword.forEach(subKeyword => {
|
||
|
if (!skippedFirstIterationBecauseItsTheTitle) {
|
||
|
skippedFirstIterationBecauseItsTheTitle = true;
|
||
|
return;
|
||
|
}
|
||
|
if (Array.isArray(subKeyword)) {
|
||
|
let allOfThemMatch = true;
|
||
|
subKeyword.forEach(subsubKeyword => {
|
||
|
if(responseWithoutComma.includes(subsubKeyword)) {
|
||
|
fullDegenerateKeywords += subsubKeyword + ',';
|
||
|
} else {
|
||
|
allOfThemMatch = false;
|
||
|
}
|
||
|
});
|
||
|
if (allOfThemMatch) {
|
||
|
degenerate = true;
|
||
|
if (!alreadyAddedKeywordForThisGroup) {
|
||
|
degenerateKeywords += keyword[0] + ',';
|
||
|
alreadyAddedKeywordForThisGroup = true;
|
||
|
}
|
||
|
}
|
||
|
} else if (responseWithoutComma.includes(subKeyword)) {
|
||
|
degenerate = true;
|
||
|
if (!alreadyAddedKeywordForThisGroup) {
|
||
|
degenerateKeywords += keyword[0] + ',';
|
||
|
fullDegenerateKeywords += subKeyword + ',';
|
||
|
alreadyAddedKeywordForThisGroup = true;
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
} else if (responseWithoutComma.includes(keyword)) {
|
||
|
degenerate = true;
|
||
|
degenerateKeywords += keyword + ',';
|
||
|
fullDegenerateKeywords += keyword + ',';
|
||
|
}
|
||
|
});
|
||
|
|
||
|
degenerateKeywords = degenerateKeywords.substr(0, degenerateKeywords.length -1);
|
||
|
fullDegenerateKeywords = fullDegenerateKeywords.substr(0, fullDegenerateKeywords.length -1);
|
||
|
|
||
|
if (degenerate) {
|
||
|
callback(true, degenerateKeywords, fullDegenerateKeywords, response);
|
||
|
} else {
|
||
|
callback(false, '', '', response);
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
// sometimes we dont have permission to redact messages, lets just ignore that
|
||
|
process.on('uncaughtException', function (exception) {
|
||
|
console.log('An error occured but it was probably not that important');
|
||
|
//console.log(exception);
|
||
|
});
|
||
|
|