flow_chat 0.7.0 → 0.8.1

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.
@@ -160,6 +160,7 @@ module FlowChat
160
160
 
161
161
  context["request.id"] = phone_number
162
162
  context["request.gateway"] = :whatsapp_cloud_api
163
+ context["request.platform"] = :whatsapp
163
164
  context["request.message_id"] = message_id
164
165
  context["request.msisdn"] = Phonelib.parse(phone_number).e164
165
166
  context["request.contact_name"] = contact_name
@@ -1,49 +1,21 @@
1
+ require_relative "../../base_executor"
2
+
1
3
  module FlowChat
2
4
  module Whatsapp
3
5
  module Middleware
4
- class Executor
5
- def initialize(app)
6
- @app = app
7
- FlowChat.logger.debug { "Whatsapp::Executor: Initialized WhatsApp executor middleware" }
8
- end
9
-
10
- def call(context)
11
- flow_class = context.flow
12
- action = context["flow.action"]
13
- session_id = context["session.id"]
14
-
15
- FlowChat.logger.info { "Whatsapp::Executor: Executing flow #{flow_class.name}##{action} for session #{session_id}" }
6
+ class Executor < FlowChat::BaseExecutor
7
+ protected
16
8
 
17
- whatsapp_app = build_whatsapp_app context
18
- FlowChat.logger.debug { "Whatsapp::Executor: WhatsApp app built for flow execution" }
19
-
20
- flow = flow_class.new whatsapp_app
21
- FlowChat.logger.debug { "Whatsapp::Executor: Flow instance created, invoking #{action} method" }
22
-
23
- flow.send action
24
- FlowChat.logger.warn { "Whatsapp::Executor: Flow execution failed to interact with user for #{flow_class.name}##{action}" }
25
- raise FlowChat::Interrupt::Terminate, "Unexpected end of flow."
26
- rescue FlowChat::Interrupt::Prompt => e
27
- FlowChat.logger.info { "Whatsapp::Executor: Flow prompted user - Session: #{session_id}, Prompt: '#{e.prompt.truncate(100)}'" }
28
- FlowChat.logger.debug { "Whatsapp::Executor: Prompt details - Choices: #{e.choices&.size || 0}, Has media: #{!e.media.nil?}" }
29
- # Return the same triplet format as USSD for consistency
30
- [:prompt, e.prompt, e.choices, e.media]
31
- rescue FlowChat::Interrupt::Terminate => e
32
- FlowChat.logger.info { "Whatsapp::Executor: Flow terminated - Session: #{session_id}, Message: '#{e.prompt.truncate(100)}'" }
33
- FlowChat.logger.debug { "Whatsapp::Executor: Destroying session #{session_id}" }
34
- # Clean up session and return terminal message
35
- context.session.destroy
36
- [:terminate, e.prompt, nil, e.media]
37
- rescue => error
38
- FlowChat.logger.error { "Whatsapp::Executor: Flow execution failed - #{flow_class.name}##{action}, Session: #{session_id}, Error: #{error.class.name}: #{error.message}" }
39
- FlowChat.logger.debug { "Whatsapp::Executor: Stack trace: #{error.backtrace.join("\n")}" }
40
- raise
9
+ def platform_name
10
+ "WhatsApp"
41
11
  end
42
12
 
43
- private
13
+ def log_prefix
14
+ "Whatsapp::Executor"
15
+ end
44
16
 
45
- def build_whatsapp_app(context)
46
- FlowChat.logger.debug { "Whatsapp::Executor: Building WhatsApp app instance" }
17
+ def build_platform_app(context)
18
+ FlowChat.logger.debug { "#{log_prefix}: Building WhatsApp app instance" }
47
19
  FlowChat::Whatsapp::App.new(context)
48
20
  end
49
21
  end
@@ -20,8 +20,6 @@ module FlowChat
20
20
 
21
21
  def configure_middleware_stack(builder)
