首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >qq卡片链接在线生成器,自定义卡片生成器,QQxml消息生成器

qq卡片链接在线生成器,自定义卡片生成器,QQxml消息生成器

原创
作者头像
用户11696336
发布2025-06-24 12:16:17
发布2025-06-24 12:16:17
1.2K0
举报

下载地址:https://www.pan38.com/share.php?code=pvvmX 提取码:6728 【仅供学习】

下面的代码只能用于在QQ上面生成自定义的卡片,在其他社交APP是用不了的,并且在QQ企点版也用不了哦,只能在官方QQapp才能使用。

代码语言:txt
复制
 express = require('express');
const bodyParser = require('body-parser');
const xml2js = require('xml2js');
const fs = require('fs');
const path = require('path');

const app = express();
const PORT = 3000;

// 中间件
app.use(bodyParser.text({ type: 'text/xml' }));
app.use(express.static('public'));

// 卡片数据库
let cardsDB = {};
const DB_FILE = path.join(__dirname, 'cards.json');

// 加载数据库
function loadDatabase() {
    try {
        if (fs.existsSync(DB_FILE)) {
            cardsDB = JSON.parse(fs.readFileSync(DB_FILE, 'utf8'));
        }
    } catch (err) {
        console.error('加载数据库失败:', err);
    }
}

// 保存数据库
function saveDatabase() {
    try {
        fs.writeFileSync(DB_FILE, JSON.stringify(cardsDB, null, 2));
    } catch (err) {
        console.error('保存数据库失败:', err);
    }
}

// 验证XML结构
function validateCardXML(xmlString) {
    return new Promise((resolve, reject) => {
        xml2js.parseString(xmlString, (err, result) => {
            if (err) return reject(new Error('无效的XML格式'));
            
            if (!result.msg || !result.msg.$ || !result.msg.$.serviceID) {
                return reject(new Error('缺少必要的msg属性'));
            }
            
            if (!result.msg.item || !result.msg.item[0]) {
                return reject(new Error('缺少item元素'));
            }
            
            resolve(result);
        });
    });
}

// 路由
app.post('/api/cards', async (req, res) => {
    try {
        const xmlString = req.body;
        if (!xmlString) {
            return res.status(400).json({ error: '请提供XML内容' });
        }
        
        // 验证XML
        await validateCardXML(xmlString);
        
        // 生成卡片ID
        const cardId = 'card_' + Date.now().toString(36) + Math.random().toString(36).substr(2, 5);
        
        // 存储卡片
        cardsDB[cardId] = {
            xml: xmlString,
            createdAt: new Date().toISOString(),
            views: 0
        };
        
        saveDatabase();
        
        res.json({
            success: true,
            cardId,
            viewUrl: `https://yourdomain.com/cards/${cardId}`,
            xmlUrl: `https://yourdomain.com/api/cards/${cardId}/xml`
        });
    } catch (err) {
        res.status(400).json({ error: err.message });
    }
});

app.get('/api/cards/:id/xml', (req, res) => {
    const cardId = req.params.id;
    const card = cardsDB[cardId];
    
    if (!card) {
        return res.status(404).json({ error: '卡片不存在' });
    }
    
    // 更新查看次数
    card.views++;
    saveDatabase();
    
    res.type('application/xml');
    res.send(card.xml);
});

app.get('/cards/:id', (req, res) => {
    const cardId = req.params.id;
    const card = cardsDB[cardId];
    
    if (!card) {
        return res.status(404).send('卡片不存在');
    }
    
    // 渲染卡片查看页面
    res.send(`
        <!DOCTYPE html>
        <html>
        <head>
            <title>QQ卡片查看器</title>
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <style>
                body { font-family: Arial, sans-serif; padding: 20px; }
                .card-container { max-width: 500px; margin: 0 auto; }
                .card-info { margin-top: 20px; font-size: 14px; color: #666; }
            </style>
        </head>
        <body>
            <div class="card-container" id="card-view"></div>
            <div class="card-info">
                <p>创建时间: ${new Date(card.createdAt).toLocaleString()}</p>
                <p>查看次数: ${card.views}</p>
            </div>
            <script>
                fetch('/api/cards/${cardId}/xml')
                    .then(response => response.text())
                    .then(xml => {
                        // 这里添加XML解析和渲染逻辑
                        document.getElementById('card-view').innerHTML = 
                            '<pre>' + xml + '</pre>';
                    });
            </script>
        </body>
        </html>
    `);
});

