smstools 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +135 -21
- data/lib/assets/javascripts/sms_tools/message.js.coffee +19 -4
- data/lib/sms_tools.rb +12 -0
- data/lib/sms_tools/encoding_detection.rb +19 -4
- data/lib/sms_tools/version.rb +1 -1
- data/spec/sms_tools/encoding_detection_spec.rb +30 -8
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b0c466ba58b15a65599eb4abbaac0d22a6f82ac5
|
4
|
+
data.tar.gz: 416a9721a3ada4264dee86f28e1af344b24a8dbf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1946b4d7493dfb0bd01d699f13ccd2ee7a2498daeb80b2f5070273031860e1189223837a785e8aca2c6e71bfcc63210dd7632bf8d105a80537b4264edf417df6
|
7
|
+
data.tar.gz: 2ca97dbb11cf51eb4493f152303dc5d81b6286ee83b4d7921fcaa01dcc195d0052d1d5dda7ae3b390637ce2d7285af23604c5f6822324b8a87a45e1316493b15
|
data/README.md
CHANGED
@@ -1,23 +1,70 @@
|
|
1
1
|
# Sms Tools
|
2
2
|
|
3
|
-
A small collection of
|
4
|
-
|
3
|
+
A small collection of Ruby and JavaScript classes implementing often needed functionality for
|
4
|
+
dealing with SMS messages.
|
5
5
|
|
6
|
-
The gem
|
7
|
-
|
6
|
+
The gem can also be used in a Rails application as an engine. It integrates with the asset pipeline
|
7
|
+
and gives you access to some clinet-side SMS manipulation functionality.
|
8
8
|
|
9
9
|
## Features
|
10
10
|
|
11
11
|
The following features are available on both the server side and the client
|
12
12
|
side:
|
13
13
|
|
14
|
-
- Detection of the most optimal encoding for sending an SMS message (GSM 7-bit
|
15
|
-
|
16
|
-
- Correctly determining the message's length according to the most optimal
|
17
|
-
encoding.
|
14
|
+
- Detection of the most optimal encoding for sending an SMS message (GSM 7-bit or Unicode).
|
15
|
+
- Correctly determining a message's length in the most optimal encoding.
|
18
16
|
- Concatenation detection and concatenated message parts counting.
|
19
17
|
|
20
|
-
|
18
|
+
The following can be accomplished only on the server with Ruby:
|
19
|
+
|
20
|
+
- Converting a UTF-8 string to a GSM 7-bit encoding and vice versa.
|
21
|
+
- Detecting if a UTF-8 string can be safely represented in a GSM 7-bit encoding.
|
22
|
+
- Detection of double-byte chars in the GSM 7-bit encoding.
|
23
|
+
|
24
|
+
And possibly more.
|
25
|
+
|
26
|
+
### Note on the GSM encoding
|
27
|
+
|
28
|
+
All references to the "GSM" encoding or the "GSM 7-bit alphabet" in this text actually refer to the
|
29
|
+
[GSM 03.38 spec](http://en.wikipedia.org/wiki/GSM_03.38) and [its latest
|
30
|
+
version](ftp://ftp.unicode.org/Public/MAPPINGS/ETSI/GSM0338.TXT), as defined by the Unicode
|
31
|
+
consortium.
|
32
|
+
|
33
|
+
This encoding is the most widely used one when sending SMS messages.
|
34
|
+
|
35
|
+
### Note regarding non-ASCII symbols from the GSM encoding
|
36
|
+
|
37
|
+
The GSM 03.38 encoding is used by default. This standard defines a set of
|
38
|
+
symbols which can be encoded in 7-bits each, thus allowing up to 160 symbols
|
39
|
+
per SMS message (each SMS message can contain up to 140 bytes of data).
|
40
|
+
|
41
|
+
This standard covers most of the ASCII table, but also includes some non-ASCII
|
42
|
+
symbols such as `æ`, `ø` and `å`. If you use these in your messages, you can
|
43
|
+
still send them as GSM encoded, having a 160-symbol limit. This is technically
|
44
|
+
correct.
|
45
|
+
|
46
|
+
In reality, however, some SMS routes have problems delivering messages which
|
47
|
+
contain such non-ASCII symbols in the GSM encoding. The special symbols might
|
48
|
+
be omitted, or the message might not arrive at all.
|
49
|
+
|
50
|
+
Thus, it might be safer to just send messages in Unicode if the message's text
|
51
|
+
contains any non-ASCII symbols. This is not the default as it reduces the max
|
52
|
+
symbols count to 70 per message, instead of 160, and you might not have any
|
53
|
+
issues with GSM-encoded messages. In case you do, however, you can turn off
|
54
|
+
support for the GSM encoding and just treat messages as Unicode if they contain
|
55
|
+
non-ASCII symbols.
|
56
|
+
|
57
|
+
In case you decide to do so, you have to specify it in both the Ruby and the
|
58
|
+
JavaScript part of the library, like so:
|
59
|
+
|
60
|
+
#### In Ruby
|
61
|
+
|
62
|
+
SmsTools.use_gsm_encoding = false
|
63
|
+
|
64
|
+
#### In Javascript
|
65
|
+
|
66
|
+
//= require sms_tools
|
67
|
+
SmsTools.use_gsm_encoding = false;
|
21
68
|
|
22
69
|
## Installation
|
23
70
|
|
@@ -33,32 +80,99 @@ Or install it yourself as:
|
|
33
80
|
|
34
81
|
$ gem install smstools
|
35
82
|
|
83
|
+
If you're using the gem in Rails, you may also want to add the following to your `application.js`
|
84
|
+
manifest file to gain access to the client-side features:
|
85
|
+
|
86
|
+
//= require sms_tools
|
87
|
+
|
36
88
|
## Usage
|
37
89
|
|
38
90
|
The gem consists of both server-side (Ruby) and client-side classes. You can
|
39
|
-
use either
|
91
|
+
use either.
|
40
92
|
|
41
93
|
### Server-side code
|
42
94
|
|
43
|
-
|
44
|
-
such as `SmsTools::EncodingDetection` or `SmsTools::GsmEncoding`.
|
95
|
+
First make sure you have installed the gem and have required the appropriate files.
|
45
96
|
|
46
|
-
####
|
47
|
-
|
97
|
+
#### Encoding detection
|
98
|
+
|
99
|
+
The `SmsTools::EncodingDetection` class provides you with a few simple methods to detect the most
|
100
|
+
optimal encoding for sending an SMS message, to correctly caclulate its length in that encoding and
|
101
|
+
to see if the text would need to be concatenated or will fit in a single message.
|
102
|
+
|
103
|
+
Here is an example with a non-concatenated message which is best encoded in the GSM 7-bit alphabet:
|
104
|
+
|
105
|
+
```ruby
|
106
|
+
sms_text = 'Text in GSM 03.38: ÄäøÆ with a double-byte char: ~ '
|
107
|
+
sms_encoding = SmsTools::EncodingDetection.new sms_text
|
108
|
+
|
109
|
+
sms_encoding.gsm? # => true
|
110
|
+
sms_encoding.unicode? # => false
|
111
|
+
sms_encoding.length # => 52 (because of the double-byte char)
|
112
|
+
sms_encoding.concatenated? # => false
|
113
|
+
sms_encoding.concatenated_parts # => 1
|
114
|
+
sms_encoding.encoding # => :gsm
|
115
|
+
```
|
116
|
+
|
117
|
+
Here's another example with a concatenated Unicode message:
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
sms_text = 'Я' * 90
|
121
|
+
sms_encoding = SmsTools::EncodingDetection.new sms_text
|
122
|
+
|
123
|
+
sms_encoding.gsm? # => false
|
124
|
+
sms_encoding.unicode? # => true
|
125
|
+
sms_encoding.length # => 90
|
126
|
+
sms_encoding.concatenated? # => true
|
127
|
+
sms_encoding.concatenated_parts # => 2
|
128
|
+
sms_encoding.encoding # => :unicode
|
129
|
+
```
|
130
|
+
|
131
|
+
You can check the specs for this class for more examples.
|
132
|
+
|
133
|
+
#### GSM 03.38 encoding conversion
|
134
|
+
|
135
|
+
The `SmsTools::GsmEncoding` class can be used to check if a given UTF-8 string can be fully
|
136
|
+
represented in the GSM 03.38 encoding as well as to convert from UTF-8 to GSM 03.38 and vice-versa.
|
137
|
+
|
138
|
+
The main API this class provides is the following:
|
139
|
+
|
140
|
+
```ruby
|
141
|
+
SmsTools::GsmEncoding.valid? message_text_in_utf8 # => true or false
|
142
|
+
|
143
|
+
SmsTools::GsmEncoding.from_utf8 utf8_encoded_string # => a GSM 03.38 encoded string
|
144
|
+
SmsTools::GsmEncoding.to_utf8 gsm_encoded_string # => an UTF-8 encoded string
|
145
|
+
```
|
146
|
+
|
147
|
+
Check out the source code of the class to find out more.
|
48
148
|
|
49
149
|
### Client-side code
|
50
150
|
|
51
|
-
If you're using the gem in Rails 3.
|
52
|
-
|
151
|
+
If you're using the gem in Rails 3.1 or newer, you can gain access to the `SmsTools.Message` class.
|
152
|
+
It's interface is similar to the one of `SmsTools::EncodingDetection`. Here is an example in
|
153
|
+
CoffeeScript:
|
154
|
+
|
155
|
+
```coffeescript
|
156
|
+
message = new SmsTools.Message 'The text of the message: ~'
|
157
|
+
|
158
|
+
message.encoding # => 'gsm'
|
159
|
+
message.length # => 27
|
160
|
+
message.concatenatedPartsCount # => 1
|
161
|
+
```
|
53
162
|
|
54
|
-
|
163
|
+
You can also check how long can this message be in the current most optimal encoding, if we want to
|
164
|
+
limit the number of concatenated messages we will allow to be sent:
|
55
165
|
|
56
|
-
|
166
|
+
```coffeescript
|
167
|
+
maxConcatenatedPartsCount = 2
|
168
|
+
message.maxLengthFor(maxConcatenatedPartsCount) # => 306
|
169
|
+
```
|
57
170
|
|
58
|
-
|
171
|
+
This allows you to have a dynamic instead of a fixed length limit, for when you use a non-GSM 03.38
|
172
|
+
symbol in your text, your message length limit decreases significantly.
|
59
173
|
|
60
|
-
Note that this
|
61
|
-
|
174
|
+
Note that to use this client-side code, a Rails application with an active asset pipeline is
|
175
|
+
assumed. It might be possible to use it in other setups as well, but you're on your own there.
|
62
176
|
|
63
177
|
## Contributing
|
64
178
|
|
@@ -2,6 +2,9 @@ window.SmsTools ?= {}
|
|
2
2
|
|
3
3
|
class SmsTools.Message
|
4
4
|
maxLengthForEncoding:
|
5
|
+
ascii:
|
6
|
+
normal: 160
|
7
|
+
concatenated: 153
|
5
8
|
gsm:
|
6
9
|
normal: 160
|
7
10
|
concatenated: 153
|
@@ -20,6 +23,7 @@ class SmsTools.Message
|
|
20
23
|
'€': true
|
21
24
|
'\\': true
|
22
25
|
|
26
|
+
asciiPattern: /^[\x00-\x7F]*$/
|
23
27
|
gsmEncodingPattern: /^[0-9a-zA-Z@Δ¡¿£_!Φ"¥Γ#èΛ¤éΩ%ùΠ&ìΨòΣçΘΞ:Ø;ÄäøÆ,<Ööæ=ÑñÅß>Üüåɧà€~ \$\.\-\+\(\)\*\\\/\?\|\^\}\{\[\]\'\r\n]*$/
|
24
28
|
|
25
29
|
constructor: (@text) ->
|
@@ -33,8 +37,19 @@ class SmsTools.Message
|
|
33
37
|
|
34
38
|
concatenatedPartsCount * @maxLengthForEncoding[@encoding][messageType]
|
35
39
|
|
40
|
+
use_gsm_encoding: ->
|
41
|
+
if SmsTools['use_gsm_encoding'] == undefined
|
42
|
+
true
|
43
|
+
else
|
44
|
+
SmsTools['use_gsm_encoding']
|
45
|
+
|
36
46
|
_encoding: ->
|
37
|
-
if @
|
47
|
+
if @asciiPattern.test(@text)
|
48
|
+
'ascii'
|
49
|
+
else if @use_gsm_encoding() and @gsmEncodingPattern.test(@text)
|
50
|
+
'gsm'
|
51
|
+
else
|
52
|
+
'unicode'
|
38
53
|
|
39
54
|
_concatenatedPartsCount: ->
|
40
55
|
encoding = @encoding
|
@@ -45,9 +60,9 @@ class SmsTools.Message
|
|
45
60
|
else
|
46
61
|
parseInt Math.ceil(length / @maxLengthForEncoding[encoding].concatenated), 10
|
47
62
|
|
48
|
-
|
49
|
-
|
50
|
-
|
63
|
+
# Returns the number of symbols which the given text will eat up in an SMS
|
64
|
+
# message, taking into account any double-space symbols in the GSM 03.38
|
65
|
+
# encoding.
|
51
66
|
_length: ->
|
52
67
|
length = @text.length
|
53
68
|
|
data/lib/sms_tools.rb
CHANGED
@@ -5,3 +5,15 @@ require 'sms_tools/gsm_encoding'
|
|
5
5
|
if defined?(::Rails) and ::Rails.version >= '3.1'
|
6
6
|
require 'sms_tools/rails/engine'
|
7
7
|
end
|
8
|
+
|
9
|
+
module SmsTools
|
10
|
+
class << self
|
11
|
+
def use_gsm_encoding?
|
12
|
+
@use_gsm_encoding.nil? ? true : @use_gsm_encoding
|
13
|
+
end
|
14
|
+
|
15
|
+
def use_gsm_encoding=(value)
|
16
|
+
@use_gsm_encoding = value
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -3,6 +3,10 @@ require 'sms_tools/gsm_encoding'
|
|
3
3
|
module SmsTools
|
4
4
|
class EncodingDetection
|
5
5
|
MAX_LENGTH_FOR_ENCODING = {
|
6
|
+
ascii: {
|
7
|
+
normal: 160,
|
8
|
+
concatenated: 153,
|
9
|
+
},
|
6
10
|
gsm: {
|
7
11
|
normal: 160,
|
8
12
|
concatenated: 153,
|
@@ -20,7 +24,18 @@ module SmsTools
|
|
20
24
|
end
|
21
25
|
|
22
26
|
def encoding
|
23
|
-
@encoding ||=
|
27
|
+
@encoding ||=
|
28
|
+
if text.ascii_only?
|
29
|
+
:ascii
|
30
|
+
elsif SmsTools.use_gsm_encoding? and GsmEncoding.valid?(text)
|
31
|
+
:gsm
|
32
|
+
else
|
33
|
+
:unicode
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def ascii?
|
38
|
+
encoding == :ascii
|
24
39
|
end
|
25
40
|
|
26
41
|
def gsm?
|
@@ -49,9 +64,9 @@ module SmsTools
|
|
49
64
|
concatenated_parts * MAX_LENGTH_FOR_ENCODING[encoding][message_type]
|
50
65
|
end
|
51
66
|
|
52
|
-
|
53
|
-
|
54
|
-
|
67
|
+
# Returns the number of symbols which the given text will eat up in an SMS
|
68
|
+
# message, taking into account any double-space symbols in the GSM 03.38
|
69
|
+
# encoding.
|
55
70
|
def length
|
56
71
|
length = text.length
|
57
72
|
length += text.chars.count { |char| GsmEncoding.double_byte?(char) } if gsm?
|
data/lib/sms_tools/version.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'sms_tools
|
2
|
+
require 'sms_tools'
|
3
3
|
|
4
4
|
describe SmsTools::EncodingDetection do
|
5
5
|
it "exposes the original text as a method" do
|
@@ -7,27 +7,49 @@ describe SmsTools::EncodingDetection do
|
|
7
7
|
end
|
8
8
|
|
9
9
|
describe "encoding" do
|
10
|
-
it "defaults to
|
11
|
-
detection_for('').encoding.must_equal :
|
10
|
+
it "defaults to ASCII encoding for empty messages" do
|
11
|
+
detection_for('').encoding.must_equal :ascii
|
12
12
|
end
|
13
13
|
|
14
|
-
it "returns
|
15
|
-
detection_for('foo bar baz').encoding.must_equal :
|
14
|
+
it "returns ASCII as encoding for simple ASCII text" do
|
15
|
+
detection_for('foo bar baz').encoding.must_equal :ascii
|
16
16
|
end
|
17
17
|
|
18
18
|
it "returns GSM as encoding for special symbols defined in GSM 03.38" do
|
19
19
|
detection_for('09azAZ@Δ¡¿£_!Φ"¥Γ#èΛ¤éΩ%ùΠ&ìΨòΣçΘΞ:Ø;ÄäøÆ,<Ööæ=ÑñÅß>Üüåɧà€~').encoding.must_equal :gsm
|
20
20
|
end
|
21
21
|
|
22
|
-
it "returns
|
23
|
-
detection_for('Foo bar {} [baz]! Larodi $5. What else?').encoding.must_equal :
|
24
|
-
detection_for("Spaces and newlines are GSM 03.38, too: \r\n").encoding.must_equal :
|
22
|
+
it "returns ASCII as encoding for puntucation and newline symbols" do
|
23
|
+
detection_for('Foo bar {} [baz]! Larodi $5. What else?').encoding.must_equal :ascii
|
24
|
+
detection_for("Spaces and newlines are GSM 03.38, too: \r\n").encoding.must_equal :ascii
|
25
25
|
end
|
26
26
|
|
27
27
|
it "returns Unicode when non-GSM Unicode symbols are used" do
|
28
28
|
detection_for('Foo bar лароди').encoding.must_equal :unicode
|
29
29
|
detection_for('∞').encoding.must_equal :unicode
|
30
30
|
end
|
31
|
+
|
32
|
+
describe 'with SmsTools.use_gsm_encoding = false' do
|
33
|
+
before do
|
34
|
+
SmsTools.use_gsm_encoding = false
|
35
|
+
end
|
36
|
+
|
37
|
+
after do
|
38
|
+
SmsTools.use_gsm_encoding = true
|
39
|
+
end
|
40
|
+
|
41
|
+
it "returns Unicode as encoding for special symbols defined in GSM 03.38" do
|
42
|
+
detection_for('09azAZ@Δ¡¿£_!Φ"¥Γ#èΛ¤éΩ%ùΠ&ìΨòΣçΘΞ:Ø;ÄäøÆ,<Ööæ=ÑñÅß>Üüåɧà€~').encoding.must_equal :unicode
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'returns ASCII for simple ASCII text' do
|
46
|
+
detection_for('Hello world.').encoding.must_equal :ascii
|
47
|
+
end
|
48
|
+
|
49
|
+
it "defaults to ASCII encoding for empty messages" do
|
50
|
+
detection_for('').encoding.must_equal :ascii
|
51
|
+
end
|
52
|
+
end
|
31
53
|
end
|
32
54
|
|
33
55
|
describe "message length" do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: smstools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dimitar Dimitrov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-10-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -111,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
111
111
|
version: '0'
|
112
112
|
requirements: []
|
113
113
|
rubyforge_project:
|
114
|
-
rubygems_version: 2.
|
114
|
+
rubygems_version: 2.4.5.1
|
115
115
|
signing_key:
|
116
116
|
specification_version: 4
|
117
117
|
summary: Small library of classes for common SMS-related functionality.
|