chore: update project structure and enhance plugin functionality
- Added new entries to .gitignore for database files. - Updated go.mod and go.sum to include new indirect dependencies for database and ORM support. - Refactored event handling to improve message reply functionality in the protocol. - Enhanced the dispatcher to allow for better event processing and logging. - Removed outdated plugin documentation and unnecessary files to streamline the codebase. - Improved welcome message formatting and screenshot options for better user experience.
This commit is contained in:
125
internal/database/database.go
Normal file
125
internal/database/database.go
Normal file
@@ -0,0 +1,125 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"gorm.io/driver/sqlite"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// Database 数据库接口,预留其他数据库接入
|
||||
type Database interface {
|
||||
// GetDB 获取指定 bot 的数据库连接(使用表前缀区分不同 bot 的数据)
|
||||
GetDB(botID string) (*gorm.DB, error)
|
||||
// Close 关闭所有数据库连接
|
||||
Close() error
|
||||
}
|
||||
|
||||
// SQLiteDatabase SQLite 数据库实现
|
||||
// 使用表前缀来区分不同 bot 的数据,所有 bot 共享同一个数据库文件和连接
|
||||
type SQLiteDatabase struct {
|
||||
mu sync.RWMutex
|
||||
db *gorm.DB // 共享的数据库连接
|
||||
dbs map[string]*gorm.DB // botID -> db (缓存,实际都指向同一个连接)
|
||||
logger *zap.Logger
|
||||
dbPath string
|
||||
options []gorm.Option
|
||||
}
|
||||
|
||||
// NewSQLiteDatabase 创建 SQLite 数据库实例
|
||||
// dbPath: 数据库文件路径(可以为空,使用默认路径)
|
||||
// 所有 bot 共享同一个数据库文件,通过表前缀区分
|
||||
func NewSQLiteDatabase(logger *zap.Logger, dbPath string, options ...gorm.Option) Database {
|
||||
if dbPath == "" {
|
||||
dbPath = "data/cellbot.db"
|
||||
}
|
||||
return &SQLiteDatabase{
|
||||
dbs: make(map[string]*gorm.DB),
|
||||
logger: logger.Named("database"),
|
||||
dbPath: dbPath,
|
||||
options: options,
|
||||
}
|
||||
}
|
||||
|
||||
// GetDB 获取指定 bot 的数据库连接
|
||||
// 使用表前缀来区分不同 bot 的数据,所有 bot 共享同一个数据库文件和连接
|
||||
func (d *SQLiteDatabase) GetDB(botID string) (*gorm.DB, error) {
|
||||
if botID == "" {
|
||||
return nil, fmt.Errorf("botID cannot be empty")
|
||||
}
|
||||
|
||||
// 初始化共享数据库连接(如果还没有)
|
||||
d.mu.Lock()
|
||||
if d.db == nil {
|
||||
// 确保数据库目录存在
|
||||
dir := filepath.Dir(d.dbPath)
|
||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||
d.mu.Unlock()
|
||||
return nil, fmt.Errorf("failed to create database directory: %w", err)
|
||||
}
|
||||
|
||||
// 所有 bot 共享同一个数据库文件和连接
|
||||
// 通过表前缀区分不同 bot 的数据
|
||||
db, err := gorm.Open(sqlite.Open(d.dbPath), d.options...)
|
||||
if err != nil {
|
||||
d.mu.Unlock()
|
||||
return nil, fmt.Errorf("failed to open database: %w", err)
|
||||
}
|
||||
|
||||
d.db = db
|
||||
d.logger.Info("Shared database connection created",
|
||||
zap.String("db_path", d.dbPath))
|
||||
}
|
||||
d.mu.Unlock()
|
||||
|
||||
// 所有 bot 返回同一个连接(通过缓存避免重复查找)
|
||||
d.mu.RLock()
|
||||
if cached, ok := d.dbs[botID]; ok {
|
||||
d.mu.RUnlock()
|
||||
return cached, nil
|
||||
}
|
||||
d.mu.RUnlock()
|
||||
|
||||
// 缓存连接引用(实际都指向同一个连接)
|
||||
d.mu.Lock()
|
||||
if cached, ok := d.dbs[botID]; ok {
|
||||
d.mu.Unlock()
|
||||
return cached, nil
|
||||
}
|
||||
d.dbs[botID] = d.db
|
||||
d.mu.Unlock()
|
||||
|
||||
return d.db, nil
|
||||
}
|
||||
|
||||
// Close 关闭所有数据库连接
|
||||
func (d *SQLiteDatabase) Close() error {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
|
||||
// 关闭共享的数据库连接
|
||||
if d.db != nil {
|
||||
if sqlDB, err := d.db.DB(); err == nil {
|
||||
if err := sqlDB.Close(); err != nil {
|
||||
d.logger.Error("Failed to close database", zap.Error(err))
|
||||
return err
|
||||
}
|
||||
}
|
||||
d.db = nil
|
||||
}
|
||||
|
||||
// 清空缓存
|
||||
d.dbs = make(map[string]*gorm.DB)
|
||||
|
||||
d.logger.Info("Database connection closed")
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetDBPath 获取数据库文件路径
|
||||
func (d *SQLiteDatabase) GetDBPath() string {
|
||||
return d.dbPath
|
||||
}
|
||||
Reference in New Issue
Block a user