bianchi 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6fe9c6aabbf8e704a9ea9403896cc71c9aedf9a5f8bf5a5433469dba9e80d40b
4
- data.tar.gz: 4caa2699c795f348136640d2300e636c8ce2848daf7605a0596749507034286a
3
+ metadata.gz: 57689540f35b1837b227a23ec9b9badd237e5e1bda6b7f0b5c3d64443b404fd9
4
+ data.tar.gz: b963e56598337607ef36f0d4ebb514c9a83e354c3dc65d55d3ad299c856668b3
5
5
  SHA512:
6
- metadata.gz: 3f56b2bf18384a755a4e6022b457e450c54efeb088926e112fca3b0ba6a7732a3762d83243a30572fd704c0131c816154e7cf4bbb3548fb489af5c0f11bdbec9
7
- data.tar.gz: f763c36ef9616506fc87223383bb73487f0fc37901e8e14e99078970ad86c618b97f6b4602ef8140f95d182d23f62c23878fe72c68db9b84f3075ed3e5db8419
6
+ metadata.gz: 9272b56f5a057de49f9695cc615afcf05fbdcb14db6f31f582bf8d6b421b4dc8787ba5fbbcab87a120aaf4fd0519fad88c66f842423984915dbf271de3076207
7
+ data.tar.gz: ce5f129f37e80ff25fa642af17ae8d5f31b467f580419a7b053afe941979f6e09cf9183668a9443aea262c2d933f41a1656401098e6ef6d8d8ac26ed890b2d22
data/README.md CHANGED
@@ -1,43 +1,197 @@
1
- # bianchi
1
+ # Bianchi
2
+ A DSL (Domain-Specific Language) and a minimalist framework in Ruby, tailored for USSD development. Structured around a menu page approach, Bianchi offers a comprehensive suite of methods and generators, streamlining the process of building USSD applications efficiently and easily.
2
3
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/bianchi`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+ ## Installation
5
+ Add `gem 'bianchi', '~> 0.1.0'` to your gem file and run `bundle install`
4
6
 
5
- TODO: Delete this and the text above, and describe your gem
7
+ Bianchi relies on Redis and requires the `REDIS_URL` environment variable to be set, pointing to your Redis instance. Ensure Redis is installed, running, and that REDIS_URL is correctly configured before using Bianchi.
6
8
 
7
- ## Installation
9
+ ## Getting Started
10
+
11
+ To initialize a new USSD project, generate a project directory using Bianchi's command-line interface. Use the following Ruby command:
12
+
13
+ ```ruby
14
+ bundle exec bianchi setup -p provider_name
15
+ ```
16
+
17
+ Replace `provider_name` with your desired provider. Currently supported providers include: africa_is_talking.
18
+
19
+ This command creates a `ussd/engine.rb` file in the project root directory. Here's a sample content of `ussd/engine.rb`:
20
+
21
+ ```ruby
22
+ module USSD
23
+ class Engine
24
+ def self.start(params)
25
+ Bianchi::USSD::Engine.start(params, provider: :africa_is_talking) do
26
+ # e.g menu :main, options
27
+ end
28
+ end
29
+ end
30
+ end
31
+ ```
32
+
33
+ To define menus for your USSD applications' engine instance, use the following command:
34
+
35
+ ```ruby
36
+ menu :menu_name, options
37
+ ```
38
+
39
+ For example, let's define our first menu, which serves as the initial menu of the application, and let's call this the main menu:
40
+
41
+ ```ruby
42
+ menu :main, initial: true
43
+ ```
44
+ now that we have the initial menu up let's generate our pages for that menu using Bianchi's command-line interface. Use the following Ruby command:
45
+ ```ruby
46
+ command: bundle exec bianchi g menu menu_name page page_number
47
+ example: bianchi g menu main page 1
48
+ ```
49
+ This creates a `ussd/main_menu/page_1` file in the project root directory. Here's a sample content of the file:
50
+
51
+ ```ruby
52
+ module USSD
53
+ module MainMenu
54
+ class Page1 < Bianchi::USSD::Page
55
+ def request
56
+ end
57
+
58
+ def response
59
+ end
60
+ end
61
+ end
62
+ end
63
+ ```
8
64
 
9
- Add this line to your application's Gemfile:
65
+ In the `ussd/main_menu/page_1` file, the main application code goes into the `request` and `response` methods. Here's a sample code to illustrate the usage:
10
66
 
11
67
  ```ruby
