Skip to content
This repository was archived by the owner on May 14, 2024. It is now read-only.

Commit ee19f4b

Browse files
authored
Merge pull request #18 from Bardin08/f/15-add-send_file-command
Add file sending command
2 parents e1d795a + 27d0e02 commit ee19f4b

File tree

16 files changed

+543
-1
lines changed

16 files changed

+543
-1
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
4+
using FileReceiver.Common.Enums;
5+
6+
using Telegram.Bot.Types;
7+
8+
namespace FileReceiver.Bl.Abstract.Services
9+
{
10+
public interface IFileReceivingService
11+
{
12+
Task UpdateFileReceivingState(long userId, FileReceivingState newState);
13+
Task FinishReceivingTransaction(long userId);
14+
Task<bool> SaveDocument(Document document);
15+
Task<bool> SavePhoto(PhotoSize photoSize);
16+
Task<FileReceivingState> GetFileReceivingStateForUser(long userId);
17+
Task<bool> CheckIfSessionExists(Guid token);
18+
}
19+
}

src/FileReceiver.Bl.Impl/Factories/CommandHandlerFactory.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public ICommandHandler CreateCommandHandler(string command)
2828
"/profile" => _serviceProvider.GetService<ProfileCommandHandler>(),
2929
"/profile_edit" => _serviceProvider.GetService<ProfileEditCommandHandler>(),
3030
"/start_receiving" => _serviceProvider.GetService<StartReceivingCommandHandler>(),
31+
"/send_file" => _serviceProvider.GetService<SendFileCommandHandler>(),
3132
{ } when command.StartsWith("/") => _serviceProvider.GetService<DefaultCommandHandler>(),
3233
_ => null
3334
};

src/FileReceiver.Bl.Impl/Factories/UpdateHandlerFactory.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public IUpdateHandler CreateUpdateHandler(TransactionType transactionType)
2626
TransactionType.Registration => _serviceProvider.GetService<RegistrationUpdateHandler>(),
2727
TransactionType.EditProfile => _serviceProvider.GetService<EditProfileUpdateHandler>(),
2828
TransactionType.FileReceivingSessionCreating => _serviceProvider.GetService<FileReceivingSessionCreatingUpdateHandler>(),
29+
TransactionType.FileSending => _serviceProvider.GetService<FileSendingUpdateHandler>(),
2930
_ => _serviceProvider.GetService<DefaultUpdateHandler>(),
3031
};
3132
}

src/FileReceiver.Bl.Impl/FileReceiverBlInstaller.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ private static void AddServices(this IServiceCollection services)
3333
services.AddTransient<IBotMessagesService, BotMessagesService>();
3434
services.AddTransient<IUserRegistrationService, UserRegistrationService>();
3535
services.AddTransient<IFileReceivingSessionService, FileReceivingSessionService>();
36+
services.AddTransient<IFileReceivingService, FileReceivingService>();
3637
}
3738

3839
private static void AddMapperConfiguration(this IServiceCollection services)
@@ -56,6 +57,7 @@ private static void AddCommandHandlers(this IServiceCollection services)
5657
services.AddTransient<ProfileCommandHandler, ProfileCommandHandler>();
5758
services.AddTransient<ProfileEditCommandHandler, ProfileEditCommandHandler>();
5859
services.AddTransient<StartReceivingCommandHandler, StartReceivingCommandHandler>();
60+
services.AddTransient<SendFileCommandHandler, SendFileCommandHandler>();
5961
}
6062

6163
private static void AddUpdateHandlers(this IServiceCollection services)
@@ -64,6 +66,7 @@ private static void AddUpdateHandlers(this IServiceCollection services)
6466
services.AddTransient<DefaultUpdateHandler, DefaultUpdateHandler>();
6567
services.AddTransient<EditProfileUpdateHandler, EditProfileUpdateHandler>();
6668
services.AddTransient<FileReceivingSessionCreatingUpdateHandler, FileReceivingSessionCreatingUpdateHandler>();
69+
services.AddTransient<FileSendingUpdateHandler, FileSendingUpdateHandler>();
6770
}
6871

