koishi-plugin-kbot
Version:
A muti-function qq bot for koishi
88 lines (87 loc) • 4.61 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.apply = exports.Config = void 0;
const jsx_runtime_1 = require("@satorijs/element/jsx-runtime");
const koishi_1 = require("koishi");
const logger = new koishi_1.Logger('plugins/youtube');
exports.Config = koishi_1.Schema.object({
youtubeDataApiKey: koishi_1.Schema.string()
.required()
.description('请提供YouTube Data API v3 (必填) 详情: https://developers.google.com/youtube/v3/getting-started'),
useImage: koishi_1.Schema.boolean().default(false).description('是否使用图片模式 (需要 puppeteer 支持!)'),
});
const apiEndPointPrefix = 'https://www.googleapis.com/youtube/v3/videos';
const youtubeRegex = /(?:https?:\/\/)?(?:www\.)?(?:youtube\.com\/(?:watch\?(?=.*v=\w+)(?:\S+)?|embed\/\w+|\S+)|youtu\.be\/\w+)(?:\S+)?/ig;
const videoRegex = /^(?:https?:\/\/)?(?:i\.|www\.|img\.)?(?:youtu\.be\/|youtube\.com\/|ytimg\.com\/)(?:embed\/|v\/|vi\/|vi_webp\/|watch\?v=|watch\?.+&v=)?((\w|-){11})(?:\S+)?$/;
async function fetchDataFromAPI(ctx, config, videoId) {
try {
const data = await ctx.http.get(`${apiEndPointPrefix}?id=${videoId}&key=${config.youtubeDataApiKey}&part=snippet,contentDetails,statistics,status`);
return data;
}
catch (error) {
logger.error(`YouTube API 请求失败: ${error}`);
throw new Error('YouTube API 请求失败');
}
}
function getIDFromURLByRegex(url) {
const [, id] = url.match(videoRegex) || [];
return id;
}
function apply(ctx, config) {
ctx.middleware(async (session, next) => {
const contentArray = session.content.match(youtubeRegex);
const isYoutube = contentArray && contentArray.length > 0;
if (!isYoutube)
return next();
try {
contentArray.map(async (content) => {
logger.info(`捕获到 Youtube 视频链接: ${content}`);
let id;
let tagString = '无';
if (content.includes('https://youtu.be')) {
const index = content.lastIndexOf('/');
id = content.substring(index + 1, content.length);
}
else {
id = getIDFromURLByRegex(content);
}
const result = await fetchDataFromAPI(ctx, config, id);
if (result.items.length === 0)
return '未能成功解析, 或许视频不存在';
const { snippet: { title, description, channelTitle, thumbnails: { medium: { url }, }, publishedAt, tags, }, statistics, } = result.items[0];
if (tags)
tagString = tags.length > 1 ? tags.join(', ') : tags[0];
logger.info(`Youtube视频解析成功: ${title}`);
if (ctx.puppeteer && config.useImage) {
// TODO 待优化样式
await session.send((0, jsx_runtime_1.jsxs)("html", { style: {
padding: '1rem',
color: '#fff',
background: '#000',
fontSize: '14px',
lineHeight: '1.5',
fontFamily: 'sans-serif',
fontWeight: 'normal',
}, children: [(0, jsx_runtime_1.jsx)("img", { src: url }), (0, jsx_runtime_1.jsxs)("p", { children: ["\u9891\u9053: ", channelTitle] }), (0, jsx_runtime_1.jsxs)("p", { children: ["\u6807\u9898: ", title] }), (0, jsx_runtime_1.jsxs)("p", { children: ["\u63CF\u8FF0: ", description.length > 50 ? `${description.slice(0, 50)}...` : description] }), (0, jsx_runtime_1.jsxs)("p", { children: ["\u53D1\u5E03\u65F6\u95F4: ", publishedAt] }), (0, jsx_runtime_1.jsxs)("p", { children: ["\u6807\u7B7E: ", tagString] }), (0, jsx_runtime_1.jsxs)("p", { children: ["\u64AD\u653E\u91CF: ", statistics.viewCount] }), (0, jsx_runtime_1.jsxs)("p", { children: ["\u70B9\u8D5E: ", statistics.likeCount] })] }));
}
else {
await session.send(`<image url="${url}" />
频道: ${channelTitle}
标题: ${title}
描述: ${description.length > 50 ? `${description.slice(0, 50)}...` : description}
发布时间: ${publishedAt}
标签: ${tagString}
播放量: ${statistics.viewCount}
点赞: ${statistics.likeCount}
`);
}
});
}
catch (error) {
logger.error(error);
return 'Youtube视频解析发生错误';
}
return next();
});
}
exports.apply = apply;