module.exports = SKBlob
var BufferUtils = require('../lib/buffer-utils')
var Story = require('./story')
var fileType = require('file-type')
var JSZip = require('jszip')
/**
* Snapchat Blob wrapper
*
* @class
* @param {Buffer} data
*/
function SKBlob (data) {
var self = this
if (!(self instanceof SKBlob)) return new SKBlob(data)
if (!(data instanceof Buffer)) {
data = new Buffer(data)
}
self._data = data
self._type = fileType(data)
self._isImage = BufferUtils.isImage(data)
self._isMPEG4 = BufferUtils.isMPEG4(data)
self._isVideo = self._isMPEG4
self._isMedia = BufferUtils.isMedia(data)
// TODO
self._overlay = null
}
/**
* The underlying data for the image or video.
*
* @name SKBlob#data
* @property {Buffer}
* @readonly
*/
Object.defineProperty(SKBlob.prototype, 'data', {
get: function () { return this._data }
})
/**
* Information about the media type.
*
* @name SKBlob#type
* @property {Buffer}
* @readonly
*/
Object.defineProperty(SKBlob.prototype, 'type', {
get: function () { return this._type }
})
/**
* The overlay for the video if applicable.
*
* @name SKBlob#overlay
* @property {Buffer}
* @readonly
*/
Object.defineProperty(SKBlob.prototype, 'overlay', {
get: function () { return this._overlay }
})
/**
* Whether or not this blob represents an image (PNG or JPEG).
*
* @name SKBlob#isImage
* @property {boolean}
* @readonly
*/
Object.defineProperty(SKBlob.prototype, 'isImage', {
get: function () { return this._isImage }
})
/**
* Whether or not this blob represents a video (MPEG4).
*
* @name SKBlob#isVideo
* @property {boolean}
* @readonly
*/
Object.defineProperty(SKBlob.prototype, 'isVideo', {
get: function () { return this._isVideo }
})
/**
* Whether or not this blob represents an MPEG4 video.
*
* @name SKBlob#isMPEG4
* @property {boolean}
* @readonly
*/
Object.defineProperty(SKBlob.prototype, 'isMPEG4', {
get: function () { return this._isMPEG4 }
})
/**
* Whether or not this blob represents a supported image or video format.
*
* @name SKBlob#isMedia
* @property {boolean}
* @readonly
*/
Object.defineProperty(SKBlob.prototype, 'isMedia', {
get: function () { return this._isMedia }
})
/**
* Initializes and returns a new SKBlob from the given raw data.
* Does not handle encrypted data.
*
* @static
* @param {Buffer} data
* @param {function} cb
*/
SKBlob.initWithData = function (data, cb) {
if (!data) {
return cb('error empty blob')
}
if (typeof data === 'string') {
data = new Buffer(data)
}
if (BufferUtils.isCompressed(data)) {
var files = SKBlob.decompress(data)
return cb(null, files)
}
var blob = new SKBlob(data)
return cb(blob.isMedia ? null : 'unknown blob format', blob)
}
/**
* Initializes and returns a new SKBlob from the given story and raw data.
*
* @static
* @param {Buffer} data
* @param {Story} story
* @param {function} cb
*/
SKBlob.initWithStoryData = function (data, story, cb) {
if (!(story instanceof Story)) {
throw new Error('SKBlob.initWithStoryData invalid story')
}
if (typeof data === 'string') {
data = new Buffer(data)
}
if (BufferUtils.isCompressed(data)) {
var files = SKBlob.decompress(data)
return cb(null, files)
}
return SKBlob.decrypt(data, story, cb)
}
/**
* Unarchives blobs initialized with anonymous data.
*
* @static
* @param {Buffer} data
* @param {function} cb
*/
SKBlob.decompress = function (data, cb) {
var zip = new JSZip(data)
var files = Object.keys(zip.files).map(function (filename) {
var decompressed = zip.file(filename).asNodeBuffer()
return {
name: filename,
blob: new SKBlob(decompressed)
}
})
return files
}
/**
* @static
* @param {Buffer} data
* @param {Story} story
* @param {function} cb
*/
SKBlob.decrypt = function (data, story, cb) {
if (!(story instanceof Story)) {
throw new Error('SKBlob.decrypt invalid story')
}
if (!BufferUtils.isCompressed(data) && !BufferUtils.isMedia(data) && story) {
data = BufferUtils.decryptStory(data, story.mediaKey, story.mediaIV)
}
if (BufferUtils.isCompressed(data)) {
var files = SKBlob.decompress(data)
return cb(null, files)
}
var blob = new SKBlob(data)
return cb(blob.isMedia ? null : 'unknown blob format', blob)
}