Spaces:
Sleeping
Sleeping
| // SCRAPE BY NEKOLABS | |
| // CHANNEL WA: https://whatsapp.com/channel/0029VbANq6v0VycMue9vPs3u | |
| const axios = require("axios"); | |
| const cheerio = require("cheerio"); | |
| class NCS { | |
| constructor() { | |
| this.baseUrl = "https://ncs.io"; | |
| this.validGenres = { | |
| "31": "Alternative Dance", "33": "Alternative Pop", "23": "Ambient", "34": "Anti-Pop", | |
| "1": "Bass", "18": "Bass House", "26": "Brazilian Phonk", "27": "Breakbeat", | |
| "2": "Chill", "24": "Chill Bass", "35": "Chill Pop", "85": "Colour Bass", | |
| "65": "Complextro", "36": "Dance-Pop", "66": "Deep House", "45": "Disco", | |
| "46": "Disco House", "3": "Drum & Bass", "4": "Drumstep", "5": "Dubstep", | |
| "6": "EDM", "47": "Electro", "48": "Electro House", "7": "Electronic", | |
| "39": "Electronic Pop", "83": "Electronic Rock", "17": "Future Bass", "68": "Future Bounce", | |
| "8": "Future House", "69": "Future Rave", "57": "Future Trap", "40": "Futurepop", | |
| "51": "Garage", "15": "Glitch Hop", "82": "Hardcore", "9": "Hardstyle", | |
| "10": "House", "41": "Hyperpop", "11": "Indie Dance", "91": "J-Pop", | |
| "84": "Jersey Club", "28": "Jump-Up", "29": "Liquid DnB", "60": "Lofi Hip-Hop", | |
| "12": "Melodic Dubstep", "54": "Melodic House", "22": "Midtempo Bass", "30": "Neurofunk", | |
| "87": "Nu-Jazz", "16": "Phonk", "86": "Pluggnb", "19": "Pop", | |
| "55": "Progressive House", "88": "RnB", "89": "Speed Garage", "73": "Tech House", | |
| "80": "Techno", "81": "Trance", "14": "Trap", "74": "Tribal House", | |
| "21": "UKG", "90": "Witch House" | |
| }; | |
| this.validMoods = { | |
| "1": "Angry", "33": "angry", "26": "Chasing", "2": "Dark", "35": "dark", | |
| "36": "dramatic", "3": "Dreamy", "27": "Eccentric", "28": "Elegant", "6": "energetic", | |
| "4": "Epic", "5": "Euphoric", "37": "exciting", "7": "Fear", "29": "Floating", | |
| "8": "Funny", "9": "Glamorous", "10": "Gloomy", "11": "Happy", "30": "Heavy", | |
| "12": "Hopeful", "13": "Laid Back", "38": "majestic", "14": "Mysterious", "34": "negative", | |
| "39": "neutral", "15": "Peaceful", "40": "positive", "32": "powerful", "16": "Quirky", | |
| "17": "relaxed", "18": "Restless", "19": "romantic", "20": "sad", "21": "scary", | |
| "31": "Sentimental", "22": "Sexy", "23": "Suspense", "41": "tense", "24": "Weird" | |
| }; | |
| } | |
| validateParam(type, value) { | |
| const validList = type === "genre" ? this.validGenres : this.validMoods; | |
| return value && validList[value] ? String(value) : ""; | |
| } | |
| async searchTracks(query, genre = "", mood = "") { | |
| try { | |
| const validGenre = this.validateParam("genre", genre); | |
| const validMood = this.validateParam("mood", mood); | |
| const url = `${this.baseUrl}/music-search?q=${encodeURIComponent(query)}&genre=${validGenre}&mood=${validMood}`; | |
| const { data } = await axios.get(url, { | |
| headers: { | |
| "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36" | |
| } | |
| }); | |
| const $ = cheerio.load(data); | |
| const tracks = []; | |
| $("table.tablesorter tbody tr").each((_, el) => { | |
| const $row = $(el); | |
| const $play = $row.find(".player-play"); | |
| const tid = $play.attr("data-tid") || ""; | |
| const title = $play.attr("data-track") || ""; | |
| const artist = $play.attr("data-artistraw") || ""; | |
| const versions = $play.attr("data-versions") || ""; | |
| const genre = $play.attr("data-genre") || ""; | |
| const previewUrl = $play.attr("data-url") || ""; | |
| const previewStart = $play.attr("data-preview") || "0"; | |
| const image = $row.find("td img[alt]").attr("src") || ""; | |
| const genres = []; | |
| const moods = []; | |
| $row.find("td:nth-child(5) a.tag").each((i, tag) => { | |
| const $tag = $(tag); | |
| const text = $tag.text().trim(); | |
| const href = $tag.attr("href") || ""; | |
| if (href.includes("genre=")) genres.push(text); | |
| else if (href.includes("mood=")) moods.push(text); | |
| }); | |
| const releaseDate = $row.find("td:nth-child(6)").text().trim(); | |
| if (tid && title) { | |
| tracks.push({ | |
| tid, | |
| title, | |
| artist, | |
| versions, | |
| genre, | |
| image, | |
| genres, | |
| moods, | |
| previewUrl, | |
| previewStart, | |
| releaseDate | |
| }); | |
| } | |
| }); | |
| return tracks; | |
| } catch (err) { | |
| console.error("Error while searching NCS:", err.message); | |
| return []; | |
| } | |
| } | |
| } | |
| const ncs = new NCS(); | |
| const handler = async (req, res) => { | |
| try { | |
| const { text, genre, mood } = req.query; | |
| if (!text) { | |
| return res.status(400).json({ | |
| success: false, | |
| error: 'Missing required parameter: text' | |
| }); | |
| } | |
| const results = await ncs.searchTracks(text, genre || "", mood || ""); | |
| res.json({ | |
| author: 'Herza', | |
| success: true, | |
| data: results | |
| }); | |
| } catch (error) { | |
| res.status(500).json({ | |
| success: false, | |
| error: error.message | |
| }); | |
| } | |
| }; | |
| module.exports = { | |
| name: 'NCS Music Search', | |
| description: 'Search NoCopyrightSounds tracks by keyword with optional genre and mood filters', | |
| type: 'GET', | |
| routes: ['api/search/ncs'], | |
| tags: ['search', 'music', 'ncs', 'tools'], | |
| parameters: ['text', 'genre (optional)', 'mood (optional)'], | |
| enabled: true, | |
| main: ['Search'], | |
| handler | |
| }; |