initial commit
This commit is contained in:
247
index.js
Normal file
247
index.js
Normal file
@@ -0,0 +1,247 @@
|
||||
function Searxng(matrixClient) {
|
||||
this.matrixClient = matrixClient;
|
||||
this.uploadMatrixClient = matrixClient;
|
||||
this.blacklistedImgRooms = [];
|
||||
this.blacklistedUimgRooms = [];
|
||||
this.cooldownImmuneUsers = [];
|
||||
this.roomCooldowns = new Map();
|
||||
this.searxngInstance = "";
|
||||
this.searxngParameters = "enabled_engines=duckduckgo images__images,bing images__images&disabled_engines=flickr__images,nyaa__images,qwant images__images,google images__images,artic__images,deviantart__images,library of congress__images,unsplash__images,openverse__images"
|
||||
}
|
||||
|
||||
Searxng.prototype.setUploadMatrixClient = function(uploadMatrixClient){ this.uploadMatrixClient = uploadMatrixClient; };
|
||||
Searxng.prototype.setBlacklistedImgRooms = function(blacklistedImgRooms){ this.blacklistedImgRooms = blacklistedImgRooms; };
|
||||
Searxng.prototype.setBlacklistedUimgRooms = function(blacklistedUimgRooms){ this.blacklistedUimgRooms = blacklistedUimgRooms; };
|
||||
Searxng.prototype.setCooldownImmuneUsers = function(cooldownImmuneUsers){ this.cooldownImmuneUsers = cooldownImmuneUsers; };
|
||||
Searxng.prototype.setRoomCooldowns = function(roomCooldowns){ this.roomCooldowns = roomCooldowns; };
|
||||
Searxng.prototype.setSearxngInstance = function(searxngInstance){ this.searxngInstance = searxngInstance; };
|
||||
Searxng.prototype.setSearxngParameters = function(searxngParameters){ this.searxngParameters = searxngParameters; };
|
||||
|
||||
const axios = require('axios');
|
||||
const request = require('request');
|
||||
|
||||
const lastCooldownTimes = new Map();
|
||||
const lastWarningTimes = new Map();
|
||||
|
||||
const imageSearchCmd = "!img"
|
||||
const unsafeImageSearchCmd = "!uimg"
|
||||
|
||||
const searxngCommands = [
|
||||
imageSearchCmd,
|
||||
unsafeImageSearchCmd
|
||||
];
|
||||
|
||||
function sendImage(results, resultIndex, roomId, name, searchCommand, retryCount, matrixClient, uploadMatrixClient) {
|
||||
|
||||
const resultObj = results[resultIndex]
|
||||
var imageURL;
|
||||
if (typeof resultObj === 'undefined' || resultObj == null || typeof resultObj.img_src === 'undefined' || resultObj.img_src == null || resultObj.img_src === '') {
|
||||
imageURL = "";
|
||||
}
|
||||
else {
|
||||
imageURL = resultObj.img_src;
|
||||
if (imageURL.startsWith("//")) {
|
||||
imageURL = "https:" + imageURL;
|
||||
}
|
||||
}
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
const imageResponse = await axios.get(imageURL, { responseType: 'arraybuffer' });
|
||||
var imageType = imageResponse.headers['content-type'];
|
||||
console.debug("[Search text: "+searchCommand+"], "+"[imageURL: "+imageURL+"], "+"[retryCount: "+retryCount+"]"+", [Engine: "+resultObj.engines[0]+"]"+", [content-type: "+imageType+"]");
|
||||
const uploadResponse = await uploadMatrixClient.uploadContent(imageResponse.data, { rawResponse: false, type: imageType });
|
||||
const matrixUrl = uploadResponse.content_uri;
|
||||
switch(imageType) {
|
||||
case "image/jpeg":
|
||||
case "image/jpg":
|
||||
name = name + ".jpg";
|
||||
break;
|
||||
case "image/png":
|
||||
name = name + ".png";
|
||||
break;
|
||||
case "image/gif":
|
||||
name = name + ".gif";
|
||||
break;
|
||||
case "application/octet-stream":
|
||||
const urlImageType = imageURL.substring(imageURL.lastIndexOf("."));
|
||||
|
||||
switch(urlImageType) {
|
||||
case ".jpg":
|
||||
case ".jpeg":
|
||||
imageType = "image/jpg";
|
||||
name = name + ".jpg";
|
||||
break;
|
||||
case ".png":
|
||||
imageType = "image/png";
|
||||
name = name + ".png";
|
||||
break;
|
||||
case ".gif":
|
||||
imageType = "image/gif";
|
||||
name = name + ".gif";
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
matrixClient.sendImageMessage(roomId, matrixUrl, {"mimetype": imageType}, name, null);
|
||||
matrixClient.sendTyping(roomId, false, 3000);
|
||||
} catch (error) {
|
||||
retryCount = retryCount + 1;
|
||||
resultIndex = resultIndex + 1;
|
||||
|
||||
if (retryCount > 3 || resultIndex > (results.length - 1)) {
|
||||
matrixClient.sendNotice(roomId, "Error occurred during \"" + searchCommand + "\"");
|
||||
console.error("ERROR! [Search text: "+searchCommand+"], "+"[imageURL: "+imageURL+"], "+"[retryCount: "+retryCount+"]"+", [Engine: "+resultObj.engines[0]+"]");
|
||||
console.error(error);
|
||||
}
|
||||
else {
|
||||
console.warn("Trying next result for '"+searchCommand+"'");
|
||||
console.error(error);
|
||||
sendImage(results, resultIndex, roomId, name, searchCommand, retryCount, matrixClient, uploadMatrixClient);
|
||||
}
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
Searxng.prototype.handleMessage = function(event, room) {
|
||||
|
||||
const messagePieces = event.getContent().body.split(" ");
|
||||
|
||||
if (searxngCommands.indexOf(messagePieces[0]) > -1) {
|
||||
|
||||
var cooldown = false;
|
||||
|
||||
if (this.blacklistedImgRooms.indexOf(room.roomId) >=0) {
|
||||
this.matrixClient.sendNotice(room.roomId, "Image searching has been disabled in this room.");
|
||||
return;
|
||||
}
|
||||
else if (this.blacklistedUimgRooms.indexOf(room.roomId) >=0 && messagePieces[0] == unsafeImageSearchCmd) {
|
||||
this.matrixClient.sendNotice(room.roomId, "Image searching without safesearch is disabled in this room.");
|
||||
return;
|
||||
}
|
||||
else if (!room.currentState.maySendMessage(this.matrixClient.getUserId())) {
|
||||
console.warn("Don't have permission to post in room "+room.roomId);
|
||||
return;
|
||||
}
|
||||
else if (this.cooldownImmuneUsers.indexOf(event.getSender()) < 0) {
|
||||
const roomCooldown = this.roomCooldowns.get(room.roomId);
|
||||
|
||||
if (roomCooldown != undefined) {
|
||||
|
||||
const currentTime = Date.now();
|
||||
const lastRoomCooldownTime = lastCooldownTimes.get(room.roomId);
|
||||
if (lastRoomCooldownTime != undefined) {
|
||||
const timeSinceLastCooldown = currentTime - lastRoomCooldownTime;
|
||||
|
||||
if (!isNaN(timeSinceLastCooldown) && (currentTime - lastRoomCooldownTime) < roomCooldown) {
|
||||
|
||||
const lastRoomWarningTime = lastWarningTimes.get(room.roomId);
|
||||
|
||||
if (isNaN(lastRoomWarningTime) || lastRoomWarningTime != lastRoomCooldownTime) {
|
||||
this.matrixClient.sendNotice(room.roomId, "This room has a mandatory cooldown between image commands. Try again later.");
|
||||
lastWarningTimes.set(room.roomId, lastRoomCooldownTime);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
lastCooldownTimes.set(room.roomId, currentTime);
|
||||
cooldown = true;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
var toSearch;
|
||||
var resultIndex = 0;
|
||||
|
||||
if (messagePieces.length <= 1) {
|
||||
this.matrixClient.sendNotice(room.roomId, "No search terms provided");
|
||||
return;
|
||||
}
|
||||
else if (messagePieces.length == 2) {
|
||||
toSearch = messagePieces[1].trim();
|
||||
}
|
||||
else {
|
||||
if (isNaN(messagePieces[1])) {
|
||||
toSearch = event.getContent().body.substr(messagePieces[0].length+1);
|
||||
}
|
||||
else {
|
||||
resultIndex = Number(messagePieces[1]) - 1;
|
||||
|
||||
if (resultIndex < 0) {
|
||||
this.matrixClient.sendNotice(room.roomId, "Invalid result index given.");
|
||||
return;
|
||||
}
|
||||
|
||||
toSearch = event.getContent().body.substr(messagePieces[0].length+messagePieces[1].length+2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const searchURL = this.searxngInstance + "/searxng/search?category_images=1&pageno=1&time_range=&format=json&"+this.searxngParameters+"&safesearch="+(messagePieces[0] == unsafeImageSearchCmd ? "0" : "1")+"&q=" + toSearch;
|
||||
this.matrixClient.sendTyping(room.roomId, true, 3000);
|
||||
const matrixClient = this.matrixClient;
|
||||
const uploadMatrixClient = this.uploadMatrixClient;
|
||||
request(searchURL, function (error, response, body) {
|
||||
try {
|
||||
if (error == null || error == "") {
|
||||
const bodyObj = JSON.parse(body);
|
||||
const results = bodyObj.results;
|
||||
|
||||
if (typeof results === 'undefined' || results == null || results.length <= 0) {
|
||||
matrixClient.sendNotice(room.roomId, "No results found for \""+toSearch+"\"");
|
||||
return;
|
||||
}
|
||||
else if (resultIndex > (results.length - 1)) {
|
||||
matrixClient.sendNotice(room.roomId, "No result found for \""+toSearch+"\" at position "+(resultIndex+1));
|
||||
return;
|
||||
}
|
||||
|
||||
sendImage(results, resultIndex, room.roomId, toSearch, event.getContent().body, 0, matrixClient, uploadMatrixClient);
|
||||
}
|
||||
else {
|
||||
matrixClient.sendNotice(room.roomId, "Error occurred during \"" + event.getContent().body + "\"");
|
||||
console.error(error);
|
||||
}
|
||||
} catch (error) {
|
||||
matrixClient.sendNotice(room.roomId, "Error occurred during \"" + event.getContent().body + "\"");
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
if (cooldown) {
|
||||
lastCooldownTimes.set(room.roomId, Date.now());
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
} catch (error) {
|
||||
this.matrixClient.sendNotice(room.roomId, "Error occurred during \"" + event.getContent().body + "\"");
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
Searxng.prototype.startUploadMatrixClient = function() {
|
||||
(async () => {
|
||||
this.uploadMatrixClient.startClient({initialSyncLimit: 1});
|
||||
})();
|
||||
}
|
||||
|
||||
Searxng.prototype.getFormattedHelp = function() {
|
||||
return "\
|
||||
<code>!img [image_search_text]</code> - Return top result for image<br />\
|
||||
<code>!img [n] [image_search_text]</code> - Return nth result for image. [n] must be a positive number (example: <code>!img 3 cat memes</code>)<br />\
|
||||
<code>!uimg</code> - Same as !img but without safesearch";
|
||||
|
||||
}
|
||||
|
||||
Searxng.prototype.getHelp = function() {
|
||||
return "!img [image_search_text]\" - Return top result for image\r\n\
|
||||
\"!img [n] [image_search_text]\" - Return nth result for image. [n] must be a positive number (example: '!img 3 cat memes')\r\n\
|
||||
\"!uimg\" - Same as !img but without safesearch";
|
||||
|
||||
}
|
||||
|
||||
module.exports = Searxng;
|
Reference in New Issue
Block a user