Created
July 20, 2025 10:00
-
-
Save taiapi/1e62b69ff4df12ea1cc802fbaf882ce5 to your computer and use it in GitHub Desktop.
Upload lệnh sing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const axios = require("axios"); | |
| const Youtube = require("youtube-search-api"); | |
| const { createReadStream, unlinkSync } = require("fs-extra"); | |
| function sleep(ms) { | |
| return new Promise(resolve => setTimeout(resolve, ms)); | |
| } | |
| async function getDownloadUrlFromOceansaver(link, maxRetries = 5, retryDelayMs = 5000) { | |
| if (!link) throw new Error("Thiếu link YouTube"); | |
| let taskId = null; | |
| let attempts = 0; | |
| try { | |
| const resDownload = await axios.get("https://p.oceansaver.in/ajax/download.php", { | |
| params: { | |
| copyright: 0, | |
| format: "mp3", | |
| url: link, | |
| api: "30de256ad09118bd6b60a13de631ae2cea6e5f9d" // API key mẫu | |
| }, | |
| headers: { | |
| "referer": "https://y2meta.is", | |
| "origin": "https://y2meta.is", | |
| "user-agent": "Mozilla/5.0" | |
| } | |
| }); | |
| const downloadResult = resDownload.data; | |
| taskId = downloadResult?.id; | |
| if (!taskId) { | |
| throw new Error("Không lấy được ID xử lý từ API. Phản hồi: " + JSON.stringify(downloadResult)); | |
| } | |
| } catch (error) { | |
| throw new Error(`Lỗi khi lấy ID xử lý từ API: ${error.message}`); | |
| } | |
| while (attempts < maxRetries) { | |
| try { | |
| if (attempts > 0) { | |
| await sleep(retryDelayMs); | |
| } | |
| const resProgress = await axios.get(`https://p.oceansaver.in/api/progress`, { | |
| params: { id: taskId }, | |
| headers: { | |
| "referer": "https://y2meta.is", | |
| "origin": "https://y2meta.is", | |
| "user-agent": "Mozilla/5.0" | |
| } | |
| }); | |
| const progressData = resProgress.data; | |
| if (progressData.success === 1 && progressData.download_url) { | |
| return { download_url: progressData.download_url }; | |
| } else if (progressData.progress < 1000) { | |
| attempts++; | |
| console.log(`Video vẫn đang được xử lý. Thử lại lần ${attempts}/${maxRetries}...`); | |
| } else { | |
| throw new Error(`Không lấy được link tải. Trạng thái: ${progressData.status}. Phản hồi: ` + JSON.stringify(progressData)); | |
| } | |
| } catch (error) { | |
| if (!error.message.includes("Video vẫn đang được xử lý")) { | |
| throw new Error(`Lỗi khi gọi API progress: ${error.message}`); | |
| } | |
| attempts++; | |
| console.log(`Lỗi tạm thời khi gọi API progress. Thử lại lần ${attempts}/${maxRetries}...`); | |
| } | |
| } | |
| throw new Error(`Đã thử lại ${maxRetries} lần nhưng video vẫn chưa xử lý xong hoặc không lấy được link tải.`); | |
| } | |
| module.exports.config = { | |
| name: "sing", | |
| version: "2.2.0", | |
| hasPermssion: 0, | |
| credits: "D-Jukie & gấu", | |
| description: "Phát nhạc thông qua link YouTube hoặc từ khoá tìm kiếm bằng API.", | |
| commandCategory: "Phương tiện", | |
| usages: "[tên bài hát]", | |
| cooldowns: 5, | |
| }; | |
| module.exports.convertHMS = function(value) { | |
| const sec = parseInt(value, 10); | |
| let hours = Math.floor(sec / 3600); | |
| let minutes = Math.floor((sec - (hours * 3600)) / 60); | |
| let seconds = sec - (hours * 3600) - (minutes * 60); | |
| if (hours < 10) hours = "0" + hours; | |
| if (minutes < 10) minutes = "0" + minutes; | |
| if (seconds < 10) seconds = "0" + seconds; | |
| return (hours != "00" ? hours + ":" : "") + minutes + ":" + seconds; | |
| }; | |
| async function sendMusic(api, event, youtubeLink, title, duration) { | |
| try { | |
| api.sendMessage("⏳ Đang xử lý yêu cầu...", event.threadID); | |
| const timestart = Date.now(); | |
| const { download_url } = await getDownloadUrlFromOceansaver(youtubeLink); | |
| const { data: stream } = await axios.get(download_url, { responseType: "stream" }); | |
| const processingTime = Math.floor((Date.now() - timestart) / 1000); | |
| const timeNow = new Date().toLocaleString("vi-VN", { timeZone: "Asia/Ho_Chi_Minh", hour: "2-digit", minute: "2-digit", second: "2-digit" }); | |
| const msg = { | |
| body: `🎬 Tiêu đề: ${title}\n⏱️ Thời lượng: ${duration}\n⏳ Thời gian xử lý: ${processingTime} giây\n⏰ Lúc: ${timeNow}`, | |
| attachment: stream | |
| }; | |
| api.sendMessage(msg, event.threadID); | |
| } catch (error) { | |
| console.error("Lỗi trong quá trình xử lý nhạc:", error); | |
| api.sendMessage(`❌ Đã xảy ra lỗi: ${error.message}`, event.threadID); | |
| } | |
| } | |
| module.exports.run = async function({ api, event, args }) { | |
| if (args.length === 0) { | |
| return api.sendMessage("⚠️ Vui lòng nhập tên bài hát hoặc link YouTube!", event.threadID, event.messageID); | |
| } | |
| const keywordSearch = args.join(" "); | |
| if (keywordSearch.includes("https://")) { | |
| try { | |
| const videoInfo = (await Youtube.GetListByKeyword(keywordSearch, false, 1)).items[0]; | |
| if (!videoInfo) { | |
| return api.sendMessage("❌ Không tìm thấy thông tin video từ link này.", event.threadID); | |
| } | |
| await sendMusic(api, event, keywordSearch, videoInfo.title, videoInfo.length.simpleText); | |
| } catch (e) { | |
| console.error(e); | |
| api.sendMessage("❌ Đã có lỗi xảy ra khi lấy thông tin video từ link.", event.threadID); | |
| } | |
| } else { | |
| try { | |
| api.sendMessage("", event.threadID, event.messageID); | |
| const searchResults = (await Youtube.GetListByKeyword(keywordSearch, false, 10)).items; | |
| if (!searchResults || searchResults.length === 0) { | |
| return api.sendMessage("❌ Không tìm thấy kết quả phù hợp.", event.threadID); | |
| } | |
| let msg = ""; | |
| const links = []; | |
| const titles = []; | |
| const durations = []; | |
| for (let i = 0; i < searchResults.length; i++) { | |
| const value = searchResults[i]; | |
| const videoId = typeof value.id === "string" ? value.id : value.id.videoId; | |
| links.push(videoId); | |
| titles.push(value.title); | |
| durations.push(value.length.simpleText); | |
| msg += `${i + 1}. ${value.title}\n - Kênh: ${value.channelTitle}\n - Thời lượng: ${value.length.simpleText}\n\n`; | |
| } | |
| const body = `📝 Có ${links.length} kết quả:\n\n${msg}👉 Vui lòng reply tin nhắn này với số thứ tự bài hát bạn muốn chọn.`; | |
| api.sendMessage(body, event.threadID, (error, info) => { | |
| if (error) return console.error(error); | |
| global.client.handleReply.push({ | |
| type: "reply", | |
| name: module.exports.config.name, | |
| messageID: info.messageID, | |
| author: event.senderID, | |
| links, | |
| titles, | |
| durations | |
| }); | |
| }); | |
| } catch (e) { | |
| console.error(e); | |
| api.sendMessage("❌ Đã có lỗi xảy ra khi tìm kiếm.", event.threadID); | |
| } | |
| } | |
| }; | |
| module.exports.handleReply = async function({ api, event, handleReply }) { | |
| if (event.senderID !== handleReply.author) { | |
| return api.sendMessage("⛔ Bạn không phải người yêu cầu, không thể chọn.", event.threadID, event.messageID); | |
| } | |
| const choice = parseInt(event.body); | |
| if (isNaN(choice) || choice < 1 || choice > handleReply.links.length) { | |
| return api.sendMessage("⚠️ Lựa chọn không hợp lệ. Vui lòng chọn một số trong danh sách.", event.threadID, event.messageID); | |
| } | |
| api.unsendMessage(handleReply.messageID); | |
| const videoId = handleReply.links[choice - 1]; | |
| const youtubeLink = `https://www.youtube.com/watch?v=${videoId}`; | |
| const title = handleReply.titles[choice - 1]; | |
| const duration = handleReply.durations[choice - 1]; | |
| await sendMusic(api, event, youtubeLink, title, duration); | |
| }; | |
| module.exports.getDownloadUrlFromOceansaver = getDownloadUrlFromOceansaver; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment