twilio-split-sms
Version:
Forked version of codesleuth's split-sms: An SMS message splitter with support for both GSM and Unicode.
714 lines (664 loc) • 16.9 kB
JavaScript
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.splitter = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
var gsmvalidator = require('./gsmvalidator');
function isHighSurrogate(code) {
return code >= 0xD800 && code <= 0xDBFF;
}
module.exports.split = function (message, options) {
options = options || { summary: false };
if (message === '') {
return {
parts: [{
content: options.summary ? undefined : '',
length: 0,
bytes: 0
}],
totalLength: 0,
totalBytes: 0
};
}
var messages = [];
var length = 0;
var bytes = 0;
var totalBytes = 0;
var totalLength = 0;
var messagePart = '';
function bank() {
var msg = {
content: options.summary ? undefined : messagePart,
length: length,
bytes: bytes
};
messages.push(msg);
totalLength += length;
length = 0;
totalBytes += bytes;
bytes = 0;
messagePart = '';
}
for (var i = 0, count = message.length; i < count; i++) {
var c = message.charAt(i);
if (!gsmvalidator.validateCharacter(c)) {
if (isHighSurrogate(c.charCodeAt(0))) {
i++;
}
c = '\u0020';
} else if (gsmvalidator.validateExtendedCharacter(c)) {
if (bytes === 152) bank();
bytes++;
}
bytes++;
length++;
if (!options.summary) messagePart += c;
if (bytes === 153) bank();
}
if (bytes > 0) bank();
if (messages[1] && totalBytes <= 160) {
return {
parts: [{
content: options.summary ? undefined : messages[0].content + messages[1].content,
length: totalLength,
bytes: totalBytes
}],
totalLength: totalLength,
totalBytes: totalBytes
};
}
return {
parts: messages,
totalLength: totalLength,
totalBytes: totalBytes
};
};
},{"./gsmvalidator":2}],2:[function(require,module,exports){
// TODO Add descriptions in comments for codes that cannot be represented with visible characters.
var GSM_charCodes = [
10, //
12, //
13, //
32, //
33, // !
34, // "
35, // #
36, // $
37, // %
38, // &
39, // '
40, // (
41, // )
42, // *
43, // +
44, // ,
45, // -
46, // .
47, // /
48, // 0
49, // 1
50, // 2
51, // 3
52, // 4
53, // 5
54, // 6
55, // 7
56, // 8
57, // 9
58, // :
59, // ;
60, // <
61, // =
62, // >
63, // ?
64, // @
65, // A
66, // B
67, // C
68, // D
69, // E
70, // F
71, // G
72, // H
73, // I
74, // J
75, // K
76, // L
77, // M
78, // N
79, // O
80, // P
81, // Q
82, // R
83, // S
84, // T
85, // U
86, // V
87, // W
88, // X
89, // Y
90, // Z
91, // [
92, // \
93, // ]
94, // ^
95, // _
97, // a
98, // b
99, // c
100, // d
101, // e
102, // f
103, // g
104, // h
105, // i
106, // j
107, // k
108, // l
109, // m
110, // n
111, // o
112, // p
113, // q
114, // r
115, // s
116, // t
117, // u
118, // v
119, // w
120, // x
121, // y
122, // z
123, // {
124, // |
125, // }
126, // ~
161, // ¡
163, // £
164, // ¤
165, // ¥
167, // §
191, // ¿
196, // Ä
197, // Å
198, // Æ
199, // Ç
201, // É
209, // Ñ
214, // Ö
216, // Ø
220, // Ü
223, // ß
224, // à
228, // ä
229, // å
230, // æ
232, // è
233, // é
236, // ì
241, // ñ
242, // ò
246, // ö
248, // ø
249, // ù
252, // ü
915, // Γ
916, // Δ
920, // Θ
923, // Λ
926, // Ξ
928, // Π
931, // Σ
934, // Φ
936, // Ψ
937, // Ω
8364, // €,
// Twilio Smart Encoded Characters
171, // «
187, // »
8220, // “
8221, // ”
698, // ʺ
750, // ˮ
8223, // ‟
10077, // ❝
10078, // ❞
12317, // 〝
12318, // 〞
65282, // "
8216, // ‘
8217, // ’
699, // ʻ
712, // ˈ
700, // ʼ
701, // ʽ
697, // ʹ
8219, // ‛
65287, // '
180, // ´
714, // ˊ
96, // `
715, // ˋ
10075, // ❛
10076, // ❜
787, // ̓
788, // ̔
65040, // ︐
65041, // ︑
247, // ÷
188, // ¼
189, // ½
190, // ¾
10744, // ⧸
823, // ̷
824, // ̸
8260, // ⁄
8725, // ∕
65295, // /
10745, // ⧹
10741, // ⧵
8421, // ⃥
65128, // ﹨
65340, // \
818, // ̲
65343, // _
8402, // ⃒
8403, // ⃓
8739, // ∣
65372, // |
9144, // ⎸
9145, // ⎹
9168, // ⏐
9116, // ⎜
9119, // ⎟
9148, // ⎼
9149, // ⎽
8213, // ―
65123, // ﹣
65293, // -
8208, // ‐
8259, // ⁃
65131, // ﹫
65312, // @
65129, // ﹩
65284, // $
451, // ǃ
65045, // ︕
65111, // ﹗
65281, // !
65119, // ﹟
65283, // #
65130, // ﹪
65285, // %
65120, // ﹠
65286, // &
8218, // ‚
806, // ̦
65104, // ﹐
65105, // ﹑
65292, // ,
65380, // 、
10088, // ❨
10090, // ❪
65113, // ﹙
65288, // (
10222, // ⟮
10629, // ⦅
10089, // ❩
10091, // ❫
65114, // ﹚
65289, // )
10223, // ⟯
10630, // ⦆
8270, // ⁎
8727, // ∗
8859, // ⊛
10018, // ✢
10019, // ✣
10020, // ✤
10021, // ✥
10033, // ✱
10034, // ✲
10035, // ✳
10042, // ✺
10043, // ✻
10044, // ✼
10045, // ✽
10051, // ❃
10057, // ❉
10058, // ❊
10059, // ❋
10694, // ⧆
65121, // ﹡
65290, // *
726, // ˖
65122, // ﹢
65291, // +
12290, // 。
65106, // ﹒
65294, // .
65377, // 。
65296, // 0
65297, // 1
65298, // 2
65299, // 3
65300, // 4
65301, // 5
65302, // 6
65303, // 7
65304, // 8
65305, // 9
720, // ː
760, // ˸
10626, // ⦂
42889, // ꞉
65043, // ︓
65306, // :
8271, // ⁏
65044, // ︔
65108, // ﹔
65307, // ;
65124, // ﹤
65308, // <
839, // ͇
42890, // ꞊
65126, // ﹦
65309, // =
65125, // ﹥
65310, // >
65046, // ︖
65110, // ﹖
65311, // ?
65313, // A
7424, // ᴀ
65314, // B
665, // ʙ
65315, // C
7428, // ᴄ
65316, // D
7429, // ᴅ
65317, // E
7431, // ᴇ
65318, // F
42800, // ꜰ
65319, // G
610, // ɢ
65320, // H
668, // ʜ
65321, // I
618, // ɪ
65322, // J
7434, // ᴊ
65323, // K
7435, // ᴋ
65324, // L
671, // ʟ
65325, // M
7437, // ᴍ
65326, // N
628, // ɴ
65327, // O
7439, // ᴏ
65328, // P
7448, // ᴘ
65329, // Q
65330, // R
640, // ʀ
65331, // S
42801, // ꜱ
65332, // T
7451, // ᴛ
65333, // U
7452, // ᴜ
65334, // V
7456, // ᴠ
65335, // W
7457, // ᴡ
65336, // X
65337, // Y
655, // ʏ
65338, // Z
7458, // ᴢ
710, // ˆ
770, // ̂
65342, // ^
7629, // ᷍
10100, // ❴
65115, // ﹛
65371, // {
10101, // ❵
65116, // ﹜
65373, // }
65339, // [
65341, // ]
732, // ˜
759, // ˷
771, // ̃
816, // ̰
820, // ̴
8764, // ∼
65374, // ~
160, //
8192, //
8193, //
8194, //
8195, //
8196, //
8197, //
8198, //
8199, //
8200, //
8201, //
8202, //
8239, //
8287, //
12288, //
141, //
159, //
128, //
144, //
155, //
16, //
9, //
0, //
3, //
4, //
23, //
25, //
17, //
18, //
19, //
20, //
8215, // ‗
8212, // —
8211, // –
8218, // ‚
8239, //
8249, // ‹
8250, // ›
8252, // ‼
8222, // „
8221, // ”
8220, // “
8219, // ‛
8230, // …
8232, //
8233, //
8287, //
8288 //
];
// TODO Add descriptions in comments for codes that cannot be represented with visible characters.
var GSMe_charCodes = [
12, //
91, // [
92, // \
93, // ]
94, // ^
123, // {
124, // |
125, // }
126, // ~
8364, // €
// Twilio smart encoded characters that transliterate to extended GSM
710, // ˆ
770, // ̂
65342, // ^
7629, // ᷍
10100, // ❴
65115, // ﹛
65371, // {
8821, // ≵
65116, // ﹜
65373, // }
10745, // ⧹
10741, // ⧵
8421, // ⃥
65128, // ﹨
65340, // \
65339, // [
65341, // ]
732, // ˜
759, // ˷
771, // ̃
816, // ̰
820, // ̴
8764, // ∼
65374, // ~
8402, // ⃒
8403, // ⃓
8739, // ∣
65372, // |
9144, // ⎸
9145, // ⎹
9168, // ⏐
9116, // ⎜
9119 // ⎟
];
function existsInArray(code, array) {
var len = array.length;
var i = 0;
while (i < len) {
var e = array[i];
if (code === e) return true;
i++;
}
return false;
}
function validateCharacter(character) {
var code = character.charCodeAt(0);
return existsInArray(code, GSM_charCodes);
}
function validateMessage(message) {
for (var i = 0; i < message.length; i++) {
if (!validateCharacter(message.charAt(i))) return false;
}
return true;
}
function validateExtendedCharacter(character) {
var code = character.charCodeAt(0);
return existsInArray(code, GSMe_charCodes);
}
module.exports.validateCharacter = validateCharacter;
module.exports.validateMessage = validateMessage;
module.exports.validateExtendedCharacter = validateExtendedCharacter;
},{}],3:[function(require,module,exports){
var gsmValidator = require('./gsmvalidator'),
gsmSplitter = require('./gsmsplitter'),
unicodeSplitter = require('./unicodesplitter');
function calculateRemaining(parts, singleBytes, multiBytes, charBytes) {
var max = parts.length === 1 ? singleBytes : multiBytes;
return (max - parts[parts.length - 1].bytes) / charBytes;
}
var UNICODE = module.exports.UNICODE = 'Unicode';
var GSM = module.exports.GSM = 'GSM';
module.exports.split = function (message, options) {
var characterset = options && options.characterset;
options = {
summary: options && options.summary
};
var isGsm = (characterset === undefined && gsmValidator.validateMessage(message)) || characterset === GSM;
var splitResult, singleBytes, multiBytes, charBytes;
if (isGsm) {
splitResult = gsmSplitter.split(message, options);
singleBytes = 160;
multiBytes = 153;
charBytes = 1;
} else {
splitResult = unicodeSplitter.split(message, options);
singleBytes = 140;
multiBytes = 134;
charBytes = 2;
}
var remainingInPart = calculateRemaining(splitResult.parts, singleBytes, multiBytes, charBytes);
return {
characterSet: isGsm ? GSM : UNICODE,
parts: splitResult.parts,
bytes: splitResult.totalBytes,
length: splitResult.totalLength,
remainingInPart: remainingInPart
};
};
},{"./gsmsplitter":1,"./gsmvalidator":2,"./unicodesplitter":4}],4:[function(require,module,exports){
function isHighSurrogate(code) {
return code >= 0xD800 && code <= 0xDBFF;
}
module.exports.split = function (message, options) {
options = options || { summary: false };
if (message === '') {
return {
parts: [{
content: options.summary ? undefined : '',
length: 0,
bytes: 0
}],
totalLength: 0,
totalBytes: 0
};
}
var messages = [];
var length = 0;
var bytes = 0;
var totalBytes = 0;
var totalLength = 0;
var partStart = 0;
function bank(partEnd) {
var msg = {
content: options.summary ? undefined : (partEnd ? message.substring(partStart, partEnd + 1) : message.substring(partStart)),
length: length,
bytes: bytes
};
messages.push(msg);
partStart = partEnd + 1;
totalLength += length;
length = 0;
totalBytes += bytes;
bytes = 0;
}
for (var i = 0, count = message.length; i < count; i++) {
var code = message.charCodeAt(i);
var highSurrogate = isHighSurrogate(code);
if (highSurrogate) {
if (bytes === 132) bank(i - 1);
bytes += 2;
i++;
}
bytes += 2;
length++;
if (bytes === 134) bank(i);
}
if (bytes > 0) bank();
if (messages[1] && totalBytes <= 140) {
return {
parts: [{
content: options.summary ? undefined : message,
length: totalLength,
bytes: totalBytes
}],
totalLength: totalLength,
totalBytes: totalBytes
};
}
return {
parts: messages,
totalLength: totalLength,
totalBytes: totalBytes
};
};
},{}]},{},[3])(3)
});