net10
This commit is contained in:
+8
-2
@@ -1,4 +1,4 @@
|
|||||||
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
|
|
||||||
COPY ./src ./src
|
COPY ./src ./src
|
||||||
@@ -6,10 +6,16 @@ COPY ./src ./src
|
|||||||
RUN dotnet restore "src/Telegram2VkBot/Telegram2VkBot.csproj"
|
RUN dotnet restore "src/Telegram2VkBot/Telegram2VkBot.csproj"
|
||||||
RUN dotnet publish "src/Telegram2VkBot/Telegram2VkBot.csproj" -c Release -o /app/publish --no-restore
|
RUN dotnet publish "src/Telegram2VkBot/Telegram2VkBot.csproj" -c Release -o /app/publish --no-restore
|
||||||
|
|
||||||
FROM mcr.microsoft.com/dotnet/runtime:8.0 AS runtime
|
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get install -y --no-install-recommends curl \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY --from=build /app/publish .
|
COPY --from=build /app/publish .
|
||||||
|
|
||||||
|
ENV ASPNETCORE_URLS=http://+:8080
|
||||||
|
EXPOSE 8080
|
||||||
|
|
||||||
ENTRYPOINT ["dotnet", "Telegram2VkBot.dll"]
|
ENTRYPOINT ["dotnet", "Telegram2VkBot.dll"]
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,15 @@ services:
|
|||||||
#VK__GroupId: ${VK_GROUP_ID}
|
#VK__GroupId: ${VK_GROUP_ID}
|
||||||
#VK__ApiVersion: ${VK_API_VERSION:-5.199}
|
#VK__ApiVersion: ${VK_API_VERSION:-5.199}
|
||||||
DB__Path: /data/mapping.sqlite
|
DB__Path: /data/mapping.sqlite
|
||||||
|
ASPNETCORE_URLS: http://+:8080
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
volumes:
|
volumes:
|
||||||
- ./data:/data
|
- ./data:/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "curl -fsS http://127.0.0.1:8080/health >/dev/null || exit 1"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 12s
|
||||||
|
retries: 3
|
||||||
|
start_period: 45s
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.Hosting;
|
|
||||||
|
|
||||||
namespace Telegram2VkBot;
|
namespace Telegram2VkBot;
|
||||||
|
|
||||||
public static class Program
|
public static class Program
|
||||||
{
|
{
|
||||||
public static async Task Main(string[] args)
|
public static async Task Main(string[] args)
|
||||||
{
|
{
|
||||||
var builder = Host.CreateApplicationBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
builder.Services.Configure<TelegramOptions>(builder.Configuration.GetSection("TELEGRAM"));
|
builder.Services.Configure<TelegramOptions>(builder.Configuration.GetSection("TELEGRAM"));
|
||||||
builder.Services.Configure<VkOptions>(builder.Configuration.GetSection("VK"));
|
builder.Services.Configure<VkOptions>(builder.Configuration.GetSection("VK"));
|
||||||
@@ -17,9 +14,20 @@ public static class Program
|
|||||||
{
|
{
|
||||||
client.Timeout = TimeSpan.FromSeconds(60);
|
client.Timeout = TimeSpan.FromSeconds(60);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
builder.Services.AddHttpClient(TelegramApiHealthCheck.HttpClientName, client =>
|
||||||
|
{
|
||||||
|
client.Timeout = TimeSpan.FromSeconds(15);
|
||||||
|
});
|
||||||
|
|
||||||
builder.Services.AddSingleton<VkApiClient>();
|
builder.Services.AddSingleton<VkApiClient>();
|
||||||
builder.Services.AddSingleton<MappingRepository>();
|
builder.Services.AddSingleton<MappingRepository>();
|
||||||
|
|
||||||
|
builder.Services.AddHealthChecks()
|
||||||
|
.AddCheck<TelegramApiHealthCheck>(
|
||||||
|
name: "telegram",
|
||||||
|
tags: new[] { "telegram" });
|
||||||
|
|
||||||
builder.Services.AddHostedService<ForwardWorker>();
|
builder.Services.AddHostedService<ForwardWorker>();
|
||||||
|
|
||||||
builder.Logging.AddSimpleConsole(options =>
|
builder.Logging.AddSimpleConsole(options =>
|
||||||
@@ -28,8 +36,11 @@ public static class Program
|
|||||||
options.TimestampFormat = "yyyy-MM-dd HH:mm:ss ";
|
options.TimestampFormat = "yyyy-MM-dd HH:mm:ss ";
|
||||||
});
|
});
|
||||||
|
|
||||||
var host = builder.Build();
|
var app = builder.Build();
|
||||||
await host.RunAsync();
|
|
||||||
|
app.MapHealthChecks("/health");
|
||||||
|
app.MapGet("/", () => Results.Redirect("/health"));
|
||||||
|
|
||||||
|
await app.RunAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Worker">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@@ -9,10 +9,7 @@
|
|||||||
<None Update="appsettings.json">
|
<None Update="appsettings.json">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.9" />
|
<PackageReference Include="Microsoft.Data.Sqlite" Version="10.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
|
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" />
|
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
|
|
||||||
<PackageReference Include="Telegram.Bot" Version="22.9.5.3" />
|
<PackageReference Include="Telegram.Bot" Version="22.9.5.3" />
|
||||||
<PackageReference Include="VkNet" Version="1.78.0" />
|
<PackageReference Include="VkNet" Version="1.78.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
|
namespace Telegram2VkBot;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Проверка доступности Telegram Bot API (getMe).
|
||||||
|
/// </summary>
|
||||||
|
public sealed class TelegramApiHealthCheck : IHealthCheck
|
||||||
|
{
|
||||||
|
public const string HttpClientName = "TelegramHealth";
|
||||||
|
|
||||||
|
private readonly TelegramOptions _telegram;
|
||||||
|
private readonly IHttpClientFactory _httpFactory;
|
||||||
|
|
||||||
|
public TelegramApiHealthCheck(IOptions<TelegramOptions> telegram, IHttpClientFactory httpFactory)
|
||||||
|
{
|
||||||
|
_telegram = telegram.Value;
|
||||||
|
_httpFactory = httpFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<HealthCheckResult> CheckHealthAsync(
|
||||||
|
HealthCheckContext context,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(_telegram.BotToken))
|
||||||
|
return HealthCheckResult.Unhealthy("TELEGRAM__BotToken не задан.");
|
||||||
|
|
||||||
|
var url = $"https://api.telegram.org/bot{_telegram.BotToken}/getMe";
|
||||||
|
var http = _httpFactory.CreateClient(HttpClientName);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var response = await http.GetAsync(url, cancellationToken).ConfigureAwait(false);
|
||||||
|
var json = await response.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (!response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
return HealthCheckResult.Unhealthy(
|
||||||
|
$"Telegram API HTTP {(int)response.StatusCode}",
|
||||||
|
data: new Dictionary<string, object> { ["body"] = Truncate(json, 500) });
|
||||||
|
}
|
||||||
|
|
||||||
|
using var doc = JsonDocument.Parse(json);
|
||||||
|
if (!doc.RootElement.TryGetProperty("ok", out var ok) || ok.ValueKind != JsonValueKind.True)
|
||||||
|
{
|
||||||
|
var desc = doc.RootElement.TryGetProperty("description", out var d) ? d.GetString() : json;
|
||||||
|
return HealthCheckResult.Unhealthy($"Telegram getMe: ok=false, {desc}");
|
||||||
|
}
|
||||||
|
|
||||||
|
var username = doc.RootElement.TryGetProperty("result", out var result)
|
||||||
|
&& result.TryGetProperty("username", out var un)
|
||||||
|
? un.GetString()
|
||||||
|
: null;
|
||||||
|
|
||||||
|
return HealthCheckResult.Healthy(
|
||||||
|
username is null ? "Telegram API доступен." : $"Telegram API: @{username}");
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return HealthCheckResult.Unhealthy("Не удалось связаться с Telegram API.", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string Truncate(string s, int max)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(s) || s.Length <= max)
|
||||||
|
return s;
|
||||||
|
return string.Concat(s.AsSpan(0, max), "…");
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user