22
22
  FlowChat.logger.debug { "Whatsapp::Processor: Configuring WhatsApp middleware stack" }
23
- builder.use FlowChat::Session::Middleware
24
- FlowChat.logger.debug { "Whatsapp::Processor: Added Session::Middleware" }
25
23
 
26
24
  builder.use middleware
27
25
  FlowChat.logger.debug { "Whatsapp::Processor: Added custom middleware" }
data/lib/flow_chat.rb CHANGED
@@ -15,7 +15,6 @@ module FlowChat
15
15
  end
16
16
 
17
17
  def self.setup_instrumentation!
18
- require_relative "flow_chat/instrumentation/setup"
19
18
  FlowChat::Instrumentation::Setup.setup_instrumentation!
20
19
  end
21
20
 
@@ -27,13 +26,4 @@ module FlowChat
27
26
  def self.metrics
28
27
  FlowChat::Instrumentation::Setup.metrics_collector
29
28
  end
30
- end
31
-
32
- loader.eager_load
33
-
34
- # Auto-setup instrumentation in Rails environments
35
- if defined?(Rails)
36
- Rails.application.config.after_initialize do
37
- FlowChat.setup_instrumentation!
38
- end
39
- end
29
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flow_chat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stefan Froelich
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-06-07 00:00:00.000000000 Z
11
+ date: 2025-06-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: zeitwerk
@@ -107,6 +107,7 @@ files:
107
107
  - docs/images/simulator.png
108
108
  - docs/instrumentation.md
109
109
  - docs/media.md
110
+ - docs/sessions.md
110
111
  - docs/testing.md
111
112
  - docs/ussd-setup.md
112
113
  - docs/whatsapp-setup.md
@@ -118,6 +119,8 @@ files:
118
119
  - examples/whatsapp_message_job.rb
119
120
  - flow_chat.gemspec
120
121
  - lib/flow_chat.rb
122
+ - lib/flow_chat/base_app.rb
123
+ - lib/flow_chat/base_executor.rb
121
124
  - lib/flow_chat/base_processor.rb
122
125
  - lib/flow_chat/config.rb
123
126
  - lib/flow_chat/context.rb
@@ -139,7 +142,6 @@ files:
139
142
  - lib/flow_chat/ussd/middleware/choice_mapper.rb
140
143
  - lib/flow_chat/ussd/middleware/executor.rb
141
144
  - lib/flow_chat/ussd/middleware/pagination.rb
142
- - lib/flow_chat/ussd/middleware/resumable_session.rb
143
145
  - lib/flow_chat/ussd/processor.rb
144
146
  - lib/flow_chat/ussd/renderer.rb
145
147
  - lib/flow_chat/version.rb
@@ -1,39 +0,0 @@
1
- module FlowChat
2
- module Ussd
3
- module Middleware
4
- class ResumableSession
5
- def initialize(app)
6
- @app = app
7
- end
8
-
9
- def call(context)
10
- if FlowChat::Config.ussd.resumable_sessions_enabled && context["ussd.request"].present?
11
- # First, try to find any interruption session.
12
- # The session key can be:
13
- # - a global session (key: "global")
14
- # - a provider-specific session (key: <provider>)
15
- session_key = self.class.session_key(context)
16
- resumable_session = context["session.store"].get(session_key)
17
-
18
- if resumable_session.present? && valid?(resumable_session)
19
- context.merge! resumable_session
20
- end
21
- end
22
-
23
- @app.call(context)
24
- end
25
-
26
- private
27
-
28
- def valid?(session)
29
- return true unless FlowChat::Config.ussd.resumable_sessions_timeout_seconds
30
-
31
- last_active_at = Time.parse session.dig("context", "last_active_at")
32
- (Time.current - FlowChat::Config.ussd.resumable_sessions_timeout_seconds) < last_active_at
33
- rescue
34
- false
35
- end
36
- end
37
- end
38
- end
39
- end