add voice service call service and more

This commit is contained in:
2025-11-25 16:49:18 +03:30
parent 60d20a2734
commit 9ba81d944f
49 changed files with 4428 additions and 19 deletions

View File

@@ -0,0 +1,56 @@
using Microsoft.AspNetCore.Mvc;
using GreenHome.Application;
namespace GreenHome.Api.Controllers;
[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
private readonly IAuthService authService;
public AuthController(IAuthService authService)
{
this.authService = authService;
}
[HttpPost("send-code")]
public async Task<ActionResult<SendCodeResponse>> SendCode(
[FromBody] SendCodeRequest request,
CancellationToken cancellationToken)
{
var result = await authService.SendVerificationCodeAsync(request, cancellationToken);
if (!result.Success)
{
return BadRequest(result);
}
return Ok(result);
}
[HttpPost("verify-code")]
public async Task<ActionResult<VerifyCodeResponse>> VerifyCode(
[FromBody] VerifyCodeRequest request,
CancellationToken cancellationToken)
{
var result = await authService.VerifyCodeAsync(request, cancellationToken);
if (!result.Success)
{
return BadRequest(result);
}
return Ok(result);
}
[HttpGet("can-resend")]
public async Task<ActionResult<bool>> CanResend(
[FromQuery] string mobile,
CancellationToken cancellationToken)
{
var canResend = await authService.CanResendCodeAsync(mobile, cancellationToken);
return Ok(new { canResend });
}
}

View File

@@ -35,4 +35,31 @@ public class DevicesController : ControllerBase
var id = await deviceService.AddDeviceAsync(dto, cancellationToken);
return Ok(id);
}
[HttpGet("user/{userId}")]
public async Task<ActionResult<IReadOnlyList<DeviceDto>>> GetUserDevices(int userId, CancellationToken cancellationToken)
{
var result = await deviceService.GetUserDevicesAsync(userId, cancellationToken);
return Ok(result);
}
[HttpGet("filtered")]
public async Task<ActionResult<PagedResult<DeviceDto>>> GetDevices(
[FromQuery] int userId,
[FromQuery] string? search = null,
[FromQuery] int page = 1,
[FromQuery] int pageSize = 10,
CancellationToken cancellationToken = default)
{
var filter = new DeviceFilter
{
UserId = userId,
Search = search,
Page = page,
PageSize = pageSize
};
var result = await deviceService.GetDevicesAsync(filter, cancellationToken);
return Ok(result);
}
}

View File

@@ -0,0 +1,138 @@
using GreenHome.Sms.Ippanel;
using Microsoft.AspNetCore.Mvc;
namespace GreenHome.Api.Controllers;
/// <summary>
/// Controller for testing SMS service
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class SmsTestController : ControllerBase
{
private readonly ISmsService smsService;
private readonly ILogger<SmsTestController> logger;
public SmsTestController(ISmsService smsService, ILogger<SmsTestController> logger)
{
this.smsService = smsService;
this.logger = logger;
}
/// <summary>
/// Test sending Webservice SMS
/// </summary>
/// <param name="request">SMS request details</param>
/// <returns>SMS response</returns>
[HttpPost("webservice")]
public async Task<IActionResult> TestWebserviceSms([FromBody] WebserviceSmsRequest request)
{
try
{
logger.LogInformation("Testing Webservice SMS to {Recipient}", request.Recipient);
var result = await smsService.SendWebserviceSmsAsync(request);
logger.LogInformation("Webservice SMS sent successfully.");
return Ok(new
{
success = true,
message = "پیامک با موفقیت ارسال شد",
data = result
});
}
catch (Exception ex)
{
logger.LogError(ex, "Error sending Webservice SMS");
return StatusCode(500, new
{
success = false,
message = "خطا در ارسال پیامک",
error = ex.Message
});
}
}
/// <summary>
/// Test sending Pattern SMS
/// </summary>
/// <param name="request">Pattern SMS request details</param>
/// <returns>SMS response</returns>
[HttpPost("pattern")]
public async Task<IActionResult> TestPatternSms([FromBody] PatternSmsRequest request)
{
try
{
logger.LogInformation("Testing Pattern SMS to {Recipient} with pattern {PatternCode}",
request.Recipients, request.PatternCode);
var result = await smsService.SendPatternSmsAsync(request);
logger.LogInformation("Pattern SMS sent successfully");
return Ok(new
{
success = true,
message = "پیامک با موفقیت ارسال شد",
data = result
});
}
catch (Exception ex)
{
logger.LogError(ex, "Error sending Pattern SMS");
return StatusCode(500, new
{
success = false,
message = "خطا در ارسال پیامک",
error = ex.Message
});
}
}
/// <summary>
/// Quick test with default values (for easy testing)
/// </summary>
/// <param name="phoneNumber">Phone number to send SMS to</param>
/// <returns>SMS response</returns>
[HttpPost("quick-test/{phoneNumber}")]
public async Task<IActionResult> QuickTest(string phoneNumber)
{
try
{
logger.LogInformation("Quick test SMS to {PhoneNumber}", phoneNumber);
var request = new WebserviceSmsRequest
{
Sender = "10001001", // شما می‌توانید این را از تنظیمات بخوانید
Recipient = phoneNumber,
Message = "این یک پیامک تست از سرویس GreenHome است. " + DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")
};
var result = await smsService.SendWebserviceSmsAsync(request);
return Ok(new
{
success = true,
message = "پیامک تست با موفقیت ارسال شد",
data = result,
testInfo = new
{
phoneNumber,
sentAt = DateTime.Now
}
});
}
catch (Exception ex)
{
logger.LogError(ex, "Error in quick test SMS");
return StatusCode(500, new
{
success = false,
message = "خطا در ارسال پیامک تست",
error = ex.Message
});
}
}
}

