Skip to content

Commit d9adb6c

Browse files
committed
REfactor cahnnel creation
1 parent 1025bbf commit d9adb6c

4 files changed

Lines changed: 199 additions & 17 deletions

File tree

app/services/telegram/channel_service.rb

Lines changed: 72 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Сервис для работы с Telegram каналами
22
module Telegram
33
class ChannelService
4-
def initialize(bot)
4+
def initialize(bot = Telegram.bot)
55
@bot = bot
66
end
77

@@ -97,38 +97,28 @@ def get_channel_info(username)
9797
end
9898
end
9999

100-
# Добавляет канал в подписки пользователя
101-
# @param user [TelegramUser] - пользователь
102-
# @param channel_username [String] - username канала
103-
# @return [Hash] - результат операции { success: true/false, message: String, channel: Channel }
104-
def add_channel_for_user(user, channel_username)
100+
# Добавляет или обновляет канал в базе данных по username
101+
# @param channel_username [String] - username канала (может быть в разных форматах)
102+
# @return [Hash] - результат операции { success: true/false, channel: Channel, message: String }
103+
def add_channel_to_database(channel_username)
105104
# Парсим username
106105
username = parse_channel_username(channel_username)
107106

108107
unless username
109108
return {
110109
success: false,
110+
channel: nil,
111111
message: I18n.t('telegram_bot.channels.add.invalid_format')
112112
}
113113
end
114114

115-
# Проверяем лимит каналов для бесплатных пользователей
116-
limit_checker = Limits::LimitChecker.new(user)
117-
unless limit_checker.can_add_channel?
118-
return {
119-
success: false,
120-
message: I18n.t('telegram_bot.channels.add.limit_reached',
121-
limit: ApplicationConfig.free_channels_limit,
122-
current: limit_checker.current_channels_count)
123-
}
124-
end
125-
126115
# Получаем информацию о канале
127116
channel_info = get_channel_info(username)
128117

129118
unless channel_info
130119
return {
131120
success: false,
121+
channel: nil,
132122
message: I18n.t('telegram_bot.channels.add.not_found', channel: "@#{username}")
133123
}
134124
end
@@ -147,6 +137,7 @@ def add_channel_for_user(user, channel_username)
147137
unless channel.save
148138
return {
149139
success: false,
140+
channel: nil,
150141
message: I18n.t('telegram_bot.channels.add.error', error: channel.errors.full_messages.join(', '))
151142
}
152143
end
@@ -159,6 +150,70 @@ def add_channel_for_user(user, channel_username)
159150
)
160151
end
161152

153+
{
154+
success: true,
155+
channel: channel,
156+
message: nil
157+
}
158+
rescue StandardError => e
159+
Bugsnag.notify(e) { |b| b.metadata = { channel_username: channel_username, action: 'add_channel_to_database' } }
160+
161+
ErrorNotificationService.notify_service_error(e,
162+
service: self.class,
163+
method: 'add_channel_to_database',
164+
metadata: {
165+
channel_username: channel_username,
166+
error_class: e.class.name,
167+
error_message: e.message
168+
}
169+
)
170+
Rails.logger.error "Error adding channel to database: #{e.message}"
171+
172+
{
173+
success: false,
174+
channel: nil,
175+
message: I18n.t('telegram_bot.channels.add.error', error: e.message)
176+
}
177+
end
178+
179+
# Добавляет канал в подписки пользователя
180+
# @param user [TelegramUser] - пользователь
181+
# @param channel_username [String] - username канала
182+
# @return [Hash] - результат операции { success: true/false, message: String, channel: Channel }
183+
def add_channel_for_user(user, channel_username)
184+
# Парсим username
185+
username = parse_channel_username(channel_username)
186+
187+
unless username
188+
return {
189+
success: false,
190+
message: I18n.t('telegram_bot.channels.add.invalid_format')
191+
}
192+
end
193+
194+
# Проверяем лимит каналов для бесплатных пользователей
195+
limit_checker = Limits::LimitChecker.new(user)
196+
unless limit_checker.can_add_channel?
197+
return {
198+
success: false,
199+
message: I18n.t('telegram_bot.channels.add.limit_reached',
200+
limit: ApplicationConfig.free_channels_limit,
201+
current: limit_checker.current_channels_count)
202+
}
203+
end
204+
205+
# Добавляем или обновляем канал в базе данных
206+
channel_result = add_channel_to_database(channel_username)
207+
208+
unless channel_result[:success]
209+
return {
210+
success: false,
211+
message: channel_result[:message]
212+
}
213+
end
214+
215+
channel = channel_result[:channel]
216+
162217
# Проверяем, не подписан ли уже пользователь
163218
subscription = user.subscriptions.find_by(channel: channel)
164219