12
- gem 'bianchi'
68
+ module USSD
69
+ module MainMenu
70
+ class Page1 < Bianchi::USSD::Page
71
+ def request
72
+ render_and_await(request_body)
73
+ end
74
+
75
+ def response
76
+ case session_input_body
77
+ when "1"
78
+ redirect_to_greetings_menu_page_1
79
+ when "2"
80
+ redirect_to_repeat_menu_page_1
81
+ else
82
+ render_and_await("invalid input \n" + request_body)
83
+ end
84
+ end
85
+
86
+ private
87
+
88
+ def request_body
89
+ <<~MSG
90
+ Welcome
91
+ 1. Greetings
92
+ 2. Repeat my name
93
+ MSG
94
+ end
95
+ end
96
+ end
97
+ end
13
98
  ```
14
99
 
15
- And then execute:
100
+ In this example, when a page is requested, you send some information, and the end user submits data for that request. The `response` method processes the response data and can move to a new page request, end the session, or send a response from there.
101
+ ### Page Renders
16
102
 
17
- $ bundle install
103
+ In Bianchi USSD applications, any method that starts with `render` sends data back to the user. Typically, we either send data and expect a response or send data and terminate the session. Here are the two main methods for rendering pages:
18
104
 
19
- Or install it yourself as:
105
+ - `render_and_await(string)`: Responds to the user and expects the user to respond.
20
106
 
21
- $ gem install bianchi
107
+ - `render_and_end(string)`: Responds to the user and terminates the session.
22
108
 
23
- ## Usage
109
+ Here's how you can use these methods in Ruby:
110
+ ```ruby
111
+ render_and_await("Please select an option:")
112
+ ```
113
+ This method sends the message "Please select an option:" to the user and awaits their response.
114
+ ```ruby
115
+ render_and_end("Thank you for using our service. Goodbye!")
116
+ ```
117
+ This method sends the message "Thank you for using our service. Goodbye!" to the user and terminates the session.
118
+
119
+ ### Page Session
120
+
121
+ In Bianchi USSD applications, the `session` serves as an information tracker between all the pages and records all interactions between the user and the application. It contains valuable information necessary for the USSD application to function properly.
122
+
123
+ Here are the methods available within the page session:
124
+
125
+ - `session_params`: Returns a hash containing all the data the provider sent.
126
+ - `session_input_body`: Retrieves the user's current input.
127
+ - `session_mobile_number`: Returns the current user's phone number dialing the code.
128
+ - `session_session_id`: Provides the session's ID.
129
+ - `session.store`: Accesses the current session's cache. Further details about this will be discussed later.
130
+
131
+ ### Page Store
132
+
133
+ In Bianchi USSD applications, the `session.store` serves as the main application cache, where data can be stored and accessed across all pages.
134
+
135
+ Here are the methods available within the page store:
136
+
137
+ - `session.store.set(key, value)`: Stores a key-value pair in the cache.
138
+ - `session.store.get(key)`: Retrieves the value associated with a given key from the cache.
139
+ - `session.store.all`: Returns the entire cache as a hash.
24
140
 
25
- TODO: Write usage instructions here
141
+ Here's how you can use these methods to manage your application's cache:
26
142
 
27
- ## Development
143
+ ```ruby
144
+ # Storing data in the cache
145
+ session.store.set('user_id', 123)
146
+
147
+ # Retrieving data from the cache
148
+ user_id = session.store.get('user_id')
149
+
150
+ # Retrieving the entire cache
151
+ all_data = session.store.all
152
+ ```
153
+
154
+ ### Page Redirects
155
+
156
+ In Bianchi USSD applications, any method that starts with `redirect_to` initiates another page request to be sent to the user. An example use case is when you want to transition to another menu page after processing the user's response.
28
157
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
158
+ For instance, in the snippet of the main menu page provided earlier, we use `redirect_to_greetings_menu_page_1` when the user selects "1". This directs the application to the greetings menu page 1's request.
30
159
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
160
+ Here are the methods available within the page redirects:
32
161
 
33
- ## Contributing
162
+ - `redirect_to_menu_[menu_name]_page_[page_number]`: Redirects to a specified menu using the `menu_name` and loads the page specified by `page_number`.
163
+ - `redirect_to_[next|previous]_page`: Redirects to the next or previous page within the same menu.
34
164
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/bianchi. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/bianchi/blob/master/CODE_OF_CONDUCT.md).
165
+ Here's how you can use these methods within your Bianchi USSD application:
36
166
 
37
- ## License
167
+ ```ruby
168
+ # Redirecting to a specific menu page
169
+ redirect_to_menu_greetings_page_1
170
+
171
+ # Redirecting to the next or previous page in the same menu
172
+ redirect_to_next_page
173
+ redirect_to_previous_page
174
+ ```
38
175
 
39
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
176
+ ## Responding to the Provider
40
177
 
41
- ## Code of Conduct
178
+ Once all processes are completed, the next step is to prepare the response to send to the provider. The provider prompt data is accessible via the engine instance's `prompt_data` attribute.
42
179
 
43
- Everyone interacting in the bianchi project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/bianchi/blob/master/CODE_OF_CONDUCT.md).
180
+ Here's an example of how you can retrieve the provider prompt data in your USSD application:
181
+
182
+ ```ruby
183
+ module USSD
184
+ class Engine
185
+ def self.start(params)
186
+ Bianchi::USSD::Engine.start(params, provider: :africa_is_talking) do
187
+ menu :main, options
188
+ menu :greetings
189
+ menu :repeat
190
+ end
191
+ end
192
+ end
193
+ end
194
+
195
+ # Retrieving provider prompt data
196
+ provider_data = USSD::Engine.new(provider_params).prompt_data
197
+ ```
data/bianchi.gemspec CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |spec|
6
6
  spec.name = "bianchi"
7
7
  spec.version = Bianchi::VERSION
8
8
  spec.authors = ["Dapilah Sydney"]
9
- spec.email = ['dapilah.sydney@gmail.com']
9
+ spec.email = ["dapilah.sydney@gmail.com"]
10
10
 
11
11
  spec.summary = "Write a short summary, because RubyGems requires one."
12
12
  spec.homepage = "https://github.com/SydDaps/Bianchi"
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # rubocop:disable Metrics/ParameterLists
4
3
  module Bianchi
5
4
  module Cli
6
5
  class Main < Thor
@@ -25,10 +24,10 @@ module Bianchi
25
24
  \x5 Example: `bianchi setup -p :africa_is_talking`
26
25
 
27
26
  LONG_DESC
28
- method_option :provider, :aliases => "-p", type: :string, :desc => "Set up ussd project for provider"
27
+ method_option :provider, aliases: "-p", type: :string, desc: "Set up ussd project for provider"
29
28
  def setup
30
29
  @provider = options[:provider]
31
- unless ["africa_is_talking", "none"].include? @provider
30
+ unless %w[africastalking none].include? @provider
32
31
  say("Error: provider #{@provider} is not yet configured.", :yellow)
33
32
  exit(1)
34
33
  end
@@ -63,4 +62,3 @@ module Bianchi
63
62
  end
64
63
  end
65
64
  end
66
- # rubocop:enable Metrics/ParameterLists
@@ -1,11 +1,9 @@
1
1
  module USSD
2
2
  module <%= @menu_name.camelize %>Menu
3
3
  class Page<%= @page_number %> < Bianchi::USSD::Page
4
- def request
5
- end
4
+ def request; end
6
5
 
7
- def response
8
- end
6
+ def response; end
9
7
  end
10
8
  end
11
9
  end
@@ -29,8 +29,11 @@ module Bianchi
29
29
  page = constant_name.safe_constantize
30
30
 
31
31
  unless page
32
- raise PageLoadError,
33
- "#{constant_name} is supposed to be defined to process #{menu_name} menu #{page_number}"
32
+ raise PageLoadError, <<~MSG
33
+ \n
34
+ #{constant_name} is supposed to be defined to process #{menu_name} menu #{page_number}.
35
+ generate menu page with `bianchi g menu #{menu_name} page #{page_number[4..]}`
36
+ MSG
34
37
  end
