feat: add telegram bot (#71)

This commit is contained in:
Buer
2024-02-23 18:24:25 +08:00
committed by GitHub
parent 43b4ee37d9
commit e90f4c99fc
33 changed files with 1726 additions and 29 deletions

View File

@@ -40,7 +40,7 @@ var allowedChannelOrderFields = map[string]bool{
"priority": true,
}
func GetChannelsList(params *GenericParams) (*DataResult, error) {
func GetChannelsList(params *GenericParams) (*DataResult[Channel], error) {
var channels []*Channel
db := DB.Omit("key")
@@ -52,7 +52,7 @@ func GetChannelsList(params *GenericParams) (*DataResult, error) {
db = db.Where("id = ? or name LIKE ? or "+keyCol+" = ?", common.String2Int(params.Keyword), params.Keyword+"%", params.Keyword)
}
return PaginateAndOrder(db, &params.PaginationParams, &channels, allowedChannelOrderFields)
return PaginateAndOrder[Channel](db, &params.PaginationParams, &channels, allowedChannelOrderFields)
}
func GetAllChannels() ([]*Channel, error) {

View File

@@ -8,6 +8,10 @@ import (
"gorm.io/gorm"
)
type modelable interface {
any
}
type GenericParams struct {
PaginationParams
Keyword string `form:"keyword"`
@@ -19,14 +23,14 @@ type PaginationParams struct {
Order string `form:"order"`
}
type DataResult struct {
Data interface{} `json:"data"`
Page int `json:"page"`
Size int `json:"size"`
TotalCount int64 `json:"total_count"`
type DataResult[T modelable] struct {
Data *[]*T `json:"data"`
Page int `json:"page"`
Size int `json:"size"`
TotalCount int64 `json:"total_count"`
}
func PaginateAndOrder(db *gorm.DB, params *PaginationParams, result interface{}, allowedOrderFields map[string]bool) (*DataResult, error) {
func PaginateAndOrder[T modelable](db *gorm.DB, params *PaginationParams, result *[]*T, allowedOrderFields map[string]bool) (*DataResult[T], error) {
// 获取总数
var totalCount int64
err := db.Model(result).Count(&totalCount).Error
@@ -34,8 +38,6 @@ func PaginateAndOrder(db *gorm.DB, params *PaginationParams, result interface{},
return nil, err
}
fmt.Println("totalCount", totalCount)
// 分页
if params.Page < 1 {
params.Page = 1
@@ -80,7 +82,7 @@ func PaginateAndOrder(db *gorm.DB, params *PaginationParams, result interface{},
}
// 返回结果
return &DataResult{
return &DataResult[T]{
Data: result,
Page: params.Page,
Size: params.Size,

View File

@@ -94,7 +94,7 @@ var allowedLogsOrderFields = map[string]bool{
"type": true,
}
func GetLogsList(params *LogsListParams) (*DataResult, error) {
func GetLogsList(params *LogsListParams) (*DataResult[Log], error) {
var tx *gorm.DB
var logs []*Log
@@ -122,10 +122,10 @@ func GetLogsList(params *LogsListParams) (*DataResult, error) {
tx = tx.Where("channel_id = ?", params.Channel)
}
return PaginateAndOrder(tx, &params.PaginationParams, &logs, allowedLogsOrderFields)
return PaginateAndOrder[Log](tx, &params.PaginationParams, &logs, allowedLogsOrderFields)
}
func GetUserLogsList(userId int, params *LogsListParams) (*DataResult, error) {
func GetUserLogsList(userId int, params *LogsListParams) (*DataResult[Log], error) {
var logs []*Log
tx := DB.Where("user_id = ?", userId).Omit("id")
@@ -146,7 +146,7 @@ func GetUserLogsList(userId int, params *LogsListParams) (*DataResult, error) {
tx = tx.Where("created_at <= ?", params.EndTimestamp)
}
return PaginateAndOrder(tx, &params.PaginationParams, &logs, allowedLogsOrderFields)
return PaginateAndOrder[Log](tx, &params.PaginationParams, &logs, allowedLogsOrderFields)
}
func SearchAllLogs(keyword string) (logs []*Log, err error) {

View File

@@ -2,14 +2,15 @@ package model
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/driver/postgres"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"one-api/common"
"os"
"strings"
"time"
"gorm.io/driver/mysql"
"gorm.io/driver/postgres"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
var DB *gorm.DB
@@ -113,6 +114,10 @@ func InitDB() (err error) {
if err != nil {
return err
}
err = db.AutoMigrate(&TelegramMenu{})
if err != nil {
return err
}
common.SysLog("database migrated")
err = createRootAccountIfNeed()
return err

View File

@@ -29,14 +29,14 @@ var allowedRedemptionslOrderFields = map[string]bool{
"redeemed_time": true,
}
func GetRedemptionsList(params *GenericParams) (*DataResult, error) {
func GetRedemptionsList(params *GenericParams) (*DataResult[Redemption], error) {
var redemptions []*Redemption
db := DB
if params.Keyword != "" {
db = db.Where("id = ? or name LIKE ?", common.String2Int(params.Keyword), params.Keyword+"%")
}
return PaginateAndOrder(db, &params.PaginationParams, &redemptions, allowedRedemptionslOrderFields)
return PaginateAndOrder[Redemption](db, &params.PaginationParams, &redemptions, allowedRedemptionslOrderFields)
}
func GetRedemptionById(id int) (*Redemption, error) {

73
model/telegram_menu.go Normal file
View File

@@ -0,0 +1,73 @@
package model
import (
"errors"
"one-api/common"
)
type TelegramMenu struct {
Id int `json:"id"`
Command string `json:"command" gorm:"type:varchar(32);uniqueIndex"`
Description string `json:"description" gorm:"type:varchar(255);default:''"`
ParseMode string `json:"parse_mode" gorm:"type:varchar(255);default:'MarkdownV2'"`
ReplyMessage string `json:"reply_message"`
}
var allowedTelegramMenusOrderFields = map[string]bool{
"id": true,
"command": true,
}
func GetTelegramMenusList(params *GenericParams) (*DataResult[TelegramMenu], error) {
var menus []*TelegramMenu
db := DB
if params.Keyword != "" {
db = db.Where("id = ? or command LIKE ?", common.String2Int(params.Keyword), params.Keyword+"%")
}
return PaginateAndOrder[TelegramMenu](db, &params.PaginationParams, &menus, allowedTelegramMenusOrderFields)
}
// 查询菜单列表 只查询command和description
func GetTelegramMenus() ([]*TelegramMenu, error) {
var menus []*TelegramMenu
err := DB.Select("command, description").Find(&menus).Error
return menus, err
}
// 根据command查询菜单
func GetTelegramMenuByCommand(command string) (*TelegramMenu, error) {
menu := &TelegramMenu{}
err := DB.Where("command = ?", command).First(menu).Error
return menu, err
}
func GetTelegramMenuById(id int) (*TelegramMenu, error) {
if id == 0 {
return nil, errors.New("id 为空!")
}
telegramMenu := TelegramMenu{Id: id}
var err error = nil
err = DB.First(&telegramMenu, "id = ?", id).Error
return &telegramMenu, err
}
func IsTelegramCommandAlreadyTaken(command string, id int) bool {
query := DB.Where("command = ?", command)
if id != 0 {
query = query.Not("id", id)
}
return query.Find(&TelegramMenu{}).RowsAffected == 1
}
func (menu *TelegramMenu) Insert() error {
return DB.Create(menu).Error
}
func (menu *TelegramMenu) Update() error {
return DB.Model(menu).Updates(menu).Error
}
func (menu *TelegramMenu) Delete() error {
return DB.Delete(menu).Error
}

View File

@@ -32,7 +32,7 @@ var allowedTokenOrderFields = map[string]bool{
"used_quota": true,
}
func GetUserTokensList(userId int, params *GenericParams) (*DataResult, error) {
func GetUserTokensList(userId int, params *GenericParams) (*DataResult[Token], error) {
var tokens []*Token
db := DB.Where("user_id = ?", userId)
@@ -40,7 +40,13 @@ func GetUserTokensList(userId int, params *GenericParams) (*DataResult, error) {
db = db.Where("name LIKE ?", params.Keyword+"%")
}
return PaginateAndOrder(db, &params.PaginationParams, &tokens, allowedTokenOrderFields)
return PaginateAndOrder[Token](db, &params.PaginationParams, &tokens, allowedTokenOrderFields)
}
// 获取状态为可用的令牌
func GetUserEnabledTokens(userId int) (tokens []*Token, err error) {
err = DB.Where("user_id = ? and status = ?", userId, common.TokenStatusEnabled).Find(&tokens).Error
return tokens, err
}
func ValidateUserToken(key string) (token *Token, err error) {

View File

@@ -21,6 +21,7 @@ type User struct {
Email string `json:"email" gorm:"index" validate:"max=50"`
GitHubId string `json:"github_id" gorm:"column:github_id;index"`
WeChatId string `json:"wechat_id" gorm:"column:wechat_id;index"`
TelegramId int64 `json:"telegram_id" gorm:"bigint,column:telegram_id;default:0;"`
VerificationCode string `json:"verification_code" gorm:"-:all"` // this field is only for Email verification, don't save it to database!
AccessToken string `json:"access_token" gorm:"type:char(32);column:access_token;uniqueIndex"` // this token is for system management
Quota int `json:"quota" gorm:"type:int;default:0"`
@@ -32,6 +33,8 @@ type User struct {
CreatedTime int64 `json:"created_time" gorm:"bigint"`
}
type UserUpdates func(*User)
func GetMaxUserId() int {
var user User
DB.Last(&user)
@@ -46,14 +49,14 @@ var allowedUserOrderFields = map[string]bool{
"created_time": true,
}
func GetUsersList(params *GenericParams) (*DataResult, error) {
func GetUsersList(params *GenericParams) (*DataResult[User], error) {
var users []*User
db := DB.Omit("password")
if params.Keyword != "" {
db = db.Where("id = ? or username LIKE ? or email LIKE ? or display_name LIKE ?", common.String2Int(params.Keyword), params.Keyword+"%", params.Keyword+"%", params.Keyword+"%")
}
return PaginateAndOrder(db, &params.PaginationParams, &users, allowedUserOrderFields)
return PaginateAndOrder[User](db, &params.PaginationParams, &users, allowedUserOrderFields)
}
func GetUserById(id int, selectAll bool) (*User, error) {
@@ -70,6 +73,17 @@ func GetUserById(id int, selectAll bool) (*User, error) {
return &user, err
}
func GetUserByTelegramId(telegramId int64) (*User, error) {
if telegramId == 0 {
return nil, errors.New("telegramId 为空!")
}
var user User
err := DB.First(&user, "telegram_id = ?", telegramId).Error
return &user, err
}
func GetUserIdByAffCode(affCode string) (int, error) {
if affCode == "" {
return 0, errors.New("affCode 为空!")
@@ -131,6 +145,10 @@ func (user *User) Update(updatePassword bool) error {
return err
}
func UpdateUser(id int, fields map[string]interface{}) error {
return DB.Model(&User{}).Where("id = ?", id).Updates(fields).Error
}
func (user *User) Delete() error {
if user.Id == 0 {
return errors.New("id 为空!")
@@ -216,6 +234,10 @@ func IsGitHubIdAlreadyTaken(githubId string) bool {
return DB.Where("github_id = ?", githubId).Find(&User{}).RowsAffected == 1
}
func IsTelegramIdAlreadyTaken(telegramId int64) bool {
return DB.Where("telegram_id = ?", telegramId).Find(&User{}).RowsAffected == 1
}
func IsUsernameAlreadyTaken(username string) bool {
return DB.Where("username = ?", username).Find(&User{}).RowsAffected == 1
}