smess 1.0.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.
@@ -0,0 +1,25 @@
1
+ module Smess
2
+ class Sms
3
+
4
+ attr_accessor :to, :message, :originator, :output, :results
5
+
6
+ def initialize(*args)
7
+ opts = args.first || {}
8
+ @to = opts.fetch(:to, nil)
9
+ @message = opts.fetch(:message, "")
10
+ @originator = opts.fetch(:originator, nil)
11
+ @output = opts.fetch(:output, "auto")
12
+ end
13
+
14
+ def deliver
15
+ out_class = output
16
+ out = ("Smess::#{out_class.to_s.camelize}").constantize.new
17
+ results = out.deliver_sms self
18
+ end
19
+
20
+ def delivered?
21
+ @results[:response_code] == "0" rescue false
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,91 @@
1
+ # encoding: UTF-8
2
+
3
+ module Smess
4
+
5
+ class << self
6
+
7
+ # cleans and forces the selected country prefix on the number given
8
+ # if international is set a lighter cleaning is done to preserve any existing country code
9
+ # this is not entirely problem-free for US area codes without leading 0.
10
+ def clean_phone(num)
11
+ num = num.to_s
12
+
13
+ return nil if /\{[a-z]+:.+\}/.match(num)
14
+
15
+ # make num all digits
16
+ num = num.gsub(/\D/,"")
17
+
18
+ if num.length > 0 && num[0..1] == "00"
19
+ num = num[2..-1]
20
+ elsif num.length > 0 && num[0] == "0"
21
+ # cut away leading zeros
22
+ num = num[1..-1] # while num[0] == "0"
23
+ # Add country code unless the start of the number is the correct country code
24
+ unless num[0..Smess.config.country_code.to_s.length-1] == Smess.config.country_code.to_s
25
+ num = Smess.config.country_code.to_s + num
26
+ end
27
+ elsif !Smess.config.international
28
+ # Add country code unless the start of the number is the correct country code
29
+ unless num[0..Smess.config.country_code.to_s.length-1] == Smess.config.country_code.to_s
30
+ num = Smess.config.country_code.to_s + num
31
+ end
32
+ end
33
+
34
+ # number must be in a valid range
35
+ unless (10..15) === num.length
36
+ return nil
37
+ end
38
+
39
+ num
40
+ end
41
+
42
+
43
+
44
+ # returns an array of strings of gsm-compatible lengths
45
+ # performance issue: utf8_safe_split also loops over the split point
46
+ # this should be used when sending via concatenating providers
47
+ def split_sms(text)
48
+ return [text] unless text.sms_length > 160
49
+
50
+ result = []
51
+ while text.sms_length > 0
52
+ end_char = 151
53
+ part = ""
54
+ while part.sms_length < 152 && part != text
55
+ end_char = end_char + 1
56
+ part = text.utf8_safe_split(end_char)[0] || ""
57
+ end
58
+ result << part
59
+ text = text.utf8_safe_split(end_char)[1] || ""
60
+ end
61
+ result
62
+ end
63
+
64
+ # returns an array of strings of <160 char lengths
65
+ # splits on whitespace and will mangle non-space whitespace
66
+ # this should be used when sending via non-concatenating providers
67
+ def separate_sms(text)
68
+ return [text] unless text.sms_length > 160
69
+
70
+ end_char = 160
71
+ result = []
72
+ while text.sms_length > end_char
73
+ part = ""
74
+ parts = text.utf8_safe_split(end_char)
75
+ text = parts[1]
76
+ splitpoint = end_char-parts[0].reverse.index(/[^\w-]+/)
77
+ split = parts[0].utf8_safe_split(splitpoint)
78
+ result << split[0].strip
79
+ text = (split[1]+text).strip rescue text
80
+ end
81
+ result << text
82
+ end
83
+
84
+
85
+ def booleanize(value)
86
+ value.to_s.downcase == "true"
87
+ end
88
+
89
+
90
+ end
91
+ end
@@ -0,0 +1,3 @@
1
+ module Smess
2
+ VERSION = '1.0.0'
3
+ end
@@ -0,0 +1,122 @@
1
+ class String
2
+ def to_underscore
3
+ self.gsub(/::/, '/').
4
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
5
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
6
+ tr("-", "_").
7
+ downcase
8
+ end
9
+
10
+
11
+ def valid_utf8?
12
+ !!unpack("U") rescue false
13
+ end
14
+
15
+ def utf8_safe_split(n)
16
+ if length <= n
17
+ [self, nil]
18
+ else
19
+ before = self[0, n]
20
+ after = self[n..-1]
21
+ until after.valid_utf8?
22
+ n = n - 1
23
+ before = self[0, n]
24
+ after = self[n..-1]
25
+ end
26
+ [before, after.empty? ? nil : after]
27
+ end
28
+ end
29
+
30
+ # like strlen but with SMS alphabet calculations
31
+ def sms_length
32
+ escaped = Regexp.escape('€|^{}[]~\\')
33
+ pattern = Regexp.new( "["+escaped+"]" )
34
+
35
+ self.length + self.scan(pattern).length
36
+ end
37
+
38
+
39
+ def strip_nongsm_chars(replacement = "")
40
+ ret = self.dup
41
+ ret.strip_nongsm_chars!(replacement)
42
+ ret
43
+ end
44
+
45
+ # Cleans a string to comply with the GSM alphabet
46
+ def strip_nongsm_chars!(replacement = "")
47
+ # Should this be a patch to String?
48
+
49
+ # keeping them here in canse I need them
50
+ #$basic_alpha = array(
51
+ # '@','£','$','¥','è','é','ù','ì','ò','Ç',"\n",'Ø','ø',"\r",'Å','å',
52
+ # 'Δ','_','Φ','Γ','Λ','Ω','Π','Ψ','Σ','Θ','Ξ','Æ','æ','ß','É',' ',
53
+ # '!','"','#','¤','%','&','\'','(',')','*','+',',','-','.','/','0',
54
+ # '1','2','3','4','5','6','7','8','9',':',';','<','=','>','?','¡',
55
+ # 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
56
+ # 'Q','R','S','T','U','V','W','X','Y','Z','Ä','Ö','Ñ','Ü','§','¿',
57
+ # 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p',
58
+ # 'q','r','s','t','u','v','w','x','y','z','ä','ö','ñ','ü','à'
59
+ #);
60
+ #$extended_alpha = array('|','^','€','{','}','[',']','~','\\');
61
+ #$all_alpha = array_merge($basic_alpha, $extended_alpha);
62
+
63
+ allowed = '@£$¥èéùìòÇ'+"\n"+'Øø'+"\r"+'ÅåΔ_ΦΓΛΩΠΨΣΘΞÆæßÉ'+' '+Regexp.escape('!"#¤%&\'()*+,-.')+'\/'+Regexp.escape('0123456789:;<=>?¡ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÑܧ¿abcdefghijklmnopqrstuvwxyzäöñüà|^€{}[]~\\')
64
+
65
+ map = {
66
+ /á|â|ã/ => "a",
67
+ /ê|ẽ|ë/ => "e",
68
+ /í|î|ï/ => "i",
69
+ /ó|ô|õ/ => "o",
70
+ /ú|ů|û/ => "u",
71
+ /ç/ => "Ç"
72
+ }
73
+
74
+ map.each do |key, value|
75
+ self.gsub!(key, value)
76
+ end
77
+
78
+ pattern = Regexp.new( "[^"+allowed+"]" )
79
+ self.gsub!(pattern,"")
80
+ end
81
+
82
+
83
+ # cleans and adds the country prefix on the string given preserveing any existing country code
84
+ # this is not entirely problem-free for US area codes without leading 0.
85
+ # if force_country_code is set it forces the selected country prefix on the string given
86
+ # yes old, yes crappy, yes convoluted... legacy stuff, ok.
87
+ def msisdn(*args)
88
+ ret = self.dup
89
+ ret.msisdn!(*args)
90
+ ret.empty? ? nil : ret
91
+ end
92
+ def msisdn!(country_code = 1, force_country_code = false)
93
+ self.replace("") and return self if /\{[a-z]+:.+\}/.match(self) # custom crap
94
+
95
+ # make num all digits
96
+ self.gsub!(/\D/,"")
97
+
98
+ if length > 0 && self[0..1] == "00"
99
+ self.replace(self[2..-1])
100
+ elsif length > 0 && self[0] == "0"
101
+ # cut away leading zeros
102
+ self.replace(self[1..-1])
103
+ # Add country code unless the start of the number is the correct country code
104
+ unless self[0..country_code.to_s.length-1] == country_code.to_s
105
+ self.prepend(country_code.to_s)
106
+ end
107
+ elsif force_country_code
108
+ # Add country code unless the start of the number is the correct country code
109
+ unless self[0..country_code.to_s.length-1] == country_code.to_s
110
+ self.prepend(country_code.to_s)
111
+ end
112
+ end
113
+
114
+ # number must be in a valid range
115
+ unless (10..15) === self.length
116
+ self.replace("") and return self
117
+ end
118
+
119
+ self
120
+ end
121
+
122
+ end
metadata ADDED
@@ -0,0 +1,192 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: smess
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Martin Westin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-09-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 2.4.0
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: 2.4.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: jahtml_formatter
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: dotenv
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: mail
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: savon
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '='
74
+ - !ruby/object:Gem::Version
75
+ version: 1.2.0
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '='
81
+ - !ruby/object:Gem::Version
82
+ version: 1.2.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: httpi
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: clickatell
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: twilio-ruby
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: activesupport
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - '>='
130
+ - !ruby/object:Gem::Version
131
+ version: '3.0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - '>='
137
+ - !ruby/object:Gem::Version
138
+ version: '3.0'
139
+ description: A mess of SMS messaging
140
+ email: martin@eimermusic.com
141
+ executables: []
142
+ extensions: []
143
+ extra_rdoc_files: []
144
+ files:
145
+ - lib/smess/country_code_registry.rb
146
+ - lib/smess/logging.rb
147
+ - lib/smess/outputs/auto.rb
148
+ - lib/smess/outputs/clickatell.rb
149
+ - lib/smess/outputs/etisalatdemo.rb
150
+ - lib/smess/outputs/global_mouth.rb
151
+ - lib/smess/outputs/iconectiv.rb
152
+ - lib/smess/outputs/ipx.rb
153
+ - lib/smess/outputs/ipxus.rb
154
+ - lib/smess/outputs/mblox.rb
155
+ - lib/smess/outputs/mm7.rb
156
+ - lib/smess/outputs/smsglobal.rb
157
+ - lib/smess/outputs/test.rb
158
+ - lib/smess/outputs/twilio.rb
159
+ - lib/smess/sms.rb
160
+ - lib/smess/utils.rb
161
+ - lib/smess/version.rb
162
+ - lib/smess.rb
163
+ - lib/string.rb
164
+ - Gemfile
165
+ - Gemfile.lock
166
+ - LICENSE
167
+ - README.md
168
+ homepage: https://github.com/eimermusic/smess
169
+ licenses: []
170
+ metadata: {}
171
+ post_install_message:
172
+ rdoc_options: []
173
+ require_paths:
174
+ - lib
175
+ required_ruby_version: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - '>='
178
+ - !ruby/object:Gem::Version
179
+ version: 1.9.2
180
+ required_rubygems_version: !ruby/object:Gem::Requirement
181
+ requirements:
182
+ - - '>='
183
+ - !ruby/object:Gem::Version
184
+ version: 1.3.7
185
+ requirements: []
186
+ rubyforge_project:
187
+ rubygems_version: 2.0.2
188
+ signing_key:
189
+ specification_version: 4
190
+ summary: A messy SMS messenger supporting every aggregator I have gotten my hands
191
+ on
192
+ test_files: []