using System.Net.Http.Headers; using System.Net.Http.Json; using System.Text; using System.Text.Json; using ForgejoReleaseSync.DTOs.Forgejo; using Microsoft.Extensions.Logging; namespace ForgejoReleaseSync.Services; public class ForgejoService(HttpClient httpClient, AppConfig config, ILogger logger) { public async Task> CreateReleaseAsync(string owner, string repo, string body, string name, string tagName, CancellationToken token = default) { try { var dto = new ForgejoCreateReleaseDto(body, false, false, name, false, tagName, ""); var json = JsonSerializer.Serialize(dto, AppJsonSerializerContext.Default.ForgejoCreateReleaseDto); using var content = new StringContent(json, Encoding.UTF8, "application/json"); using var request = new HttpRequestMessage(HttpMethod.Post, new Uri($"{config.ForgejoInstacne}/api/v1/repos/{owner}/{repo}/releases")); request.Content = content; request.Headers.Authorization = new AuthenticationHeaderValue("token", config.ForgejoToken); using var response = await httpClient.SendAsync(request, token); response.EnsureSuccessStatusCode(); var responseStream = await response.Content.ReadAsStreamAsync(token); var releases = await JsonSerializer.DeserializeAsync(responseStream, AppJsonSerializerContext.Default.ListForgejoReleaseResponseDto, token); return releases ?? []; } catch (Exception e) { logger.LogError(e, "Failed to create forgejo release"); throw; } } public async Task> FetchRepoReleasesAsync(string owner, string repo, CancellationToken token = default) { try { var response = await httpClient.GetAsync( new Uri($"{config.ForgejoInstacne}/api/v1/repos/{owner}/{repo}/releases?per_page=3&page=1")); response.EnsureSuccessStatusCode(); var responseStream = await response.Content.ReadAsStreamAsync(token); var releases = await JsonSerializer.DeserializeAsync(responseStream, AppJsonSerializerContext.Default.ListForgejoReleaseResponseDto, token); return releases ?? []; } catch (Exception ex) { logger.LogError(ex, "Failed to fetch forgejo releases"); throw; } } public async Task UploadReleaseAssetAsync(string owner, string repo, long releaseId, string filePath, CancellationToken token = default) { using var request = new HttpRequestMessage(HttpMethod.Post, new Uri($"{config.ForgejoInstacne}/api/v1/repos/{owner}/{repo}/releases/{releaseId}/assets")); request.Headers.Authorization = new AuthenticationHeaderValue("token", config.ForgejoToken); await using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true); using var fileContent = new StreamContent(fileStream); fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); using var formData = new MultipartFormDataContent(); formData.Add(fileContent, "attachment", Path.GetFileName(filePath)); request.Content = formData; using var response = await httpClient.SendAsync(request,HttpCompletionOption.ResponseHeadersRead, token); response.EnsureSuccessStatusCode(); } }