View File

@@ -8,10 +8,12 @@ namespace GreenHome.Api.Controllers;
public class TelemetryController : ControllerBase
{
private readonly ITelemetryService telemetryService;
private readonly IAlertService alertService;
public TelemetryController(ITelemetryService telemetryService)
public TelemetryController(ITelemetryService telemetryService, IAlertService alertService)
{
this.telemetryService = telemetryService;
this.alertService = alertService;
}
[HttpGet]
@@ -37,6 +39,26 @@ public class TelemetryController : ControllerBase
TimestampUtc = DateTime.UtcNow
};
var id = await telemetryService.AddAsync(dto, cancellationToken);
// Check and send alerts if needed (fire and forget)
_ = Task.Run(async () =>
{
try
{
// Get deviceId from the saved telemetry record
var deviceId = dto.DeviceId;
if (deviceId > 0)
{
await alertService.CheckAndSendAlertsAsync(deviceId, dto, cancellationToken);
}
}
catch
{
// Log error but don't fail the request
// Errors are logged in AlertService
}
}, cancellationToken);
return Ok(id);
}

View File

@@ -0,0 +1,270 @@
using GreenHome.VoiceCall.Avanak;
using Microsoft.AspNetCore.Mvc;
namespace GreenHome.Api.Controllers;
/// <summary>
/// Controller for testing Voice Call service (Avanak)
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class VoiceCallTestController : ControllerBase
{
private readonly IVoiceCallService voiceCallService;
private readonly ILogger<VoiceCallTestController> logger;
public VoiceCallTestController(IVoiceCallService voiceCallService, ILogger<VoiceCallTestController> logger)
{
this.voiceCallService = voiceCallService;
this.logger = logger;
}
/// <summary>
/// Test getting account status
/// </summary>
/// <returns>Account status response</returns>
[HttpGet("account-status")]
public async Task<IActionResult> GetAccountStatus()
{
try
{
logger.LogInformation("Testing AccountStatus");
var result = await voiceCallService.GetAccountStatusAsync();
logger.LogInformation("AccountStatus retrieved successfully");
return Ok(new
{
success = true,
message = "وضعیت حساب با موفقیت دریافت شد",
data = result
});
}
catch (Exception ex)
{
logger.LogError(ex, "Error getting account status");
return StatusCode(500, new
{
success = false,
message = "خطا در دریافت وضعیت حساب",
error = ex.Message
});
}
}
/// <summary>
/// Test generating TTS (Text-to-Speech)
/// </summary>
/// <param name="request">TTS generation request</param>
/// <returns>TTS generation response</returns>
[HttpPost("generate-tts")]
public async Task<IActionResult> GenerateTTS([FromBody] GenerateTTSRequest request)
{
try
{
logger.LogInformation("Testing GenerateTTS for text: {Text}", request.Text);
var result = await voiceCallService.GenerateTTSAsync(request);
logger.LogInformation("TTS generated successfully");
return Ok(new
{
success = true,
message = "تولید صوت با موفقیت انجام شد",
data = result
});
}
catch (Exception ex)
{
logger.LogError(ex, "Error generating TTS");
return StatusCode(500, new
{
success = false,
message = "خطا در تولید صوت",
error = ex.Message
});
}
}
/// <summary>
/// Test QuickSend (sending voice call with uploaded audio file)
/// </summary>
/// <param name="request">QuickSend request</param>
/// <returns>QuickSend response</returns>
[HttpPost("quick-send")]
public async Task<IActionResult> QuickSend([FromBody] QuickSendRequest request)
{
try
{
logger.LogInformation("Testing QuickSend to {Recipient} with MessageId {MessageId}",
request.Recipient, request.MessageId);
var result = await voiceCallService.QuickSendAsync(request);
logger.LogInformation("QuickSend completed successfully");
return Ok(new
{
success = true,
message = "تماس صوتی با موفقیت ارسال شد",
data = result
});
}
catch (Exception ex)
{
logger.LogError(ex, "Error sending quick voice call");
return StatusCode(500, new
{
success = false,
message = "خطا در ارسال تماس صوتی",
error = ex.Message
});
}
}
/// <summary>
/// Test QuickSendWithTTS (sending voice call with TTS)
/// </summary>
/// <param name="request">QuickSendWithTTS request</param>
/// <returns>QuickSendWithTTS response</returns>
[HttpPost("quick-send-with-tts")]
public async Task<IActionResult> QuickSendWithTTS([FromBody] QuickSendWithTTSRequest request)
{
try
{
logger.LogInformation("Testing QuickSendWithTTS to {Number} with text: {Text}",
request.Number, request.Text);
var result = await voiceCallService.QuickSendWithTTSAsync(request);
if (result != null && result.IsSuccess)
{
logger.LogInformation("QuickSendWithTTS completed successfully. QuickSendId: {QuickSendId}",
result.QuickSendId);
}
else
{
logger.LogWarning("QuickSendWithTTS failed with ReturnValue: {ReturnValue}",
result?.ReturnValue ?? 0);
}
return Ok(new
{
success = result?.IsSuccess ?? false,
message = result?.IsSuccess == true
? "تماس صوتی با موفقیت ارسال شد"
: $"خطا در ارسال تماس صوتی (کد خطا: {result?.ReturnValue})",
data = result,
quickSendId = result?.QuickSendId ?? 0
});
}
catch (Exception ex)
{
logger.LogError(ex, "Error sending quick voice call with TTS");
return StatusCode(500, new
{
success = false,
message = "خطا در ارسال تماس صوتی",
error = ex.Message
});
}
}
/// <summary>
/// Test getting QuickSend status
/// </summary>
/// <param name="request">GetQuickSend request</param>
/// <returns>QuickSend status response</returns>
[HttpPost("quick-send-status")]
public async Task<IActionResult> GetQuickSendStatus([FromBody] GetQuickSendRequest request)
{
try
{
logger.LogInformation("Testing GetQuickSendStatus for QuickSendId: {QuickSendId}",
request.QuickSendId);
var result = await voiceCallService.GetQuickSendStatusAsync(request);
logger.LogInformation("QuickSendStatus retrieved successfully");
return Ok(new
{
success = true,
message = "وضعیت تماس صوتی با موفقیت دریافت شد",
data = result
});
}
catch (Exception ex)
{
logger.LogError(ex, "Error getting quick send status");
return StatusCode(500, new
{
success = false,
message = "خطا در دریافت وضعیت تماس صوتی",
error = ex.Message
});
}
}
/// <summary>
/// Quick test with default values (for easy testing)
/// </summary>
/// <param name="phoneNumber">Phone number to send voice call to</param>
/// <param name="text">Text to convert to speech (optional)</param>
/// <returns>QuickSendWithTTS response</returns>
[HttpPost("quick-test/{phoneNumber}")]
public async Task<IActionResult> QuickTest(string phoneNumber, [FromQuery] string? text = null)
{
try
{
var testText = text ?? $"سلام. این یک تماس صوتی تست از سرویس GreenHome است. زمان تست: {DateTime.Now:yyyy/MM/dd HH:mm:ss}";
logger.LogInformation("Quick test voice call to {PhoneNumber} with text: {Text}",
phoneNumber, testText);
var request = new QuickSendWithTTSRequest
{
Number = phoneNumber,
Text = testText,
ServerID = 0 // Default
};
var result = await voiceCallService.QuickSendWithTTSAsync(request);
if (result != null && result.IsSuccess)
{
logger.LogInformation("Quick test voice call sent successfully. QuickSendId: {QuickSendId}",
result.QuickSendId);
}
return Ok(new
{
success = result?.IsSuccess ?? false,
message = result?.IsSuccess == true
? "تماس صوتی تست با موفقیت ارسال شد"
: $"خطا در ارسال تماس صوتی تست (کد خطا: {result?.ReturnValue})",
data = result,
quickSendId = result?.QuickSendId ?? 0,
testInfo = new
{
phoneNumber,
text = testText,
sentAt = DateTime.Now
}
});
}
catch (Exception ex)
{
logger.LogError(ex, "Error in quick test voice call");
return StatusCode(500, new
{
success = false,
message = "خطا در ارسال تماس صوتی تست",
error = ex.Message
});
}
}
}