db/seeds.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@
77
# ["Action", "Comedy", "Drama", "Horror"].each do |genre_name|
88
# MovieGenre.find_or_create_by!(name: genre_name)
99
# end
10+
11+
Telegram::ChannelService.new.add_channel_to_database '@problemhunt'
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# Рефакторинг ChannelService: Выделение метода add_channel_to_database
2+
3+
## Обзор
4+
5+
Был выполнен рефакторинг сервиса `Telegram::ChannelService` с целью выделения логики добавления канала в базу данных в отдельный метод `add_channel_to_database`.
6+
7+
## Цели рефакторинга
8+
9+
1. **Single Responsibility Principle**: Разделение ответственности между методами
10+
2. **Reusability**: Создание метода, который можно использовать в других частях приложения
11+
3. **Testability**: Упрощение тестирования отдельных компонентов
12+
4. **Maintainability**: Улучшение читаемости и поддержки кода
13+
14+
## Изменения
15+
16+
### 1. Новый метод `add_channel_to_database`
17+
18+
**Локация**: `app/services/telegram/channel_service.rb:103-177`
19+
20+
**Сигнатура**:
21+
```ruby
22+
def add_channel_to_database(channel_username)
23+
```
24+
25+
**Ответственность**:
26+
- Парсинг username канала
27+
- Получение информации о канале через Telegram API
28+
- Создание или обновление канала в базе данных
29+
- Обработка ошибок базы данных
30+
31+
**Возвращаемое значение**:
32+
```ruby
33+
{
34+
success: true/false,
35+
channel: Channel/nil,
36+
message: String/nil
37+
}
38+
```
39+
40+
### 2. Обновленный метод `add_channel_for_user`
41+
42+
**Изменения**:
43+
- Удалена логика работы с базой данных
44+
- Добавлен вызов нового метода `add_channel_to_database`
45+
- Упрощена структура метода
46+
- Сохранена логика работы с подписками
47+
48+
### 3. Тесты
49+
50+
**Локация**: `test/services/telegram/channel_service_test.rb:222-249`
51+
52+
Добавлен тест `test_add_channel_to_database_creates_new_channel_with_username` который проверяет:
53+
- Успешное создание нового канала
54+
- Корректность сохраненных данных
55+
- Правильную работу с моками Telegram API
56+
57+
## Архитектурные преимущества
58+
59+
### 1. Разделение ответственности
60+
- `add_channel_to_database` - работа с данными канала
61+
- `add_channel_for_user` - бизнес-логика подписок
62+
63+
### 2. Возможность переиспользования
64+
Метод `add_channel_to_database` может быть использован в:
65+
- Административных функциях
66+
- Фоновых задачах обновления каналов
67+
- API endpoints для массового добавления каналов
68+
69+
### 3. Улучшенная обработка ошибок
70+
- Каждая операция имеет свою собственную обработку ошибок
71+
- Более детальное логирование ошибок
72+
- Консистентные сообщения об ошибках
73+
74+
## Потенциальные улучшения
75+
76+
1. **Валидация на уровне сервиса**: Можно добавить дополнительную валидацию перед созданием канала
77+
2. **Кеширование информации о каналах**: Для уменьшения количества запросов к Telegram API
78+
3. **Батчная обработка**: Возможность добавления нескольких каналов за раз
79+
80+
## Backward Compatibility
81+
82+
Рефакторинг полностью сохраняет обратную совместимость. Публичный интерфейс сервиса `add_channel_for_user` остался без изменений.
83+
84+
## Тестирование
85+
86+
Все существующие тесты продолжают проходить. Новый тест покрывает основной сценарий использования метода `add_channel_to_database`.
87+
88+
```
89+
21 runs, 70 assertions, 0 failures, 0 errors, 0 skips
90+
```
91+
92+
## Заключение
93+
94+
Рефакторинг успешно завершен. Код стал более модульным, тестируемым и соответствующим принципам SOLID. Новый метод можно безопасно использовать в других частях приложения.

test/services/telegram/channel_service_test.rb

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,4 +216,35 @@ class Telegram::ChannelServiceTest < ActiveSupport::TestCase
216216
end
217217
end
218218
end
219+
220+
# Тесты add_channel_to_database
221+
222+
test 'add_channel_to_database creates new channel with username' do
223+
# Мокаем get_channel_info чтобы возвращать тестовые данные
224+
mock_channel_info = {
225+
id: 12345,
226+
username: 'testchannel',
227+
title: 'Test Channel',
228+
description: 'Test Description',
229+
member_count: 1000
230+
}
231+
232+
@service.stubs(:get_channel_info).returns(mock_channel_info)
233+
234+
result = @service.add_channel_to_database('@testchannel')
235+
236+
assert result[:success]
237+
assert_not_nil result[:channel]
238+
assert_nil result[:message]
239+
240+
channel = result[:channel]
241+
assert_equal 12345, channel.telegram_id
242+
assert_equal 'testchannel', channel.username
243+
assert_equal 'Test Channel', channel.title
244+
assert_equal 'Test Description', channel.description
245+
assert_equal 1000, channel.subscribers_count
246+
247+
# Возвращаем оригинальный метод
248+
@service.unstub(:get_channel_info)
249+
end
219250
end

0 commit comments

Comments
 (0)