mirror of
https://github.com/DrizzleTime/Foxel.git
synced 2026-05-07 05:32:49 +08:00
refactor: 统一命名空间为Foxel.Api,移除不必要的using语句,优化代码结构
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Foxel.Models;
|
||||
using Foxel.Models.Request.Album;
|
||||
using Foxel.Models.Response.Album;
|
||||
using Foxel.Services.Media;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Foxel.Controllers;
|
||||
namespace Foxel.Api;
|
||||
|
||||
[Authorize]
|
||||
[Route("api/album")]
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
using Foxel.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Foxel.Models.Request.Auth;
|
||||
using Foxel.Models.Response.Auth;
|
||||
using Foxel.Services.Auth;
|
||||
using Foxel.Services.Configuration;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Foxel.Controllers;
|
||||
namespace Foxel.Api;
|
||||
|
||||
[Route("api/auth")]
|
||||
public class AuthController(IAuthService authService, IConfigService configuration) : BaseApiController
|
||||
@@ -119,15 +119,15 @@ public class AuthController(IAuthService authService, IConfigService configurati
|
||||
|
||||
switch (result)
|
||||
{
|
||||
case GitHubAuthResult.Success:
|
||||
case OAuthResult.Success:
|
||||
return Redirect($"/login?token={Uri.EscapeDataString(data!)}");
|
||||
|
||||
case GitHubAuthResult.UserNotBound:
|
||||
case OAuthResult.UserNotBound:
|
||||
return Redirect($"/bind?githubId={data}");
|
||||
case GitHubAuthResult.InvalidCode:
|
||||
case GitHubAuthResult.TokenRequestFailed:
|
||||
case GitHubAuthResult.UserInfoFailed:
|
||||
case GitHubAuthResult.InvalidUserId:
|
||||
case OAuthResult.InvalidCode:
|
||||
case OAuthResult.TokenRequestFailed:
|
||||
case OAuthResult.UserInfoFailed:
|
||||
case OAuthResult.InvalidUserId:
|
||||
default:
|
||||
return Redirect($"/login?error=github_auth_failed&message={Uri.EscapeDataString(message)}");
|
||||
}
|
||||
@@ -147,15 +147,15 @@ public class AuthController(IAuthService authService, IConfigService configurati
|
||||
|
||||
switch (result)
|
||||
{
|
||||
case LinuxDoAuthResult.Success:
|
||||
case OAuthResult.Success:
|
||||
return Redirect($"/login?token={Uri.EscapeDataString(data!)}");
|
||||
|
||||
case LinuxDoAuthResult.UserNotBound:
|
||||
case OAuthResult.UserNotBound:
|
||||
return Redirect($"/bind?linuxdoId={data}");
|
||||
case LinuxDoAuthResult.InvalidCode:
|
||||
case LinuxDoAuthResult.TokenRequestFailed:
|
||||
case LinuxDoAuthResult.UserInfoFailed:
|
||||
case LinuxDoAuthResult.InvalidUserId:
|
||||
case OAuthResult.InvalidCode:
|
||||
case OAuthResult.TokenRequestFailed:
|
||||
case OAuthResult.UserInfoFailed:
|
||||
case OAuthResult.InvalidUserId:
|
||||
default:
|
||||
return Redirect($"/login?error=linuxdo_auth_failed&message={Uri.EscapeDataString(message)}");
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Foxel.Models;
|
||||
using Foxel.Services.Background;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Foxel.Controllers;
|
||||
namespace Foxel.Api;
|
||||
|
||||
[Authorize]
|
||||
[Route("api/background-tasks")]
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Foxel.Models;
|
||||
using System.Security.Claims;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using System.Text;
|
||||
using System.Security.Claims;
|
||||
using Foxel.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Foxel.Controllers
|
||||
namespace Foxel.Api
|
||||
{
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Foxel.Models;
|
||||
using Foxel.Models.DataBase;
|
||||
using Foxel.Models.Request.Config;
|
||||
using Foxel.Services.Configuration;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Foxel.Controllers;
|
||||
namespace Foxel.Api;
|
||||
|
||||
[Authorize(Roles = "Administrator")]
|
||||
[Route("api/config")]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using Foxel.Controllers;
|
||||
using Foxel.Models;
|
||||
using Foxel.Models.Response.Face;
|
||||
using Foxel.Models.Response.Picture;
|
||||
using Foxel.Services.AI;
|
||||
using Foxel.Services.Management;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using Foxel.Controllers;
|
||||
using Foxel.Models;
|
||||
using Foxel.Models.Request.Album;
|
||||
using Foxel.Models.Response.Album;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using Foxel.Controllers;
|
||||
using Foxel.Models;
|
||||
using Foxel.Models.Response.Face;
|
||||
using Foxel.Models.Response.Picture;
|
||||
using Foxel.Services.AI;
|
||||
using Foxel.Services.Management;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
@@ -3,7 +3,6 @@ using Microsoft.AspNetCore.Mvc;
|
||||
using Foxel.Models;
|
||||
using Foxel.Models.Response.Log;
|
||||
using Foxel.Models.Request.Log;
|
||||
using Foxel.Controllers;
|
||||
using Foxel.Services.Management;
|
||||
|
||||
namespace Foxel.Api.Management;
|
||||
|
||||
@@ -2,7 +2,6 @@ using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Foxel.Models;
|
||||
using Foxel.Models.Response.Picture;
|
||||
using Foxel.Controllers;
|
||||
using Foxel.Services.Management;
|
||||
|
||||
namespace Foxel.Api.Management;
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
using Foxel.Controllers;
|
||||
using Foxel.Models;
|
||||
using Foxel.Models.Request.Storage;
|
||||
using Foxel.Models.Response.Storage;
|
||||
using Foxel.Services.Attributes;
|
||||
using Foxel.Services.Management;
|
||||
using Foxel.Services.Storage;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Foxel.Controllers;
|
||||
using Foxel.Models;
|
||||
using Foxel.Services.VectorDB;
|
||||
using Foxel.Services.VectorDb;
|
||||
|
||||
namespace Foxel.Api.Management;
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ using Microsoft.AspNetCore.Mvc;
|
||||
using Foxel.Models;
|
||||
using Foxel.Models.Request.User;
|
||||
using Foxel.Models.Response.User;
|
||||
using Foxel.Controllers;
|
||||
using Foxel.Services.Management;
|
||||
|
||||
namespace Foxel.Api.Management;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using Foxel.Controllers;
|
||||
using Foxel.Models;
|
||||
using Foxel.Models.DataBase;
|
||||
using Foxel.Models.Request.Picture;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Foxel.Models;
|
||||
using Foxel.Models.Request.Tag;
|
||||
using Foxel.Models.Response.Tag;
|
||||
using Foxel.Services.Media;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Foxel.Controllers;
|
||||
namespace Foxel.Api;
|
||||
|
||||
[Route("api/tag")]
|
||||
public class TagController(ITagService tagService) : BaseApiController
|
||||
|
||||
@@ -12,9 +12,9 @@ using Foxel.Services.Initializer;
|
||||
using Foxel.Services.Management;
|
||||
using Foxel.Services.Media;
|
||||
using Foxel.Services.Storage;
|
||||
using Foxel.Services.VectorDB;
|
||||
using Foxel.Services.Background.Processors;
|
||||
using Foxel.Services.Mapping;
|
||||
using Foxel.Services.VectorDb;
|
||||
|
||||
namespace Foxel.Extensions;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Text.Json;
|
||||
using Foxel.Services.Attributes;
|
||||
|
||||
namespace Foxel.Models.DataBase;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Foxel.Services.Attributes;
|
||||
using Foxel.Services.Storage;
|
||||
|
||||
namespace Foxel.Models.DataBase;
|
||||
|
||||
|
||||
@@ -2,12 +2,7 @@ namespace Foxel.Models;
|
||||
|
||||
public record PaginatedResult<T> : BaseResult<List<T>>
|
||||
{
|
||||
|
||||
|
||||
public int Page { get; set; } = 1;
|
||||
public int PageSize { get; set; } = 10;
|
||||
public int TotalCount { get; set; }
|
||||
public int TotalPages => (int)Math.Ceiling(TotalCount / (double)PageSize);
|
||||
public bool HasPreviousPage => Page > 1;
|
||||
public bool HasNextPage => Page < TotalPages;
|
||||
public int Page { get; init; } = 1;
|
||||
public int PageSize { get; init; } = 10;
|
||||
public int TotalCount { get; init; }
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Foxel.Services.Attributes; // For StorageType enum
|
||||
using Foxel.Services.Storage;
|
||||
|
||||
// For StorageType enum
|
||||
|
||||
namespace Foxel.Models.Request.Storage;
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Foxel.Services.Attributes; // For StorageType enum
|
||||
using Foxel.Services.Storage;
|
||||
|
||||
// For StorageType enum
|
||||
|
||||
namespace Foxel.Models.Request.Storage;
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using Foxel.Services.Attributes; // For StorageType enum
|
||||
using Foxel.Services.Storage;
|
||||
|
||||
// For StorageType enum
|
||||
|
||||
namespace Foxel.Models.Response.Storage;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Foxel.Extensions;
|
||||
using Foxel.Services.Initializer;
|
||||
using Foxel.Services.VectorDB;
|
||||
using Foxel.Services.VectorDb;
|
||||
using Microsoft.AspNetCore.HttpOverrides;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using Foxel.Models.DataBase;
|
||||
|
||||
namespace Foxel.Services.AI;
|
||||
|
||||
public interface IFaceClusteringService
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -10,7 +10,10 @@ using static Foxel.Utils.AuthHelper;
|
||||
|
||||
namespace Foxel.Services.Auth;
|
||||
|
||||
public class AuthService(IDbContextFactory<MyDbContext> dbContextFactory, IConfigService configuration, ILogger<AuthService> logger)
|
||||
public class AuthService(
|
||||
IDbContextFactory<MyDbContext> dbContextFactory,
|
||||
IConfigService configuration,
|
||||
ILogger<AuthService> logger)
|
||||
: IAuthService
|
||||
{
|
||||
public async Task<(bool success, string message, User? user)> RegisterUserAsync(RegisterRequest request)
|
||||
@@ -196,11 +199,11 @@ public class AuthService(IDbContextFactory<MyDbContext> dbContextFactory, IConfi
|
||||
$"https://github.com/login/oauth/authorize?client_id={Uri.EscapeDataString(githubClientId)}&redirect_uri={Uri.EscapeDataString(githubCallback)}";
|
||||
}
|
||||
|
||||
public async Task<(GitHubAuthResult result, string message, string? data)> ProcessGitHubCallbackAsync(string code)
|
||||
public async Task<(OAuthResult result, string message, string? data)> ProcessGitHubCallbackAsync(string code)
|
||||
{
|
||||
if (string.IsNullOrEmpty(code))
|
||||
{
|
||||
return (GitHubAuthResult.InvalidCode, "GitHub授权码无效", null);
|
||||
return (OAuthResult.InvalidCode, "GitHub授权码无效", null);
|
||||
}
|
||||
|
||||
string githubClientId = configuration["Authentication:GitHubClientId"];
|
||||
@@ -219,7 +222,7 @@ public class AuthService(IDbContextFactory<MyDbContext> dbContextFactory, IConfi
|
||||
{
|
||||
var errorContent = await tokenResponse.Content.ReadAsStringAsync();
|
||||
logger.LogError("获取GitHub访问令牌失败: {StatusCode}, {ErrorContent}", tokenResponse.StatusCode, errorContent);
|
||||
return (GitHubAuthResult.TokenRequestFailed, $"获取GitHub访问令牌失败: {errorContent}", null);
|
||||
return (OAuthResult.TokenRequestFailed, $"获取GitHub访问令牌失败: {errorContent}", null);
|
||||
}
|
||||
|
||||
var tokenResponseContent = await tokenResponse.Content.ReadAsStringAsync();
|
||||
@@ -229,7 +232,7 @@ public class AuthService(IDbContextFactory<MyDbContext> dbContextFactory, IConfi
|
||||
accessTokenElement.GetString() == null)
|
||||
{
|
||||
logger.LogError("GitHub响应中未找到access_token: {TokenResponseContent}", tokenResponseContent);
|
||||
return (GitHubAuthResult.TokenRequestFailed, "获取GitHub访问令牌失败,响应中未包含令牌。", null);
|
||||
return (OAuthResult.TokenRequestFailed, "获取GitHub访问令牌失败,响应中未包含令牌。", null);
|
||||
}
|
||||
|
||||
var accessToken = accessTokenElement.GetString();
|
||||
@@ -242,7 +245,7 @@ public class AuthService(IDbContextFactory<MyDbContext> dbContextFactory, IConfi
|
||||
{
|
||||
var errorContent = await userResponse.Content.ReadAsStringAsync();
|
||||
logger.LogError("获取GitHub用户信息失败: {StatusCode}, {ErrorContent}", userResponse.StatusCode, errorContent);
|
||||
return (GitHubAuthResult.UserInfoFailed, $"获取GitHub用户信息失败: {errorContent}", null);
|
||||
return (OAuthResult.UserInfoFailed, $"获取GitHub用户信息失败: {errorContent}", null);
|
||||
}
|
||||
|
||||
var userContent = await userResponse.Content.ReadAsStringAsync();
|
||||
@@ -275,34 +278,34 @@ public class AuthService(IDbContextFactory<MyDbContext> dbContextFactory, IConfi
|
||||
|
||||
if (string.IsNullOrEmpty(githubUserId))
|
||||
{
|
||||
return (GitHubAuthResult.InvalidUserId, "无法从GitHub获取用户ID", null);
|
||||
return (OAuthResult.InvalidUserId, "无法从GitHub获取用户ID", null);
|
||||
}
|
||||
|
||||
var (isSuccess, message, user) = await FindGitHubUserAsync(githubUserId);
|
||||
|
||||
if (!isSuccess || user == null)
|
||||
{
|
||||
return (GitHubAuthResult.UserNotBound, "GitHub用户未绑定到系统账户", githubUserId);
|
||||
return (OAuthResult.UserNotBound, "GitHub用户未绑定到系统账户", githubUserId);
|
||||
}
|
||||
|
||||
var jwtToken = await GenerateJwtTokenAsync(user);
|
||||
return (GitHubAuthResult.Success, "GitHub授权成功", jwtToken);
|
||||
return (OAuthResult.Success, "GitHub授权成功", jwtToken);
|
||||
}
|
||||
|
||||
public string GetLinuxDoLoginUrl()
|
||||
{
|
||||
string linuxdoClientId = configuration["Authentication:LinuxDoClientId"];
|
||||
string linuxdoCallback = configuration["Authentication:LinuxDoCallbackUrl"];
|
||||
string state = Guid.NewGuid().ToString();
|
||||
string state = Guid.NewGuid().ToString();
|
||||
return
|
||||
$"https://connect.linux.do/oauth2/authorize?response_type=code&client_id={Uri.EscapeDataString(linuxdoClientId)}&redirect_uri={Uri.EscapeDataString(linuxdoCallback)}&state={Uri.EscapeDataString(state)}";
|
||||
}
|
||||
|
||||
public async Task<(LinuxDoAuthResult result, string message, string? data)> ProcessLinuxDoCallbackAsync(string code)
|
||||
public async Task<(OAuthResult result, string message, string? data)> ProcessLinuxDoCallbackAsync(string code)
|
||||
{
|
||||
if (string.IsNullOrEmpty(code))
|
||||
{
|
||||
return (LinuxDoAuthResult.InvalidCode, "LinuxDo授权码无效", null);
|
||||
return (OAuthResult.InvalidCode, "LinuxDo授权码无效", null);
|
||||
}
|
||||
|
||||
string linuxdoClientId = configuration["Authentication:LinuxDoClientId"];
|
||||
@@ -331,7 +334,7 @@ public class AuthService(IDbContextFactory<MyDbContext> dbContextFactory, IConfi
|
||||
{
|
||||
var errorContent = await tokenResponse.Content.ReadAsStringAsync();
|
||||
logger.LogError("获取LinuxDo访问令牌失败: {StatusCode}, {ErrorContent}", tokenResponse.StatusCode, errorContent);
|
||||
return (LinuxDoAuthResult.TokenRequestFailed, $"获取LinuxDo访问令牌失败: {errorContent}", null);
|
||||
return (OAuthResult.TokenRequestFailed, $"获取LinuxDo访问令牌失败: {errorContent}", null);
|
||||
}
|
||||
|
||||
var tokenResponseContent = await tokenResponse.Content.ReadAsStringAsync();
|
||||
@@ -341,7 +344,7 @@ public class AuthService(IDbContextFactory<MyDbContext> dbContextFactory, IConfi
|
||||
accessTokenElement.GetString() == null)
|
||||
{
|
||||
logger.LogError("LinuxDo响应中未找到access_token: {TokenResponseContent}", tokenResponseContent);
|
||||
return (LinuxDoAuthResult.TokenRequestFailed, "获取LinuxDo访问令牌失败,响应中未包含令牌。", null);
|
||||
return (OAuthResult.TokenRequestFailed, "获取LinuxDo访问令牌失败,响应中未包含令牌。", null);
|
||||
}
|
||||
|
||||
var accessToken = accessTokenElement.GetString();
|
||||
@@ -355,7 +358,7 @@ public class AuthService(IDbContextFactory<MyDbContext> dbContextFactory, IConfi
|
||||
{
|
||||
var errorContent = await userResponse.Content.ReadAsStringAsync();
|
||||
logger.LogError("获取LinuxDo用户信息失败: {StatusCode}, {ErrorContent}", userResponse.StatusCode, errorContent);
|
||||
return (LinuxDoAuthResult.UserInfoFailed, $"获取LinuxDo用户信息失败: {errorContent}", null);
|
||||
return (OAuthResult.UserInfoFailed, $"获取LinuxDo用户信息失败: {errorContent}", null);
|
||||
}
|
||||
|
||||
var userContent = await userResponse.Content.ReadAsStringAsync();
|
||||
@@ -382,18 +385,18 @@ public class AuthService(IDbContextFactory<MyDbContext> dbContextFactory, IConfi
|
||||
|
||||
if (string.IsNullOrEmpty(linuxdoUserId))
|
||||
{
|
||||
return (LinuxDoAuthResult.InvalidUserId, "无法从LinuxDo获取用户ID", null);
|
||||
return (OAuthResult.InvalidUserId, "无法从LinuxDo获取用户ID", null);
|
||||
}
|
||||
|
||||
var (isSuccess, message, user) = await FindLinuxDoUserAsync(linuxdoUserId);
|
||||
|
||||
if (!isSuccess || user == null)
|
||||
{
|
||||
return (LinuxDoAuthResult.UserNotBound, "LinuxDo用户未绑定到系统账户", linuxdoUserId);
|
||||
return (OAuthResult.UserNotBound, "LinuxDo用户未绑定到系统账户", linuxdoUserId);
|
||||
}
|
||||
|
||||
var jwtToken = await GenerateJwtTokenAsync(user);
|
||||
return (LinuxDoAuthResult.Success, "LinuxDo授权成功", jwtToken);
|
||||
return (OAuthResult.Success, "LinuxDo授权成功", jwtToken);
|
||||
}
|
||||
|
||||
public async Task<(bool success, string message, User? user)> BindAccountAsync(BindAccountRequest request)
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
namespace Foxel.Services.Auth;
|
||||
|
||||
public enum GitHubAuthResult
|
||||
{
|
||||
Success, // 授权成功并找到绑定用户
|
||||
UserNotBound, // 授权成功但用户未绑定
|
||||
InvalidCode, // 授权码无效
|
||||
TokenRequestFailed, // 获取访问令牌失败
|
||||
UserInfoFailed, // 获取用户信息失败
|
||||
InvalidUserId // 无法获取GitHub用户ID
|
||||
}
|
||||
@@ -3,6 +3,16 @@ using Foxel.Models.Request.Auth;
|
||||
|
||||
namespace Foxel.Services.Auth;
|
||||
|
||||
public enum OAuthResult
|
||||
{
|
||||
Success,
|
||||
UserNotBound,
|
||||
InvalidCode,
|
||||
TokenRequestFailed,
|
||||
UserInfoFailed,
|
||||
InvalidUserId
|
||||
}
|
||||
|
||||
public interface IAuthService
|
||||
{
|
||||
Task<(bool success, string message, User? user)> RegisterUserAsync(RegisterRequest request);
|
||||
@@ -14,7 +24,7 @@ public interface IAuthService
|
||||
Task<(bool success, string message, User? user)> UpdateUserInfoAsync(int userId, UpdateUserRequest request);
|
||||
string GetGitHubLoginUrl();
|
||||
string GetLinuxDoLoginUrl();
|
||||
Task<(GitHubAuthResult result, string message, string? data)> ProcessGitHubCallbackAsync(string code);
|
||||
Task<(LinuxDoAuthResult result, string message, string? data)> ProcessLinuxDoCallbackAsync(string code);
|
||||
Task<(OAuthResult result, string message, string? data)> ProcessGitHubCallbackAsync(string code);
|
||||
Task<(OAuthResult result, string message, string? data)> ProcessLinuxDoCallbackAsync(string code);
|
||||
Task<(bool success, string message, User? user)> BindAccountAsync(BindAccountRequest request);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
namespace Foxel.Services.Auth;
|
||||
|
||||
public enum LinuxDoAuthResult
|
||||
{
|
||||
Success, // 授权成功并找到绑定用户
|
||||
UserNotBound, // 授权成功但用户未绑定
|
||||
InvalidCode, // 授权码无效
|
||||
TokenRequestFailed, // 获取访问令牌失败
|
||||
UserInfoFailed, // 获取用户信息失败
|
||||
InvalidUserId // 无法获取LinuxDo用户ID
|
||||
}
|
||||
@@ -85,7 +85,7 @@ namespace Foxel.Services.Background.Processors
|
||||
using var scope = serviceProvider.CreateScope();
|
||||
var storageService = scope.ServiceProvider.GetRequiredService<IStorageService>();
|
||||
|
||||
if (picture.StorageMode.StorageType == Attributes.StorageType.Local)
|
||||
if (picture.StorageMode.StorageType == StorageType.Local)
|
||||
{
|
||||
logger.LogInformation(
|
||||
"Picture {PictureId} is Local. Attempting to download via StorageService for consistency.",
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using Foxel.Models.DataBase;
|
||||
using Foxel.Services.AI;
|
||||
using Foxel.Services.Storage;
|
||||
using Foxel.Services.VectorDB;
|
||||
using Foxel.Utils;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Text.Json;
|
||||
using Foxel.Services.VectorDb;
|
||||
// using Foxel.Services.Attributes; // StorageType enum might not be directly needed here anymore
|
||||
using Microsoft.Extensions.DependencyInjection; // For CreateScope
|
||||
using Microsoft.AspNetCore.Hosting; // For IWebHostEnvironment
|
||||
@@ -117,7 +117,7 @@ namespace Foxel.Services.Background.Processors
|
||||
string actualThumbnailPathForAI;
|
||||
|
||||
// Check the StorageType of the associated StorageMode
|
||||
if (picture.StorageMode.StorageType == Attributes.StorageType.Local)
|
||||
if (picture.StorageMode.StorageType == StorageType.Local)
|
||||
{
|
||||
// As with PictureTaskProcessor, safer to use DownloadFileAsync for consistency
|
||||
_logger.LogInformation("Picture {PictureId} thumbnail is Local. Attempting to download via StorageService for AI.", pictureId);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using Foxel.Models.DataBase;
|
||||
using Foxel.Services.Attributes;
|
||||
using Foxel.Services.Configuration;
|
||||
using Foxel.Services.Logging;
|
||||
using Foxel.Services.Storage;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Foxel.Services.Initializer;
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using Foxel.Models; // For PaginatedResult
|
||||
using Foxel.Models.Request.Storage;
|
||||
using Foxel.Models.Response.Storage;
|
||||
using Foxel.Services.Attributes; // For StorageType
|
||||
using Foxel.Services.Storage;
|
||||
|
||||
// For StorageType
|
||||
|
||||
namespace Foxel.Services.Management;
|
||||
|
||||
|
||||
@@ -2,12 +2,12 @@ using Foxel.Models;
|
||||
using Foxel.Models.DataBase;
|
||||
using Foxel.Models.Request.Storage;
|
||||
using Foxel.Models.Response.Storage;
|
||||
using Foxel.Services.Attributes;
|
||||
using Foxel.Services.Storage.Providers; // Required for config types like LocalStorageConfig, etc.
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Text.Json;
|
||||
using Foxel.Services.Configuration; // Added for IConfigService
|
||||
using Foxel.Services.Configuration;
|
||||
using Foxel.Services.Storage; // Added for IConfigService
|
||||
|
||||
namespace Foxel.Services.Management;
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ using Foxel.Services.AI;
|
||||
using Foxel.Services.Background;
|
||||
using Foxel.Services.Configuration;
|
||||
using Foxel.Services.Storage;
|
||||
using Foxel.Services.VectorDB;
|
||||
using Foxel.Services.Mapping;
|
||||
using Foxel.Services.VectorDb;
|
||||
using Foxel.Utils;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Foxel.Models;
|
||||
using Foxel.Models.DataBase;
|
||||
using Foxel.Models.Response.Tag;
|
||||
using Foxel.Services.Media;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Foxel.Services;
|
||||
namespace Foxel.Services.Media;
|
||||
|
||||
public class TagService(IDbContextFactory<MyDbContext> contextFactory, ILogger<TagService> logger) : ITagService
|
||||
{
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using Foxel.Services.Attributes;
|
||||
|
||||
namespace Foxel.Services.Storage;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -4,7 +4,6 @@ using COSXML.CosException;
|
||||
using COSXML.Model.Object;
|
||||
using COSXML.Model.Tag;
|
||||
using COSXML.Transfer;
|
||||
using Foxel.Services.Attributes;
|
||||
using Foxel.Services.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using Foxel.Services.Attributes;
|
||||
using Foxel.Services.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using Amazon.S3;
|
||||
using Amazon.S3.Model;
|
||||
using Amazon.S3.Transfer;
|
||||
using Foxel.Services.Attributes;
|
||||
using Foxel.Services.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Foxel.Services.Attributes;
|
||||
using Foxel.Services.Configuration;
|
||||
using System.Net;
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using Foxel.Services.Attributes;
|
||||
using Foxel.Services.Configuration;
|
||||
|
||||
namespace Foxel.Services.Storage.Providers;
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using Foxel.Models.DataBase;
|
||||
|
||||
namespace Foxel.Services.Attributes;
|
||||
namespace Foxel.Services.Storage;
|
||||
|
||||
public enum StorageType
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Reflection;
|
||||
using Foxel.Services.Attributes;
|
||||
using Microsoft.EntityFrameworkCore; // For IDbContextFactory
|
||||
using System.Text.Json; // For JsonSerializer
|
||||
using Foxel.Services.Storage.Providers; // For specific config classes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Foxel.Models.Vector;
|
||||
|
||||
namespace Foxel.Services.VectorDB;
|
||||
namespace Foxel.Services.VectorDb;
|
||||
|
||||
public interface IVectorDbService
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.VectorData;
|
||||
using Microsoft.SemanticKernel.Connectors.InMemory;
|
||||
|
||||
namespace Foxel.Services.VectorDB;
|
||||
namespace Foxel.Services.VectorDb;
|
||||
|
||||
public class InMemoryVectorDbService : IVectorDbService
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@ using Microsoft.Extensions.VectorData;
|
||||
using Microsoft.SemanticKernel.Connectors.Qdrant;
|
||||
using Qdrant.Client;
|
||||
|
||||
namespace Foxel.Services.VectorDB;
|
||||
namespace Foxel.Services.VectorDb;
|
||||
|
||||
public class QdrantVectorDbService(IDbContextFactory<MyDbContext> contextFactory, IConfigService configService)
|
||||
: IVectorDbService
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Foxel.Services.Configuration;
|
||||
|
||||
namespace Foxel.Services.VectorDB;
|
||||
namespace Foxel.Services.VectorDb;
|
||||
|
||||
public class VectorDbInitializer : IHostedService
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@ using Foxel.Models.Vector;
|
||||
using Foxel.Services.Configuration;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace Foxel.Services.VectorDB;
|
||||
namespace Foxel.Services.VectorDb;
|
||||
|
||||
public class VectorDbManager(IServiceProvider serviceProvider, IConfigService configService)
|
||||
: IVectorDbService
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Foxel.Utils;
|
||||
|
||||
public static class AiHelper
|
||||
@@ -10,17 +8,15 @@ public static class AiHelper
|
||||
/// <param name="aiResponse">AI生成的响应文本</param>
|
||||
/// <param name="logger">日志记录器</param>
|
||||
/// <returns>包含标题和描述的元组</returns>
|
||||
public static (string title, string description) ExtractTitleAndDescription(string aiResponse, ILogger? logger = null)
|
||||
public static (string title, string description) ExtractTitleAndDescription(string aiResponse,
|
||||
ILogger? logger = null)
|
||||
{
|
||||
string title = "AI生成的标题";
|
||||
string description = "AI生成的描述";
|
||||
|
||||
try
|
||||
{
|
||||
// 尝试解析JSON响应
|
||||
if (aiResponse.Contains("{") && aiResponse.Contains("}"))
|
||||
{
|
||||
// 提取JSON部分
|
||||
int jsonStartIndex = aiResponse.IndexOf('{');
|
||||
int jsonEndIndex = aiResponse.LastIndexOf('}') + 1;
|
||||
|
||||
@@ -34,7 +30,8 @@ public static class AiHelper
|
||||
|
||||
try
|
||||
{
|
||||
var result = System.Text.Json.JsonSerializer.Deserialize<ImageAnalysisResult>(jsonPart, options);
|
||||
var result =
|
||||
System.Text.Json.JsonSerializer.Deserialize<ImageAnalysisResult>(jsonPart, options);
|
||||
if (result != null)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(result.Title))
|
||||
@@ -93,15 +90,14 @@ public static class AiHelper
|
||||
return (title, description);
|
||||
}
|
||||
|
||||
// 用于解析JSON的类
|
||||
public class ImageAnalysisResult
|
||||
{
|
||||
public string Title { get; set; } = string.Empty;
|
||||
public string Description { get; set; } = string.Empty;
|
||||
public string Title { get; init; } = string.Empty;
|
||||
public string Description { get; init; } = string.Empty;
|
||||
}
|
||||
|
||||
public class TagsResult
|
||||
{
|
||||
public string[] Tags { get; set; } = Array.Empty<string>();
|
||||
public string[] Tags { get; init; } = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@ using SixLabors.ImageSharp.Metadata.Profiles.Exif;
|
||||
using System.Globalization;
|
||||
using Foxel.Models;
|
||||
using Foxel.Models.Enums;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
|
||||
namespace Foxel.Utils;
|
||||
|
||||
@@ -13,21 +12,6 @@ namespace Foxel.Utils;
|
||||
/// </summary>
|
||||
public static class ImageHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取完整URL路径
|
||||
/// </summary>
|
||||
/// <param name="serverUrl">服务器URL</param>
|
||||
/// <param name="relativePath">相对路径</param>
|
||||
/// <returns>完整URL路径</returns>
|
||||
public static string GetFullPath(string serverUrl, string relativePath)
|
||||
{
|
||||
if (string.IsNullOrEmpty(relativePath))
|
||||
return string.Empty;
|
||||
if (relativePath.StartsWith("https://"))
|
||||
return relativePath;
|
||||
return $"{serverUrl.TrimEnd('/')}{relativePath}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建缩略图
|
||||
/// </summary>
|
||||
@@ -76,58 +60,6 @@ public static class ImageHelper
|
||||
return thumbnailFileInfo.Length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查图像是否包含透明像素
|
||||
/// </summary>
|
||||
/// <param name="image">要检查的图像</param>
|
||||
/// <returns>如果图像包含透明像素则返回true</returns>
|
||||
private static bool HasTransparency(Image image)
|
||||
{
|
||||
// 检查图像格式是否支持透明度
|
||||
if (image.PixelType.AlphaRepresentation == PixelAlphaRepresentation.None)
|
||||
{
|
||||
return false; // 图像格式不支持透明度
|
||||
}
|
||||
|
||||
// 对于小图片,逐像素检查是否有透明度
|
||||
if (image.Width * image.Height <= 1000 * 1000) // 对于不超过1000x1000的图片
|
||||
{
|
||||
using var imageWithAlpha = image.CloneAs<Rgba32>();
|
||||
|
||||
for (int y = 0; y < imageWithAlpha.Height; y++)
|
||||
{
|
||||
for (int x = 0; x < imageWithAlpha.Width; x++)
|
||||
{
|
||||
if (imageWithAlpha[x, y].A < 255)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
using var imageWithAlpha = image.CloneAs<Rgba32>();
|
||||
int sampleSize = Math.Max(image.Width, image.Height) / 100;
|
||||
sampleSize = Math.Max(1, sampleSize);
|
||||
|
||||
for (int y = 0; y < imageWithAlpha.Height; y += sampleSize)
|
||||
{
|
||||
for (int x = 0; x < imageWithAlpha.Width; x += sampleSize)
|
||||
{
|
||||
if (imageWithAlpha[x, y].A < 255)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据原始文件大小调整质量参数
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user