@@ -0,0 +1,102 @@
|
||||
package taskser
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"91porn-server/models/v/dailytaskmod"
|
||||
"91porn-server/models/v/oncetaskmod"
|
||||
"91porn-server/models/v/prizemod"
|
||||
"91porn-server/models/v/taskmod"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
type TaskStatus int
|
||||
|
||||
const (
|
||||
UnDone TaskStatus = iota + 1 // 未完成
|
||||
Finish // 已完成
|
||||
Receive // 已领取
|
||||
ReDo // 重做
|
||||
)
|
||||
|
||||
// 签到信息返回
|
||||
type SignDetailsResponse struct {
|
||||
List []Config `json:"list"` // 列表
|
||||
Value int64 `json:"value"` // 累计签到天数
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
ID primitive.ObjectID `json:"id"` // 文档ID
|
||||
Title string `json:"title"` // 任务标题
|
||||
Desc string `json:"desc"` // 任务描述
|
||||
Prizes []prizemod.Prize `json:"prizes"` // 奖品列表
|
||||
FinishCondition int64 `json:"finishCondition"` // 达成条件
|
||||
FinishValue int64 `json:"finishValue"` // 完成数量
|
||||
Status TaskStatus `json:"status"` // 任务状态 1:未完成 2:已完成 3:已领取
|
||||
BoonType taskmod.ConfigType `json:"boonType"` // 福利类型
|
||||
IsToday bool `json:"isToday"` // 是否是今日任务
|
||||
}
|
||||
|
||||
type TaskResponse struct {
|
||||
JewelBoxDetails struct {
|
||||
List []Config `json:"list"` // 列表
|
||||
Value int64 `json:"value"` // 累计活跃值
|
||||
TotalValue int64 `json:"totalValue"` // 总活跃值
|
||||
} `json:"jewelBoxDetails"` // 宝箱详情
|
||||
TaskList []Config `json:"taskList"` // 任务列表
|
||||
}
|
||||
|
||||
type TaskDetailsResponse struct {
|
||||
TaskList []Config `json:"taskList"` // 任务列表
|
||||
Value int64 `json:"value"` // 累计金币/充值金额
|
||||
}
|
||||
|
||||
type DailyTaskResponse struct {
|
||||
ID primitive.ObjectID `json:"id"` // 任务id
|
||||
Title string `json:"title"` // 任务标题
|
||||
Img string `json:"img"` // 任务图标
|
||||
Type dailytaskmod.DailyTaskTypeEnum `json:"type"` // 0 每日广告点击; 1 每日邀请
|
||||
Desc string `json:"desc"` // 任务说明
|
||||
Link string `json:"link"` // 跳转地址
|
||||
Status int `json:"status"` // 0 未完成; 1 已完成未领取; 2 已领取
|
||||
StartAt time.Time `json:"startAt"` // 场次开始时间;CountdownType=1 时为红包雨场次时间,否则零值
|
||||
EndAt time.Time `json:"endAt"` // 场次结束时间;CountdownType=1 时为红包雨场次时间,否则零值
|
||||
CountdownType int `json:"countdownType"` // 倒计时类型 0-无 1-红包雨倒计时
|
||||
}
|
||||
|
||||
type DailyTaskResponseDetail struct {
|
||||
Prizes []*prizemod.Prize `json:"prizes"` // 奖品列表, 与签到相同
|
||||
FinishCondition uint64 `json:"finishCondition"` // 达成条件. 比如点击广告任务中, 表示3次点击才可以领取奖励
|
||||
FinishCount uint64 `json:"finishCount"` // 已完成数量. 比如比如点击广告任务中 2表示已经点击2次广告
|
||||
Status int `json:"status"` // 0 未完成; 1 已完成未领取; 2 已领取
|
||||
}
|
||||
|
||||
type OnceTaskResponse struct {
|
||||
ID primitive.ObjectID `json:"id"` // 任务id
|
||||
Title string `json:"title"` // 任务标题
|
||||
Img string `json:"img"` // 任务图标
|
||||
Type oncetaskmod.OnceTaskTypeEnum `json:"type"` // 0 每日广告点击; 1 每日邀请
|
||||
Prizes []*prizemod.Prize `json:"prizes"` // 奖品列表, 与签到相同
|
||||
Desc string `json:"desc"` // 任务说明
|
||||
Link string `json:"link"` // 跳转地址
|
||||
Status int `json:"status"` // 0 未完成; 1 已完成未领取; 2 已领取
|
||||
StartAt time.Time `json:"startAt"` // 场次开始时间;CountdownType=1 时为红包雨场次时间,否则零值
|
||||
EndAt time.Time `json:"endAt"` // 场次结束时间;CountdownType=1 时为红包雨场次时间,否则零值
|
||||
CountdownType int `json:"countdownType"` // 倒计时类型 0-无 1-红包雨倒计时
|
||||
}
|
||||
|
||||
type NewTaskResponse struct {
|
||||
DailyTasks []DailyTaskResponse `json:"dailyTask"`
|
||||
OnceTasks []OnceTaskResponse `json:"onceTask"`
|
||||
GrowthTasks []*GrowthTaskResponse `json:"growthTasks"`
|
||||
}
|
||||
|
||||
type GrowthTaskResponse struct {
|
||||
ID primitive.ObjectID `json:"id"` // 任务id
|
||||
Title string `json:"title"` // 任务标题
|
||||
Img string `json:"img"` // 任务图标
|
||||
Type int `json:"type" bson:"type"` // 配置类型 1-购买金币
|
||||
SubTitle string `json:"subTitle"` // 子标题
|
||||
Status int `json:"status"` // 0 未完成; 1 已完成未领取; 2 已领取
|
||||
}
|
||||
@@ -0,0 +1,433 @@
|
||||
package taskser
|
||||
|
||||
import (
|
||||
"91porn-server/app/appg"
|
||||
"91porn-server/common/db"
|
||||
"91porn-server/common/log"
|
||||
"91porn-server/common/stderr"
|
||||
"91porn-server/common/timeutil"
|
||||
"91porn-server/models/v/prizemod"
|
||||
"91porn-server/models/v/signtaskmod"
|
||||
"91porn-server/models/v/taskrecordmod"
|
||||
"91porn-server/models/v/txnmod"
|
||||
"91porn-server/models/v/usermod"
|
||||
"encoding/json"
|
||||
"sort"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
// 签到
|
||||
func Sign(uid uint64, configID string) (code stderr.Code) {
|
||||
now := time.Now()
|
||||
id, err := primitive.ObjectIDFromHex(configID)
|
||||
if err != nil {
|
||||
return stderr.ErrParamError
|
||||
}
|
||||
// 获取用户信息
|
||||
u, err := usermod.FindUserByUID(uid)
|
||||
if err != nil || u == nil {
|
||||
code = stderr.UserIsNotExists
|
||||
return
|
||||
}
|
||||
// 获取配置列表
|
||||
signConfig, err := signtaskmod.GetConfigList()
|
||||
if err != nil {
|
||||
return stderr.ErrDbQueryError
|
||||
}
|
||||
// 查询当前签到配置
|
||||
configInfo, err := signtaskmod.GetConfigByID(id)
|
||||
if err != nil {
|
||||
return stderr.ErrDbQueryError
|
||||
}
|
||||
// 异常判定 未配置签到福利/签到福利类型不正确
|
||||
if configInfo == nil || signConfig == nil || len(signConfig) == 0 {
|
||||
log.Info("未配置签到福利")
|
||||
return stderr.ErrInvalidRequest
|
||||
}
|
||||
// 查询签到信息
|
||||
signRecordMap := make(map[string]bool, 0)
|
||||
taskInfo, err := taskrecordmod.GetSignRecord(uid)
|
||||
if err != nil {
|
||||
return stderr.ErrDbQueryError
|
||||
}
|
||||
if taskInfo == nil {
|
||||
log.Info("未查询到签到任务")
|
||||
return stderr.ErrDbQueryError
|
||||
}
|
||||
for _, taskId := range taskInfo.SignRecord {
|
||||
signRecordMap[taskId.Hex()] = true
|
||||
}
|
||||
// 判断是否重复签到
|
||||
if _, ok := signRecordMap[configID]; ok {
|
||||
log.Info("已签到")
|
||||
return stderr.HasSigned
|
||||
}
|
||||
// 计算相差多少天
|
||||
duration := timeutil.BeginningOfDay(now).Sub(taskInfo.SignTime)
|
||||
diffDays := int64(duration.Hours() / 24)
|
||||
// 判断此签到是否是当天签到
|
||||
if configInfo.FinishCondition-1 != diffDays {
|
||||
log.Info("条件不匹配")
|
||||
return stderr.ErrInvalidRequest
|
||||
}
|
||||
// 获取奖品列表
|
||||
prizes, err := prizemod.GetPrizeListByIDs(configInfo.Prizes)
|
||||
if err != nil {
|
||||
return stderr.ErrDbQueryError
|
||||
}
|
||||
// 获取额外奖品列表
|
||||
signCount := len(signRecordMap)
|
||||
for _, item := range signConfig {
|
||||
if item.FinishCondition == int64(signCount)+1 {
|
||||
extraPrizeIds, e := prizemod.GetPrizeListByIDs(item.ExtraPrizes)
|
||||
if e != nil {
|
||||
continue
|
||||
}
|
||||
prizes = append(prizes, extraPrizeIds...)
|
||||
}
|
||||
}
|
||||
// 更新签到记录(事务)
|
||||
if err = appg.VideoDB.Trans(func(t *db.MongoTool) error {
|
||||
if err = taskrecordmod.TaskSignUpdate(t, uid, id); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return stderr.ErrDbTransError
|
||||
}
|
||||
// 发放奖励
|
||||
for _, v := range prizes {
|
||||
for i := 0; i < int(v.Count); i++ {
|
||||
handler, err := prizemod.Run(uid, *v, txnmod.SignBoon)
|
||||
if err != nil {
|
||||
log.Error("签到发放奖励handler失败:", log.Any("err", err))
|
||||
continue
|
||||
}
|
||||
err = appg.VideoDB.Trans(func(t *db.MongoTool) error {
|
||||
err = handler.Run(t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = txnmod.InsertManyTransactionLog(t, handler.GetTransactionLog())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Error("签到发放奖励事务失败:", log.Any("err", err))
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
return stderr.Success
|
||||
}
|
||||
|
||||
// 补签
|
||||
func ReSign(uid uint64, configID string) (code stderr.Code) {
|
||||
now := time.Now()
|
||||
redisKey := "task::resign::" + strconv.FormatUint(uid, 10)
|
||||
if appg.Redis.Exists(redisKey) {
|
||||
return stderr.ExceededTimes
|
||||
}
|
||||
id, err := primitive.ObjectIDFromHex(configID)
|
||||
if err != nil {
|
||||
return stderr.ErrParamError
|
||||
}
|
||||
// 获取用户信息
|
||||
u, err := usermod.FindUserByUID(uid)
|
||||
if err != nil || u == nil {
|
||||
code = stderr.UserIsNotExists
|
||||
return
|
||||
}
|
||||
// 获取配置列表
|
||||
signConfig, err := signtaskmod.GetConfigList()
|
||||
if err != nil {
|
||||
return stderr.ErrDbQueryError
|
||||
}
|
||||
// 查询当前签到配置
|
||||
configInfo, err := signtaskmod.GetConfigByID(id)
|
||||
if err != nil {
|
||||
return stderr.ErrDbQueryError
|
||||
}
|
||||
// 异常判定 未配置签到福利/签到福利类型不正确
|
||||
if configInfo == nil || signConfig == nil || len(signConfig) == 0 {
|
||||
log.Info("未配置签到福利")
|
||||
return stderr.ErrInvalidRequest
|
||||
}
|
||||
//查询签到信息
|
||||
signRecordMap := make(map[string]bool, 0)
|
||||
taskInfo, err := taskrecordmod.GetSignRecord(uid)
|
||||
if err != nil {
|
||||
return stderr.ErrDbQueryError
|
||||
}
|
||||
if taskInfo == nil {
|
||||
log.Info("未查询到签到任务")
|
||||
return stderr.ErrDbQueryError
|
||||
}
|
||||
for _, taskId := range taskInfo.SignRecord {
|
||||
signRecordMap[taskId.Hex()] = true
|
||||
}
|
||||
// 判断是否重复签到
|
||||
if _, ok := signRecordMap[configID]; ok {
|
||||
log.Info("已签到")
|
||||
return stderr.HasSigned
|
||||
}
|
||||
// 计算相差多少天
|
||||
duration := timeutil.BeginningOfDay(now).Sub(taskInfo.SignTime)
|
||||
diffDays := int64(duration.Hours() / 24)
|
||||
// 判断是否在补签范围
|
||||
if configInfo.FinishCondition > diffDays {
|
||||
log.Info("条件不匹配")
|
||||
return stderr.ErrInvalidRequest
|
||||
}
|
||||
|
||||
// redis作为倒计时(一天只能补签一次)
|
||||
seconds := int64(timeutil.BeginningOfTomorrow(now).Sub(now).Seconds())
|
||||
err = appg.Redis.Set(redisKey, configID, time.Duration(seconds)*time.Second)
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
}
|
||||
return stderr.Success
|
||||
}
|
||||
|
||||
// 补签回调
|
||||
func ReSignCallBack(uid uint64) (code stderr.Code) {
|
||||
now := time.Now()
|
||||
redisKey := "task::resign::" + strconv.FormatUint(uid, 10)
|
||||
if !appg.Redis.Exists(redisKey) {
|
||||
return stderr.ErrParamError
|
||||
}
|
||||
configID, err := appg.Redis.Get(redisKey)
|
||||
if err != nil {
|
||||
log.Error("redis缓存不存在!")
|
||||
return stderr.ErrParamError
|
||||
}
|
||||
if configID == nil {
|
||||
log.Error("签到配置不存在!")
|
||||
return stderr.ErrParamError
|
||||
}
|
||||
|
||||
id, err := primitive.ObjectIDFromHex(*configID)
|
||||
if err != nil {
|
||||
return stderr.ErrParamError
|
||||
}
|
||||
// 获取用户信息
|
||||
u, err := usermod.FindUserByUID(uid)
|
||||
if err != nil || u == nil {
|
||||
code = stderr.UserIsNotExists
|
||||
return
|
||||
}
|
||||
// 获取配置列表
|
||||
signConfig, err := signtaskmod.GetConfigList()
|
||||
if err != nil {
|
||||
return stderr.ErrDbQueryError
|
||||
}
|
||||
// 查询当前签到配置
|
||||
configInfo, err := signtaskmod.GetConfigByID(id)
|
||||
if err != nil {
|
||||
return stderr.ErrDbQueryError
|
||||
}
|
||||
// 异常判定 未配置签到福利/签到福利类型不正确
|
||||
if configInfo == nil || signConfig == nil || len(signConfig) == 0 {
|
||||
log.Info("未配置签到福利")
|
||||
return stderr.ErrInvalidRequest
|
||||
}
|
||||
//查询签到信息
|
||||
signRecordMap := make(map[string]bool, 0)
|
||||
taskInfo, err := taskrecordmod.GetSignRecord(uid)
|
||||
if err != nil {
|
||||
return stderr.ErrDbQueryError
|
||||
}
|
||||
if taskInfo == nil {
|
||||
log.Info("未查询到签到任务")
|
||||
return stderr.ErrDbQueryError
|
||||
}
|
||||
for _, taskId := range taskInfo.SignRecord {
|
||||
signRecordMap[taskId.Hex()] = true
|
||||
}
|
||||
// 判断是否重复签到
|
||||
if _, ok := signRecordMap[*configID]; ok {
|
||||
log.Info("已签到")
|
||||
return stderr.HasSigned
|
||||
}
|
||||
// 计算相差多少天
|
||||
duration := timeutil.BeginningOfDay(now).Sub(taskInfo.SignTime)
|
||||
diffDays := int64(duration.Hours() / 24)
|
||||
// 判断是否在补签范围
|
||||
if configInfo.FinishCondition > diffDays {
|
||||
log.Info("条件不匹配")
|
||||
return stderr.ErrInvalidRequest
|
||||
}
|
||||
// 获取奖品列表
|
||||
prizes, err := prizemod.GetPrizeListByIDs(configInfo.Prizes)
|
||||
if err != nil {
|
||||
return stderr.ErrDbQueryError
|
||||
}
|
||||
// 获取额外奖品列表
|
||||
signCount := len(signRecordMap)
|
||||
for _, item := range signConfig {
|
||||
if item.FinishCondition == int64(signCount) {
|
||||
extraPrizeIds, e := prizemod.GetPrizeListByIDs(item.ExtraPrizes)
|
||||
if e != nil {
|
||||
continue
|
||||
}
|
||||
prizes = append(prizes, extraPrizeIds...)
|
||||
}
|
||||
}
|
||||
// 更新签到记录(事务)
|
||||
if err = appg.VideoDB.Trans(func(t *db.MongoTool) error {
|
||||
if err = taskrecordmod.TaskSignUpdate(t, uid, id); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return stderr.ErrDbTransError
|
||||
}
|
||||
// 发放奖励
|
||||
for _, v := range prizes {
|
||||
for i := 0; i < int(v.Count); i++ {
|
||||
handler, err := prizemod.Run(uid, *v, txnmod.SignBoon)
|
||||
if err != nil {
|
||||
log.Error("签到发放奖励handler失败:", log.Any("err", err))
|
||||
continue
|
||||
}
|
||||
err = appg.VideoDB.Trans(func(t *db.MongoTool) error {
|
||||
err = handler.Run(t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = txnmod.InsertManyTransactionLog(t, handler.GetTransactionLog())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Error("签到发放奖励事务失败:", log.Any("err", err))
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
return stderr.Success
|
||||
}
|
||||
|
||||
// 获取签到额外奖励
|
||||
func SignExtraPrizes(uid uint64) (out []map[string]interface{}, code stderr.Code) {
|
||||
out = make([]map[string]interface{}, 0)
|
||||
taskInfo, err := taskrecordmod.GetSignRecord(uid)
|
||||
if err != nil {
|
||||
return out, stderr.ErrDbQueryError
|
||||
}
|
||||
signRecords := make([]primitive.ObjectID, 0)
|
||||
if taskInfo != nil {
|
||||
signRecords = taskInfo.SignRecord
|
||||
}
|
||||
signConfig, err := signtaskmod.GetConfigList()
|
||||
if err != nil {
|
||||
return out, stderr.ErrDbQueryError
|
||||
}
|
||||
// 获取奖品列表
|
||||
prizes, err := prizemod.GetPrizeList()
|
||||
for _, item := range signConfig {
|
||||
if len(item.ExtraPrizes) == 0 {
|
||||
continue
|
||||
}
|
||||
extraPrizes := getPrizeList(item.ExtraPrizes, prizes)
|
||||
for _, prize := range extraPrizes {
|
||||
b, _ := json.Marshal(&prize)
|
||||
var extraPrizeMap map[string]interface{}
|
||||
_ = json.Unmarshal(b, &extraPrizeMap)
|
||||
days := item.FinishCondition - int64(len(signRecords))
|
||||
if days < 0 {
|
||||
days = 0
|
||||
}
|
||||
extraPrizeMap["finishCondition"] = days
|
||||
// 设置额外奖励领取状态
|
||||
if len(signRecords) >= int(item.FinishCondition) {
|
||||
extraPrizeMap["extraPrizeStatus"] = true
|
||||
} else {
|
||||
extraPrizeMap["extraPrizeStatus"] = false
|
||||
}
|
||||
out = append(out, extraPrizeMap)
|
||||
}
|
||||
}
|
||||
sort.Slice(out, func(i, j int) bool {
|
||||
valI := out[i]["extraPrizeStatus"].(bool)
|
||||
valJ := out[j]["extraPrizeStatus"].(bool)
|
||||
return !valI && valJ
|
||||
})
|
||||
return out, stderr.Success
|
||||
}
|
||||
|
||||
// 获取签到详情
|
||||
func GetSignDetails(uid uint64) (out SignDetailsResponse, code stderr.Code) {
|
||||
now := time.Now()
|
||||
// 获取配置列表
|
||||
signConfig, err := signtaskmod.GetConfigList()
|
||||
if err != nil {
|
||||
return out, stderr.ErrDbQueryError
|
||||
}
|
||||
// 查询用户签到信息
|
||||
signRecordMap := make(map[string]bool, 0)
|
||||
taskInfo, err := taskrecordmod.GetSignRecord(uid)
|
||||
if err != nil {
|
||||
return out, stderr.ErrDbQueryError
|
||||
}
|
||||
// 新增用户任务记录
|
||||
if taskInfo == nil {
|
||||
taskInfo, err = taskrecordmod.TaskSignInit(uid)
|
||||
if err != nil {
|
||||
return out, stderr.ErrDbQueryError
|
||||
}
|
||||
}
|
||||
// 计算相差多少天
|
||||
diffDays := int(timeutil.BeginningOfDay(now).Sub(taskInfo.SignTime).Hours() / 24)
|
||||
// 判断是否重置数据
|
||||
if diffDays >= len(signConfig) {
|
||||
taskInfo, err = taskrecordmod.TaskSignReset(uid)
|
||||
if err != nil {
|
||||
return out, stderr.ErrDbQueryError
|
||||
}
|
||||
}
|
||||
// 构建签到记录map
|
||||
for _, item := range taskInfo.SignRecord {
|
||||
signRecordMap[item.String()] = true
|
||||
}
|
||||
// 获取奖品列表
|
||||
prizes, err := prizemod.GetPrizeList()
|
||||
if err != nil {
|
||||
return out, stderr.ErrDbQueryError
|
||||
}
|
||||
out.Value = int64(len(taskInfo.SignRecord))
|
||||
out.List = make([]Config, len(signConfig))
|
||||
for i, v := range signConfig {
|
||||
taskConfig := Config{
|
||||
ID: v.ID,
|
||||
Prizes: getPrizeList(v.Prizes, prizes),
|
||||
FinishCondition: v.FinishCondition,
|
||||
Title: v.Title,
|
||||
Desc: v.Desc,
|
||||
Status: UnDone,
|
||||
}
|
||||
// 存在表示已经签到,不存在则需要判断是否是补签
|
||||
if _, ok := signRecordMap[v.ID.String()]; ok {
|
||||
// 如果存在,标记为已完成
|
||||
taskConfig.Status = Finish
|
||||
} else {
|
||||
diffDays = int(timeutil.BeginningOfDay(now).Sub(taskInfo.SignTime).Hours() / 24)
|
||||
if i < diffDays {
|
||||
taskConfig.Status = ReDo
|
||||
}
|
||||
}
|
||||
out.List[i] = taskConfig
|
||||
}
|
||||
// 当日任务标识
|
||||
if diffDays >= 0 && diffDays < len(out.List) {
|
||||
out.List[diffDays].IsToday = true
|
||||
}
|
||||
return out, stderr.Success
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,20 @@
|
||||
package taskser
|
||||
|
||||
import (
|
||||
"91porn-server/models/v/prizemod"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
// 获取奖品详情列表 通过奖品ID列表
|
||||
func getPrizeList(ids []primitive.ObjectID, mPrize map[primitive.ObjectID]prizemod.Prize) []prizemod.Prize {
|
||||
out := make([]prizemod.Prize, 0, len(ids))
|
||||
for _, v := range ids {
|
||||
item, ok := mPrize[v]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
out = append(out, item)
|
||||
}
|
||||
return out
|
||||
}
|
||||
Reference in New Issue
Block a user