Rebrand MMTL to MeBox (name, logo, Docker image) (#17)

* Rebrand MMTL to MeBox across codebase and assets

Rename the project display name, Go module path, environment variable
prefix (MEBOX_*), Docker image references, and UI branding from MMTL/mmtl
to MeBox/mebox. Replace logo assets with the new MeBox icon and keep
legacy SQLite migration support for existing mmtl.db deployments.

Co-authored-by: truewhile <truewhile@users.noreply.github.com>

* Fix logo icons: use cube-only crop without truncated text

Previous icon generation cropped too much of the source image, including
partial MeBox wordmark text that was cut off in square icon containers.
Regenerate logo-64/192/512, favicon, and SVG from cube-only region.

Co-authored-by: truewhile <truewhile@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: truewhile <truewhile@users.noreply.github.com>
This commit is contained in:
truewhile
2026-09-02 16:26:28 +08:00
committed by GitHub
parent a50ceaf1a7
commit b0fe40142a
435 changed files with 1152 additions and 1149 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ import (
"gorm.io/gorm"
"gorm.io/gorm/logger"
"github.com/ShukeBta/MMTL/internal/config"
"github.com/truewhile/MeBox/internal/config"
)
// Open initialises the configured GORM database. database.type=auto chooses
+2 -2
View File
@@ -12,8 +12,8 @@ import (
"gorm.io/gorm"
"gorm.io/gorm/logger"
"github.com/ShukeBta/MMTL/internal/config"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/truewhile/MeBox/internal/config"
"github.com/truewhile/MeBox/internal/model"
)
// DatabaseStatus describes the currently active database engine and runtime metrics.
+10 -10
View File
@@ -6,8 +6,8 @@ import (
"github.com/glebarez/sqlite"
"gorm.io/gorm"
"github.com/ShukeBta/MMTL/internal/config"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/truewhile/MeBox/internal/config"
"github.com/truewhile/MeBox/internal/model"
)
func TestMaskDSN(t *testing.T) {
@@ -16,16 +16,16 @@ func TestMaskDSN(t *testing.T) {
want string
}{
{
in: "postgres://admin:secret123@localhost:5432/mmtl?sslmode=disable",
want: "postgres://admin:******@localhost:5432/mmtl?sslmode=disable",
in: "postgres://admin:secret123@localhost:5432/mebox?sslmode=disable",
want: "postgres://admin:******@localhost:5432/mebox?sslmode=disable",
},
{
in: "host=localhost port=5432 user=admin password=secret dbname=mmtl sslmode=disable",
want: "host=localhost port=5432 user=admin password=****** dbname=mmtl sslmode=disable",
in: "host=localhost port=5432 user=admin password=secret dbname=mebox sslmode=disable",
want: "host=localhost port=5432 user=admin password=****** dbname=mebox sslmode=disable",
},
{
in: "sqlite://data/mmtl.db",
want: "sqlite://data/mmtl.db",
in: "sqlite://data/mebox.db",
want: "sqlite://data/mebox.db",
},
{
in: "",
@@ -53,7 +53,7 @@ func TestInspectDatabaseStatus(t *testing.T) {
cfg := &config.Config{}
cfg.Database.Type = "sqlite"
cfg.Database.DBPath = "./data/mmtl.db"
cfg.Database.DBPath = "./data/mebox.db"
st := InspectDatabaseStatus(db, cfg)
if st == nil {
@@ -62,7 +62,7 @@ func TestInspectDatabaseStatus(t *testing.T) {
if st.Type != "sqlite" {
t.Fatalf("expected sqlite, got %s", st.Type)
}
if st.DBPath != "./data/mmtl.db" {
if st.DBPath != "./data/mebox.db" {
t.Fatalf("expected db_path, got %s", st.DBPath)
}
if st.TableCounts["users"] != 1 {
+5 -5
View File
@@ -8,8 +8,8 @@ import (
"github.com/glebarez/sqlite"
"gorm.io/gorm"
"github.com/ShukeBta/MMTL/internal/config"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/truewhile/MeBox/internal/config"
"github.com/truewhile/MeBox/internal/model"
)
func TestOpenRequiresConfig(t *testing.T) {
@@ -28,7 +28,7 @@ func TestOpenRequiresConfig(t *testing.T) {
func TestOpenSQLiteWithNilLoggerConfiguresPool(t *testing.T) {
cfg := &config.Config{}
cfg.Database.Type = "sqlite"
cfg.Database.DBPath = filepath.Join(t.TempDir(), "mmtl.db")
cfg.Database.DBPath = filepath.Join(t.TempDir(), "mebox.db")
cfg.Database.WALMode = true
cfg.Database.BusyTimeout = 5000
cfg.Database.CacheSize = -2000
@@ -278,7 +278,7 @@ func TestSQLiteMigrationCompleteMarker(t *testing.T) {
func TestSQLiteMigrationFallsBackToDataDirDefaultPath(t *testing.T) {
dir := t.TempDir()
sqlitePath := filepath.Join(dir, "mmtl.db")
sqlitePath := filepath.Join(dir, "mebox.db")
src, err := gorm.Open(sqlite.Open(sqlitePath), &gorm.Config{})
if err != nil {
t.Fatal(err)
@@ -362,7 +362,7 @@ func TestSQLiteMigrationFallsBackToDataDirDefaultPath(t *testing.T) {
func TestOpenSQLiteMigrationSourceUsesFallbackSourcePath(t *testing.T) {
dir := t.TempDir()
sqlitePath := filepath.Join(dir, "mmtl.db")
sqlitePath := filepath.Join(dir, "mebox.db")
src, err := gorm.Open(sqlite.Open(sqlitePath), &gorm.Config{})
if err != nil {
t.Fatal(err)
+1 -1
View File
@@ -6,7 +6,7 @@ import (
"gorm.io/gorm"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/truewhile/MeBox/internal/model"
)
func ensureLibraryRootsCompatibility(db *gorm.DB) error {
+1 -1
View File
@@ -3,7 +3,7 @@ package database
import (
"gorm.io/gorm"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/truewhile/MeBox/internal/model"
)
// AutoMigrate creates tables for every model registered in the model package.
@@ -7,7 +7,7 @@ import (
"github.com/glebarez/sqlite"
"gorm.io/gorm"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/truewhile/MeBox/internal/model"
)
func TestEnsureEmbyMountsCompatibility(t *testing.T) {
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"go.uber.org/zap"
"gorm.io/gorm"
"github.com/ShukeBta/MMTL/internal/config"
"github.com/truewhile/MeBox/internal/config"
)
// MigrateSQLiteToCurrentIfNeeded copies an existing SQLite database into
@@ -9,7 +9,7 @@ import (
"gorm.io/gorm"
"gorm.io/gorm/clause"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/truewhile/MeBox/internal/model"
)
func resetBootstrapTargetBeforeSQLiteMigrationIfSafe(src, target *gorm.DB, log *zap.Logger) error {
+1 -1
View File
@@ -10,7 +10,7 @@ import (
"gorm.io/gorm/clause"
"gorm.io/gorm/schema"
"github.com/ShukeBta/MMTL/internal/model"
"github.com/truewhile/MeBox/internal/model"
)
func copyModelTables(src, target *gorm.DB, batchSize int) (map[string]int64, int64, error) {
+23 -16
View File
@@ -12,7 +12,7 @@ import (
"gorm.io/gorm"
"gorm.io/gorm/logger"
"github.com/ShukeBta/MMTL/internal/config"
"github.com/truewhile/MeBox/internal/config"
)
func openSQLiteMigrationSource(cfg *config.Config, sqlitePath string) (*gorm.DB, error) {
@@ -36,23 +36,30 @@ func sqliteMigrationSourcePath(cfg *config.Config, log *zap.Logger) (string, err
}
}
fallback := filepath.Join(strings.TrimSpace(cfg.App.DataDir), "mmtl.db")
if fallback == "" || sameCleanPath(configured, fallback) {
return "", nil
// Prefer the new default filename, then fall back to legacy MMTL SQLite files.
candidates := []string{
filepath.Join(strings.TrimSpace(cfg.App.DataDir), "mebox.db"),
filepath.Join(strings.TrimSpace(cfg.App.DataDir), "mmtl.db"),
}
exists, err := regularFileExists(fallback)
if err != nil {
return "", fmt.Errorf("stat default sqlite migration source: %w", err)
for _, fallback := range candidates {
if fallback == "" || sameCleanPath(configured, fallback) {
continue
}
exists, err := regularFileExists(fallback)
if err != nil {
return "", fmt.Errorf("stat default sqlite migration source: %w", err)
}
if !exists {
continue
}
if log != nil && configured != "" {
log.Warn("configured sqlite migration source not found; using data-dir default",
zap.String("configured", configured),
zap.String("fallback", fallback))
}
return fallback, nil
}
if !exists {
return "", nil
}
if log != nil && configured != "" {
log.Warn("configured sqlite migration source not found; using data-dir default",
zap.String("configured", configured),
zap.String("fallback", fallback))
}
return fallback, nil
return "", nil
}
func regularFileExists(path string) (bool, error) {
+10 -10
View File
@@ -8,14 +8,14 @@ import (
"gorm.io/gorm"
"github.com/ShukeBta/MMTL/internal/config"
"github.com/truewhile/MeBox/internal/config"
)
func installSQLiteWriteGate(db *gorm.DB) {
if db == nil {
return
}
const lockedKey = "mmtl:sqlite_write_locked"
const lockedKey = "mebox:sqlite_write_locked"
gate := newSQLiteWriteGate()
lock := func(tx *gorm.DB) {
ctx := context.Background()
@@ -39,14 +39,14 @@ func installSQLiteWriteGate(db *gorm.DB) {
}
lock(tx)
}
_ = db.Callback().Create().Before("gorm:create").Register("mmtl:sqlite_write_lock", lock)
_ = db.Callback().Create().After("gorm:create").Register("mmtl:sqlite_write_unlock", unlock)
_ = db.Callback().Update().Before("gorm:update").Register("mmtl:sqlite_write_lock", lock)
_ = db.Callback().Update().After("gorm:update").Register("mmtl:sqlite_write_unlock", unlock)
_ = db.Callback().Delete().Before("gorm:delete").Register("mmtl:sqlite_write_lock", lock)
_ = db.Callback().Delete().After("gorm:delete").Register("mmtl:sqlite_write_unlock", unlock)
_ = db.Callback().Raw().Before("gorm:raw").Register("mmtl:sqlite_write_lock", rawLock)
_ = db.Callback().Raw().After("gorm:raw").Register("mmtl:sqlite_write_unlock", unlock)
_ = db.Callback().Create().Before("gorm:create").Register("mebox:sqlite_write_lock", lock)
_ = db.Callback().Create().After("gorm:create").Register("mebox:sqlite_write_unlock", unlock)
_ = db.Callback().Update().Before("gorm:update").Register("mebox:sqlite_write_lock", lock)
_ = db.Callback().Update().After("gorm:update").Register("mebox:sqlite_write_unlock", unlock)
_ = db.Callback().Delete().Before("gorm:delete").Register("mebox:sqlite_write_lock", lock)
_ = db.Callback().Delete().After("gorm:delete").Register("mebox:sqlite_write_unlock", unlock)
_ = db.Callback().Raw().Before("gorm:raw").Register("mebox:sqlite_write_lock", rawLock)
_ = db.Callback().Raw().After("gorm:raw").Register("mebox:sqlite_write_unlock", unlock)
}
func isReadOnlySQL(sql string) bool {