6972
private static void AddCallbackQueryHandlers(this IServiceCollection services)
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
using System.Threading.Tasks;
2+
3+
using AutoMapper;
4+
5+
using FileReceiver.Bl.Abstract.Handlers;
6+
using FileReceiver.Bl.Abstract.Services;
7+
using FileReceiver.Common.Enums;
8+
using FileReceiver.Common.Extensions;
9+
using FileReceiver.Common.Models;
10+
using FileReceiver.Dal.Abstract.Repositories;
11+
using FileReceiver.Dal.Entities;
12+
13+
using Telegram.Bot.Types;
14+
15+
namespace FileReceiver.Bl.Impl.Handlers.Commands
16+
{
17+
public class SendFileCommandHandler : ICommandHandler
18+
{
19+
private readonly IBotMessagesService _botMessagesService;
20+
private readonly IUserRepository _userRepository;
21+
private readonly ITransactionRepository _transactionRepository;
22+
private readonly IMapper _mapper;
23+
24+
public SendFileCommandHandler(
25+
IBotMessagesService botMessagesService,
26+
IUserRepository userRepository,
27+
ITransactionRepository transactionRepository,
28+
IMapper mapper)
29+
{
30+
_botMessagesService = botMessagesService;
31+
_userRepository = userRepository;
32+
_transactionRepository = transactionRepository;
33+
_mapper = mapper;
34+
}
35+
36+
public async Task HandleCommandAsync(Update update)
37+
{
38+
var userId = update.GetTgUserId();
39+
40+
if (!await _userRepository.CheckIfUserExistsAsync(userId))
41+
{
42+
await _botMessagesService.SendErrorAsync(userId,
43+
"You should register before you can use this command, to do this you can use command /register");
44+
return;
45+
}
46+
47+
var transactionData = new TransactionDataModel();
48+
transactionData.AddDataPiece(TransactionDataParameter.FileReceivingState,
49+
FileReceivingState.TokenReceived);
50+
51+
var transaction = new TransactionModel()
52+
{
53+
UserId = userId,
54+
TransactionType = TransactionType.FileSending,
55+
TransactionState = TransactionState.Active,
56+
TransactionData = transactionData,
57+
};
58+
59+
await _transactionRepository.AddAsync(_mapper.Map<TransactionEntity>(transaction));
60+
await _botMessagesService.SendTextMessageAsync(userId, "Okay, send me the session token");
61+
}
62+
}
63+
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
using System;
2+
using System.Linq;
3+
using System.Threading.Tasks;
4+
5+
using FileReceiver.Bl.Abstract.Handlers;
6+
using FileReceiver.Bl.Abstract.Services;
7+
using FileReceiver.Common.Enums;
8+
using FileReceiver.Common.Extensions;
9+
10+
using Telegram.Bot.Types;
11+
12+
namespace FileReceiver.Bl.Impl.Handlers.TelegramUpdate
13+
{
14+
public class FileSendingUpdateHandler : IUpdateHandler
15+
{
16+
private readonly IFileReceivingService _fileReceivingService;
17+
private readonly IBotMessagesService _botMessagesService;
18+
19+
public FileSendingUpdateHandler(
20+
IFileReceivingService fileReceivingService,
21+
IBotMessagesService botMessagesService)
22+
{
23+
_fileReceivingService = fileReceivingService;
24+
_botMessagesService = botMessagesService;
25+
}
26+
27+
public async Task HandleUpdateAsync(Update update)
28+
{
29+
var userId = update.GetTgUserId();
30+
31+
var data = new FileSendingUpdateData()
32+
{
33+
UserId = userId,
34+
Update = update,
35+
};
36+
37+
var fileReceivingState = await _fileReceivingService.GetFileReceivingStateForUser(userId);
38+
39+
switch (fileReceivingState)
40+
{
41+
case FileReceivingState.TokenReceived:
42+
await HandleReceivedToken(data);
43+
break;
44+
case FileReceivingState.FileReceived:
45+
await HandleReceivedFile(data);
46+
break;
47+
default:
48+
throw new ArgumentOutOfRangeException();
49+
}
50+
}
51+
52+
private async Task HandleReceivedToken(FileSendingUpdateData data)
53+
{
54+
if (!await ParseTokenAndCheckIfSessionExists(data))
55+
{
56+
return;
57+
}
58+
59+
await _botMessagesService.SendTextMessageAsync(data.UserId, "Okay and now send me the file please");
60+
await _fileReceivingService.UpdateFileReceivingState(data.UserId, FileReceivingState.FileReceived);
61+
}
62+
63+
64+
private async Task HandleReceivedFile(FileSendingUpdateData data)
65+
{
66+
if (data.Update.Message.Document is not null)
67+
{
68+
var isDocumentSaved = await _fileReceivingService.SaveDocument(data.Update.Message.Document);
69+
70+
if (!isDocumentSaved)
71+
{
72+
await _botMessagesService.SendErrorAsync(data.UserId,
73+
"An error occured while saving file. Try again");
74+
return;
75+
}
76+
}
77+
78+
if (data.Update.Message.Photo is not null)
79+
{
80+
// Telegram always returns 4 photos. The last one is in original quality
81+
var isPhotoSaved = await _fileReceivingService.SavePhoto(data.Update.Message.Photo.Last());
82+
83+
if (!isPhotoSaved)
84+
{
85+
await _botMessagesService.SendErrorAsync(data.UserId,
86+
"An error occured while photo saving. Try again");
87+
return;
88+
}
89+
}
90+
91+
await _botMessagesService.SendTextMessageAsync(data.UserId, "Your file saved");
92+
await _fileReceivingService.UpdateFileReceivingState(data.UserId, FileReceivingState.Complete);
93+
await _fileReceivingService.FinishReceivingTransaction(data.UserId);
94+
}
95+
96+
private async Task<bool> ParseTokenAndCheckIfSessionExists(FileSendingUpdateData data)
97+
{
98+
bool isTokenParsed = Guid.TryParse(data.Update.Message.Text, out Guid token);
99+
100+
if (!isTokenParsed)
101+
{
102+
await _botMessagesService.SendErrorAsync(data.UserId, "Invalid token. Try another one");
103+
return false;
104+
}
105+
106+
if (!await _fileReceivingService.CheckIfSessionExists(token))
107+
{
108+
await _botMessagesService.SendErrorAsync(data.UserId, "Session with this token is not exists");
109+
return false;
110+
}
111+
112+
return true;
113+
}
114+
115+
private class FileSendingUpdateData
116+
{
117+
public long UserId { get; set; }
118+
public Update Update { get; set; }
119+
}
120+
}
121+
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
using System;
2+
using System.Threading.Tasks;
3+
4+
using AutoMapper;
5+
6+
using FileReceiver.Bl.Abstract.Services;
7+
using FileReceiver.Common.Enums;
8+
using FileReceiver.Common.Exceptions;
9+
using FileReceiver.Common.Models;
10+
using FileReceiver.Dal.Abstract.Repositories;
11+
using FileReceiver.Dal.Entities.Enums;
12+
13+
using Telegram.Bot.Types;
14+
15+
namespace FileReceiver.Bl.Impl.Services
16+
{
17+
public class FileReceivingService : IFileReceivingService
18+
{
19+
private readonly IBotMessagesService _botMessagesService;
20+
private readonly ITransactionRepository _transactionRepository;
21+
private readonly IFileReceivingSessionRepository _fileReceivingSessionRepository;
22+
private readonly IMapper _mapper;
23+
24+
public FileReceivingService(
25+
IBotMessagesService botMessagesService,
26+
ITransactionRepository transactionRepository,
27+
IFileReceivingSessionRepository fileReceivingSessionRepository,
28+
IMapper mapper)
29+
{
30+
_botMessagesService = botMessagesService;
31+
_transactionRepository = transactionRepository;
32+
_fileReceivingSessionRepository = fileReceivingSessionRepository;
33+
_mapper = mapper;
34+
}
35+
36+
public async Task UpdateFileReceivingState(long userId, FileReceivingState newState)
37+
{
38+
var transactionEntity = await _transactionRepository.GetLastActiveTransactionByUserId(userId);
39+
40+
if (transactionEntity.TransactionType is not TransactionTypeDb.FileSending)
41+
{
42+
throw new InvalidTransactionTypeException();
43+
}
44+
45+
var transactionData = new TransactionDataModel(transactionEntity.TransactionData);
46+
transactionData.UpdateParameter(TransactionDataParameter.FileReceivingState, newState);
47+
transactionEntity.TransactionData = transactionData.ParametersAsJson;
48+
49+
await _transactionRepository.UpdateAsync(transactionEntity);
50+
}
51+
52+
public async Task FinishReceivingTransaction(long userId)
53+
{
54+
var transactionEntity = await _transactionRepository.GetLastActiveTransactionByUserId(userId);
55+
if (transactionEntity.TransactionType is not TransactionTypeDb.FileSending)
56+
{
57+
return;
58+
}
59+
60+
transactionEntity.TransactionState = TransactionStateDb.Committed;
61+
await _transactionRepository.UpdateAsync(transactionEntity);
62+
}
63+
64+
public async Task<bool> SaveDocument(Document document)
65+
{
66+
// TODO: Add saving the document to the datasource
67+
await Task.Delay(5000);
68+
return true;
69+
}
70+
71+
public async Task<bool> SavePhoto(PhotoSize photoSize)
72+
{
73+
// TODO: Add saving the photo to the datasource
74+
await Task.Delay(5000);
75+
return true;
76+
}
77+
78+
public async Task<FileReceivingState> GetFileReceivingStateForUser(long userId)
79+
{
80+
try
81+
{
82+
var transaction = await GetTransactionAndNotifyIfItsTypeInvalid(userId);
83+
84+
return transaction.TransactionData.GetDataPiece<FileReceivingState>(
85+
TransactionDataParameter.FileReceivingState);
86+
}
87+
catch (InvalidTransactionTypeException)
88+
{
89+
await _botMessagesService.SendErrorAsync(userId, "An error occured while processing you input. " +
90+
"Try to use command /cancel and then start " +
91+
"a file sending process again");
92+
return await Task.FromResult(FileReceivingState.None);
93+
}
94+
}
95+
96+
public async Task<bool> CheckIfSessionExists(Guid token)
97+
{
98+
var session = await _fileReceivingSessionRepository.GetByIdAsync(token);
99+
return session is not null;
100+
}
101+
102+
// TODO: maybe create a separate service for actioning with transactions?
103+
private async Task<TransactionModel> GetTransactionAndNotifyIfItsTypeInvalid(long userId)
104+
{
105+
var transaction = _mapper.Map<TransactionModel>(
106+
await _transactionRepository.GetLastActiveTransactionByUserId(userId));
107+
if (transaction.TransactionType is not TransactionType.FileSending)
108+
{
109+
throw new InvalidTransactionTypeException();
110+
}
111+
112+
return transaction;
113+
}
114+
}
115+
}

src/FileReceiver.Bl.Impl/Services/UpdateHandlerService.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ public async Task HandleUpdateAsync(Update update)
4545
case { Message: { Text: { } } }:
4646
await HandleMessageAsync(update);
4747
break;
48+
case { Message: { Document: { } } or { Photo: { } } }:
49+
await HandleMessageAsync(update);
50+
break;
4851
case { CallbackQuery: { Message: { Text: { } } } cb }:
4952
await HandleCallbackQuery(cb);
5053
break;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace FileReceiver.Common.Enums
2+
{
3+
public enum FileReceivingState
4+
{
5+
None,
6+
CommandReceived,
7+
TokenReceived,
8+
FileReceived,
9+
Complete,
10+
}
11+
}

src/FileReceiver.Common/Enums/TransactionDataParameter.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ public enum TransactionDataParameter
66
RegistrationState = 1,
77
ProfileEditingAction = 2,
88
FileReceivingSessionId = 3,
9+
FileReceivingState = 4,
910
}
1011
}

0 commit comments

Comments
 (0)