/*Canopy - The next generation of stoner streaming software Copyright (C) 2024-2025 Rainbownapkin and the TTN Community This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see .*/ //NPM Imports const validator = require('validator');//No express here, so regular validator it is! //Create link cache /** * Basic RAM-Based cache of links, so we don't have to re-pull things after we get them */ module.exports.cache = new Map(); /** * Validates links and returns a marked link object that can be returned to the client to format/embed accordingly * @param {String} link - URL to Validate * @returns {Object} Marked link object */ module.exports.markLink = async function(link){ //Check link cache for the requested link const cachedLink = module.exports.cache.get(link); //If we have a cached result if(cachedLink){ //return the cached link return cachedLink; } //Set max file size to 4MB const maxSize = 4000000; //Assume links are guilty until proven innocent var type = "malformedLink" //Make sure we have an actual, factual URL if(validator.isURL(link)){ //The URL is valid, so this is at least a dead link type = 'deadLink'; //Don't try this at home, we're what you call "Experts" //TODO: Handle this shit simultaneously and send the chat before its done, then send updated types for each link as they're pulled individually try{ //Pull content type var response = await fetch(link,{ method: "HEAD", }); //If we made it this far then the link is, at the very least, not dead. type = 'link' //Get file type from header const fileType = response.headers.get('content-type'); const fileSize = response.headers.get('content-length'); //If they're reporting file types if(fileType != null){ //If we have an image if(fileType.match('image/')){ //If the file size is unreported OR it's smaller than 4MB (not all servers report this and images that big are pretty rare) if(fileSize == null || fileSize <= maxSize){ //Mark link as an image type = 'image'; } //If it's a video }else if(fileType.match('video/mp4' || 'video/webm')){ //If the server is reporting file-size and it's reporting under 4MB (Reject unreported sizes to be on the safe side is video is huge) if(fileSize != null && fileSize <= maxSize){ //mark link as a video type = 'video'; } } } //Probably bad form but if something happens in here I'm blaming whoever hosted the link //maybe don't host a fucked up server and I wouldn't handle with an empty catch }catch{}; } //Create the link object from processed information const linkObj = { link, type } //Cache the result module.exports.cache.set(link, linkObj); //Set timer to remove cache entry in five minutes setTimeout(()=>{ module.exports.cache.delete(link); }, 300000) //return the link return linkObj; }