redis
All checks were successful
Build docker and publish / build (20.15.1) (push) Successful in 7m33s
All checks were successful
Build docker and publish / build (20.15.1) (push) Successful in 7m33s
This commit is contained in:
parent
282e1e4087
commit
50f6995d60
@ -15,10 +15,10 @@ Logger: # 日志配置
|
||||
Level: debug # 日志级别: debug, info, warn, error, panic, fatal
|
||||
|
||||
MySQL:
|
||||
Addr: 154.12.35.103:3306 # host 网络模式; bridge 模式改为 mysql:3306
|
||||
Addr: 103.150.215.44:3306 # host 网络模式; bridge 模式改为 mysql:3306
|
||||
Username: root # MySQL用户名
|
||||
Password: jpcV41ppanel # MySQL密码,与 .env MYSQL_ROOT_PASSWORD 一致
|
||||
Dbname: ppanel # MySQL数据库名
|
||||
Dbname: hifast # MySQL数据库名
|
||||
Config: charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai
|
||||
MaxIdleConns: 10
|
||||
MaxOpenConns: 100
|
||||
|
||||
@ -107,8 +107,6 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
||||
err = rds.Ping(context.Background()).Err()
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
} else {
|
||||
_ = rds.FlushAll(context.Background()).Err()
|
||||
}
|
||||
authLimiter := limit.NewPeriodLimit(86400, 15, rds, config.SendCountLimitKeyPrefix, limit.Align())
|
||||
nonceStore := signature.NewRedisNonceStore(rds)
|
||||
|
||||
@ -276,8 +276,13 @@ func main() {
|
||||
SELECT user_id AS uid FROM ` + "`order`" + ` WHERE status = ? AND user_id > 0
|
||||
UNION
|
||||
SELECT user_id AS uid FROM apple_iap_transactions WHERE user_id > 0
|
||||
UNION
|
||||
SELECT user_id AS uid FROM user_subscribe WHERE user_id > 0
|
||||
) t
|
||||
INNER JOIN user u ON u.id = t.uid
|
||||
WHERE u.id NOT IN (
|
||||
SELECT user_id FROM user_auth_methods WHERE auth_type = 'email' AND auth_identifier = 'devneeds52@gmail.com'
|
||||
)
|
||||
ORDER BY t.uid
|
||||
`, orderStatusCompleted).Scan(&paidIDs).Error
|
||||
if err != nil {
|
||||
@ -674,10 +679,22 @@ func main() {
|
||||
now := time.Now()
|
||||
familyCount := 0
|
||||
|
||||
// ── 为了配合基于新 UID 的条件检查,预先构建映射 ──
|
||||
deviceCountByNewUID := make(map[int64]int)
|
||||
for i := range devices {
|
||||
deviceCountByNewUID[devices[i].UserId]++
|
||||
}
|
||||
hasEmailByNewUID := make(map[int64]bool)
|
||||
for i := range auths {
|
||||
if auths[i].AuthType == "email" {
|
||||
hasEmailByNewUID[auths[i].UserId] = true
|
||||
}
|
||||
}
|
||||
|
||||
err = dstDB.Transaction(func(tx *gorm.DB) error {
|
||||
for _, uid := range paidIDs {
|
||||
// 只为多设备用户创建家庭组
|
||||
if len(deviceByUser[uid]) <= 1 {
|
||||
// 只为多设备且有邮箱的用户创建家庭组
|
||||
if deviceCountByNewUID[uid] <= 1 || !hasEmailByNewUID[uid] {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -753,55 +770,58 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 查找原用户的家庭组(如果不存在则创建,虽然理论上 Step 8 已经为多设备用户创建了)
|
||||
var family UserFamily
|
||||
if err := tx.Where("owner_user_id = ?", s.OwnerUID).First(&family).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
// 补救措施:为该用户创建一个家庭组
|
||||
family = UserFamily{
|
||||
OwnerUserId: s.OwnerUID,
|
||||
MaxMembers: defaultFamilyMaxSize,
|
||||
Status: 1,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
// 仅仅当原用户有邮箱时,才尝试将其加入家庭组(无邮箱的仅拆分为独立用户)
|
||||
if hasEmailByNewUID[s.OwnerUID] {
|
||||
// 4. 查找原用户的家庭组(如果不存在则创建,虽然理论上 Step 8 已经为多设备用户创建了)
|
||||
var family UserFamily
|
||||
if err := tx.Where("owner_user_id = ?", s.OwnerUID).First(&family).Error; err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
// 补救措施:为该用户创建一个家庭组
|
||||
family = UserFamily{
|
||||
OwnerUserId: s.OwnerUID,
|
||||
MaxMembers: defaultFamilyMaxSize,
|
||||
Status: 1,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
if err := tx.Create(&family).Error; err != nil {
|
||||
return fmt.Errorf("创建家庭组补救失败(owner=%d): %w", s.OwnerUID, err)
|
||||
}
|
||||
|
||||
// 创建家主成员
|
||||
ownerMember := UserFamilyMember{
|
||||
FamilyId: family.Id,
|
||||
UserId: s.OwnerUID,
|
||||
Role: familyRoleOwner,
|
||||
Status: 1,
|
||||
JoinSource: "migration_split_recovery",
|
||||
JoinedAt: now,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
if err := tx.Create(&ownerMember).Error; err != nil {
|
||||
return fmt.Errorf("创建家主成员补救失败(owner=%d): %w", s.OwnerUID, err)
|
||||
}
|
||||
familyCount++ // 更新计数器
|
||||
} else {
|
||||
return fmt.Errorf("查找家庭组失败(owner=%d): %w", s.OwnerUID, err)
|
||||
}
|
||||
if err := tx.Create(&family).Error; err != nil {
|
||||
return fmt.Errorf("创建家庭组补救失败(owner=%d): %w", s.OwnerUID, err)
|
||||
}
|
||||
|
||||
// 创建家主成员
|
||||
ownerMember := UserFamilyMember{
|
||||
FamilyId: family.Id,
|
||||
UserId: s.OwnerUID,
|
||||
Role: familyRoleOwner,
|
||||
Status: 1,
|
||||
JoinSource: "migration_split_recovery",
|
||||
JoinedAt: now,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
if err := tx.Create(&ownerMember).Error; err != nil {
|
||||
return fmt.Errorf("创建家主成员补救失败(owner=%d): %w", s.OwnerUID, err)
|
||||
}
|
||||
familyCount++ // 更新计数器
|
||||
} else {
|
||||
return fmt.Errorf("查找家庭组失败(owner=%d): %w", s.OwnerUID, err)
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 加入家庭组
|
||||
member := UserFamilyMember{
|
||||
FamilyId: family.Id,
|
||||
UserId: newUser.Id,
|
||||
Role: familyRoleMember,
|
||||
Status: 1,
|
||||
JoinSource: "migration_split",
|
||||
JoinedAt: s.Device.CreatedAt,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
if err := tx.Create(&member).Error; err != nil {
|
||||
return fmt.Errorf("添加家庭成员失败: %w", err)
|
||||
// 5. 加入家庭组
|
||||
member := UserFamilyMember{
|
||||
FamilyId: family.Id,
|
||||
UserId: newUser.Id,
|
||||
Role: familyRoleMember,
|
||||
Status: 1,
|
||||
JoinSource: "migration_split",
|
||||
JoinedAt: s.Device.CreatedAt,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
if err := tx.Create(&member).Error; err != nil {
|
||||
return fmt.Errorf("添加家庭成员失败: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
splitCount++
|
||||
|
||||
5
说明文档.md
5
说明文档.md
@ -15,16 +15,17 @@
|
||||
| 2026-03-11 | 提供今天所有 ERROR 报错指令 | [x] 已完成 | 已提供根据日期过滤 ERROR 的命令 |
|
||||
| 2026-03-12 | 分析并确认 Unknown column 错误 | [x] 已完成 | 确认为 `user_device` 缺少 `short_code` 字段,已提供 SQL |
|
||||
| 2026-03-12 | 提供 SSL 证书替换指令 | [x] 已完成 | 已提供备份与替换证书的组合指令 |
|
||||
| 2026-03-17 | 合并 internal 到 internal/main | [x] 已完成 | 已查验均为fast-forward,受限网络/权限,需手动push完成合并 |
|
||||
|
||||
certbot certonly --manual --preferred-challenges dns -d airoport.win -d "*.airoport.win" -d hifastapp.com
|
||||
|
||||
|
||||
|
||||
gunzip -c mysql_dump_20260317_145137.sql.gz \
|
||||
gunzip -c mysql_dump_20260318_052811.sql.gz \
|
||||
| docker exec -i ppanel-mysql mysql -uroot -pjpcV41ppanel
|
||||
|
||||
|
||||
go run scripts/migrate_paid_users.go -src 'root:rootpassword@tcp(127.0.0.1:3306)/ppanel?charset=utf8mb4&parseTime=True&loc=Local' -dst 'root:jpcV41ppanel@tcp(154.12.35.103:3306)/ppanel?charset=utf8mb4&parseTime=True&loc=Local' -clean
|
||||
go run scripts/migrate_paid_users.go -src 'root:rootpassword@tcp(127.0.0.1:3306)/ppanel?charset=utf8mb4&parseTime=True&loc=Local' -dst 'root:jpcV41ppanel@tcp(103.150.215.44:3306)/hifast?charset=utf8mb4&parseTime=True&loc=Local' -clean
|
||||
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user