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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4180ff46eb40f9d709cf9895d1dc493aeec4203c
4
- data.tar.gz: cba4fd705516f2418dfae93ce3732231e30faba5
3
+ metadata.gz: b0c466ba58b15a65599eb4abbaac0d22a6f82ac5
4
+ data.tar.gz: 416a9721a3ada4264dee86f28e1af344b24a8dbf
5
5
  SHA512:
6
- metadata.gz: b3b26b73c00f2acbb9e107ecc24738b97a713a3579c685339226b9ba369c0d2080ff7b40357a472c0dc9ebe41bca0f8ed38e28cd132242ce7ed3e514a78d69c3
7
- data.tar.gz: 9b7a0e6a64fdaec4f8f05130dc3b4ac735f2848fddfd1bbd8d274ec2b6e9781fcdb993ef121357e77f6b4c486508a067e6480516a72fd33d7c28007397f0fde5
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 useful Ruby and JavaScript classes implementing often
4
- needed functionality for dealing with SMS messages.
3
+ A small collection of Ruby and JavaScript classes implementing often needed functionality for
4
+ dealing with SMS messages.
5
5
 
6
- The gem is also a Rails engine and using it in your Rails app will allow you
7
- to also use the JavaScript classes via the asset pipeline.
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
- or Unicode).
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
- And more.
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 one.
91
+ use either.
40
92
 
41
93
  ### Server-side code
42
94
 
43
- If you use the gem in Rails or via Bundler, just use the appropriate class,
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
- #### `EncodingDetection`
47
- #### `GsmEncoding`
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.x or newer, you can just add the following
52
- to your `application.js` file to gain access to the JavaScript classes:
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
- #= require 'sms_tools/all'
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
- Or require only the files you need:
166
+ ```coffeescript
167
+ maxConcatenatedPartsCount = 2
168
+ message.maxLengthFor(maxConcatenatedPartsCount) # => 306
169
+ ```
57
170
 
58
- #= require 'sms_tools/message'
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 assumes you're using the asset pipeline. You need to have a
61
- CoffeeScript preprocessor set up.
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 @gsmEncodingPattern.test(@text) then 'gsm' else 'unicode'
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
- # Returns the number of symbols, which the given text will take up in an SMS
49
- # message, taking into account any double-space symbols in the GSM 03.38
50
- # encoding.
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 ||= GsmEncoding.valid?(text) ? :gsm : :unicode
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
- # Returns the number of symbols, which the given text will take up in an SMS
53
- # message, taking into account any double-space symbols in the GSM 03.38
54
- # encoding.
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?
@@ -1,3 +1,3 @@
1
1
  module SmsTools
2
- VERSION = '0.0.1'
2
+ VERSION = '0.1.0'
3
3
  end
@@ -1,5 +1,5 @@
1
1
  require 'spec_helper'
2
- require 'sms_tools/encoding_detection'
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 GSM encoding for empty messages" do
11
- detection_for('').encoding.must_equal :gsm
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 GSM as encoding for simple ASCII text" do
15
- detection_for('foo bar baz').encoding.must_equal :gsm
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 GSM as encoding for puntucation and newline symbols" do
23
- detection_for('Foo bar {} [baz]! Larodi $5. What else?').encoding.must_equal :gsm
24
- detection_for("Spaces and newlines are GSM 03.38, too: \r\n").encoding.must_equal :gsm
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.1
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: 2014-01-17 00:00:00.000000000 Z
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.2.0
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.