telegram-support-bot 0.1.09 → 0.1.10

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 15900469360f291d85f69a938dc8f25cc9826ec0fab4105c954e0f58aea48868
4
- data.tar.gz: 441423cab220f879327d6474bafb069c8fa099966f7cc45c6ac2896944a52238
3
+ metadata.gz: 9263ca971ffb1e1bb24ae8bc23342c4596748573e7b694485173e14dd2d82d44
4
+ data.tar.gz: fce5aa69e55343db503d12779a3b66b4f2caabd407f18b1e6668532d1abf9bbb
5
5
  SHA512:
6
- metadata.gz: 5fa0913384b4a0ecc87dd7c37cc546fc6d8a5e937c9154b7bdeb91d80ed3070cb33d4f5bc6d9d051fe5d84b865bfc904638528e7259cb4a366f5e978e448ecf3
7
- data.tar.gz: c844cfaf107d7bed62378b7dfd170d28ee8a4e81f17802c7924cc8629a0dc3485242b5966dbc0371bdddffa2bbd5e861068e0970ebb5d5561c7da1b3a663b06d
6
+ metadata.gz: 60ab56248d3f245ab2aa8530f8b6c2254003e881c08f632d75e81648cafa0273d35c9cb35cd4d2aece9ec567de0e5effae6ef97205f578cc931695bfa01b1769
7
+ data.tar.gz: 2e6f1fa2f22a606cc418a2f3f054cc38a7565093d4187c609333583ca22db00c77b9f313f3f45aa0dac6eb5877d1386de91f2ba72730e3bab3caf5fdb9d2294f
data/.idea/workspace.xml CHANGED
@@ -4,15 +4,15 @@
4
4
  <option name="autoReloadType" value="SELECTIVE" />
5
5
  </component>
6
6
  <component name="ChangeListManager">
7
- <list default="true" id="edf498b0-8552-42f1-846d-0c79d29ff991" name="Changes" comment="">
8
- <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
9
- <change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
10
- </list>
7
+ <list default="true" id="edf498b0-8552-42f1-846d-0c79d29ff991" name="Changes" comment="" />
11
8
  <option name="SHOW_DIALOG" value="false" />
12
9
  <option name="HIGHLIGHT_CONFLICTS" value="true" />
13
10
  <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
14
11
  <option name="LAST_RESOLUTION" value="IGNORE" />
15
12
  </component>
13
+ <component name="EmbeddingIndexingInfo">
14
+ <option name="cachedIndexableFilesCount" value="26" />
15
+ </component>
16
16
  <component name="FileTemplateManagerImpl">
17
17
  <option name="RECENT_TEMPLATES">
18
18
  <list>
@@ -26,6 +26,10 @@
26
26
  <component name="MarkdownSettingsMigration">
27
27
  <option name="stateVersion" value="1" />
28
28
  </component>
29
+ <component name="McpProjectServerCommands">
30
+ <commands />
31
+ <urls />
32
+ </component>
29
33
  <component name="ProjectColorInfo">{
30
34
  &quot;associatedIndex&quot;: 4
31
35
  }</component>
@@ -37,30 +41,38 @@
37
41
  <option name="hideEmptyMiddlePackages" value="true" />
38
42
  <option name="showLibraryContents" value="true" />
39
43
  </component>
