UNPKG

@tsuk1ko/cq-websocket

Version:

A Node SDK for developing QQ chatbots based on WebSocket, which is depending on CoolQ and CQHTTP API plugin.

127 lines (117 loc) 2.96 kB
const isSupportedTag = require('./isSupportedTag'); const CQTag = require('./CQTag'); const { CQAt, CQAnonymous, CQBFace, CQCustomMusic, CQDice, CQEmoji, CQFace, CQImage, CQMusic, CQRecord, CQRPS, CQSFace, CQShake, CQShare, CQText, } = require('./models'); const CQTAGS_EXTRACTOR = /\[CQ[^\]]*\]/g; const CQTAG_ANALYSOR = /\[CQ:([a-z]+?)(?:,((,?[a-zA-Z0-9-_.]+=[^,[\]]*)*))?\]/; function parseData(dataStr = '') { return dataStr ? dataStr .split(',') .map(opt => opt.split('=')) .reduce((data, [k, v]) => { data[k] = v; return data; }, {}) : null; } function castCQTag(cqtag) { let proto; switch (cqtag._type) { case 'anonymous': proto = CQAnonymous.prototype; break; case 'at': proto = CQAt.prototype; break; case 'bface': proto = CQBFace.prototype; break; case 'music': proto = cqtag.data.type === 'custom' ? CQCustomMusic.prototype : CQMusic.prototype; break; case 'dice': proto = CQDice.prototype; break; case 'emoji': proto = CQEmoji.prototype; break; case 'face': proto = CQFace.prototype; break; case 'image': proto = CQImage.prototype; break; case 'record': proto = CQRecord.prototype; break; case 'rps': proto = CQRPS.prototype; break; case 'sface': proto = CQSFace.prototype; break; case 'shake': proto = CQShake.prototype; break; case 'share': proto = CQShare.prototype; break; case 'text': proto = CQText.prototype; } return Object.setPrototypeOf(cqtag, proto).coerce(); } /** * @param {string|any[]} message */ module.exports = function parse(message) { if (typeof message === 'string') { let textTagScanner = 0; const nonTextTags = (message.match(CQTAGS_EXTRACTOR) || []) .map(_tag => _tag.match(CQTAG_ANALYSOR)) .filter(_tag => _tag && isSupportedTag(_tag[1])) .map(_tag => new CQTag(_tag[1], parseData(_tag[2]))) .map(castCQTag); // insert text tags into appropriate position const ret = nonTextTags.reduce((tags, cqtag, index) => { const cqtagStr = cqtag.toString(); const cqtagIndex = message.indexOf(cqtagStr); if (cqtagIndex !== textTagScanner) { const text = message.substring(textTagScanner, cqtagIndex); tags.push(new CQText(text)); } tags.push(cqtag); textTagScanner = cqtagIndex + cqtagStr.length; return tags; }, []); if (textTagScanner < message.length) { // there is still text const text = message.substring(textTagScanner); ret.push(new CQText(text)); } return ret; } if (Array.isArray(message)) { return message .filter(_tag => isSupportedTag(_tag.type)) .map(_tag => new CQTag(_tag.type, _tag.data)) .map(castCQTag); } return []; };