bianchi 0.1.1 → 0.1.2

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: 57689540f35b1837b227a23ec9b9badd237e5e1bda6b7f0b5c3d64443b404fd9
4
- data.tar.gz: b963e56598337607ef36f0d4ebb514c9a83e354c3dc65d55d3ad299c856668b3
3
+ metadata.gz: 3a8d03b012d92b96f021d80a4ce43c668d75f7003978feb81b189cdcb71952be
4
+ data.tar.gz: b1c13d1ead41b898177e6915f06d134a0a762fb367b95cadbbb688d031c4767a
5
5
  SHA512:
6
- metadata.gz: 9272b56f5a057de49f9695cc615afcf05fbdcb14db6f31f582bf8d6b421b4dc8787ba5fbbcab87a120aaf4fd0519fad88c66f842423984915dbf271de3076207
7
- data.tar.gz: ce5f129f37e80ff25fa642af17ae8d5f31b467f580419a7b053afe941979f6e09cf9183668a9443aea262c2d933f41a1656401098e6ef6d8d8ac26ed890b2d22
6
+ metadata.gz: 5178fa0c0e7a8b65829b004d348b73dc74a0305789e03edbdb0af2fe9ac1236281dd31835052281791289b7a48912b918ec536969aa27de484d16a383a8edcf3
7
+ data.tar.gz: 7b961616077c63d17997d26837b1207bfd3718f5abc27e34a4fdb15ebbea3ec0b7754c846d0cbc1e77ba2984f974bff259e7100716dcf50b1af12f8e2d34346c
@@ -0,0 +1,45 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - '*'
7
+ pull_request:
8
+ branches:
9
+ - main
10
+
11
+ jobs:
12
+ rubocop:
13
+ runs-on: ubuntu-latest
14
+
15
+ services:
16
+ redis:
17
+ image: redis
18
+ ports:
19
+ - 6379:6379
20
+ options: --entrypoint redis-server
21
+
22
+ steps:
23
+ - name: Checkout code
24
+ uses: actions/checkout@v4.1.1
25
+
26
+ - name: Set up Ruby
27
+ uses: ruby/setup-ruby@v1.171.0
28
+ with:
29
+ ruby-version: 3.0
30
+
31
+ - name: Install dependencies
32
+ run: |
33
+ gem install bundler
34
+ bundle install
35
+
36
+ - name: Run RuboCop
37
+ run: bundle exec rubocop
38
+
39
+ - name: Start Redis
40
+ run: docker ps -a
41
+
42
+ - name: Run RSpec tests
43
+ env:
44
+ REDIS_URL: redis://localhost:6379
45
+ run: bundle exec rspec
data/.gitignore CHANGED
@@ -9,3 +9,4 @@
9
9
 
10
10
  # rspec failure tracking
11
11
  .rspec_status
12
+ .byebug_history
data/.rubocop.yml CHANGED
@@ -1,6 +1,7 @@
1
1
  AllCops:
2
2
  NewCops: enable
3
3
  TargetRubyVersion: 3.0
4
+ SuggestExtensions: false
4
5
 
5
6
  Style/StringLiterals:
6
7
  Enabled: true
@@ -18,3 +19,4 @@ Metrics/MethodLength:
18
19
 
19
20
 
20
21
 
22
+
@@ -0,0 +1,5 @@
1
+ {
2
+ "cSpell.words": [
3
+ "appsnmobile"
4
+ ]
5
+ }
data/Gemfile CHANGED
@@ -9,6 +9,6 @@ gem "rake", "~> 13.0"
9
9
 
10
10
  gem "rspec", "~> 3.0"
11
11
 
12
- gem "rubocop", "~> 0.80"
12
+ gem "rubocop", "~> 1.60", ">= 1.60.2"
13
13
 
14
14
  gem "byebug"
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- bianchi (0.1.0)
4
+ bianchi (0.1.2)
5
5
  activesupport
6
6
  json
7
7
  redis
@@ -32,10 +32,11 @@ GEM
32
32
  i18n (1.14.1)
33
33
  concurrent-ruby (~> 1.0)
34
34
  json (2.7.1)
35
+ language_server-protocol (3.17.0.3)
35
36
  minitest (5.21.2)
36
37
  mutex_m (0.2.0)
37
38
  parallel (1.24.0)
38
- parser (3.3.0.2)
39
+ parser (3.3.0.5)
39
40
  ast (~> 2.4.1)
40
41
  racc
41
42
  racc (1.7.3)
@@ -60,15 +61,17 @@ GEM
60
61
  diff-lcs (>= 1.2.0, < 2.0)
61
62
  rspec-support (~> 3.12.0)
62
63
  rspec-support (3.12.1)
63
- rubocop (0.93.1)
64
+ rubocop (1.60.2)
65
+ json (~> 2.3)
66
+ language_server-protocol (>= 3.17.0)
64
67
  parallel (~> 1.10)
