Initial commit

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 13:57:10 +08:00
co-authored by Claude Opus 5
commit 8679200f41
1897 changed files with 257900 additions and 0 deletions
+312
View File
@@ -0,0 +1,312 @@
package sourcemod
import (
"encoding/json"
"fmt"
"time"
"91porn-server/app/appg"
"91porn-server/common"
"91porn-server/common/cachev2"
"91porn-server/common/constant/redisconst"
"91porn-server/common/db"
"91porn-server/common/log"
"91porn-server/models"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
var mdb *db.MongoDB
const table = models.Source
const (
pingListCacheKey = "source:ping-list:v1"
pingListCacheTTL = time.Minute
)
type pingListCache struct {
Domains []string `json:"domains"`
Sources []*SourceRes `json:"sources"`
}
func coll(t *db.MongoTool) *db.MongoTool {
if t == nil {
return mdb.Coll(table)
}
return t.Coll(table)
}
// initIndex 索引设置
func initIndex() {
many := []mongo.IndexModel{
{
Keys: bson.D{{Key: "type", Value: 1}},
Options: options.Index().SetUnique(true).SetSparse(true),
},
{
Keys: bson.D{{Key: "domain", Value: 1}},
},
{
Keys: bson.D{{Key: "isActive", Value: 1}},
},
{
Keys: bson.D{{Key: "createdAt", Value: -1}},
},
}
if _, err := coll(nil).CreateIndex(many); err != nil {
panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err))
}
}
// PingList 返回
func PingList() (rd []string, rs []*SourceRes) {
// 域名配置体积较大且更新频率低,通过共享缓存避免每次启动请求都读取 MongoDB。
result := pingListCache{}
_, err := cachev2.Classes().
CacheTime(pingListCacheTTL).
Key(pingListCacheKey).
ResBind(&result).
Cache(loadPingList)
if err != nil {
log.Error("PingList cache error", log.E(err))
result = loadPingList()
}
return result.Domains, result.Sources
}
func loadPingList() pingListCache {
return buildPingList(List())
}
func buildPingList(data []*SourceRes) pingListCache {
if len(data) == 0 {
return pingListCache{}
}
dataLen := len(data)
d := make([]string, 0, dataLen)
s := make([]*SourceRes, 0, dataLen)
for _, v := range data {
switch v.Type {
case Ping:
for _, v := range v.Domain {
d = append(d, v.Url)
}
case Image, Audio, Common, Group, Telegram, Guide, PROXYRULE, FAQ, QRCODE, WELFARE, ACT, PromoteURL, AppStore, BusinessCooperation, ShareURL, PreSaleBgImg:
s = append(s, v)
case Vid:
s = append(s, v)
}
}
d = d[:len(d):len(d)]
s = s[:len(s):len(s)]
return pingListCache{Domains: d, Sources: s}
}
func clearPingListCache() {
if _, err := cachev2.Classes().Delete(pingListCacheKey); err != nil {
log.Error("clear PingList cache error", log.E(err))
}
}
// GetCdnURL GetCdnURL
func GetCdnURL() (rd []Domain) {
data := List()
if len(data) == 0 {
return
}
var d []Domain
for _, v := range data {
switch v.Type {
case Common, Vid:
d = append(d, v.Domain...)
}
}
rd = d
return
}
// List 返回
func List() (array []*SourceRes) {
if err := coll(nil).Find(&array, bson.M{"isActive": true}); err != nil {
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "List", table, "Find", err))
}
return
}
// List 返回
func WebList() (array []*SourceRes) {
if err := coll(nil).Find(&array, bson.M{}); err != nil {
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "WebList", table, "Find", err))
}
return
}
// GetCustomerStat 获取客服状态
func GetCustomerStat() bool {
var s *SourceRes
if err := coll(nil).FindOne(&s, bson.M{"type": Customer}); err != nil {
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetCustomerStat", table, "FindOne", err))
return true
}
if s == nil {
return true
}
return s.IsActive
}
// 随机获取推广页域名
func GetRandomPromotionURL() string {
if cnt, err := appg.Redis.SCard(redisconst.LandDomainCacheKey); cnt == 0 || err != nil {
purls := GetPromoteURLArray()
if len(purls) > 0 {
_, _ = appg.Redis.SAdd(redisconst.LandDomainCacheKey, purls)
}
}
purl, err := appg.Redis.SRandMember(redisconst.LandDomainCacheKey)
if err != nil {
return getPromoteURL()
}
return purl
}
// 获取推广url数组
func GetPromoteURLArray() []string {
data := GetPromoteURLList()
purls := make([]string, 0)
if data != nil {
purls = make([]string, 0, len(data.Domain))
for _, v := range data.Domain {
purls = append(purls, v.Url)
}
}
return purls
}
// GetPromoteURLList 返回
func GetPromoteURLList() (data *SourceWebRes) {
if err := coll(nil).FindOne(&data, bson.M{"type": PromoteURL, "isActive": true}); err != nil {
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetPromoteURLList", table, "FindOne", err))
}
return
}
// getPromoteURL 返回
func getPromoteURL() string {
var s *SourceRes
if err := coll(nil).FindOne(&s, bson.M{"type": PromoteURL, "isActive": true}); err != nil {
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "getPromoteURL", table, "FindOne", err))
}
if s != nil {
return s.Domain[0].Url
}
return ""
}
// Insert SourceInsert
func Insert(s *Source) error {
s.UpdatedAt = time.Now()
s.CreatedAt = time.Now()
if _, err := coll(nil).InsertOne(&s); err != nil {
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "Insert", table, "InsertOne", err))
return err
}
clearPingListCache()
return nil
}
// Update 修改
func Update(id primitive.ObjectID, sType SourceType, set *SourceEdit) error {
set.UpdatedAt = time.Now()
if _, err := coll(nil).UpdateOne(bson.M{"_id": id, "type": sType}, bson.M{"$set": set}); err != nil {
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "Update", table, "UpdateOne", err),
log.Any("id", id),
log.Any("sType", sType),
log.Any("set", set),
)
return err
}
clearPingListCache()
return nil
}
// EditDomain 修改
func EditDomain(id primitive.ObjectID, edit *SourceEdit) error {
edit.UpdatedAt = time.Now()
update, _ := common.ToBsonM(edit)
if _, err := coll(nil).UpdateOne(bson.M{"_id": id}, bson.M{"$set": update}); err != nil {
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "EditDomain", table, "UpdateOne", err),
log.Any("id", id),
log.Any("edit", *edit),
)
return err
}
clearPingListCache()
return nil
}
// Remove SourceRemove
func Remove(ids []primitive.ObjectID) error {
if _, err := coll(nil).DeleteMany(bson.M{"_id": bson.M{"$in": ids}}); err != nil {
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "Remove", table, "DeleteMany", err),
log.Any("ids", ids),
)
return err
}
clearPingListCache()
return nil
}
func GetWeightCdnURL() string {
var cho []common.Choice
data, err := appg.Redis.Get(redisconst.CdnCacheKey)
//不存在cdn缓存
if err != nil || data == nil {
var choice []common.Choice
cdn := GetCdnURL()
for _, v := range cdn {
if v.Weight == 0 {
continue
}
choice = append(choice, common.Choice{Weight: int(v.Weight), Item: v.Url})
}
cbyte, _ := json.Marshal(choice)
_ = appg.Redis.Set(redisconst.CdnCacheKey, cbyte, redisconst.CdnCacheExpire)
c, err := common.WeightedChoice(choice)
if err != nil {
if len(cdn) > 0 {
return cdn[0].Url
}
}
return c.Item.(string)
}
_ = json.Unmarshal([]byte(*data), &cho)
c, _ := common.WeightedChoice(cho)
return c.Item.(string)
}
func GetVideoAndImgCdn() (videoCdn []string, imgCdn []string) {
data := List()
if len(data) == 0 {
return
}
dataLen := len(data)
videoCdn = make([]string, 0, dataLen)
imgCdn = make([]string, 0, dataLen)
for _, v := range data {
if v.Type == Vid {
for _, d := range v.Domain {
videoCdn = append(videoCdn, d.Url)
}
}
if v.Type == Image {
for _, d := range v.Domain {
imgCdn = append(imgCdn, d.Url)
}
}
}
return
}