@broid/twilio
Version:
Convert Twilio messages into Activity Streams 2 with Broid Integration
153 lines (152 loc) • 5.27 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const schemas_1 = require("@broid/schemas");
const utils_1 = require("@broid/utils");
const Promise = require("bluebird");
const R = require("ramda");
const uuid = require("uuid");
class Parser {
constructor(serviceName, serviceID, logLevel) {
this.serviceID = serviceID;
this.generatorName = serviceName;
this.logger = new utils_1.Logger('parser', logLevel);
}
validate(event) {
this.logger.debug('Validation process', { event });
const parsed = utils_1.cleanNulls(event);
if (!parsed || R.isEmpty(parsed)) {
return Promise.resolve(null);
}
if (!parsed.type) {
this.logger.debug('Type not found.', { parsed });
return Promise.resolve(null);
}
return schemas_1.default(parsed, 'activity')
.then(() => parsed)
.catch((err) => {
this.logger.error(err);
return null;
});
}
parse(event) {
this.logger.debug('Parse process', { event });
const normalized = utils_1.cleanNulls(event);
if (!normalized || R.isEmpty(normalized)) {
return Promise.resolve(null);
}
const parseMedia = (media) => {
let mediaType = '';
if (media.mediatype.startsWith('image')) {
mediaType = 'Image';
}
if (media.mediatype.startsWith('video')) {
mediaType = 'Video';
}
if (mediaType !== '') {
return {
mediaType: media.mediatype,
type: mediaType,
url: media.url,
};
}
return null;
};
const activitystreams = this.createActivityStream(normalized);
activitystreams.actor = {
id: normalized.senderPhoneNumber,
name: normalized.senderPhoneNumber,
type: 'Person',
};
activitystreams.target = {
id: normalized.toPhoneNumber,
name: normalized.toPhoneNumber,
type: 'Person',
};
if (normalized.numMedia === 1) {
const m = parseMedia(normalized.mediaURLs[0]);
if (m) {
activitystreams.object = {
id: normalized.eventID || this.createIdentifier(),
mediaType: m.mediaType,
type: m.type,
url: m.url,
};
if (normalized.text && !R.isEmpty(normalized.text)) {
activitystreams.object.content = normalized.text;
}
}
}
else if (normalized.numMedia > 1) {
let attachments = R.map((mediaURL) => {
const m = parseMedia(mediaURL);
if (m) {
return m;
}
return null;
}, normalized.mediaURLs);
attachments = R.reject(R.isNil)(attachments);
if (!R.isEmpty(attachments)) {
activitystreams.object = {
attachment: attachments,
content: normalized.text,
id: normalized.eventID || this.createIdentifier(),
type: 'Note',
};
}
}
if (!activitystreams.object && !R.isEmpty(normalized.text)) {
activitystreams.object = {
content: normalized.text,
id: normalized.eventID || this.createIdentifier(),
type: 'Note',
};
}
return Promise.resolve(activitystreams);
}
normalize(event) {
this.logger.debug('Event received to normalize');
const body = R.path(['request', 'body'], event);
if (!body || R.isEmpty(body)) {
return Promise.resolve(null);
}
const senderPhoneNumber = body.From;
const toPhoneNumber = body.To;
const text = body.Body;
const eventID = body.MessageSid;
const data = {
eventID,
mediaURLs: R.reject(R.isNil)(R.map((num) => {
const url = body[`MediaUrl${num}`];
if (url) {
return {
mediatype: body[`MediaContentType${num}`],
url,
};
}
return null;
}, R.range(0, 11))),
numMedia: Number(body.NumMedia),
senderPhoneNumber,
text,
timestamp: body.timestamp || Math.floor(Date.now() / 1000),
toPhoneNumber,
};
return Promise.resolve(data);
}
createIdentifier() {
return uuid.v4();
}
createActivityStream(normalized) {
return {
'@context': 'https://www.w3.org/ns/activitystreams',
'generator': {
id: this.serviceID,
name: this.generatorName,
type: 'Service',
},
'published': normalized.timestamp || Math.floor(Date.now() / 1000),
'type': 'Create',
};
}
}
exports.Parser = Parser;