65
- parser (>= 2.7.1.5)
68
+ parser (>= 3.3.0.2)
66
69
  rainbow (>= 2.2.2, < 4.0)
67
- regexp_parser (>= 1.8)
68
- rexml
69
- rubocop-ast (>= 0.6.0)
70
+ regexp_parser (>= 1.8, < 3.0)
71
+ rexml (>= 3.2.5, < 4.0)
72
+ rubocop-ast (>= 1.30.0, < 2.0)
70
73
  ruby-progressbar (~> 1.7)
71
- unicode-display_width (>= 1.4.0, < 2.0)
74
+ unicode-display_width (>= 2.4.0, < 3.0)
72
75
  rubocop-ast (1.30.0)
73
76
  parser (>= 3.2.1.0)
74
77
  ruby-progressbar (1.13.0)
@@ -76,9 +79,10 @@ GEM
76
79
  thor (1.3.0)
77
80
  tzinfo (2.0.6)
78
81
  concurrent-ruby (~> 1.0)
79
- unicode-display_width (1.8.0)
82
+ unicode-display_width (2.5.0)
80
83
 
81
84
  PLATFORMS
85
+ arm64-darwin-22
82
86
  x86_64-darwin-23
83
87
 
84
88
  DEPENDENCIES
@@ -86,7 +90,7 @@ DEPENDENCIES
86
90
  byebug
87
91
  rake (~> 13.0)
88
92
  rspec (~> 3.0)
89
- rubocop (~> 0.80)
93
+ rubocop (~> 1.60, >= 1.60.2)
90
94
 
91
95
  BUNDLED WITH
92
96
  2.2.3
data/README.md CHANGED
@@ -1,10 +1,11 @@
1
1
  # Bianchi
2
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.
3
+ A basic test run with bianchi can be found here https://github.com/SydDaps/sinatra_bianchi_example
3
4
 
4
5
  ## Installation
5
- Add `gem 'bianchi', '~> 0.1.0'` to your gem file and run `bundle install`
6
+ Add `gem 'bianchi', '~> 0.1.1'` to your gem file and run `bundle install`
6
7
 
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.
8
+ Bianchi relies on Redis and requires the `REDIS_URL` environment variable to be set, pointing to your Redis instance. Ensure Redis is installed, and running, and that REDIS_URL is correctly configured before using Bianchi.
8
9
 
9
10
  ## Getting Started
10
11
 
@@ -14,7 +15,7 @@ To initialize a new USSD project, generate a project directory using Bianchi's c
14
15
  bundle exec bianchi setup -p provider_name
