243 lines
6.6 KiB
Go
243 lines
6.6 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/Wei-Shaw/sub2api/internal/service"
|
|
|
|
"github.com/Wei-Shaw/sub2api/internal/pkg/pagination"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type proxyRepository struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
func NewProxyRepository(db *gorm.DB) service.ProxyRepository {
|
|
return &proxyRepository{db: db}
|
|
}
|
|
|
|
func (r *proxyRepository) Create(ctx context.Context, proxy *service.Proxy) error {
|
|
m := proxyModelFromService(proxy)
|
|
err := r.db.WithContext(ctx).Create(m).Error
|
|
if err == nil {
|
|
applyProxyModelToService(proxy, m)
|
|
}
|
|
return err
|
|
}
|
|
|
|
func (r *proxyRepository) GetByID(ctx context.Context, id int64) (*service.Proxy, error) {
|
|
var m proxyModel
|
|
err := r.db.WithContext(ctx).First(&m, id).Error
|
|
if err != nil {
|
|
return nil, translatePersistenceError(err, service.ErrProxyNotFound, nil)
|
|
}
|
|
return proxyModelToService(&m), nil
|
|
}
|
|
|
|
func (r *proxyRepository) Update(ctx context.Context, proxy *service.Proxy) error {
|
|
m := proxyModelFromService(proxy)
|
|
err := r.db.WithContext(ctx).Save(m).Error
|
|
if err == nil {
|
|
applyProxyModelToService(proxy, m)
|
|
}
|
|
return err
|
|
}
|
|
|
|
func (r *proxyRepository) Delete(ctx context.Context, id int64) error {
|
|
return r.db.WithContext(ctx).Delete(&proxyModel{}, id).Error
|
|
}
|
|
|
|
func (r *proxyRepository) List(ctx context.Context, params pagination.PaginationParams) ([]service.Proxy, *pagination.PaginationResult, error) {
|
|
return r.ListWithFilters(ctx, params, "", "", "")
|
|
}
|
|
|
|
// ListWithFilters lists proxies with optional filtering by protocol, status, and search query
|
|
func (r *proxyRepository) ListWithFilters(ctx context.Context, params pagination.PaginationParams, protocol, status, search string) ([]service.Proxy, *pagination.PaginationResult, error) {
|
|
var proxies []proxyModel
|
|
var total int64
|
|
|
|
db := r.db.WithContext(ctx).Model(&proxyModel{})
|
|
|
|
// Apply filters
|
|
if protocol != "" {
|
|
db = db.Where("protocol = ?", protocol)
|
|
}
|
|
if status != "" {
|
|
db = db.Where("status = ?", status)
|
|
}
|
|
if search != "" {
|
|
searchPattern := "%" + search + "%"
|
|
db = db.Where("name ILIKE ?", searchPattern)
|
|
}
|
|
|
|
if err := db.Count(&total).Error; err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
if err := db.Offset(params.Offset()).Limit(params.Limit()).Order("id DESC").Find(&proxies).Error; err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
outProxies := make([]service.Proxy, 0, len(proxies))
|
|
for i := range proxies {
|
|
outProxies = append(outProxies, *proxyModelToService(&proxies[i]))
|
|
}
|
|
|
|
return outProxies, paginationResultFromTotal(total, params), nil
|
|
}
|
|
|
|
func (r *proxyRepository) ListActive(ctx context.Context) ([]service.Proxy, error) {
|
|
var proxies []proxyModel
|
|
err := r.db.WithContext(ctx).Where("status = ?", service.StatusActive).Find(&proxies).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
outProxies := make([]service.Proxy, 0, len(proxies))
|
|
for i := range proxies {
|
|
outProxies = append(outProxies, *proxyModelToService(&proxies[i]))
|
|
}
|
|
return outProxies, nil
|
|
}
|
|
|
|
// ExistsByHostPortAuth checks if a proxy with the same host, port, username, and password exists
|
|
func (r *proxyRepository) ExistsByHostPortAuth(ctx context.Context, host string, port int, username, password string) (bool, error) {
|
|
var count int64
|
|
err := r.db.WithContext(ctx).Model(&proxyModel{}).
|
|
Where("host = ? AND port = ? AND username = ? AND password = ?", host, port, username, password).
|
|
Count(&count).Error
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return count > 0, nil
|
|
}
|
|
|
|
// CountAccountsByProxyID returns the number of accounts using a specific proxy
|
|
func (r *proxyRepository) CountAccountsByProxyID(ctx context.Context, proxyID int64) (int64, error) {
|
|
var count int64
|
|
err := r.db.WithContext(ctx).Table("accounts").
|
|
Where("proxy_id = ?", proxyID).
|
|
Count(&count).Error
|
|
return count, err
|
|
}
|
|
|
|
// GetAccountCountsForProxies returns a map of proxy ID to account count for all proxies
|
|
func (r *proxyRepository) GetAccountCountsForProxies(ctx context.Context) (map[int64]int64, error) {
|
|
type result struct {
|
|
ProxyID int64 `gorm:"column:proxy_id"`
|
|
Count int64 `gorm:"column:count"`
|
|
}
|
|
var results []result
|
|
err := r.db.WithContext(ctx).
|
|
Table("accounts").
|
|
Select("proxy_id, COUNT(*) as count").
|
|
Where("proxy_id IS NOT NULL").
|
|
Group("proxy_id").
|
|
Scan(&results).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
counts := make(map[int64]int64)
|
|
for _, r := range results {
|
|
counts[r.ProxyID] = r.Count
|
|
}
|
|
return counts, nil
|
|
}
|
|
|
|
// ListActiveWithAccountCount returns all active proxies with account count, sorted by creation time descending
|
|
func (r *proxyRepository) ListActiveWithAccountCount(ctx context.Context) ([]service.ProxyWithAccountCount, error) {
|
|
var proxies []proxyModel
|
|
err := r.db.WithContext(ctx).
|
|
Where("status = ?", service.StatusActive).
|
|
Order("created_at DESC").
|
|
Find(&proxies).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Get account counts
|
|
counts, err := r.GetAccountCountsForProxies(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Build result with account counts
|
|
result := make([]service.ProxyWithAccountCount, 0, len(proxies))
|
|
for i := range proxies {
|
|
proxy := proxyModelToService(&proxies[i])
|
|
if proxy == nil {
|
|
continue
|
|
}
|
|
result = append(result, service.ProxyWithAccountCount{
|
|
Proxy: *proxy,
|
|
AccountCount: counts[proxy.ID],
|
|
})
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
type proxyModel struct {
|
|
ID int64 `gorm:"primaryKey"`
|
|
Name string `gorm:"size:100;not null"`
|
|
Protocol string `gorm:"size:20;not null"`
|
|
Host string `gorm:"size:255;not null"`
|
|
Port int `gorm:"not null"`
|
|
Username string `gorm:"size:100"`
|
|
Password string `gorm:"size:100"`
|
|
Status string `gorm:"size:20;default:active;not null"`
|
|
CreatedAt time.Time `gorm:"not null"`
|
|
UpdatedAt time.Time `gorm:"not null"`
|
|
DeletedAt gorm.DeletedAt `gorm:"index"`
|
|
}
|
|
|
|
func (proxyModel) TableName() string { return "proxies" }
|
|
|
|
func proxyModelToService(m *proxyModel) *service.Proxy {
|
|
if m == nil {
|
|
return nil
|
|
}
|
|
return &service.Proxy{
|
|
ID: m.ID,
|
|
Name: m.Name,
|
|
Protocol: m.Protocol,
|
|
Host: m.Host,
|
|
Port: m.Port,
|
|
Username: m.Username,
|
|
Password: m.Password,
|
|
Status: m.Status,
|
|
CreatedAt: m.CreatedAt,
|
|
UpdatedAt: m.UpdatedAt,
|
|
}
|
|
}
|
|
|
|
func proxyModelFromService(p *service.Proxy) *proxyModel {
|
|
if p == nil {
|
|
return nil
|
|
}
|
|
return &proxyModel{
|
|
ID: p.ID,
|
|
Name: p.Name,
|
|
Protocol: p.Protocol,
|
|
Host: p.Host,
|
|
Port: p.Port,
|
|
Username: p.Username,
|
|
Password: p.Password,
|
|
Status: p.Status,
|
|
CreatedAt: p.CreatedAt,
|
|
UpdatedAt: p.UpdatedAt,
|
|
}
|
|
}
|
|
|
|
func applyProxyModelToService(proxy *service.Proxy, m *proxyModel) {
|
|
if proxy == nil || m == nil {
|
|
return
|
|
}
|
|
proxy.ID = m.ID
|
|
proxy.CreatedAt = m.CreatedAt
|
|
proxy.UpdatedAt = m.UpdatedAt
|
|
}
|