// 启动服务器
loadDatabase();
app.listen(PORT, () => {
    console.log(`QQ卡片生成器服务运行在 http://localhost:${PORT}`);
});
代码语言:txt
复制
class QQCardParser {
    constructor(xmlString) {
        this.xmlString = xmlString;
        this.parsedData = null;
        this.errors = [];
    }

    async parse() {
        try {
            const parser = new xml2js.Parser({
                explicitArray: false,
                ignoreAttrs: false
            });
            
            this.parsedData = await parser.parseStringPromise(this.xmlString);
            this.validateStructure();
            return this.getNormalizedData();
        } catch (err) {
            this.errors.push(`XML解析错误: ${err.message}`);
            throw new Error(this.errors.join('\n'));
        }
    }

    validateStructure() {
        if (!this.parsedData.msg) {
            this.errors.push('缺少根元素msg');
            return;
        }

        const msg = this.parsedData.msg;
        const requiredMsgAttrs = ['serviceID', 'templateID', 'action'];
        requiredMsgAttrs.forEach(attr => {
            if (!msg.$[attr]) {
                this.errors.push(`msg元素缺少必要属性: ${attr}`);
            }
        });

        if (!msg.item) {
            this.errors.push('缺少item元素');
        } else {
            this.validateItem(msg.item);
        }

        if (this.errors.length > 0) {
            throw new Error('XML结构验证失败');
        }
    }

    validateItem(item) {
        if (!item.layout) {
            this.errors.push('item元素缺少layout属性');
        }

        if (!item.title && !item.summary) {
            this.errors.push('item元素必须包含title或summary');
        }
    }

    getNormalizedData() {
        const msg = this.parsedData.msg;
        const result = {
            meta: {
                serviceID: msg.$.serviceID,
                templateID: msg.$.templateID,
                action: msg.$.action,
                brief: msg.$.brief || '',
                sourceMsgId: msg.$.sourceMsgId || '0'
            },
            content: {
                layout: parseInt(msg.item.$.layout) || 0,
                title: msg.item.title || '',
                summary: msg.item.summary || '',
                picture: msg.item.picture ? {
                    cover: msg.item.picture.$.cover || '',
                    width: msg.item.picture.$.width ? parseInt(msg.item.picture.$.width) : null,
                    height: msg.item.picture.$.height ? parseInt(msg.item.picture.$.height) : null
                } : null
            },
            source: msg.source ? {
                name: msg.source.$.name || '',
                icon: msg.source.$.icon || '',
                url: msg.source.$.url || '',
                actionData: msg.source.$.actionData || ''
            } : null
        };

        return result;
    }

    static getTemplate(templateName) {
        const templates = {
            announcement: {
                meta: {
                    serviceID: "1",
                    templateID: "2",
                    action: "web",
                    brief: "公告"
                },
                content: {
                    layout: 2,
                    title: "重要公告",
                    summary: "请全体成员注意...",
                    picture: {
                        cover: "https://example.com/announce.png"
                    }
                },
                source: {
                    name: "官方公告",
                    icon: "https://example.com/logo.png"
                }
            },
            invitation: {
                meta: {
                    serviceID: "1",
                    templateID: "3",
                    action: "web",
                    brief: "邀请函"
                },
                content: {
                    layout: 1,
                    title: "活动邀请",
                    summary: "诚邀您参加我们的活动",
                    picture: {
                        cover: "https://example.com/event.jpg"
                    }
                },
                source: {
                    name: "活动中心",
                    url: "https://example

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档