smstools 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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.
|