增加微信分发机制
This commit is contained in:
parent
ac96a27072
commit
66b61e0ac4
@ -12,10 +12,7 @@ public class ApplicationDbContext : DbContext
|
|||||||
}
|
}
|
||||||
private static readonly ILoggerFactory _loggerFactory = new LoggerFactory();
|
private static readonly ILoggerFactory _loggerFactory = new LoggerFactory();
|
||||||
|
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
|
||||||
{
|
|
||||||
optionsBuilder.UseLoggerFactory(_loggerFactory);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -22,6 +22,7 @@
|
|||||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.4" />
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.4" />
|
||||||
<PackageReference Include="SharpMap" Version="1.2.0" />
|
<PackageReference Include="SharpMap" Version="1.2.0" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||||
|
<PackageReference Include="TencentCloudSDK" Version="3.0.1065" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@ -19,9 +19,9 @@ public class CloseWorker : BackgroundService
|
|||||||
{
|
{
|
||||||
while (!stoppingToken.IsCancellationRequested)
|
while (!stoppingToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
using var scope = StaticServiceProvider.Current.CreateScope();
|
var scope = StaticServiceProvider.Current.CreateScope();
|
||||||
var settingServices = scope.ServiceProvider.GetRequiredService<SettingServices>();
|
var settingServices = scope.ServiceProvider.GetRequiredService<SettingServices>();
|
||||||
var options = settingServices.GetClientOptions();
|
var options = await settingServices.GetClientOptions();
|
||||||
if (_logger.IsEnabled(LogLevel.Information))
|
if (_logger.IsEnabled(LogLevel.Information))
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
|
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
|
||||||
@ -39,6 +39,7 @@ public class CloseWorker : BackgroundService
|
|||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
await Task.Delay(options.Delay, stoppingToken);
|
await Task.Delay(options.Delay, stoppingToken);
|
||||||
|
scope.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -217,20 +217,20 @@ public class UserController : ControllerBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("/api/Setting")]
|
[HttpGet("/api/Setting")]
|
||||||
public SpiderResponse<ClientOptions> GetClientOptions([FromServices] SettingServices settingServices)
|
public async Task<SpiderResponse<ClientOptions>> GetClientOptions([FromServices] SettingServices settingServices)
|
||||||
{
|
{
|
||||||
return new SpiderResponse<ClientOptions>()
|
return new SpiderResponse<ClientOptions>()
|
||||||
{
|
{
|
||||||
IsSuccess = true, Code = SpiderResponseCode.Success, Message = "获取配置成功",
|
IsSuccess = true, Code = SpiderResponseCode.Success, Message = "获取配置成功",
|
||||||
Result = settingServices.GetClientOptions()
|
Result = await settingServices.GetClientOptions()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("/api/Setting")]
|
[HttpPost("/api/Setting")]
|
||||||
public SpiderResponse<ClientOptions> SettingClientOptions([FromBody] ClientOptionsReq options,
|
public async Task<SpiderResponse<ClientOptions>> SettingClientOptions([FromBody] ClientOptionsReq options,
|
||||||
[FromServices] SettingServices settingServices)
|
[FromServices] SettingServices settingServices)
|
||||||
{
|
{
|
||||||
var setting = settingServices.GetClientOptions();
|
var setting = await settingServices.GetClientOptions();
|
||||||
setting.Delay = options.Delay;
|
setting.Delay = options.Delay;
|
||||||
setting.DispatchingRunning = options.DispatchingRunning;
|
setting.DispatchingRunning = options.DispatchingRunning;
|
||||||
setting.CloseFileRunning = options.CloseFileRunning;
|
setting.CloseFileRunning = options.CloseFileRunning;
|
||||||
|
|||||||
@ -13,7 +13,7 @@ public class LogInfo
|
|||||||
public LogInfo(string level, string message, [CallerMemberName] string from = "")
|
public LogInfo(string level, string message, [CallerMemberName] string from = "")
|
||||||
{
|
{
|
||||||
Id = Guid.NewGuid();
|
Id = Guid.NewGuid();
|
||||||
CreateTime = DateTime.Now;
|
CreateTime = DateTime.UtcNow;
|
||||||
Message = message;
|
Message = message;
|
||||||
Level = level;
|
Level = level;
|
||||||
From = from;
|
From = from;
|
||||||
|
|||||||
185
AutoDispathingWork/Migrations/20240812130932_dbv3.Designer.cs
generated
Normal file
185
AutoDispathingWork/Migrations/20240812130932_dbv3.Designer.cs
generated
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
using WorkerService1;
|
||||||
|
using WorkerService1.Domains;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace AutoDispathingWork.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(ApplicationDbContext))]
|
||||||
|
[Migration("20240812130932_dbv3")]
|
||||||
|
partial class dbv3
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "8.0.7")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("WorkerService1.Domains.LogInfo", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreateTime")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("From")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Level")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Message")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("CreateTime");
|
||||||
|
|
||||||
|
b.ToTable("LogInfos");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WorkerService1.Domains.Polygon", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid?>("PolygonId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("PhoneNumber")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<List<List<Points>>>("Points")
|
||||||
|
.HasColumnType("jsonb");
|
||||||
|
|
||||||
|
b.Property<List<string>>("RangeCameras")
|
||||||
|
.HasColumnType("jsonb");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("PolygonId");
|
||||||
|
|
||||||
|
b.ToTable("Polygons");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WorkerService1.Domains.SmsSendRecord", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("ErrorMessage")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSuccess")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<string>("PhoneNumber")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("RefrenceId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("SendTime")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("SendTime");
|
||||||
|
|
||||||
|
b.ToTable("SmsSendRecords");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WorkerService1.Dto.Configuration.ClientOptions", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("ApiGateway")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("CloseFileApi")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<bool>("CloseFileRunning")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<int>("Delay")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<string>("DiposeOrder")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<bool>("DispatchingRunning")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<string>("GetCamerasApi")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("GetTaskApi")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("GetUserApi")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("LoginApi")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Password")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasAnnotation("Relational:JsonPropertyName", "password");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasAnnotation("Relational:JsonPropertyName", "username");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("ClientOptions");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
28
AutoDispathingWork/Migrations/20240812130932_dbv3.cs
Normal file
28
AutoDispathingWork/Migrations/20240812130932_dbv3.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace AutoDispathingWork.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class dbv3 : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "PhoneNumber",
|
||||||
|
table: "Polygons",
|
||||||
|
type: "text",
|
||||||
|
nullable: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "PhoneNumber",
|
||||||
|
table: "Polygons");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -62,6 +62,9 @@ namespace AutoDispathingWork.Migrations
|
|||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("PhoneNumber")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
b.Property<List<List<Points>>>("Points")
|
b.Property<List<List<Points>>>("Points")
|
||||||
.HasColumnType("jsonb");
|
.HasColumnType("jsonb");
|
||||||
|
|
||||||
|
|||||||
@ -30,7 +30,7 @@ builder.Services.AddCors(x =>
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
|
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
|
||||||
builder.Services.AddDbContext<ApplicationDbContext>(x =>
|
builder.Services.AddDbContextPool<ApplicationDbContext>(x =>
|
||||||
{
|
{
|
||||||
var dataSourceBuilder = new NpgsqlDataSourceBuilder(connectionString);
|
var dataSourceBuilder = new NpgsqlDataSourceBuilder(connectionString);
|
||||||
// 启用动态 JSON 序列化
|
// 启用动态 JSON 序列化
|
||||||
@ -40,7 +40,6 @@ builder.Services.AddDbContext<ApplicationDbContext>(x =>
|
|||||||
.UseLoggerFactory(new LoggerFactory())
|
.UseLoggerFactory(new LoggerFactory())
|
||||||
.LogTo(Console.WriteLine, LogLevel.Information);
|
.LogTo(Console.WriteLine, LogLevel.Information);
|
||||||
x.ConfigureWarnings(warnings => warnings.Ignore(CoreEventId.ManyServiceProvidersCreatedWarning));
|
x.ConfigureWarnings(warnings => warnings.Ignore(CoreEventId.ManyServiceProvidersCreatedWarning));
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
builder.Services.AddSwaggerGen();
|
builder.Services.AddSwaggerGen();
|
||||||
@ -53,7 +52,8 @@ builder.Services.AddMemoryCache();
|
|||||||
builder.Services.AddLogging();
|
builder.Services.AddLogging();
|
||||||
// builder.Services.AddMvcCore();
|
// builder.Services.AddMvcCore();
|
||||||
builder.Services.AddSingleton<SpiderServices>();
|
builder.Services.AddSingleton<SpiderServices>();
|
||||||
builder.Services.AddScoped<SettingServices>();
|
builder.Services.AddSingleton<SettingServices>();
|
||||||
|
builder.Services.AddSingleton<WechatRobot>();
|
||||||
// #if !DEBUG
|
// #if !DEBUG
|
||||||
builder.Services.AddHostedService<Worker>();
|
builder.Services.AddHostedService<Worker>();
|
||||||
builder.Services.AddHostedService<CloseWorker>();
|
builder.Services.AddHostedService<CloseWorker>();
|
||||||
@ -67,6 +67,9 @@ app.UseCors("AllowAllOrigin");
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
app.UseSwagger();
|
app.UseSwagger();
|
||||||
app.UseSwaggerUI();
|
app.UseSwaggerUI();
|
||||||
|
var wechatRobot = app.Services.GetService<WechatRobot>();
|
||||||
|
wechatRobot.SetKey("e68b3791-e040-4c9b-9ac0-6f424e662185");
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
app.UseDefaultFiles();
|
app.UseDefaultFiles();
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using AutoDispathingWork.Utils;
|
using AutoDispathingWork.Utils;
|
||||||
using LiteDB;
|
using LiteDB;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using WorkerService1.Dto.Configuration;
|
using WorkerService1.Dto.Configuration;
|
||||||
|
|
||||||
@ -9,7 +10,6 @@ public class SettingServices
|
|||||||
{
|
{
|
||||||
private readonly IOptionsMonitor<ClientOptions> _optionsMonitor;
|
private readonly IOptionsMonitor<ClientOptions> _optionsMonitor;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public SettingServices(IOptionsMonitor<ClientOptions> optionsMonitor)
|
public SettingServices(IOptionsMonitor<ClientOptions> optionsMonitor)
|
||||||
{
|
{
|
||||||
@ -21,23 +21,27 @@ public class SettingServices
|
|||||||
SettingClientOptions(_optionsMonitor.CurrentValue);
|
SettingClientOptions(_optionsMonitor.CurrentValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClientOptions GetClientOptions()
|
public async Task<ClientOptions> GetClientOptions()
|
||||||
{
|
{
|
||||||
using var scope = StaticServiceProvider.Current.CreateScope();
|
var scope = StaticServiceProvider.Current.CreateScope();
|
||||||
var _db = scope.ServiceProvider.GetService<ApplicationDbContext>();
|
var _db = scope.ServiceProvider.GetService<ApplicationDbContext>();
|
||||||
var clientOptions = _db.ClientOptions;
|
var clientOptions = _db.ClientOptions;
|
||||||
var dbOptions = clientOptions.FirstOrDefault();
|
var dbOptions = await clientOptions.FirstOrDefaultAsync();
|
||||||
if (dbOptions != null)
|
if (dbOptions != null)
|
||||||
{
|
{
|
||||||
|
await _db.DisposeAsync();
|
||||||
|
scope.Dispose();
|
||||||
return dbOptions;
|
return dbOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await _db.DisposeAsync();
|
||||||
|
scope.Dispose();
|
||||||
return _optionsMonitor.CurrentValue;
|
return _optionsMonitor.CurrentValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClientOptions SettingClientOptions(ClientOptions options)
|
public ClientOptions SettingClientOptions(ClientOptions options)
|
||||||
{
|
{
|
||||||
using var scope = StaticServiceProvider.Current.CreateScope();
|
var scope = StaticServiceProvider.Current.CreateScope();
|
||||||
var _db = scope.ServiceProvider.GetService<ApplicationDbContext>();
|
var _db = scope.ServiceProvider.GetService<ApplicationDbContext>();
|
||||||
var clientOptions = _db.ClientOptions;
|
var clientOptions = _db.ClientOptions;
|
||||||
var dbOptions = clientOptions.FirstOrDefault();
|
var dbOptions = clientOptions.FirstOrDefault();
|
||||||
@ -49,6 +53,9 @@ public class SettingServices
|
|||||||
|
|
||||||
clientOptions.Add(options);
|
clientOptions.Add(options);
|
||||||
_db.SaveChanges();
|
_db.SaveChanges();
|
||||||
|
|
||||||
|
_db.Dispose();
|
||||||
|
scope.Dispose();
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,12 +1,117 @@
|
|||||||
namespace WorkerService1.Services;
|
using TencentCloud.Common;
|
||||||
|
using TencentCloud.Common.Profile;
|
||||||
|
using TencentCloud.Cvm.V20170312;
|
||||||
|
using TencentCloud.Cvm.V20170312.Models;
|
||||||
|
using TencentCloud.Sms.V20210111;
|
||||||
|
using TencentCloud.Sms.V20210111.Models;
|
||||||
|
|
||||||
|
namespace WorkerService1.Services;
|
||||||
|
|
||||||
public class SmsService
|
public class SmsService
|
||||||
{
|
{
|
||||||
public Task SendSmsAsync(string phoneNumber, string message,string refrenceId)
|
public Task SendSmsAsync(string phoneNumber, string message, string refrenceId)
|
||||||
{
|
{
|
||||||
//发送短信逻辑
|
try
|
||||||
|
{
|
||||||
Console.WriteLine($"Sending SMS to {phoneNumber} with message {message} and refrenceId {refrenceId}");
|
// 必要步骤:
|
||||||
|
// 实例化一个认证对象,入参需要传入腾讯云账户密钥对 SecretId,SecretKey。
|
||||||
|
// 为了保护密钥安全,建议将密钥设置在环境变量中或者配置文件中。
|
||||||
|
// 硬编码密钥到代码中有可能随代码泄露而暴露,有安全隐患,并不推荐。
|
||||||
|
// 这里采用的是从环境变量读取的方式,需要在环境变量中先设置这两个值。
|
||||||
|
// SecretId、SecretKey 查询:https://console.cloud.tencent.com/cam/capi
|
||||||
|
Credential cred = new Credential
|
||||||
|
{
|
||||||
|
SecretId = Environment.GetEnvironmentVariable("TENCENTCLOUD_SECRET_ID"),
|
||||||
|
SecretKey = Environment.GetEnvironmentVariable("TENCENTCLOUD_SECRET_KEY")
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* 非必要步骤:
|
||||||
|
* 实例化一个客户端配置对象,可以指定超时时间等配置 */
|
||||||
|
ClientProfile clientProfile = new ClientProfile
|
||||||
|
{
|
||||||
|
/* SDK默认用TC3-HMAC-SHA256进行签名
|
||||||
|
* 非必要请不要修改这个字段 */
|
||||||
|
SignMethod = ClientProfile.SIGN_TC3SHA256
|
||||||
|
};
|
||||||
|
/* 非必要步骤
|
||||||
|
* 实例化一个客户端配置对象,可以指定超时时间等配置 */
|
||||||
|
var httpProfile = new HttpProfile
|
||||||
|
{
|
||||||
|
/* SDK默认使用POST方法。
|
||||||
|
* 如果您一定要使用GET方法,可以在这里设置。GET方法无法处理一些较大的请求 */
|
||||||
|
ReqMethod = "GET",
|
||||||
|
Timeout = 10, // 请求连接超时时间,单位为秒(默认60秒)
|
||||||
|
/* 指定接入地域域名,默认就近地域接入域名为 sms.tencentcloudapi.com ,也支持指定地域域名访问,例如广州地域的域名为 sms.ap-guangzhou.tencentcloudapi.com */
|
||||||
|
Endpoint = "sms.tencentcloudapi.com"
|
||||||
|
};
|
||||||
|
// 代理服务器,当您的环境下有代理服务器时设定(无需要直接忽略)
|
||||||
|
// httpProfile.WebProxy = Environment.GetEnvironmentVariable("HTTPS_PROXY");
|
||||||
|
|
||||||
|
|
||||||
|
clientProfile.HttpProfile = httpProfile;
|
||||||
|
/* 实例化要请求产品(以sms为例)的client对象
|
||||||
|
* 第二个参数是地域信息,可以直接填写字符串ap-guangzhou,支持的地域列表参考 https://cloud.tencent.com/document/api/382/52071#.E5.9C.B0.E5.9F.9F.E5.88.97.E8.A1.A8 */
|
||||||
|
var client = new SmsClient(cred, "ap-guangzhou", clientProfile);
|
||||||
|
|
||||||
|
|
||||||
|
/* 实例化一个请求对象,根据调用的接口和实际情况,可以进一步设置请求参数
|
||||||
|
* 您可以直接查询SDK源码确定SendSmsRequest有哪些属性可以设置
|
||||||
|
* 属性可能是基本类型,也可能引用了另一个数据结构
|
||||||
|
* 推荐使用IDE进行开发,可以方便的跳转查阅各个接口和数据结构的文档说明 */
|
||||||
|
var req = new SendSmsRequest
|
||||||
|
{
|
||||||
|
/* 基本类型的设置:
|
||||||
|
* SDK采用的是指针风格指定参数,即使对于基本类型您也需要用指针来对参数赋值。
|
||||||
|
* SDK提供对基本类型的指针引用封装函数
|
||||||
|
* 帮助链接:
|
||||||
|
* 短信控制台: https://console.cloud.tencent.com/smsv2
|
||||||
|
* 腾讯云短信小助手: https://cloud.tencent.com/document/product/382/3773#.E6.8A.80.E6.9C.AF.E4.BA.A4.E6.B5.81 */
|
||||||
|
/* 短信应用ID: 短信SdkAppId在 [短信控制台] 添加应用后生成的实际SdkAppId,示例如1400006666 */
|
||||||
|
// 应用 ID 可前往 [短信控制台](https://console.cloud.tencent.com/smsv2/app-manage) 查看
|
||||||
|
SmsSdkAppId = "1400787878",
|
||||||
|
/* 短信签名内容: 使用 UTF-8 编码,必须填写已审核通过的签名 */
|
||||||
|
// 签名信息可前往 [国内短信](https://console.cloud.tencent.com/smsv2/csms-sign) 或 [国际/港澳台短信](https://console.cloud.tencent.com/smsv2/isms-sign) 的签名管理查看
|
||||||
|
SignName = "腾讯云",
|
||||||
|
/* 模板 ID: 必须填写已审核通过的模板 ID */
|
||||||
|
// 模板 ID 可前往 [国内短信](https://console.cloud.tencent.com/smsv2/csms-template) 或 [国际/港澳台短信](https://console.cloud.tencent.com/smsv2/isms-template) 的正文模板管理查看
|
||||||
|
TemplateId = "449739",
|
||||||
|
/* 模板参数: 模板参数的个数需要与 TemplateId 对应模板的变量个数保持一致,若无模板参数,则设置为空 */
|
||||||
|
TemplateParamSet = new String[] { "1234" },
|
||||||
|
/* 下发手机号码,采用 E.164 标准,+[国家或地区码][手机号]
|
||||||
|
* 示例如:+8613711112222, 其中前面有一个+号 ,86为国家码,13711112222为手机号,最多不要超过200个手机号*/
|
||||||
|
PhoneNumberSet = new String[] { "+86" + phoneNumber },
|
||||||
|
/* 用户的 session 内容(无需要可忽略): 可以携带用户侧 ID 等上下文信息,server 会原样返回 */
|
||||||
|
SessionContext = "",
|
||||||
|
/* 短信码号扩展号(无需要可忽略): 默认未开通,如需开通请联系 [腾讯云短信小助手] */
|
||||||
|
ExtendCode = "",
|
||||||
|
/* 国内短信无需填写该项;国际/港澳台短信已申请独立 SenderId 需要填写该字段,默认使用公共 SenderId,无需填写该字段。注:月度使用量达到指定量级可申请独立 SenderId 使用,详情请联系 [腾讯云短信小助手](https://cloud.tencent.com/document/product/382/3773#.E6.8A.80.E6.9C.AF.E4.BA.A4.E6.B5.81)。 */
|
||||||
|
SenderId = ""
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
SendSmsResponse resp = client.SendSmsSync(req);
|
||||||
|
|
||||||
|
|
||||||
|
// 输出json格式的字符串回包
|
||||||
|
Console.WriteLine(AbstractModel.ToJsonString(resp));
|
||||||
|
|
||||||
|
|
||||||
|
/* 当出现以下错误码时,快速解决方案参考
|
||||||
|
* [FailedOperation.SignatureIncorrectOrUnapproved](https://cloud.tencent.com/document/product/382/9558#.E7.9F.AD.E4.BF.A1.E5.8F.91.E9.80.81.E6.8F.90.E7.A4.BA.EF.BC.9Afailedoperation.signatureincorrectorunapproved-.E5.A6.82.E4.BD.95.E5.A4.84.E7.90.86.EF.BC.9F)
|
||||||
|
* [FailedOperation.TemplateIncorrectOrUnapproved](https://cloud.tencent.com/document/product/382/9558#.E7.9F.AD.E4.BF.A1.E5.8F.91.E9.80.81.E6.8F.90.E7.A4.BA.EF.BC.9Afailedoperation.templateincorrectorunapproved-.E5.A6.82.E4.BD.95.E5.A4.84.E7.90.86.EF.BC.9F)
|
||||||
|
* [UnauthorizedOperation.SmsSdkAppIdVerifyFail](https://cloud.tencent.com/document/product/382/9558#.E7.9F.AD.E4.BF.A1.E5.8F.91.E9.80.81.E6.8F.90.E7.A4.BA.EF.BC.9Aunauthorizedoperation.smssdkappidverifyfail-.E5.A6.82.E4.BD.95.E5.A4.84.E7.90.86.EF.BC.9F)
|
||||||
|
* [UnsupportedOperation.ContainDomesticAndInternationalPhoneNumber](https://cloud.tencent.com/document/product/382/9558#.E7.9F.AD.E4.BF.A1.E5.8F.91.E9.80.81.E6.8F.90.E7.A4.BA.EF.BC.9Aunsupportedoperation.containdomesticandinternationalphonenumber-.E5.A6.82.E4.BD.95.E5.A4.84.E7.90.86.EF.BC.9F)
|
||||||
|
* 更多错误,可咨询[腾讯云助手](https://tccc.qcloud.com/web/im/index.html#/chat?webAppId=8fa15978f85cb41f7e2ea36920cb3ae1&title=Sms)
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.Read();
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -44,7 +44,7 @@ public class SpiderServices
|
|||||||
{
|
{
|
||||||
using var scope = _serviceProvider.CreateScope();
|
using var scope = _serviceProvider.CreateScope();
|
||||||
using var client = _httpClientFactory.CreateClient();
|
using var client = _httpClientFactory.CreateClient();
|
||||||
var getClientOptions = scope.ServiceProvider.GetService<SettingServices>()?
|
var getClientOptions = await scope.ServiceProvider.GetService<SettingServices>()?
|
||||||
.GetClientOptions();
|
.GetClientOptions();
|
||||||
var loginApi = getClientOptions.LoginUrl;
|
var loginApi = getClientOptions.LoginUrl;
|
||||||
var json = $@"
|
var json = $@"
|
||||||
@ -137,7 +137,7 @@ public class SpiderServices
|
|||||||
// {"state":[1],"pageNo":1,"pageSize":50,"sortType":[20,10],"createStartTime":1697290618034,"createEndTime":1699882618034}
|
// {"state":[1],"pageNo":1,"pageSize":50,"sortType":[20,10],"createStartTime":1697290618034,"createEndTime":1699882618034}
|
||||||
// {\"state\":[1],\"pageNo\":1,\"pageSize\":50,\"sortType\":[20,10],\"createStartTime\":1697204639551,\"createEndTime\":1697204639551}
|
// {\"state\":[1],\"pageNo\":1,\"pageSize\":50,\"sortType\":[20,10],\"createStartTime\":1697204639551,\"createEndTime\":1697204639551}
|
||||||
using var scope = _serviceProvider.CreateScope();
|
using var scope = _serviceProvider.CreateScope();
|
||||||
var getClientOptions = scope.ServiceProvider.GetService<SettingServices>()?
|
var getClientOptions = await scope.ServiceProvider.GetService<SettingServices>()?
|
||||||
.GetClientOptions();
|
.GetClientOptions();
|
||||||
var taskPath = getClientOptions.GetTaskUrl;
|
var taskPath = getClientOptions.GetTaskUrl;
|
||||||
var response = await client.PostAsync(taskPath,
|
var response = await client.PostAsync(taskPath,
|
||||||
@ -183,7 +183,7 @@ public class SpiderServices
|
|||||||
client.DefaultRequestHeaders.Add("module-source", "megcity-web");
|
client.DefaultRequestHeaders.Add("module-source", "megcity-web");
|
||||||
var request = query ?? new UserQuery();
|
var request = query ?? new UserQuery();
|
||||||
using var scope = _serviceProvider.CreateScope();
|
using var scope = _serviceProvider.CreateScope();
|
||||||
var getClientOptions = scope.ServiceProvider.GetService<SettingServices>()?
|
var getClientOptions = await scope.ServiceProvider.GetService<SettingServices>()?
|
||||||
.GetClientOptions();
|
.GetClientOptions();
|
||||||
var userPath = getClientOptions.GetUserUrl;
|
var userPath = getClientOptions.GetUserUrl;
|
||||||
var response = await client.PostAsync(userPath,
|
var response = await client.PostAsync(userPath,
|
||||||
@ -228,7 +228,7 @@ public class SpiderServices
|
|||||||
client.DefaultRequestHeaders.Add("module-alias", "pending-forward");
|
client.DefaultRequestHeaders.Add("module-alias", "pending-forward");
|
||||||
client.DefaultRequestHeaders.Add("module-source", "megcity-web");
|
client.DefaultRequestHeaders.Add("module-source", "megcity-web");
|
||||||
|
|
||||||
var (handlerId,phone, userRealName) = await GetUserIdByCamera(cameraName);
|
var (handlerId, phone, userRealName) = await GetUserIdByCamera(cameraName);
|
||||||
if (string.IsNullOrWhiteSpace(handlerId))
|
if (string.IsNullOrWhiteSpace(handlerId))
|
||||||
{
|
{
|
||||||
return new SpiderResponse<object>()
|
return new SpiderResponse<object>()
|
||||||
@ -248,7 +248,7 @@ public class SpiderServices
|
|||||||
TypeCode = typeCode
|
TypeCode = typeCode
|
||||||
};
|
};
|
||||||
using var scope = _serviceProvider.CreateScope();
|
using var scope = _serviceProvider.CreateScope();
|
||||||
var getClientOptions = scope.ServiceProvider.GetService<SettingServices>()?
|
var getClientOptions = await scope.ServiceProvider.GetService<SettingServices>()?
|
||||||
.GetClientOptions();
|
.GetClientOptions();
|
||||||
var dispatchPath = string.Format(getClientOptions.DiposeOrderUrl, caseNumber);
|
var dispatchPath = string.Format(getClientOptions.DiposeOrderUrl, caseNumber);
|
||||||
|
|
||||||
@ -263,8 +263,8 @@ public class SpiderServices
|
|||||||
if (spiderRes?.code == 0)
|
if (spiderRes?.code == 0)
|
||||||
{
|
{
|
||||||
var msg = $"成功分发任务,任务编号:{caseNumber},任务地址:{cameraName},任务类型:{typeCode},处理人:{userRealName}";
|
var msg = $"成功分发任务,任务编号:{caseNumber},任务地址:{cameraName},任务类型:{typeCode},处理人:{userRealName}";
|
||||||
var smsService = scope.ServiceProvider.GetService<SmsService>();
|
var smsService = scope.ServiceProvider.GetRequiredService<WechatRobot>();
|
||||||
await smsService.SendSmsAsync(phoneNumber:phone, $"{userRealName}您好,您有一条新案件,请及时处置,谢谢。",caseNumber);
|
await smsService.SendText($"{userRealName},您好,您有一条新案件,请及时处置,谢谢。", false);
|
||||||
_logger.LogInformation(msg);
|
_logger.LogInformation(msg);
|
||||||
|
|
||||||
return new SpiderResponse<object>()
|
return new SpiderResponse<object>()
|
||||||
@ -303,7 +303,7 @@ public class SpiderServices
|
|||||||
form.Add(new StringContent(caseNumber), "caseNumber");
|
form.Add(new StringContent(caseNumber), "caseNumber");
|
||||||
form.Add(new StringContent(suggestion), "suggestion");
|
form.Add(new StringContent(suggestion), "suggestion");
|
||||||
using var scope = _serviceProvider.CreateScope();
|
using var scope = _serviceProvider.CreateScope();
|
||||||
var getClientOptions = scope.ServiceProvider.GetService<SettingServices>()?
|
var getClientOptions = await scope.ServiceProvider.GetService<SettingServices>()?
|
||||||
.GetClientOptions();
|
.GetClientOptions();
|
||||||
var closeFile = getClientOptions.CloseFileUrl;
|
var closeFile = getClientOptions.CloseFileUrl;
|
||||||
|
|
||||||
@ -352,7 +352,7 @@ public class SpiderServices
|
|||||||
{{""managementIds"":[""6e9232ef-7b84-11e8-86b1-6c92bf4e6960""],""name"":""{name}"" ,""action"":""all"",""pageNo"":1,""pageSize"":200}}
|
{{""managementIds"":[""6e9232ef-7b84-11e8-86b1-6c92bf4e6960""],""name"":""{name}"" ,""action"":""all"",""pageNo"":1,""pageSize"":200}}
|
||||||
";
|
";
|
||||||
using var scope = _serviceProvider.CreateScope();
|
using var scope = _serviceProvider.CreateScope();
|
||||||
var getClientOptions = scope.ServiceProvider.GetService<SettingServices>()?
|
var getClientOptions = await scope.ServiceProvider.GetService<SettingServices>()?
|
||||||
.GetClientOptions();
|
.GetClientOptions();
|
||||||
var getCamersPath = getClientOptions.GetCamerasUrl;
|
var getCamersPath = getClientOptions.GetCamerasUrl;
|
||||||
var response = await client.PostAsync(getCamersPath,
|
var response = await client.PostAsync(getCamersPath,
|
||||||
@ -392,12 +392,12 @@ public class SpiderServices
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(string userId,string phone, string userRealName )> GetUserIdByCamera(string cameraAddress)
|
public async Task<(string userId, string phone, string userRealName )> GetUserIdByCamera(string cameraAddress)
|
||||||
{
|
{
|
||||||
using var scope = _serviceProvider.CreateScope();
|
using var scope = _serviceProvider.CreateScope();
|
||||||
var camerasResp = await GetCameras(cameraAddress);
|
var camerasResp = await GetCameras(cameraAddress);
|
||||||
var camera = camerasResp.Result?.Records.FirstOrDefault();
|
var camera = camerasResp.Result?.Records.FirstOrDefault();
|
||||||
if (camera == null) return (string.Empty,string.Empty, string.Empty);
|
if (camera == null) return (string.Empty, string.Empty, string.Empty);
|
||||||
var location = new Points(camera.lon, camera.lat);
|
var location = new Points(camera.lon, camera.lat);
|
||||||
var db = scope.ServiceProvider.GetService<ApplicationDbContext>()
|
var db = scope.ServiceProvider.GetService<ApplicationDbContext>()
|
||||||
.Polygons;
|
.Polygons;
|
||||||
@ -411,6 +411,6 @@ public class SpiderServices
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (string.Empty, string.Empty,string.Empty);
|
return (string.Empty, string.Empty, string.Empty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
118
AutoDispathingWork/WechatRobot.cs
Normal file
118
AutoDispathingWork/WechatRobot.cs
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
using System.Text;
|
||||||
|
using Microsoft.Net.Http.Headers;
|
||||||
|
|
||||||
|
namespace WorkerService1;
|
||||||
|
|
||||||
|
public class WechatRobot
|
||||||
|
{
|
||||||
|
private const string ApiUrl = "https://qyapi.weixin.qq.com";
|
||||||
|
private const int TextUtf8MaxLength = 2000;
|
||||||
|
private const int MarkdownUtf8MaxLength = 4000;
|
||||||
|
private string _key;
|
||||||
|
|
||||||
|
private static readonly MediaTypeHeaderValue ApplicationJson =
|
||||||
|
new MediaTypeHeaderValue("application/json")
|
||||||
|
{
|
||||||
|
Charset = "utf-8"
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly HttpClient _client;
|
||||||
|
private readonly ILogger<WechatRobot> _logger;
|
||||||
|
|
||||||
|
public WechatRobot(ILogger<WechatRobot> logger, HttpClient client)
|
||||||
|
{
|
||||||
|
client.BaseAddress = new Uri(ApiUrl);
|
||||||
|
this._logger = logger;
|
||||||
|
_client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WechatRobot SetKey(string key)
|
||||||
|
{
|
||||||
|
this._key = key;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SendText(string content, bool isAtAll)
|
||||||
|
{
|
||||||
|
await this.Post($"/cgi-bin/webhook/send?key={_key}", BuildTextBody(content, isAtAll));
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SendMarkdown(string content)
|
||||||
|
{
|
||||||
|
await this.Post($"/cgi-bin/webhook/send?key={_key}", BuildMarkdownBody(content));
|
||||||
|
}
|
||||||
|
|
||||||
|
private string BuildTextBody(string content, bool isAtAll)
|
||||||
|
{
|
||||||
|
var result = new StringBuilder("{\"msgtype\": \"text\",");
|
||||||
|
result.Append("\"text\": {");
|
||||||
|
result.Append($"\"content\": \"{Substring(content, TextUtf8MaxLength)}\",");
|
||||||
|
if (isAtAll)
|
||||||
|
{
|
||||||
|
result.Append($"\"mentioned_list\":[\"@all\"]");
|
||||||
|
}
|
||||||
|
|
||||||
|
result.Append("}}");
|
||||||
|
|
||||||
|
return result.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private string BuildMarkdownBody(string content)
|
||||||
|
{
|
||||||
|
var result = new StringBuilder("{\"msgtype\": \"markdown\",");
|
||||||
|
result.Append("\"markdown\": {");
|
||||||
|
result.Append($"\"content\": \"{Substring(FilterSpecialChar(content), MarkdownUtf8MaxLength)}\"");
|
||||||
|
result.Append("}}");
|
||||||
|
|
||||||
|
return result.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 截取字符串
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="content">字符串内容</param>
|
||||||
|
/// <param name="maxLength">字符串最大长度</param>
|
||||||
|
/// <returns>如果长度超出则按照 maxLength 截取返回,若没超出则原样返回 </returns>
|
||||||
|
private string Substring(string content, int maxLength)
|
||||||
|
{
|
||||||
|
var bytes = Encoding.UTF8.GetBytes(content);
|
||||||
|
if (bytes.Length > maxLength)
|
||||||
|
{
|
||||||
|
var temporaryBytes = bytes.Take(maxLength).ToArray();
|
||||||
|
return $"{Encoding.UTF8.GetString(temporaryBytes)}";
|
||||||
|
}
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 过滤 markdown 特殊字符
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="content"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private string FilterSpecialChar(string content) => content?.Replace("\"", "''").Replace("`", "'");
|
||||||
|
|
||||||
|
private async Task Post(string url, string parameters)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
HttpContent content = null;
|
||||||
|
if (!String.IsNullOrEmpty(parameters))
|
||||||
|
{
|
||||||
|
content = new StringContent(parameters, Encoding.UTF8);
|
||||||
|
if (content.Headers.ContentType != null)
|
||||||
|
{
|
||||||
|
content.Headers.ContentType.MediaType = "application/json";
|
||||||
|
content.Headers.ContentType.CharSet = "utf-8";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var resp = await _client.PostAsync(url, content);
|
||||||
|
await resp.Content.ReadAsStringAsync();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
this._logger.LogError(ex, $"WechatRobot Post fail,Url:{url},Parameters:{parameters}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -17,9 +17,9 @@ public class Worker : BackgroundService
|
|||||||
{
|
{
|
||||||
while (!stoppingToken.IsCancellationRequested)
|
while (!stoppingToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
using var scope = StaticServiceProvider.Current.CreateScope();
|
var scope = StaticServiceProvider.Current.CreateScope();
|
||||||
var settingServices = scope.ServiceProvider.GetRequiredService<SettingServices>();
|
var settingServices = scope.ServiceProvider.GetRequiredService<SettingServices>();
|
||||||
var options = settingServices.GetClientOptions();
|
var options = await settingServices.GetClientOptions();
|
||||||
if (_logger.IsEnabled(LogLevel.Information))
|
if (_logger.IsEnabled(LogLevel.Information))
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now.LocalDateTime);
|
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now.LocalDateTime);
|
||||||
@ -37,6 +37,7 @@ public class Worker : BackgroundService
|
|||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
await Task.Delay(options.Delay, stoppingToken);
|
await Task.Delay(options.Delay, stoppingToken);
|
||||||
|
scope.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user