35
38
 
36
39
  session.menu = Menu.new(menu_name)
@@ -3,10 +3,12 @@
3
3
  module Bianchi
4
4
  module USSD
5
5
  module ProviderConfigurations
6
+ include ProviderParsers::Africastalking
7
+
6
8
  def parse_params(params)
7
9
  provider_parsers = {
8
10
  none: proc { params },
9
- africa_is_talking: proc { africa_is_talking_params_parser(params) }
11
+ africastalking: proc { africastalking_params_parser(params) }
10
12
  }.with_indifferent_access
11
13
 
12
14
  parser = provider_parsers[@provider]
@@ -16,27 +18,10 @@ module Bianchi
16
18
  parser.call
17
19
  end
18
20
 
19
- def africa_is_talking_params_parser(params)
20
- required_params = %w[sessionId phoneNumber text serviceCode]
21
- left_required_params = required_params - params.keys.map(&:to_s)
22
-
23
- unless left_required_params.empty?
24
- raise ArgumentError, "#{left_required_params} required in params to start engine for provider #{@provider}"
25
- end
26
-
27
- {
28
- session_id: params["sessionId"],
29
- mobile_number: params["phoneNumber"],
30
- activity_state: params["text"] && params["text"].empty? ? "initial" : "subsequent",
31
- input_body: params["text"],
32
- service_code: params["serviceCode"]
33
- }
34
- end
35
-
36
21
  def parser_prompt_data(prompt_data)
