action_smser 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # ActionSmser
2
2
 
3
- Simple way to use SMS (Short Message Service) in the same way as ActionMailer (ActionSmser == ActionMailer).
3
+ ActionSmser == SMS && ActionMailer. Simple way to use SMS (Short Message Service) in the same way as ActionMailer.
4
4
  Includes also delivery reports and easy way to add custom gateways. See examples below.
5
5
 
6
6
  [<img src="https://secure.travis-ci.org/holli/action_smser.png" />](http://travis-ci.org/holli/action_smser)
@@ -16,7 +16,7 @@ Gemfile ->
16
16
  gem 'action_smser'
17
17
 
18
18
  # To use delivery reports
19
- bundle exec rake railties:install:migrations FROM=ActionSmser
19
+ bundle exec rake railties:install:migrations
20
20
  rake db:migrate
21
21
  ```
22
22
 
@@ -68,6 +68,37 @@ Optional delivery methods can be used by creating classes under "ActionSmser::De
68
68
  them as downcase infos. See example of :simple_http at
69
69
  https://github.com/holli/action_smser/blob/master/lib/action_smser/delivery_methods/simple_http.rb
70
70
 
71
+ Simplest case is to use simple_http and override path
72
+
73
+ ```
74
+ # Example of changing simple_http delivery path. Options are the same options that were presented above.
75
+
76
+ module ActionSmser::DeliveryMethods
77
+ class SimpleHttp
78
+ def self.deliver_path(sms, options)
79
+ "/my_gateways_api/send?user=#{options[:username]}&password=#{options[:password]}&ValidityPeriod=24:00&sender=#{sms.from_encoded}&SMSText=#{sms.body_encoded_escaped}&GSM=#{sms.to_encoded}"
80
+ end
81
+ end
82
+ end
83
+
84
+ ```
85
+
86
+ **Nexmo** (http://nexmo.com/) is supported also.
87
+
88
+ ```
89
+ ActionSmser.delivery_options[:delivery_method] = :nexmo
90
+ ActionSmser.delivery_options[:nexmo] = {
91
+ :username => 'key', :password => "password"
92
+ }
93
+
94
+ # set callback url to nexmo http://localhost:3000/action_smser/delivery_reports/gateway_commit/nexmo
95
+ ActionSmser.delivery_options[:gateway_commit]['nexmo'] = ActionSmser::DeliveryMethods::Nexmo
96
+
97
+ ```
98
+
99
+ If you add other common gateways to this framework, plz generate tests and send us a patch.
100
+
101
+
71
102
  ## Delivery reports
72
103
 
73
104
  Gem handles collecting and analysing of delivery reports. This enables you to make sure that your gateway works.
@@ -110,23 +141,24 @@ class ActionSmserConfigExample
110
141
  end
111
142
  end
112
143
 
113
-
114
144
  # This is simple proc that is used in a before filter, if it returns true it allows access to
115
145
  # http://localhost.inv:3000/action_smser/delivery_reports/ with infos about delivery reports
116
146
  ActionSmser.delivery_options[:admin_access] = ActionSmserConfigExample
117
147
 
118
- # This gives ActionSmser way to parse infos from pushed to gateway
119
- # Params is all params gotten in the request
120
- test_gateway = lambda
121
-
122
148
  # Parser is used with urls like
123
149
  # /action_smser/delivery_reports/gateway_commit/test_gateway
124
150
  # where 'test_gateway' is the part that is used for locating right parser.
125
- ActionSmser.delivery_options[:gateway_commit] = {'test_gateway' => test_gateway}
126
-
151
+ ActionSmser.delivery_options[:gateway_commit]['test_gateway'] = ActionSmserConfigExample
127
152
 
128
153
  ```
129
154
 
155
+ DeliveryReports can be searched by "dr = ::ActionSmser::DeliveryReport.where(xxx).first".
156
+ Some helpers in delivery_reports include
157
+
158
+ - dr.to_sms => creates new sms message from deliveryreport.
159
+ - dr.resent(:gateway) => creates new sms and sends it through given gateway.
160
+
161
+
130
162
  ## Other options
131
163
 
132
164
  Observers can be used by implementing "delivery_observer" in your sms class
@@ -138,12 +170,32 @@ class TestSms < ActionSmser::Base
138
170
  sms(:to => to, :from => from, :body => str)
139
171
  end
140
172
 
173
+ def before_delivery()
174
+ puts "Called just before delivery"
175
+ end
176
+
141
177
  def after_delivery(response_from_delivery_method)
142
178
  puts "Done with delivery"
143
179
  end
144
180
  end
145
181
  ```
146
182
 
183
+ Gateway committed status updates can also have observers
184
+
185
+ ```
186
+ in /config/initializers/active_smser.rb
187
+
188
+ class ActionSmserConfigGatewayObserver
189
+ def self.after_gateway_commit(delivery_reports)
190
+ puts delivery_reports.inspect
191
+ end
192
+ end
193
+
194
+ ActionSmser.gateway_commit_observer_add(ActionSmserConfigGatewayObserver)
195
+
196
+ ```
197
+
198
+
147
199
  ## Testing
148
200
 
149
201
  Default delivery method is "test_array". It saves delivered sms to ActionSmser::DeliveryMethods::TestArray.deliveries to help test your own software.
@@ -11,10 +11,11 @@ module ActionSmser
11
11
 
12
12
  ActionSmser::Logger.info("Gateway_commit found parser for gateway: #{params['gateway']}")
13
13
 
14
- dr_array = ActionSmser.delivery_options[:gateway_commit][params['gateway']].send(:process_delivery_report, params)
14
+ dr_var_array = ActionSmser.delivery_options[:gateway_commit][params['gateway']].send(:process_delivery_report, params)
15
+ dr_array = []
15
16
 
16
- if !dr_array.blank?
17
- dr_array.each do |dr_update|
17
+ if !dr_var_array.blank?
18
+ dr_var_array.each do |dr_update|
18
19
  msg_id = dr_update["msg_id"]
19
20
  dr = ActionSmser::DeliveryReport.where(:msg_id => msg_id).first
20
21
 
@@ -23,9 +24,9 @@ module ActionSmser
23
24
  dr.send("#{key}=", value) if dr.attribute_names.include?(key.to_s)
24
25
  end
25
26
 
26
-
27
27
  if dr.save
28
28
  updated_count += 1
29
+ dr_array << dr
29
30
  ActionSmser::Logger.info("Gateway_commit updated item with id: #{msg_id}, params: #{dr_update.inspect}")
30
31
  else
31
32
  ActionSmser::Logger.info("Gateway_commit problem updating item with id: #{msg_id}, params: #{dr_update.inspect}")
@@ -35,6 +36,16 @@ module ActionSmser
35
36
  end
36
37
  end
37
38
  end
39
+
40
+ begin
41
+ ActionSmser.delivery_options[:gateway_commit_observers].each do |observer|
42
+ observer.after_gateway_commit(dr_array)
43
+ end
44
+ rescue Exception => e
45
+ ActionSmser::Logger.error("Problem with gateway_commit_observers: #{e}")
46
+ end
47
+
48
+
38
49
  end
39
50
 
40
51
  if updated_count > 0
@@ -44,12 +55,18 @@ module ActionSmser
44
55
  end
45
56
  end
46
57
 
58
+
47
59
  before_filter :admin_access_only, :except => :gateway_commit
48
60
 
49
61
  def index
50
62
 
51
63
  end
52
64
 
65
+ def list
66
+
67
+ end
68
+
69
+
53
70
  def admin_access_only
54
71
  if !ActionSmser.delivery_options[:admin_access].blank? && ActionSmser.delivery_options[:admin_access].send(:admin_access, self)
55
72
  return true
@@ -1,15 +1,20 @@
1
1
  module ActionSmser
2
2
  class DeliveryReport < ActiveRecord::Base
3
3
 
4
+ has_many :re_deliveries, :class_name => self.to_s, :foreign_key => :re_delivery_of_delivery_report_id
5
+ puts self
6
+ belongs_to :re_delivery_of, :class_name => self.to_s, :foreign_key => :re_delivery_of_delivery_report_id
7
+
4
8
  def self.build_from_sms(sms, to, msg_id)
5
9
  @delivery_report = self.new
6
10
 
7
- [:from, :body, :sms_type].each do |var|
11
+ [:from, :body, :sms_type, :re_delivery_of_delivery_report_id].each do |var|
8
12
  @delivery_report.send("#{var}=", sms.send(var))
9
13
  end
10
14
  @delivery_report.to = to
11
15
  @delivery_report.msg_id = msg_id
12
16
  @delivery_report.status = "LOCAL_SENT"
17
+ @delivery_report.gateway = sms.delivery_options[:delivery_method].to_s
13
18
  @delivery_report
14
19
  end
15
20
 
@@ -22,8 +27,36 @@ module ActionSmser
22
27
  def status=(stat, skip_log = false)
23
28
  self[:status] = stat
24
29
  self.status_updated_at = Time.now
30
+ add_log("#{Time.now.to_s(:db)}: #{stat}") unless skip_log
31
+ end
32
+
33
+ def add_log(str)
25
34
  self.log = "" if self.log.nil?
26
- self.log += "#{Time.now.to_s(:db)}: #{stat}\n" if !skip_log
35
+ self.log += "#{str}\n"
36
+ end
37
+
38
+ # Copy this delivery_report information to a new sms object
39
+ def to_sms
40
+ sms_new = ActionSmser::Base.new()
41
+ [:sms_type, :to, :from, :body, :sms_type].each do |var|
42
+ sms_new.send("#{var}=", self.send(var))
43
+ end
44
+ sms_new
45
+ end
46
+
47
+ def re_deliver(gateway = :default)
48
+ ActionSmser::Logger.info("Re_delivering: #{self.inspect}")
49
+ self.update_attribute(:re_delivered, true)
50
+
51
+ sms_new = self.to_sms
52
+ sms_new.sms_type = "#{sms_new.sms_type}.re_delivery"
53
+ sms_new.re_delivery_of_delivery_report_id = self.id
54
+
55
+ unless gateway == :default
56
+ sms_new.delivery_options[:delivery_method] = gateway
57
+ end
58
+
59
+ [sms_new, sms_new.deliver]
27
60
  end
28
61
 
29
62
  end
@@ -14,28 +14,53 @@ time_span = case params['time_span'].to_s.downcase
14
14
  else
15
15
  1.week.ago..10.minutes.ago
16
16
  end
17
+
18
+ ar_timespan = ActionSmser::DeliveryReport.where(:created_at => time_span)
19
+
20
+ ar_gateway = ar_timespan
21
+ ar_gateway = ar_gateway.where(:gateway => params[:gateway]) if (params[:gateway] && params[:gateway].to_s != 'all')
22
+
17
23
  %>
18
24
 
19
25
 
20
- <h1>Delivery Reports Summary for <%= params['time_span'] %></h1>
26
+ <h1>Delivery Reports Summary for <%= params['time_span'] %> <%= "for #{params[:gateway]}" unless params[:gateway].blank? %></h1>
21
27
 
22
28
  <p>
23
29
  Show summary:
24
- <%= link_to 'Last 24 hours', delivery_reports_path(:time_span => 'Last 24 Hours') %>,
25
- <%= link_to '24 hours before that', delivery_reports_path(:time_span => 'Previous 24 Hours') %>,
26
- <%= link_to 'Last week', delivery_reports_path(:time_span => 'Last Week') %>,
27
- <%= link_to 'Week before that', delivery_reports_path(:time_span => 'Previous Week') %> or
28
- <%= link_to 'Last month', delivery_reports_path(:time_span => 'Last Month') %>.
30
+ <%= link_to 'Last 24 hours', delivery_reports_path(:time_span => 'Last 24 Hours', :gateway => params[:gateway]) %>,
31
+ <%= link_to '24 hours before that', delivery_reports_path(:time_span => 'Previous 24 Hours', :gateway => params[:gateway]) %>,
32
+ <%= link_to 'Last week', delivery_reports_path(:time_span => 'Last Week', :gateway => params[:gateway]) %>,
33
+ <%= link_to 'Week before that', delivery_reports_path(:time_span => 'Previous Week', :gateway => params[:gateway]) %> or
34
+ <%= link_to 'Last month', delivery_reports_path(:time_span => 'Last Month', :gateway => params[:gateway]) %>.
29
35
  </p>
30
36
 
31
- <h2>Delivered Within (hour:min:sec)</h2>
37
+ <h2>Select gateway</h2>
32
38
 
33
- <%
34
- ar = ActionSmser::DeliveryReport.where(:created_at => time_span)
35
- ar_delivered = ar.where(:status => 'delivered')
36
- total = ar.count
37
- total_delivered = ar_delivered.count
38
- %>
39
+ <ul>
40
+ <li>
41
+ <strong>
42
+ <%= link_to('all', delivery_reports_path(:time_span => params[:time_span]) ) %>
43
+ </strong>
44
+ &nbsp;&nbsp;
45
+ (you can select only gateways that have messages in this period)
46
+ </li>
47
+ <%
48
+ total = ar_timespan.count
49
+ grouped_by_status = ar_timespan.group(:gateway).count.each do |key, val| %>
50
+ <li>
51
+ <strong>
52
+ <%= link_to(key, delivery_reports_path(:time_span => params[:time_span], :gateway => key) ) %>
53
+ </strong>
54
+ &nbsp;&nbsp;
55
+ <%= val %> sms
56
+ &nbsp;&nbsp;
57
+ (<strong><%= number_to_percentage(100.0 * val / total, :precision => 2) %></strong>)
58
+ </li>
59
+ <% end %>
60
+ </ul>
61
+
62
+
63
+ <h2>Delivered Within (hour:min:sec)</h2>
39
64
 
40
65
  <% if ActiveRecord::Base.connection.adapter_name.downcase.to_s.include?("mysql") %>
41
66
 
@@ -47,6 +72,10 @@ Show summary:
47
72
  <th>% of delivered sms</th>
48
73
  </tr>
49
74
 
75
+ <% ar_delivered = ar_gateway.where(:status => 'delivered')
76
+ total = ar_gateway.count
77
+ total_delivered = ar_delivered.count
78
+ %>
50
79
  <% ["00:00:30", "00:01:00", "00:02:00", "00:10:00", "00:30:00", "00:90:00", "24:00:00", "48:00:00"].each do |time| %>
51
80
  <% dev_count = ar_delivered.where('TIMEDIFF(status_updated_at, created_at) < ?', time).count %>
52
81
  <tr>
@@ -66,9 +95,8 @@ Show summary:
66
95
  <h2>DeliveryReport Statuses</h2>
67
96
  <ul>
68
97
  <%
69
- quest = ActionSmser::DeliveryReport.where(:created_at => time_span)
70
- total = quest.count
71
- grouped_by_status = quest.group(:status).count.each do |key, val| %>
98
+ total = ar_gateway.count
99
+ grouped_by_status = ar_gateway.group(:status).count.each do |key, val| %>
72
100
 
73
101
  <li>
74
102
  <strong><%= key %></strong>:
@@ -91,9 +119,8 @@ Show summary:
91
119
  </tr>
92
120
 
93
121
  <%
94
- quest = ActionSmser::DeliveryReport.where(:created_at => time_span)
95
- total = quest.count
96
- grouped_by_status = quest.group(:sms_type).count.each do |key, val| %>
122
+ total = ar_gateway.count
123
+ grouped_by_status = ar_gateway.group(:sms_type).count.each do |key, val| %>
97
124
  <tr>
98
125
  <td><strong><%= key %></strong></td>
99
126
  <td><%= val %></td>
@@ -105,46 +132,3 @@ Show summary:
105
132
  </table>
106
133
 
107
134
 
108
- <hr>
109
-
110
- <% items_within_page = 20 %>
111
- <h1 id="delivery_reports_list"><%= items_within_page %> delivery_reports ordered by created_at</h1>
112
-
113
- <%
114
- offset = params[:offset].to_i
115
- offset = 0 if offset < -0
116
- %>
117
-
118
- <p>
119
- <strong>List offset: <%= offset %>.</strong>
120
- Add
121
- <%= link_to("- #{items_within_page}", delivery_reports_path(:offset => offset-items_within_page, :anchor => 'delivery_reports_list')) unless offset == 0 %>
122
- <%= link_to "+ #{items_within_page}", delivery_reports_path(:offset => offset+items_within_page, :anchor => 'delivery_reports_list') %>
123
- to offset
124
- </p>
125
-
126
- <table style="margin-top: 20px;">
127
- <tr>
128
- <th>Created_at</th>
129
- <th>Msg id</th>
130
- <th>Status</th>
131
- <th>Status updated at</th>
132
- <th>Recipient</th>
133
- <th>Sender</th>
134
- <th>Text body</th>
135
- </tr>
136
-
137
- <% ActionSmser::DeliveryReport.order('created_at DESC').offset(offset).first(items_within_page).each do |delivery_report| %>
138
- <tr>
139
- <td style="white-space: nowrap;"><%= delivery_report.created_at %></td>
140
- <td><%= delivery_report.msg_id %></td>
141
- <td><%= delivery_report.status %></td>
142
- <td style="white-space: nowrap;"><%= delivery_report.status_updated_at %></td>
143
- <td><%= delivery_report.to %></td>
144
- <td><%= delivery_report.from %></td>
145
- <td><%= delivery_report.body %></td>
146
- </tr>
147
- <% end %>
148
- </table>
149
-
150
-
@@ -0,0 +1,52 @@
1
+
2
+ <% items_within_page = 20 %>
3
+ <h1 id="delivery_reports_list"><%= items_within_page %> delivery_reports ordered by created_at</h1>
4
+
5
+ <%
6
+ offset = params[:offset].to_i
7
+ offset = 0 if offset < -0
8
+ %>
9
+
10
+ <p>
11
+ <strong>List offset: <%= offset %>.</strong>
12
+ Add
13
+ <%= link_to("- #{items_within_page}", list_delivery_reports_path(:offset => offset-items_within_page)) unless offset == 0 %>
14
+ <%= link_to "+ #{items_within_page}", list_delivery_reports_path(:offset => offset+items_within_page) %>
15
+ to offset
16
+ </p>
17
+
18
+ <table style="margin-top: 20px; font-size: 10px;">
19
+ <tr>
20
+ <th>Id</th>
21
+ <th>Created_at</th>
22
+ <th>Msg id</th>
23
+ <th>Gateway</th>
24
+ <th>Status</th>
25
+ <th>Status updated at</th>
26
+ <th>Recipient</th>
27
+ <th>Sender</th>
28
+ <th>Sms Type</th>
29
+ <th>Re Delivered</th>
30
+ <th>Re Delivery Of</th>
31
+ <th>&nbsp;O</th>
32
+ </tr>
33
+
34
+ <% ActionSmser::DeliveryReport.order('created_at DESC').offset(offset).first(items_within_page).each do |delivery_report| %>
35
+ <tr>
36
+ <td style="white-space: nowrap;"><%= delivery_report.id %></td>
37
+ <td style="white-space: nowrap;"><%= delivery_report.created_at %></td>
38
+ <td><%= delivery_report.msg_id %></td>
39
+ <td><%= delivery_report.gateway %></td>
40
+ <td><%= delivery_report.status %></td>
41
+ <td style="white-space: nowrap;"><%= delivery_report.status_updated_at %></td>
42
+ <td><%= delivery_report.to %></td>
43
+ <td><%= delivery_report.from %></td>
44
+ <td><%= delivery_report.sms_type %></td>
45
+ <td><%= delivery_report.re_delivered? %></td>
46
+ <td><%= delivery_report.re_delivery_of.msg_id unless delivery_report.re_delivery_of.blank? %></td>
47
+ <td title="<%= delivery_report.body %>">&nbsp;O</td>
48
+ </tr>
49
+ <% end %>
50
+ </table>
51
+
52
+
@@ -14,7 +14,7 @@
14
14
  }
15
15
  th, td {
16
16
  border: 1px solid gray;
17
- padding: 1px 10px 1px 3px;
17
+ padding: 1px 8px 1px 3px;
18
18
  }
19
19
 
20
20
  h1 { margin-top: 40px; }
@@ -29,6 +29,9 @@
29
29
 
30
30
  }
31
31
  hr { margin-top: 20px; margin-bottom: 10px; }
32
+
33
+ .menu { margin-top: 30px; }
34
+ .menu a { margin-right: 20px; font-size: 16px; }
32
35
 
33
36
  </STYLE>
34
37
 
@@ -37,7 +40,9 @@
37
40
 
38
41
  <h1>ActionSmser infos</h1>
39
42
 
40
- Back to <%= link_to 'Main application', '/' %>
43
+ <div class="menu">
44
+ <%= link_to 'Main application', '/' %> <%= link_to 'Summary of SMS', delivery_reports_path -%> <%= link_to 'List All SMS', list_delivery_reports_path %>
45
+ </div>
41
46
 
42
47
  <hr>
43
48