chore: baseline snapshot before moderation-strictness feature

Repo .git was damaged (refs/ missing, index truncated, object store near-empty).
Repaired via git init (rebuilt refs), stale index preserved as .git/index.corrupt-20260910.bak,
then full worktree committed as a rollback baseline.
This commit is contained in:
tamakyi
2026-09-10 10:56:27 +08:00
commit e3e59e7c69
296 changed files with 67458 additions and 0 deletions
+11
View File
@@ -0,0 +1,11 @@
// Copyright 2021 E99p1ant. All rights reserved.
package dbutil
import (
"time"
)
func Now() time.Time {
return time.Now().Truncate(time.Microsecond)
}
+24
View File
@@ -0,0 +1,24 @@
// Copyright 2022 E99p1ant. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package dbutil
import (
"time"
"gorm.io/gorm"
)
// Model a basic GoLang struct which includes the following fields: ID, CreatedAt, UpdatedAt, DeletedAt
// It may be embedded into your model or you may build your own model without it
//
// type User struct {
// gorm.Model
// }
type Model struct {
ID uint `gorm:"primarykey" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"-"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
}
+46
View File
@@ -0,0 +1,46 @@
// Copyright 2022 E99p1ant. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package dbutil
var (
DefaultPageSize = 20
MaxDefaultPageSize = 100
)
type Pagination struct {
Page int
PageSize int
}
// LimitOffset returns LIMIT and OFFSET parameter for SQL.
// The first page is page 0.
func (p Pagination) LimitOffset() (limit, offset int) {
page := p.Page
pageSize := p.PageSize
if page <= 0 {
page = 1
}
if pageSize < 1 {
pageSize = DefaultPageSize
}
return pageSize, (page - 1) * pageSize
}
type Cursor struct {
Value interface{}
PageSize int
}
func (p Cursor) Limit() int {
pageSize := p.PageSize
if pageSize < 1 {
pageSize = DefaultPageSize
}
if pageSize > MaxDefaultPageSize {
pageSize = MaxDefaultPageSize
}
return pageSize
}
+145
View File
@@ -0,0 +1,145 @@
// Copyright 2023 E99p1ant. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package dbutil
import (
"context"
"flag"
"math/rand"
"net/url"
"os"
"strconv"
"strings"
"sync"
"testing"
"time"
"gorm.io/driver/mysql"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
var flagParseOnce sync.Once
func NewTestDB(t *testing.T, migrationTables ...interface{}) (testDB *gorm.DB, cleanup func(...string) error) {
dbType := os.Getenv("DB_TYPE")
var dsn string
var dialectFunc func(string) gorm.Dialector
switch dbType {
case "mysql":
dsn = os.ExpandEnv("$DB_USER:$DB_PASSWORD@tcp($DB_HOST:$DB_PORT)/$DB_DATABASE?charset=utf8mb4&parseTime=True&loc=Local")
dialectFunc = mysql.Open
case "postgres":
dsn = os.ExpandEnv("postgres://$DB_USER:$DB_PASSWORD@$DB_HOST:$DB_PORT?sslmode=disable")
dialectFunc = postgres.Open
default:
t.Fatalf("Unknown database type: %q", dbType)
}
db, err := gorm.Open(dialectFunc(dsn), &gorm.Config{
NowFunc: Now,
SkipDefaultTransaction: true,
})
if err != nil {
t.Fatalf("Failed to open connection: %v", err)
}
ctx := context.Background()
rng := rand.New(rand.NewSource(time.Now().UnixNano()))
dbname := "tamabox-test-" + strconv.FormatUint(rng.Uint64(), 10)
err = db.WithContext(ctx).Exec(`CREATE DATABASE ` + QuoteIdentifier(dbType, dbname)).Error
if err != nil {
t.Fatalf("Failed to create test database: %v", err)
}
switch dbType {
case "mysql":
dsn = strings.ReplaceAll(dsn, os.Getenv("DB_DATABASE"), dbname)
case "postgres":
cfg, err := url.Parse(dsn)
if err != nil {
t.Fatalf("Failed to parse DSN")
}
cfg.Path = "/" + dbname
dsn = cfg.String()
}
flagParseOnce.Do(flag.Parse)
testDB, err = gorm.Open(dialectFunc(dsn), &gorm.Config{
NowFunc: Now,
SkipDefaultTransaction: true,
})
if err != nil {
t.Fatalf("Failed to open test connection: %v", err)
}
err = testDB.AutoMigrate(migrationTables...)
if err != nil {
t.Fatalf("Failed to auto migrate tables: %v", err)
}
t.Cleanup(func() {
defer func() {
if database, err := db.DB(); err == nil {
_ = database.Close()
}
}()
if t.Failed() {
t.Logf("DATABASE %s left intact for inspection", dbname)
return
}
database, err := testDB.DB()
if err != nil {
t.Fatalf("Failed to get currently open database: %v", err)
}
err = database.Close()
if err != nil {
t.Fatalf("Failed to close currently open database: %v", err)
}
err = db.WithContext(ctx).Exec(`DROP DATABASE ` + QuoteIdentifier(dbType, dbname)).Error
if err != nil {
t.Fatalf("Failed to drop test database: %v", err)
}
})
return testDB, func(tables ...string) error {
if t.Failed() {
return nil
}
for _, table := range tables {
var query string
switch dbType {
case "mysql":
query = `TRUNCATE TABLE ` + QuoteIdentifier(dbType, table)
case "postgres":
query = `TRUNCATE TABLE ` + QuoteIdentifier(dbType, table) + ` RESTART IDENTITY CASCADE`
}
err := testDB.WithContext(ctx).Exec(query).Error
if err != nil {
return err
}
}
return nil
}
}
// QuoteIdentifier quotes an "identifier" (e.g. a table or a column name) to be
// used as part of an SQL statement.
func QuoteIdentifier(typ, s string) string {
if typ == "postgres" {
return `"` + strings.ReplaceAll(s, `"`, `""`) + `"`
}
return "`" + strings.ReplaceAll(s, "`", "``") + "`"
}