15
16
  ```
16
17
 
17
- Replace `provider_name` with your desired provider. Currently supported providers include: africa_is_talking.
18
+ Replace `provider_name` with your desired provider. Currently supported providers include: africastalking.
18
19
 
19
20
  This command creates a `ussd/engine.rb` file in the project root directory. Here's a sample content of `ussd/engine.rb`:
20
21
 
@@ -22,7 +23,7 @@ This command creates a `ussd/engine.rb` file in the project root directory. Here
22
23
  module USSD
23
24
  class Engine
24
25
  def self.start(params)
25
- Bianchi::USSD::Engine.start(params, provider: :africa_is_talking) do
26
+ Bianchi::USSD::Engine.start(params, provider: :africastalking) do
26
27
  # e.g menu :main, options
27
28
  end
28
29
  end
@@ -52,11 +53,9 @@ This creates a `ussd/main_menu/page_1` file in the project root directory. Here'
52
53
  module USSD
53
54
  module MainMenu
54
55
  class Page1 < Bianchi::USSD::Page
55
- def request
56
- end
56
+ def request; end
57
57
 
58
- def response
59
- end
58
+ def response; end
60
59
  end
61
60
  end
62
61
  end
@@ -183,7 +182,7 @@ Here's an example of how you can retrieve the provider prompt data in your USSD
183
182
  module USSD
184
183
  class Engine
185
184
  def self.start(params)
186
- Bianchi::USSD::Engine.start(params, provider: :africa_is_talking) do
185
+ Bianchi::USSD::Engine.start(params, provider: :africastalking) do
187
186
  menu :main, options
188
187
  menu :greetings
189
188
  menu :repeat
data/bianchi.gemspec CHANGED
@@ -34,4 +34,5 @@ Gem::Specification.new do |spec|
34
34
  spec.add_dependency "json"
35
35
  spec.add_dependency "redis"
36
36
  spec.add_dependency "thor"
37
+ spec.metadata["rubygems_mfa_required"] = "true"
37
38
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # rubocop:disable Metrics/ParameterLists
3
4
  module Bianchi
4
5
  module Cli
5
6
  class Main < Thor
@@ -19,7 +20,7 @@ module Bianchi
19
20
  desc "setup", "sets up a new ussd project"
20
21
  long_desc <<-LONG_DESC
21
22
  Usage: bianchi setup optional(-p|--provider)
22
- \x5 Providers: [:africa_is_talking]
23
+ \x5 Providers: [:africa_is_talking, :appsnmobile]
23
24
  \x5 Example: `bianchi setup`
24
25
  \x5 Example: `bianchi setup -p :africa_is_talking`
25
26
 
@@ -27,7 +28,7 @@ module Bianchi
27
28
  method_option :provider, aliases: "-p", type: :string, desc: "Set up ussd project for provider"
28
29
  def setup
29
30
  @provider = options[:provider]
30
- unless %w[africastalking none].include? @provider
31
+ unless %w[africastalking none appsnmobile].include? @provider
31
32
  say("Error: provider #{@provider} is not yet configured.", :yellow)
32
33
  exit(1)
33
34
  end
@@ -62,3 +63,4 @@ module Bianchi
62
63
  end
63
64
  end
64
65
  end
66
+ # rubocop:enable Metrics/ParameterLists
@@ -110,10 +110,7 @@ module Bianchi
110
110
  "#{constant_name} is supposed to be defined to process #{session.menu.name} menu #{page_number}"
111
111
  end
112
112
 
113
- page.new(session).tap do |p|
114
- p.ensure_methods_defined(%i[request response])
115
- p.send(action)
116
- end
113
+ page.call(session, action)
117
114
  end
118
115
  end
119
116
  end
@@ -6,5 +6,7 @@ module Bianchi
6
6
  class PageLoadError < StandardError; end
7
7
  class MethodNameError < StandardError; end
8
8
  class ProviderError < StandardError; end
9
+ class ProviderError < StandardError; end
10
+ class DispatchRenderException < StandardError; end
9
11
  end
10
12
  end
@@ -11,6 +11,15 @@ module Bianchi
11
11
  @session = session
12
12
  end
13
13
 
14
+ def self.call(session, action)
15
+ new(session).tap do |p|
16
+ p.ensure_methods_defined(%i[request response])
17
+ p.send(action)
18
+ rescue DispatchRenderException
19
+ p
20
+ end
21
+ end
22
+
14
23
  def render(body, options = {})
15
24
  raise ArgumentError, "render body expected to be a string" unless body.is_a? String
16
25
 
@@ -22,6 +31,8 @@ module Bianchi
22
31
  s.page_number = self.class.name.split("::").last
23
32
  s.store.track_session
24
33
  end
34
+
35
+ raise DispatchRenderException
25
36
  end
26
37
 
27
38
  def load_page(page_number, menu_name)
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # rubocop:disable Style/MissingRespondToMissing
3
4
  module Bianchi
4
5
  module USSD
5
6
  module PageDelegators
@@ -100,3 +101,4 @@ module Bianchi
100
101
  end
101
102
  end
102
103
  end
104
+ # rubocop:enable Style/MissingRespondToMissing
@@ -4,11 +4,13 @@ module Bianchi
4
4
  module USSD
5
5
  module ProviderConfigurations
6
6
  include ProviderParsers::Africastalking
7
+ include ProviderParsers::Appsnmobile
7
8
 
8
9
  def parse_params(params)
9
10
  provider_parsers = {
10
11
  none: proc { params },
11
- africastalking: proc { africastalking_params_parser(params) }
12
+ africastalking: proc { africastalking_params_parser(params) },
13
+ appsnmobile: proc { appsnmobile_params_parser(params) }
12
14
  }.with_indifferent_access
13
15
 
14
16
  parser = provider_parsers[@provider]
@@ -21,7 +23,8 @@ module Bianchi
21
23
  def parser_prompt_data(prompt_data)
22
24
  provider_parsers = {
23
25
  none: proc { prompt_data },
24
- africastalking: proc { africastalking_prompt_data_parser(prompt_data) }
26
+ africastalking: proc { africastalking_prompt_data_parser(prompt_data) },
27
+ appsnmobile: proc { appsnmobile_prompt_data_parser(prompt_data) }
25
28
  }.with_indifferent_access
26
29
 
27
30
  parser = provider_parsers[@provider]
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bianchi
2
4
  module USSD
3
5
  module ProviderParsers
@@ -25,4 +27,4 @@ module Bianchi
25
27
  end
26
28
  end
27
29
  end
28
- end
30
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bianchi
4
+ module USSD
5
+ module ProviderParsers
6
+ module Appsnmobile
7
+ def appsnmobile_params_parser(params)
8
+ required_params = %w[session_id msisdn msg_type ussd_body nw_code service_code]
9
+ left_required_params = required_params - params.keys.map(&:to_s)
10
+
11
+ unless left_required_params.empty?
12
+ raise ArgumentError, "#{left_required_params} required in params to start engine for provider #{@provider}"
13
+ end
14
+
15
+ {
16
+ session_id: params["session_id"],
17
+ mobile_number: params["msisdn"],
18
+ activity_state: return_activity_state(params["msg_type"]),
19
+ input_body: params["ussd_body"],
20
+ nw_code: params["nw_code"],
21
+ service_code: params["service_code"]
22
+ }
23
+ end
24
+
25
+ def appsnmobile_prompt_data_parser(prompt_data)
26
+ msg_type = prompt_data["activity_state"] == :await ? "1" : "2"
27
+
28
+ {
29
+ session_id: prompt_data["session_id"],
30
+ msisdn: prompt_data["mobile_number"],
31
+ msg_type: msg_type,
32
+ ussd_body: prompt_data["body"],
33
+ nw_code: prompt_data["nw_code"],
34
+ service_code: prompt_data["service_code"]
35
+ }.to_json
36
+ end
37
+
38
+ def return_activity_state(msg_type)
39
+ case msg_type
40
+ when "0"
41
+ "initial"
42
+ when "1"
43
+ "subsequent"
44
+ else
45
+ raise ArgumentError, "#{@provider} sent in an unknown message type or msg_type"
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -6,7 +6,13 @@ module Bianchi
6
6
  attr_reader :session
7
7
 
8
8
  def initialize(session)
9
- @redis = Redis.new(url: ENV.fetch("REDIS_URL", nil))
9
+ redis_url = ENV.fetch("REDIS_URL", nil)
10
+ unless redis_url.present?
11
+ raise ArgumentError,
12
+ "environment variable REDIS_URL required to track engine session."
13
+ end
14
+
15
+ @redis = Redis.new(url: redis_url)
10
16
  @session = session
11
17
  end
12
18
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bianchi
4
- VERSION = "0.1.1"
4
+ VERSION = "0.1.2"
5
5
  end
data/lib/bianchi.rb CHANGED
@@ -7,6 +7,7 @@ require "thor"
7
7
 
8
8
  require_relative "bianchi/version"
9
9
  require_relative "bianchi/ussd/provider_parsers/africastalking"
10
+ require_relative "bianchi/ussd/provider_parsers/appsnmobile"
10
11
  require_relative "bianchi/ussd/provider_configurations"
11
12
  require_relative "bianchi/ussd/engine"
12
13
  require_relative "bianchi/ussd/menu"
@@ -14,7 +15,7 @@ require_relative "bianchi/ussd/session"
14
15
  require_relative "bianchi/ussd/page_delegators"
15
16
  require_relative "bianchi/ussd/page"
16
17
  require_relative "bianchi/ussd/store"
17
- require_relative "bianchi/ussd/errors"
18
+ require_relative "bianchi/ussd/exceptions"
18
19
 
19
20
  # cli
20
21
  require "bianchi/cli/main"
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.1
4
+ version: 0.1.2
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-28 00:00:00.000000000 Z
11
+ date: 2024-02-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -74,9 +74,11 @@ executables:
74
74
  extensions: []
75
75
  extra_rdoc_files: []
76
76
  files:
77
+ - ".github/workflows/ci.yml"
77
78
  - ".gitignore"
78
79
  - ".rspec"
79
80
  - ".rubocop.yml"
81
+ - ".vscode/settings.json"
80
82
  - CODE_OF_CONDUCT.md
81
83
  - Gemfile
82
84
  - Gemfile.lock
@@ -93,12 +95,13 @@ files:
93
95
  - lib/bianchi/cli/templates/engine.erb
94
96
  - lib/bianchi/cli/templates/page.erb
95
97
  - lib/bianchi/ussd/engine.rb
96
- - lib/bianchi/ussd/errors.rb
98
+ - lib/bianchi/ussd/exceptions.rb
97
99
  - lib/bianchi/ussd/menu.rb
98
100
  - lib/bianchi/ussd/page.rb
99
101
  - lib/bianchi/ussd/page_delegators.rb
100
102
  - lib/bianchi/ussd/provider_configurations.rb
101
103
  - lib/bianchi/ussd/provider_parsers/africastalking.rb
104
+ - lib/bianchi/ussd/provider_parsers/appsnmobile.rb
102
105
  - lib/bianchi/ussd/session.rb
103
106
  - lib/bianchi/ussd/store.rb
104
107
  - lib/bianchi/version.rb
@@ -112,6 +115,7 @@ metadata:
112
115
  homepage_uri: https://github.com/SydDaps/Bianchi
113
116
  source_code_uri: https://github.com/SydDaps/Bianchi
114
117
  changelog_uri: https://rubygems.org/
118
+ rubygems_mfa_required: 'true'
115
119
  post_install_message:
116
120
  rdoc_options: []
117
121
  require_paths: