Skip to content

Commit ed47d7e

Browse files
committed
separated conversation handling and state into different classes.
1 parent 70c8f56 commit ed47d7e

File tree

13 files changed

+154
-95
lines changed

13 files changed

+154
-95
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace RedmineTelegramBot.Core
8+
{
9+
10+
[Serializable]
11+
public class BotException : Exception
12+
{
13+
public BotException() { }
14+
public BotException(string message) : base(message) { }
15+
public BotException(string message, Exception inner) : base(message, inner) { }
16+
protected BotException(
17+
System.Runtime.Serialization.SerializationInfo info,
18+
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
19+
}
20+
}

RedmineTelegramBot.Core/Config/BotOptions.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ public class BotOptions
1212

1313
public string RedmineUrl { get; set; }
1414

15-
public string RedmineSecret { get; set; }
16-
1715
public string DataDirectory { get; set; }
1816
}
1917
}

RedmineTelegramBot.Core/ConversationFactory.cs

Lines changed: 0 additions & 28 deletions
This file was deleted.

RedmineTelegramBot.Core/Conversation.cs renamed to RedmineTelegramBot.Core/ConversationHandler.cs

Lines changed: 20 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,30 @@
11
using RedmineTelegramBot.Core.Models;
2-
using RestSharp;
32
using System;
4-
using System.Collections.Generic;
53
using System.Linq;
6-
using System.Text;
74
using System.Threading.Tasks;
85
using Telegram.Bot;
96
using Telegram.Bot.Types;
107