View File

@@ -19,6 +19,8 @@
<ItemGroup>
<ProjectReference Include="..\GreenHome.Application\GreenHome.Application.csproj" />
<ProjectReference Include="..\GreenHome.Infrastructure\GreenHome.Infrastructure.csproj" />
<ProjectReference Include="..\GreenHome.Sms.Ippanel\GreenHome.Sms.Ippanel.csproj" />
<ProjectReference Include="..\GreenHome.VoiceCall.Avanak\GreenHome.VoiceCall.Avanak.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,6 +1,8 @@
using FluentValidation;
using GreenHome.Application;
using GreenHome.Infrastructure;
using GreenHome.Sms.Ippanel;
using GreenHome.VoiceCall.Avanak;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
@@ -42,9 +44,33 @@ builder.Services.AddDbContext<GreenHome.Infrastructure.GreenHomeDbContext>(optio
builder.Services.AddScoped<GreenHome.Application.IDeviceService, GreenHome.Infrastructure.DeviceService>();
builder.Services.AddScoped<GreenHome.Application.ITelemetryService, GreenHome.Infrastructure.TelemetryService>();
builder.Services.AddScoped<GreenHome.Application.IDeviceSettingsService, GreenHome.Infrastructure.DeviceSettingsService>();
builder.Services.AddScoped<GreenHome.Application.IAuthService, GreenHome.Infrastructure.AuthService>();
builder.Services.AddScoped<GreenHome.Application.IAlertService, GreenHome.Infrastructure.AlertService>();
// SMS Service Configuration
builder.Services.AddIppanelSms(builder.Configuration);
// Voice Call Service Configuration
builder.Services.AddAvanakVoiceCall(builder.Configuration);
var app = builder.Build();
// Apply pending migrations automatically
using (var scope = app.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var context = services.GetRequiredService<GreenHome.Infrastructure.GreenHomeDbContext>();
context.Database.Migrate();
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred while migrating the database.");
}
}
// Configure the HTTP request pipeline.
//if (app.Environment.IsDevelopment())
{

View File

@@ -6,7 +6,12 @@
}
},
"ConnectionStrings": {
"Default": "Server=.;Database=GreenHomeDb;User Id=sa;Password=qwER12#$110;Trusted_Connection=True;MultipleActiveResultSets=true;TrustServerCertificate=True"
"Default": "Server=.;Database=GreenHomeDb;Trusted_Connection=True;MultipleActiveResultSets=true;TrustServerCertificate=True"
},
"IppanelSms": {
"BaseUrl": "https://edge.ippanel.com/v1",
"AuthorizationToken": "YTA1Zjk3N2EtNzkwOC00ZTg5LWFjZmYtZGEyZDAyNjNlZWQxM2Q2ZDVjYWE0MTA2Yzc1NDYzZDY1Y2VkMjlhMzcwNjA=",
"DefaultSender": "+983000505"
},
"AllowedHosts": "*"
}