37
22
  provider_parsers = {
38
23
  none: proc { prompt_data },
39
- africa_is_talking: proc { africa_is_talking_prompt_data_parser(prompt_data) }
24
+ africastalking: proc { africastalking_prompt_data_parser(prompt_data) }
40
25
  }.with_indifferent_access
41
26
 
42
27
  parser = provider_parsers[@provider]
@@ -45,10 +30,6 @@ module Bianchi
45
30
 
46
31
  parser.call
47
32
  end
48
-
49
- def africa_is_talking_prompt_data_parser(prompt_data)
50
- prompt_data["activity_state"] == :await ? "CON #{prompt_data['body']}" : "END #{prompt_data['body']}"
51
- end
52
33
  end
53
34
  end
54
35
  end
@@ -0,0 +1,28 @@
1
+ module Bianchi
2
+ module USSD
3
+ module ProviderParsers
4
+ module Africastalking
5
+ def africastalking_params_parser(params)
6
+ required_params = %w[sessionId phoneNumber text serviceCode]
7
+ left_required_params = required_params - params.keys.map(&:to_s)
8
+
9
+ unless left_required_params.empty?
10
+ raise ArgumentError, "#{left_required_params} required in params to start engine for provider #{@provider}"
11
+ end
12
+
13
+ {
14
+ session_id: params["sessionId"],
15
+ mobile_number: params["phoneNumber"],
16
+ activity_state: params["text"] && params["text"].empty? ? "initial" : "subsequent",
17
+ input_body: params["text"].split("*").last,
18
+ service_code: params["serviceCode"]
19
+ }
20
+ end
21
+
22
+ def africastalking_prompt_data_parser(prompt_data)
23
+ prompt_data["activity_state"] == :await ? "CON #{prompt_data['body']}" : "END #{prompt_data['body']}"
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bianchi
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.1"
5
5
  end
data/lib/bianchi.rb CHANGED
@@ -6,6 +6,7 @@ require "json"
6
6
  require "thor"
7
7
 
8
8
  require_relative "bianchi/version"
9
+ require_relative "bianchi/ussd/provider_parsers/africastalking"
9
10
  require_relative "bianchi/ussd/provider_configurations"
10
11
  require_relative "bianchi/ussd/engine"
11
12
  require_relative "bianchi/ussd/menu"
data/ussd/engine.rb CHANGED
@@ -1,7 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module USSD
2
4
  class Engine
3
5
  def self.start(params)
4
-
5
6
  Bianchi::USSD::Engine.start(params, provider: :africa_is_talking) do
6
7
  # e.g menu :main, options
7
8
  end
@@ -1,11 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module USSD
2
4
  module MainMenu
3
5
  class Page1 < Bianchi::USSD::Page
4
- def request
5
- end
6
+ def request; end
6
7
 
7
- def response
8
- end
8
+ def response; end
9
9
  end
10
10
  end
11
- end
11
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bianchi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dapilah Sydney
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-01-25 00:00:00.000000000 Z
11
+ date: 2024-01-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -98,6 +98,7 @@ files:
98
98
  - lib/bianchi/ussd/page.rb
99
99
  - lib/bianchi/ussd/page_delegators.rb
100
100
  - lib/bianchi/ussd/provider_configurations.rb
101
+ - lib/bianchi/ussd/provider_parsers/africastalking.rb
101
102
  - lib/bianchi/ussd/session.rb
102
103
  - lib/bianchi/ussd/store.rb
103
104
  - lib/bianchi/version.rb