118
namespace RedmineTelegramBot.Core
129
{
13-
public class Conversation : IConversation
10+
public class ConversationHandler : IConversationHandler
1411
{
15-
private enum State
16-
{
17-
Command,
18-
// search projects
19-
SearchProjects,
20-
// add issue
21-
AddIssueSetIssueProjectId,
22-
AddIssueSetIssueSubject,
23-
AddIssueSetIssueDescription,
24-
AddIssueSetTrackerId,
25-
}
26-
2712
private readonly ITelegramBotClient _telegramBotClient;
2813
private readonly IRedmineApiClient _redmineApiClient;
2914

30-
private State _state = State.Command;
31-
32-
// issue
33-
private AddIssueModel _createIssueModel;
15+
private readonly ConversationStateModel _conversationState;
3416

35-
public Conversation(
17+
public ConversationHandler(
3618
ITelegramBotClient telegramBotClient,
37-
IRedmineApiClient redmineApiClient)
19+
IRedmineApiClient redmineApiClient,
20+
ConversationStateModel conversationState)
3821
{
3922
_telegramBotClient = telegramBotClient;
4023
_redmineApiClient = redmineApiClient;
24+
_conversationState = conversationState;
4125
}
4226

43-
public async Task Process(Message message)
27+
public async Task Handle(Message message)
4428
{
4529
if (message.Text == $"/{Commands.Cancel}")
4630
{
@@ -49,7 +33,7 @@ public async Task Process(Message message)
4933
return;
5034
}
5135

52-
if (_state == State.Command)
36+
if (_conversationState.State == State.Command)
5337
{
5438
if (message.Text == $"/{Commands.ProjectList}")
5539
{
@@ -59,42 +43,42 @@ public async Task Process(Message message)
5943

6044
if (message.Text == $"/{Commands.AddIssue}")
6145
{
62-
_createIssueModel = new AddIssueModel();
46+
_conversationState.CreateIssueModel = new AddIssueModel();
6347
await ChangeState(message, State.AddIssueSetIssueProjectId);
6448
return;
6549
}
6650
}
6751

68-
if (_state == State.SearchProjects)
52+
if (_conversationState.State == State.SearchProjects)
6953
{
7054
await ReplyWithProjectList(message, message.Text);
7155
return;
7256
}
7357

74-
if (_state == State.AddIssueSetIssueProjectId)
58+
if (_conversationState.State == State.AddIssueSetIssueProjectId)
7559
{
76-
_createIssueModel.issue.project_id = int.Parse(message.Text);
60+
_conversationState.CreateIssueModel.issue.project_id = int.Parse(message.Text);
7761
await ChangeState(message, State.AddIssueSetIssueSubject);
7862
return;
7963
}
8064

81-
if (_state == State.AddIssueSetIssueSubject)
65+
if (_conversationState.State == State.AddIssueSetIssueSubject)
8266
{
83-
_createIssueModel.issue.subject = message.Text;
67+
_conversationState.CreateIssueModel.issue.subject = message.Text;
8468
await ChangeState(message, State.AddIssueSetIssueDescription);
8569
return;
8670
}
8771

88-
if (_state == State.AddIssueSetIssueDescription)
72+
if (_conversationState.State == State.AddIssueSetIssueDescription)
8973
{
90-
_createIssueModel.issue.description = message.Text;
74+
_conversationState.CreateIssueModel.issue.description = message.Text;
9175
await ChangeState(message, State.AddIssueSetTrackerId);
9276
return;
9377
}
9478

95-
if (_state == State.AddIssueSetTrackerId)
79+
if (_conversationState.State == State.AddIssueSetTrackerId)
9680
{
97-
_createIssueModel.issue.tracker_id = int.Parse(message.Text);
81+
_conversationState.CreateIssueModel.issue.tracker_id = int.Parse(message.Text);
9882
await AddIssue(message);
9983
await ChangeState(message, State.Command);
10084
return;
@@ -105,7 +89,7 @@ public async Task Process(Message message)
10589

10690
private async Task ChangeState(Message message, State state)
10791
{
108-
_state = state;
92+
_conversationState.State = state;
10993

11094
if (state == State.AddIssueSetIssueProjectId)
11195
{
@@ -178,7 +162,7 @@ private async Task ReplyWithTrackerList(Message message)
178162

179163
private async Task AddIssue(Message message)
180164
{
181-
var response = await _redmineApiClient.AddIssue(_createIssueModel);
165+
var response = await _redmineApiClient.AddIssue(_conversationState.CreateIssueModel);
182166
if (response.Errors != null && response.Errors.Count > 0)
183167
{
184168
await ReplyMessage(message, string.Join("\n", response.Errors));
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using RedmineTelegramBot.Core.Config;
2+
using RedmineTelegramBot.Core.Data;
3+
using RedmineTelegramBot.Core.Models;
4+
using Telegram.Bot;
5+
6+
namespace RedmineTelegramBot.Core
7+
{
8+
public class ConversationHandlerFactory : IConversationHandlerFactory
9+
{
10+
private readonly ITelegramBotClient _telegramBotClient;
11+
private readonly BotOptions _botOptions;
12+
private readonly IUserSettingsRepository _userSettingsRepository;
13+
14+
public ConversationHandlerFactory(ITelegramBotClient telegramBotClient, BotOptions botOptions, IUserSettingsRepository userSettingsRepository)
15+
{
16+
_telegramBotClient = telegramBotClient;
17+
_botOptions = botOptions;
18+
_userSettingsRepository = userSettingsRepository;
19+
}
20+
21+
public IConversationHandler CreateConversationHandler(ConversationStateModel state)
22+
{
23+
var userSettings = _userSettingsRepository.GetSettings(state.Username);
24+
if (userSettings == null)
25+
{
26+
throw new BotException("User settings not found!");
27+
}
28+
29+
var restClientFactory = new RestClientFactory(_botOptions, userSettings);
30+
31+
return new ConversationHandler(_telegramBotClient, new RedmineApiClient(restClientFactory), state);
32+
}
33+
}
34+
}

RedmineTelegramBot.Core/IConversationFactory.cs

Lines changed: 0 additions & 14 deletions
This file was deleted.

RedmineTelegramBot.Core/IConversation.cs renamed to RedmineTelegramBot.Core/IConversationHandler.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88

99
namespace RedmineTelegramBot.Core
1010
{
11-
public interface IConversation
11+
public interface IConversationHandler
1212
{
13-
Task Process(Message message);
13+
Task Handle(Message message);
1414
}
1515
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using RedmineTelegramBot.Core.Models;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
using Telegram.Bot.Types;
8+
9+
namespace RedmineTelegramBot.Core
10+
{
11+
public interface IConversationHandlerFactory
12+
{
13+
IConversationHandler CreateConversationHandler(ConversationStateModel state);
14+
}
15+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace RedmineTelegramBot.Core.Models
8+
{
9+
public class ConversationStateModel
10+
{
11+
public long ChatId { get; set; }
12+
13+
public string Username { get; set; }
14+
15+
public State State { get; set; } = State.Command;
16+
17+
public AddIssueModel CreateIssueModel { get; set; }
18+
}
19+
20+
public enum State
21+
{
22+
Command,
23+
// search projects
24+
SearchProjects,
25+
// add issue
26+
AddIssueSetIssueProjectId,
27+
AddIssueSetIssueSubject,
28+
AddIssueSetIssueDescription,
29+
AddIssueSetTrackerId,
30+
}
31+
}

RedmineTelegramBot.Core/Modules/RedmineBotModule.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,16 @@ public RedmineBotModule(BotOptions configuration)
1616

1717
public void Load(IServiceCollection services)
1818
{
19+
// config
20+
services.AddSingleton(_options);
21+
1922
// repositories
2023
services.AddTransient<IUserSettingsRepository>(c => new UsersSettingsFileRepository(_options.DataDirectory));
2124

2225
// app services
2326
services.AddTransient<IRedmineBot, RedmineBot>();
2427
services.AddSingleton<ITelegramBotClient>(c => new TelegramBotClient(_options.Token));
25-
services.AddTransient<IConversationFactory, ConversationFactory>();
26-
services.AddTransient<IRestClientFactory>(c => new RestClientFactory(_options));
28+
services.AddTransient<IConversationHandlerFactory, ConversationHandlerFactory>();
2729
services.AddTransient<IRedmineApiClient,RedmineApiClient>();
2830
}
2931
}

0 commit comments

Comments
 (0)