40
- <component name="PropertiesComponent">{
41
- &quot;keyToString&quot;: {
42
- &quot;DefaultRubyCreateTestTemplate&quot;: &quot;Minitest Spec&quot;,
43
- &quot;RSpec.Unnamed.executor&quot;: &quot;Run&quot;,
44
- &quot;Ruby.scratch_61.executor&quot;: &quot;Run&quot;,
45
- &quot;RunOnceActivity.OpenProjectViewOnStart&quot;: &quot;true&quot;,
46
- &quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
47
- &quot;git-widget-placeholder&quot;: &quot;main&quot;,
48
- &quot;last_opened_file_path&quot;: &quot;/home/max/code/tg-sample&quot;,
49
- &quot;node.js.detected.package.eslint&quot;: &quot;true&quot;,
50
- &quot;node.js.detected.package.tslint&quot;: &quot;true&quot;,
51
- &quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;,
52
- &quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;,
53
- &quot;nodejs_package_manager_path&quot;: &quot;npm&quot;,
54
- &quot;ruby.structure.view.model.defaults.configured&quot;: &quot;true&quot;,
55
- &quot;settings.editor.selected.configurable&quot;: &quot;org.jetbrains.plugins.ruby.settings.RubyActiveModuleSdkConfigurable&quot;,
56
- &quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
44
+ <component name="PropertiesComponent"><![CDATA[{
45
+ "keyToString": {
46
+ "DefaultRubyCreateTestTemplate": "Minitest Spec",
47
+ "ModuleVcsDetector.initialDetectionPerformed": "true",
48
+ "RSpec.Unnamed.executor": "Run",
49
+ "Ruby.scratch_61.executor": "Run",
50
+ "RunOnceActivity.MCP Project settings loaded": "true",
51
+ "RunOnceActivity.OpenProjectViewOnStart": "true",
52
+ "RunOnceActivity.ShowReadmeOnStart": "true",
53
+ "RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
54
+ "RunOnceActivity.git.unshallow": "true",
55
+ "RunOnceActivity.typescript.service.memoryLimit.init": "true",
56
+ "com.intellij.ml.llm.matterhorn.ej.ui.settings.DefaultModelSelectionForGA.v1": "true",
57
+ "git-widget-placeholder": "main",
58
+ "junie.onboarding.icon.badge.shown": "true",
59
+ "last_opened_file_path": "/Users/max/code/gems/telegram_support_bot",
60
+ "node.js.detected.package.eslint": "true",
61
+ "node.js.detected.package.tslint": "true",
62
+ "node.js.selected.package.eslint": "(autodetect)",
63
+ "node.js.selected.package.tslint": "(autodetect)",
64
+ "nodejs_package_manager_path": "npm",
65
+ "ruby.structure.view.model.defaults.configured": "true",
66
+ "settings.editor.selected.configurable": "org.jetbrains.plugins.ruby.settings.RubyActiveModuleSdkConfigurable",
67
+ "to.speed.mode.migration.done": "true",
68
+ "vue.rearranger.settings.migration": "true"
57
69
  },
58
- &quot;keyToStringList&quot;: {
59
- &quot;com.intellij.ide.scratch.ScratchImplUtil$2/New Scratch File&quot;: [
60
- &quot;ruby&quot;
70
+ "keyToStringList": {
71
+ "com.intellij.ide.scratch.ScratchImplUtil$2/New Scratch File": [
72
+ "ruby"
61
73
  ]
62
74
  }
63
- }</component>
75
+ }]]></component>
64
76
  <component name="RecentsManager">
65
77
  <key name="CopyFile.RECENT_KEYS">
66
78
  <recent name="$PROJECT_DIR$/spec/telegram_support_bot/adapters" />
@@ -80,11 +92,7 @@
80
92
  <RSPEC_RUN_CONFIG_SETTINGS_ID NAME="ALTERN_SDK_NAME" VALUE="" />
81
93
  <RSPEC_RUN_CONFIG_SETTINGS_ID NAME="myPassParentEnvs" VALUE="true" />
82
94
  <EXTENSION ID="BundlerRunConfigurationExtension" BUNDLE_MODE="AUTO" bundleExecEnabled="true" />
83
- <EXTENSION ID="RubyCoverageRunConfigurationExtension" track_test_folders="true" runner="rcov" ENABLE_BRANCH_COVERAGE="true" ENABLE_FORKED_COVERAGE="true">
84
- <COVERAGE_PATTERN ENABLED="true">
85
- <PATTERN REGEXPS="/.rvm/" INCLUDED="false" />
86
- </COVERAGE_PATTERN>
87
- </EXTENSION>
95
+ <EXTENSION ID="RubyCoverageRunConfigurationExtension" runner="rcov" />
88
96
  <EXTENSION ID="org.jetbrains.plugins.ruby.rails.run.RailsRunConfigurationExtension" SCRATCH_USE_RAILS_RUNNER="false" />
89
97
  <RSPEC_RUN_CONFIG_SETTINGS_ID NAME="TESTS_FOLDER_PATH" VALUE="$MODULE_DIR$/spec" />
90
98
  <RSPEC_RUN_CONFIG_SETTINGS_ID NAME="TEST_SCRIPT_PATH" VALUE="" />
@@ -111,6 +119,7 @@
111
119
  <RUBY_RUN_CONFIG NAME="ALTERN_SDK_NAME" VALUE="" />
112
120
  <RUBY_RUN_CONFIG NAME="myPassParentEnvs" VALUE="true" />
113
121
  <EXTENSION ID="BundlerRunConfigurationExtension" BUNDLE_MODE="AUTO" bundleExecEnabled="true" />
122
+ <EXTENSION ID="RubyCoverageRunConfigurationExtension" runner="rcov" />
114
123
  <EXTENSION ID="org.jetbrains.plugins.ruby.rails.run.RailsRunConfigurationExtension" SCRATCH_USE_RAILS_RUNNER="false" />
115
124
  <RUBY_RUN_CONFIG NAME="SCRIPT_PATH" VALUE="$APPLICATION_CONFIG_DIR$/scratches/scratch_61.rb" />
116
125
  <RUBY_RUN_CONFIG NAME="SCRIPT_ARGS" VALUE="" />
@@ -126,6 +135,13 @@
126
135
  </list>
127
136
  </recent_temporary>
128
137
  </component>
138
+ <component name="SharedIndexes">
139
+ <attachedChunks>
140
+ <set>
141
+ <option value="bundled-js-predefined-d6986cc7102b-9b0f141eb926-JavaScript-RM-253.30387.79" />
142
+ </set>
143
+ </attachedChunks>
144
+ </component>
129
145
  <component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
130
146
  <component name="SpringUtil" SPRING_PRE_LOADER_OPTION="true" RAKE_SPRING_PRE_LOADER_OPTION="true" RAILS_SPRING_PRE_LOADER_OPTION="true" />
131
147
  <component name="TaskManager">
@@ -141,6 +157,7 @@
141
157
  <workItem from="1708944249622" duration="627000" />
142
158
  <workItem from="1708949675518" duration="80000" />
143
159
  <workItem from="1708951183744" duration="310000" />
160
+ <workItem from="1770972800781" duration="13916000" />
144
161
  </task>
145
162
  <servers />
146
163
  </component>
data/CHANGELOG.md CHANGED
@@ -4,6 +4,19 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.1.10] - 2026-02-25
8
+
9
+ ### Added
10
+ - Multi-bot runtime support in one process with keyed configuration and processing:
11
+ `configure(:bot_key)` and `process_update(update, bot: :bot_key)`.
12
+ - Bot-scoped adapter/state-store/scheduler instances to isolate mappings, reactions, and user profiles per bot key.
13
+ - Redis state namespace isolation for non-default bot keys.
14
+ - Multi-bot isolation test coverage for message mappings, support chat routing, contact profiles, and Redis namespaces.
15
+
16
+ ### Changed
17
+ - Backward compatibility preserved: no-arg `configure` and `process_update` continue using `:default`.
18
+ - Development dependency resolution now has Ruby-version-aware constraints for older runtimes.
19
+
7
20
  ## [0.1.09] - 2026-02-13
8
21
 
9
22
  ### Added
data/README.md CHANGED
@@ -27,7 +27,7 @@ gem 'telegram-support-bot'
27
27
 
28
28
  1. **Create Your Bot** via BotFather on Telegram to get your bot token.
29
29
  2. **Deploy Your Application** and set up a controller action for webhook callbacks, directing them
30
- to `TelegramSupportBot.process_update`.
30
+ to `TelegramSupportBot.process_update` (or `TelegramSupportBot.process_update(update, bot: :your_key)` for keyed bots).
31
31
  3. **Set the Webhook URL** using the Telegram Bot API to your controller action.
32
32
 
33
33
  ### Setting Up Your Telegram Bot
@@ -60,6 +60,50 @@ TelegramSupportBot.configure do |config|
60
60
  end
61
61
  ```
62
62
 
63
+ ### Multiple Bots In One Process
64
+
65
+ Use keyed configuration when one app process serves multiple Telegram bots/chats:
66
+
67
+ ```ruby
68
+ TelegramSupportBot.configure(:default) do |config|
69
+ config.adapter_options = { token: ENV.fetch('TELEGRAM_DEFAULT_TOKEN') }
70
+ config.support_chat_id = ENV.fetch('TELEGRAM_DEFAULT_SUPPORT_CHAT_ID')
71
+ end
72
+
73
+ TelegramSupportBot.configure(:partners) do |config|
74
+ config.adapter_options = { token: ENV.fetch('TELEGRAM_PARTNERS_TOKEN') }
75
+ config.support_chat_id = ENV.fetch('TELEGRAM_PARTNERS_SUPPORT_CHAT_ID')
76
+ end
77
+
78
+ # Route incoming webhook to the matching bot key:
79
+ TelegramSupportBot.process_update(update, bot: :partners)
80
+ ```
81
+
82
+ Backward compatibility is preserved:
83
+ - `TelegramSupportBot.configure { ... }` configures `:default`
84
+ - `TelegramSupportBot.process_update(update)` processes with `:default`
85
+
86
+ Typical webhook routing in Rails:
87
+
88
+ ```ruby
89
+ # legacy/default bot
90
+ post '/v2/telegram/support' => 'api/v2/telegram#support'
91
+ # keyed bot
92
+ post '/v2/telegram/:bot_key/support' => 'api/v2/telegram#support'
93
+ ```
94
+
95
+ ```ruby
96
+ def support
97
+ update = JSON.parse(request.body.read)
98
+ bot_key = params[:bot_key].presence&.to_sym || :default
99
+ TelegramSupportBot.process_update(update, bot: bot_key)
100
+ head :ok
101
+ end
102
+ ```
103
+
104
+ When using Redis state store, non-default bot keys are namespaced automatically
105
+ (`telegram_support_bot:<bot_key>:...`) so mappings/profiles do not leak across bots.
106
+
63
107
  3. **Interact with Users**: Messages to your bot will be forwarded to the support chat, and replies
64
108
  in the chat will be sent back to the users.
65
109
 
@@ -27,9 +27,9 @@ module TelegramSupportBot
27
27
  end
28
28
  end
29
29
 
30
- def self.build(configuration)
30
+ def self.build(configuration, bot_key: TelegramSupportBot::DEFAULT_BOT_KEY)
31
31
  backend = configuration.state_store.to_sym
32
- options = configuration.state_store_options || {}
32
+ options = normalize_options(configuration.state_store_options)
33
33
 
34
34
  case backend
35
35
  when :memory
@@ -41,6 +41,7 @@ module TelegramSupportBot
41
41
  )
42
42
  when :redis
43
43
  require_relative 'state_stores/redis'
44
+ options = isolate_redis_namespace(options, bot_key)
44
45
  StateStores::Redis.new(
45
46
  mapping_ttl_seconds: configuration.mapping_ttl_seconds,
46
47
  reaction_count_ttl_seconds: configuration.reaction_count_ttl_seconds,
@@ -51,6 +52,25 @@ module TelegramSupportBot
51
52
  raise ArgumentError, "Unsupported state store backend: #{backend}"
52
53
  end
53
54
  end
55
+
56
+ def self.normalize_options(options)
57
+ (options || {}).each_with_object({}) do |(key, value), memo|
58
+ memo[key.to_sym] = value
59
+ end
60
+ end
61
+ private_class_method :normalize_options
62
+
63
+ def self.isolate_redis_namespace(options, bot_key)
64
+ normalized_bot_key = (bot_key || TelegramSupportBot::DEFAULT_BOT_KEY).to_sym
65
+ return options if normalized_bot_key == TelegramSupportBot::DEFAULT_BOT_KEY
66
+
67
+ base_namespace = options[:namespace] || StateStores::Redis::DEFAULT_NAMESPACE
68
+ suffix = ":#{normalized_bot_key}"
69
+ namespaced = base_namespace.to_s.end_with?(suffix) ? base_namespace.to_s : "#{base_namespace}#{suffix}"
70
+
71
+ options.merge(namespace: namespaced)
72
+ end
73
+ private_class_method :isolate_redis_namespace
54
74
  end
55
75
  end
56
76
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TelegramSupportBot
4
- VERSION = "0.1.09"
4
+ VERSION = "0.1.10"
5
5
  end
@@ -10,70 +10,153 @@ require_relative 'telegram_support_bot/adapters/telegram_bot'
10
10
  require_relative 'telegram_support_bot/adapters/telegram_bot_ruby'
11
11
 
12
12
  module TelegramSupportBot
13
- class << self
14
- attr_accessor :configuration
13
+ DEFAULT_BOT_KEY = :default
14
+ BOT_CONTEXT_THREAD_KEY = :telegram_support_bot_current_bot_key
15
15
 
16
+ class << self
16
17
  # Provides a method to configure the gem.
17
- def configure
18
- self.configuration ||= Configuration.new
19
- yield(configuration) if block_given?
18
+ def configure(bot_key = DEFAULT_BOT_KEY)
19
+ key = normalize_bot_key(bot_key)
20
+ config = configuration(key)
21
+ yield(config) if block_given?
22
+ config
23
+ end
24
+
25
+ def configuration(bot_key = nil)
26
+ key = bot_key.nil? ? current_bot_key : normalize_bot_key(bot_key)
27
+ configurations[key] ||= Configuration.new
28
+ end
29
+
30
+ def configuration=(config)
31
+ configurations[DEFAULT_BOT_KEY] = config
20
32
  end
21
33
 
22
34
  # Lazily builds and returns the adapter based on the current configuration.
23
35
  # This method initializes the adapter when it's first called.
24
- def adapter
25
- @adapter ||= AdapterFactory.build(configuration.adapter, configuration.adapter_options)
36
+ def adapter(bot_key = nil)
37
+ key = bot_key.nil? ? current_bot_key : normalize_bot_key(bot_key)
38
+ adapters[key] ||= AdapterFactory.build(configuration(key).adapter, configuration(key).adapter_options)
26
39
  end
27
40
 
28
- def state_store
29
- @state_store ||= StateStore.build(configuration)
41
+ def state_store(bot_key = nil)
42
+ key = bot_key.nil? ? current_bot_key : normalize_bot_key(bot_key)
43
+ state_stores[key] ||= StateStore.build(configuration(key), bot_key: key)
30
44
  end
31
45
 
32
- def message_map
33
- state_store.message_map
46
+ def message_map(bot_key = nil)
47
+ state_store(bot_key).message_map
34
48
  end
35
49
 
36
- def reverse_message_map
37
- state_store.reverse_message_map
50
+ def reverse_message_map(bot_key = nil)
51
+ state_store(bot_key).reverse_message_map
38
52
  end
39
53
 
40
- def reaction_count_state
41
- state_store.reaction_count_state
54
+ def reaction_count_state(bot_key = nil)
55
+ state_store(bot_key).reaction_count_state
42
56
  end
43
57
 
44
- def user_profiles
45
- state_store.user_profiles
58
+ def user_profiles(bot_key = nil)
59
+ state_store(bot_key).user_profiles
46
60
  end
47
61
 
48
- def user_profile(chat_id)
49
- user_profiles[chat_id] || user_profiles[chat_id.to_s] || user_profiles[chat_id.to_i]
62
+ def user_profile(chat_id, bot: nil)
63
+ profiles = user_profiles(bot)
64
+ profiles[chat_id] || profiles[chat_id.to_s] || profiles[chat_id.to_i]
50
65
  end
51
66
 
52
- def scheduler
53
- @scheduler ||= AutoAwayScheduler.new(adapter, configuration)
67
+ def scheduler(bot_key = nil)
68
+ key = bot_key.nil? ? current_bot_key : normalize_bot_key(bot_key)
69
+ schedulers[key] ||= AutoAwayScheduler.new(adapter(key), configuration(key))
54
70
  end
55
71
 
56
- def process_update(update)
57
- # Handle different types of updates
58
- if update['message']
59
- # Process standard messages
60
- process_message(update['message'])
61
- elsif update['message_reaction']
62
- process_message_reaction(update['message_reaction'])
63
- elsif update['message_reaction_count']
64
- process_message_reaction_count(update['message_reaction_count'])
65
- elsif update['my_chat_member']
66
- # Handle the bot being added to or removed from a chat
67
- handle_my_chat_member_update(update['my_chat_member'])
68
- # Add other update types as needed
69
- else
70
- # Log or handle unknown update types
71
- puts "Received an unknown type of update: #{update}"
72
+ def process_update(update, bot: DEFAULT_BOT_KEY)
73
+ with_bot_context(bot) do
74
+ # Handle different types of updates
75
+ if update['message']
76
+ # Process standard messages
77
+ process_message(update['message'])
78
+ elsif update['message_reaction']
79
+ process_message_reaction(update['message_reaction'])
80
+ elsif update['message_reaction_count']
81
+ process_message_reaction_count(update['message_reaction_count'])
82
+ elsif update['my_chat_member']
83
+ # Handle the bot being added to or removed from a chat
84
+ handle_my_chat_member_update(update['my_chat_member'])
85
+ # Add other update types as needed
86
+ else
87
+ # Log or handle unknown update types
88
+ puts "Received an unknown type of update: #{update}"
89
+ end
72
90
  end
73
91
  end
74
92
 
93
+ # Reset the adapter instance (useful for testing or reconfiguration).
94
+ def reset_adapter!(bot_key = nil)
95
+ reset_registry!(adapters, bot_key)
96
+ end
97
+
98
+ def reset_state_store!(bot_key = nil)
99
+ reset_registry!(state_stores, bot_key)
100
+ end
101
+
102
+ def reset_scheduler!(bot_key = nil)
103
+ reset_registry!(schedulers, bot_key)
104
+ end
105
+
106
+ def reset_configuration!(bot_key = nil)
107
+ reset_registry!(configurations, bot_key)
108
+ end
109
+
110
+ def reset!(bot_key = nil)
111
+ reset_adapter!(bot_key)
112
+ reset_state_store!(bot_key)
113
+ reset_scheduler!(bot_key)
114
+ reset_configuration!(bot_key)
115
+ end
116
+
75
117
  private
76
118
 
119
+ def configurations
120
+ @configurations ||= {}
121
+ end
122
+
123
+ def adapters
124
+ @adapters ||= {}
125
+ end
126
+
127
+ def state_stores
128
+ @state_stores ||= {}
129
+ end
130
+
131
+ def schedulers
132
+ @schedulers ||= {}
133
+ end
134
+
135
+ def current_bot_key
136
+ Thread.current[BOT_CONTEXT_THREAD_KEY] || DEFAULT_BOT_KEY
137
+ end
138
+
139
+ def with_bot_context(bot_key)
140
+ normalized_bot_key = normalize_bot_key(bot_key)
141
+ previous_bot_key = Thread.current[BOT_CONTEXT_THREAD_KEY]
142
+ Thread.current[BOT_CONTEXT_THREAD_KEY] = normalized_bot_key
143
+ yield
144
+ ensure
145
+ Thread.current[BOT_CONTEXT_THREAD_KEY] = previous_bot_key
146
+ end
147
+
148
+ def normalize_bot_key(bot_key)
149
+ (bot_key || DEFAULT_BOT_KEY).to_sym
150
+ end
151
+
152
+ def reset_registry!(registry, bot_key)
153
+ if bot_key.nil?
154
+ registry.clear
155
+ else
156
+ registry.delete(normalize_bot_key(bot_key))
157
+ end
158
+ end
159
+
77
160
  def process_message(message)
78
161
  chat_id = message.dig('chat', 'id')
79
162
 
@@ -511,12 +594,4 @@ module TelegramSupportBot
511
594
 
512
595
  end
513
596
 
514
- # Reset the adapter instance (useful for testing or reconfiguration).
515
- def self.reset_adapter!
516
- @adapter = nil
517
- end
518
-
519
- def self.reset_state_store!
520
- @state_store = nil
521
- end
522
597
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: telegram-support-bot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.09
4
+ version: 0.1.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Max Buslaev
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-02-13 00:00:00.000000000 Z
11
+ date: 2026-02-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis