更新代码

This commit is contained in:
hahwu 2024-11-27 14:25:52 +08:00
parent 7655b2c96f
commit 0ab62a2a65
51 changed files with 6382 additions and 3565 deletions

View File

@ -53,7 +53,7 @@ func GetReward(Reward, Score int) (int, []*item.Item) {
continue
}
if Score >= gamedata.GetIntValue(v, "Score") {
Items := item.ParseItem(gamedata.GetStringValue(v, "Items"))
Items := item.ParseItem(gamedata.GetValue(v, "Items"))
r = item.Merge(r, Items)
Reward = max(Reward, Id)
}

View File

@ -0,0 +1,23 @@
package inviteCfg
import (
"server/game/mod/item"
"server/gamedata"
)
const (
CFG_INVITE = "invite"
)
func init() {
gamedata.InitCfg(CFG_INVITE)
}
func GetInviteReward(index int) (int, []*item.Item) {
data, err := gamedata.GetDataByIntKey(CFG_INVITE, index)
if err != nil {
return 0, nil
}
return gamedata.GetIntValue(data, "reward"), item.ParseItem(gamedata.GetStringValue(data, "reward_item"))
}

View File

@ -41,6 +41,8 @@ var Server struct {
CenterAddr string
RemoteAddr string
TELOGDIR string
}
func init() {

View File

@ -161,7 +161,7 @@ func GetProgressMax() int {
log.Debug("GetProgressMax err:%v", err)
return 0
}
return gamedata.GetIntValue(data, "value")
return gamedata.GetIntValue(data, "Value")
}
func GetProgressRewardRand(Lv int) map[int]int {
@ -186,8 +186,8 @@ func GetProgressSelectNum(Lv int) int {
log.Debug("GetProgressSelectNum err:%v", err)
return 0
}
Str := gamedata.GetStringValue(data, "value")
Strarr := strings.Split(Str, ";")
Str := gamedata.GetStringValue(data, "Value")
Strarr := strings.Split(Str, "|")
for _, v := range Strarr {
a := strings.Split(v, ",")
if len(a) != 3 {

View File

@ -12,6 +12,8 @@
"HttpPort": ":8081",
"RemoteAddr":"host.docker.internal:9001",
"TELOGDIR" : "./teLog/",
"GameName": "Merge_Pet",
"GameID": 1,
"ServerType":"node",

View File

@ -138,9 +138,6 @@ func (gl *GameLogic) OpenTimestampTick() {
gl.Mdispatr.AfterFunc(time.Second*time.Duration(GoUtil.NextNoonTimestampDuration()), func() {
gl.NoonFlush()
})
gl.Mdispatr.AfterFunc(time.Second*time.Duration(GoUtil.NextNoonTimestampDuration()), func() {
gl.NoonFlush()
})
gl.CreateDailyLogFile()
go func() {
@ -906,9 +903,7 @@ func (ad *GameLogic) RegisterNetWorkFunc() {
RegisterMsgProcessFunc("ReqAutoFBAddFriend", ReqAutoFBAddFriend)
RegisterMsgProcessFunc("ReqAutoAddInviteFriend", ReqAutoAddInviteFriend)
RegisterMsgProcessFunc("ReqRecommendFriendList", ReqRecommendFriendList)
RegisterMsgProcessFunc("ReqInviteFriendData", ReqInviteFriendData)
RegisterMsgProcessFunc("ReqSelfInvited", ReqSelfInvited)
RegisterMsgProcessFunc("ReqGetInviteReward", ReqGetInviteReward)
RegisterMsgProcessFunc("ReqFriendTreasureData", ReqFriendTreasureData)
RegisterMsgProcessFunc("ReqUpdateFriendStar", ReqUpdateFriendStar)
@ -938,7 +933,8 @@ func (ad *GameLogic) RegisterNetWorkFunc() {
// 玩家
RegisterMsgProcessFunc("ReqUserInfo", ReqUserInfo)
RegisterMsgProcessFunc("ReqSetName", ReqSetName) // 设置名字
RegisterMsgProcessFunc("ReqSetName", ReqSetName) // 设置名字
RegisterMsgProcessFunc("ReqSetFacebookUrl", ReqSetFacebookUrl) // 设置facebook地址
// 棋盘
RegisterMsgProcessFunc("ReqSetEnergyMul", RegSetEneryFunc) //设置能量倍数
@ -970,7 +966,7 @@ func (ad *GameLogic) RegisterNetWorkFunc() {
RegisterMsgProcessFunc("ReqAgreeCardGive", ReqAgreeCardGive) // 同意赠送卡牌
RegisterMsgProcessFunc("ReqRefuseCardGive", ReqRefuseCardGive) // 拒绝赠送卡牌
RegisterMsgProcessFunc("ReqCardExchange", ReqCardExchange) // 请求换卡牌
RegisterMsgProcessFunc("ReqCardExchange", ReqCardExchange) // 请求换卡牌
RegisterMsgProcessFunc("ReqSelectCardExchange", ReqSelectCardExchange) // 选择交换的卡牌
RegisterMsgProcessFunc("ReqAgreeCardExchange", ReqAgreeCardExchange) // 完成交换卡牌
RegisterMsgProcessFunc("ReqRefuseCardSelect", ReqRefuseCardSelect) // 拒绝选择卡牌进行交换
@ -1013,6 +1009,11 @@ func (ad *GameLogic) RegisterNetWorkFunc() {
RegisterMsgProcessFunc("ReqRefuseFriend", ReqRefuseFriend) // 拒绝申请
RegisterMsgProcessFunc("ReqDelFriend", ReqDelFriend) // 删除好友
// Facebook邀请好友
RegisterMsgProcessFunc("ReqInviteFriendData", ReqInviteFriendData) // 请求邀请好友数据
RegisterMsgProcessFunc("ReqSelfInvited", ReqSelfInvited) // 请求自己邀请的好友
RegisterMsgProcessFunc("ReqGetInviteReward", ReqGetInviteReward) // 领取邀请奖励
// 榜单
RegisterMsgProcessFunc("ReqRank", ReqRank) // 请求榜单数据
@ -1137,58 +1138,6 @@ func (ad *GameLogic) CreateLogManager() {
func (ad *GameLogic) InitActivity() {
ad.m_CronEntryIDs = make(map[int]*LimitActPeriod)
activityCfg := gamedata.GetConfigByName("Activity")
c := cron.New()
timeStamp := time.Now().Unix()
t := time.Unix(timeStamp, 0).Local()
nianchu := timeStamp - (int64)(t.Hour()*3600+t.Minute()*60+t.Second()) - int64((t.YearDay()-1)*3600*24)
for i := 0; i < activityCfg.NumRecord(); i++ {
record := activityCfg.Record(i).(*gamedata.ActivityRecord)
start := record.StartTime
var LAP = LimitActPeriod{}
LAP.StartCronID, _ = c.AddFunc(start, func() {
log.Debug("Next: UTC", c.Entry(LAP.StartCronID).Next.Unix())
G_GameLogicPtr.M_LimitActiveList = append(G_GameLogicPtr.M_LimitActiveList, record.Id)
cur := int32(time.Now().Unix())
GoUtil.CallEvent(MergeConst.OpenNewLimitActivity, []interface{}{record.Id, cur, cur + int32(record.Duration), record.Type})
go func() {
LeafTimer := ad.Mdispatr.AfterFunc(time.Duration(record.Duration)*time.Second, func() {
GoUtil.CallEvent(MergeConst.CloseNewLimitActivity, []interface{}{record})
G_GameLogicPtr.M_LimitActiveList = GoUtil.DeleteEleByValue(G_GameLogicPtr.M_LimitActiveList, record.Id)
})
LAP.EndTimer = LeafTimer
}()
})
ad.m_CronEntryIDs[record.Id] = &LAP
}
c.Start()
for k, v := range ad.m_CronEntryIDs {
ret := ad.JudgeIsActivity(c, k)
if ret == 3 { //已经结束
delete(ad.m_CronEntryIDs, k)
}
if ret == 2 {
key := k
value := v
G_GameLogicPtr.M_LimitActiveList = append(G_GameLogicPtr.M_LimitActiveList, k)
go func() {
delta := ad.CalcDeltaEndTime(c, key)
LeafTimer := ad.Mdispatr.AfterFunc(time.Duration(delta)*time.Second, func() {
record := activityCfg.Index(key).(*gamedata.ActivityRecord)
GoUtil.CallEvent(MergeConst.CloseNewLimitActivity, []interface{}{record})
G_GameLogicPtr.M_LimitActiveList = GoUtil.DeleteEleByValue(G_GameLogicPtr.M_LimitActiveList, key)
})
value.EndTimer = LeafTimer
Schedule := c.Entry(value.StartCronID).Schedule
Next := Schedule.Next(time.Unix(nianchu, 0))
value.StartTime = int32(Next.Unix())
value.EndTime = int32(Next.Unix()) + activityCfg.Index(key).(*gamedata.ActivityRecord).Duration
}()
}
}
}
func (ad *GameLogic) AddLog(Log *Log) {

View File

@ -71,6 +71,9 @@ func ReqGmCommand(args []interface{}) error {
CardMod.AddCard(3)
FriendMod := player.PlayMod.getFriendMod()
FriendMod.Card = make(map[string]*card.CardInfo)
case "setProgress":
num, _ := strconv.Atoi(arg[1])
player.PlayMod.getLimitedTimeEventMod().Progress = num
case "champshipGroup":
G_GameLogicPtr.ChampshipMgrSend(&MsgMod.Msg{
Type: MsgMod.HANDLE_TYPE_CHAMPSHIP_GROUP,

View File

@ -711,3 +711,18 @@ func (p *Player) HandleInChampshipRank() {
}
G_GameLogicPtr.ChampshipMgrSend(m)
}
func (p *Player) AddLog(Uid int, Type int, Param string) {
FriendMod := p.PlayMod.getFriendMod()
Id := FriendMod.AddLog(Uid, Type, Param)
p.PlayMod.save()
p.PushClientRes(&msg.NotifyFriendLog{
Info: &msg.ResFriendLog{
Player: G_GameLogicPtr.GetResSimplePlayerByUid(Uid),
Type: int32(Type),
Param: Param,
Id: int32(Id),
Time: int32(GoUtil.Now()),
},
})
}

View File

@ -14,6 +14,7 @@ import (
"server/msg"
"server/pkg/github.com/name5566/leaf/log"
"server/pkg/github.com/name5566/leaf/timer"
telog "server/thinkdata"
"time"
"github.com/robfig/cron/v3"
@ -252,7 +253,7 @@ func (p *PlayerBaseData) SaveDataFromDB(Key interface{}) bool {
var buf bytes.Buffer
encode := gob.NewEncoder(&buf)
encode.Encode(p.KeyValueData)
log.Debug("player :%d KeyValueData Save:%v ", p.Data.DwUin, p.KeyValueData)
// log.Debug("player :%d KeyValueData Save:%v ", p.Data.DwUin, p.KeyValueData)
db.SavePlayerClientData(&db.SqlModStruct{
DwUin: p.Data.DwUin,
ModData: buf.Bytes(),
@ -537,9 +538,11 @@ func (p *PlayerBaseData) AddExp(exp int) (int, error) {
ChargeMod := p.M_Player.PlayMod.getChargeMod()
ChargeMod.TriggerChargeUnlock(int(p.Data.Level), ChessMod.GetEmitList())
p.M_Player.PushClientRes(ChargeMod.BackData())
telog.Te.Track(p.Data.UserName, p.Data.UserName, "level_up", map[string]interface{}{})
}
p.M_Player.PushClientRes(p.BackAsset())
return upLv, nil
}
func (p *PlayerBaseData) GetLevel() int {

View File

@ -316,7 +316,6 @@ func (p *PlayerFriendData) ReqSelfInvited(buf []byte) {
}
}
res.IdLists = InviteIds
agent := p.GetPlayer().GetAgentByPlayer()
data, _ := proto.Marshal(res)
G_getGameLogic().PackResInfo(agent, "ResSelfInvited", data)
@ -766,134 +765,6 @@ func (p *PlayerFriendData) ReqAutoAddInviteFriend(buf []byte) {
proto.Unmarshal(buf, req)
res := &msg.ResAutoAddInviteFriend{}
for m := 0; m < len(req.Ids); m++ {
findSql := "SELECT * FROM t_player_baseinfo WHERE dwUin = ?"
sqlStruckBInfo := db.ResPlayerBaseInfo{}
tempId, _ := strconv.Atoi(req.Ids[m])
var PlayerId int32 = int32(tempId)
if err2 := db.SqlDb.Get(&sqlStruckBInfo, findSql, req.Ids[m]); err2 != nil {
} else {
PlayerId = sqlStruckBInfo.DwUin
}
if PlayerId == p.M_Player.M_DwUin {
continue
}
if p.IsFriend(PlayerId) {
continue
}
sqlStrs := []string{}
sqlStr := "SELECT * FROM t_player_Friend_Data WHERE dwUin = ?"
sqlStruck := db.SqlFriendStruct{}
sqlStruck.FriendList = ""
sqlStruck.DwUin = p.M_Player.M_DwUin
isHave := false
if err := db.SqlDb.Get(&sqlStruck, sqlStr, p.M_Player.M_DwUin); err != nil {
isHave = false
} else {
isHave = true
}
atrarr := []string{}
if sqlStruck.FriendList != "" {
atrarr = append(atrarr, sqlStruck.FriendList)
}
atrarr = append(atrarr, strconv.Itoa(int(PlayerId)))
sqlStruck.FriendList = strings.Join(atrarr, "_")
params := [][]any{}
if isHave {
sqlStrs = append(sqlStrs, "UPDATE t_player_Friend_Data SET FriendList = ? WHERE dwUin = ?")
t1 := []any{}
t1 = append(t1, sqlStruck.FriendList)
t1 = append(t1, sqlStruck.DwUin)
params = append(params, t1)
} else {
sqlStrs = append(sqlStrs, "INSERT INTO t_player_Friend_Data(dwUin, FriendList) VALUES(?, ?)")
p.IsHaveDataDb = true
t1 := []any{}
t1 = append(t1, p.M_Player.M_DwUin)
t1 = append(t1, sqlStruck.FriendList)
params = append(params, t1)
}
//////////////
sqlStruck1 := db.SqlFriendStruct{}
sqlStruck1.FriendList = ""
isHave1 := false
if err := db.SqlDb.Get(&sqlStruck1, sqlStr, PlayerId); err != nil {
isHave1 = false
} else {
isHave1 = true
}
atrarr1 := []string{}
if sqlStruck1.FriendList != "" {
atrarr1 = append(atrarr1, sqlStruck1.FriendList)
}
atrarr1 = append(atrarr1, strconv.Itoa(int(p.M_Player.M_DwUin)))
sqlStruck1.FriendList = strings.Join(atrarr1, "_")
if isHave1 {
sqlStrs = append(sqlStrs, "UPDATE t_player_Friend_Data SET FriendList = ? WHERE dwUin = ?")
t1 := []any{}
t1 = append(t1, sqlStruck1.FriendList)
t1 = append(t1, sqlStruck1.DwUin)
params = append(params, t1)
} else {
sqlStrs = append(sqlStrs, "INSERT INTO t_player_Friend_Data(dwUin, FriendList) VALUES(?, ?)")
t1 := []any{}
t1 = append(t1, PlayerId)
t1 = append(t1, sqlStruck1.FriendList)
params = append(params, t1)
}
err := db.SeriesTransaction(sqlStrs, params)
if err == nil {
finfo := &msg.FriendInfo{}
Profile := G_GameLogicPtr.MPlayerProfileManager.GetPlayerProfile(PlayerId)
DecorateCnt, ActiveTime, FaceBookId := G_GameLogicPtr.MPlayerProfileManager.GetPlayerDecorate(PlayerId)
if Profile != nil {
finfo.DwUin = Profile.DwUin
finfo.ImageFrame = Profile.ImageFrame
finfo.ImageIcon = Profile.ImageIcon
finfo.NickName = Profile.NickName
finfo.DecorateCnt = int32(DecorateCnt)
finfo.ActiveTime = int32(ActiveTime)
finfo.FaceBookId = FaceBookId
} else {
finfo.DwUin = PlayerId
finfo.ImageFrame = 1
finfo.ImageIcon = 1
finfo.NickName = "Player" + strconv.Itoa(int(PlayerId))
finfo.DecorateCnt = int32(DecorateCnt)
finfo.ActiveTime = int32(ActiveTime)
finfo.FaceBookId = FaceBookId
sql := &db.SqlPlayerProfileStruct{}
sql.DwUin = PlayerId
sql.ImageFrame = 1
sql.ImageIcon = 1
sql.NickName = "Player" + strconv.Itoa(int(PlayerId))
sql.PicURL = ""
G_GameLogicPtr.MPlayerProfileManager.UpdateNewProfile(sql)
}
p.Data.FriendInfos = append(p.Data.FriendInfos, finfo)
player, ok := G_GameLogicPtr.M_Players[PlayerId]
if ok {
if player.GetGameData("PlayerFriendData") != nil {
player.GetIFGameData("PlayerFriendData").(*PlayerFriendData).NotifySuccessInviteAddFriend(p.M_Player.M_DwUin)
}
}
}
}
agent := p.GetPlayer().GetAgentByPlayer()
data, _ := proto.Marshal(res)
G_getGameLogic().PackResInfo(agent, "ResAutoAddInviteFriend", data)

View File

@ -42,19 +42,25 @@ func handle(p *Player, m *msg.Msg) error {
switch m.Type {
case msg.HANDLE_TYPE_DEL, msg.HANDLE_TYPE_APPLY, msg.HADNLE_TYPE_AGREE, msg.HANDLE_TYPE_REQ_CARD:
return HandleFriendMsg(p, m)
case msg.HANDLE_TYPE_INVITE_ADD_FRIEND:
FriendMod := p.PlayMod.getFriendMod()
FriendMod.AddFriend(m.From)
p.PlayMod.save()
case msg.HANDLE_TYPE_INVITE_FRIEND:
InviteMod := p.PlayMod.getInviteMod()
InviteMod.AddInvite(m.From)
p.PlayMod.save()
p.PushClientRes(InviteMod.NotifySuccess())
case msg.HANDLE_TYPE_SEND_CARD: // B收到A赠送的卡牌
CardInfo := m.Extra.(*card.CardInfo)
FriendMod := p.PlayMod.getFriendMod()
FriendMod.SetCardInfo(CardInfo)
p.PushClientRes(
&proto.NotifyFriendCard{
Info: GetCardInfoMsg(CardInfo),
},
)
p.PlayMod.save()
case msg.HANDLE_TYPE_AGREE_CARD: // A收到B同意卡牌
CardInfo := m.Extra.(*card.CardInfo)
CardMod := p.PlayMod.getCardMod()
@ -70,6 +76,7 @@ func handle(p *Player, m *msg.Msg) error {
msg := &msg.Msg{Type: msg.HANDLE_TYPE_REG_CARD_FINISH, From: v}
FriendMgrSend(msg)
}
p.AddLog(int(p.M_DwUin), friend.LOG_TYPE_CARD_ACCEPT_GIVE, fmt.Sprintf("%d", CardInfo.CardId))
p.PlayMod.save()
p.PushClientRes(
&proto.NotifyFriendCard{
@ -97,6 +104,7 @@ func handle(p *Player, m *msg.Msg) error {
FriendMod := p.PlayMod.getFriendMod()
CardInfo := m.Extra.(*card.CardInfo)
FriendMod.SetCardInfo(CardInfo)
p.AddLog(int(p.M_DwUin), friend.LOG_TYPE_CARD_SELECT_GET, fmt.Sprintf("%d", CardInfo.CardId))
p.PlayMod.save()
p.PushClientRes(
&proto.NotifyFriendCard{
@ -165,11 +173,11 @@ func HandleServerMsg(p *Player, msg *msg.Msg) error {
// 处理好友请求
func HandleFriendMsg(p *Player, m *msg.Msg) error {
FriendMod := p.PlayMod.getFriendMod()
FriendMod.HandleMsg(m)
PlayerSimpleData := G_GameLogicPtr.GetResSimplePlayerByUid(m.From)
switch m.Type {
case msg.HANDLE_TYPE_APPLY: // 好友申请
FriendMod.AddFriendApply(m.From)
p.AddLog(m.From, friend.LOG_TYPE_FRIEND_APPLY, "")
p.PushClientRes(&proto.ResFriendApplyNotify{
Player: PlayerSimpleData,
Type: friend.FRIEND_NOTIFY_APPLY,
@ -180,6 +188,7 @@ func HandleFriendMsg(p *Player, m *msg.Msg) error {
Player: PlayerSimpleData,
Type: friend.FRIEND_NOTIFY_APPLY,
})
p.AddLog(m.From, friend.LOG_TYPE_FRIEND_BECOME, "")
case msg.HANDLE_TYPE_DEL: // 删除好友
FriendMod.DelFriend(m.From)
p.PushClientRes(&proto.ResFriendApplyNotify{
@ -200,6 +209,7 @@ func HandleFriendMsg(p *Player, m *msg.Msg) error {
},
)
}
p.PlayMod.save()
return nil
}
@ -227,16 +237,9 @@ func FriendListBackData(p *Player) {
FriendMod := p.PlayMod.getFriendMod()
var fl []*proto.ResPlayerSimple
for k := range FriendMod.FriendList {
ps := G_GameLogicPtr.GetSimplePlayerByUid(k)
ps := G_GameLogicPtr.GetResSimplePlayerByUid(k)
if ps != nil {
fl = append(fl, &proto.ResPlayerSimple{
Uid: int32(ps.Uid),
Name: ps.Name,
Level: int32(ps.Level),
Avatar: int32(ps.Avatar),
Face: int32(ps.Face),
Decorate: int32(ps.Decorate),
})
fl = append(fl, ps)
}
}
p.PushClientRes(&proto.ResFriendList{
@ -248,15 +251,9 @@ func FriendApplyBackData(p *Player) {
FriendMod := p.PlayMod.getFriendMod()
var al []*proto.ResPlayerSimple
for k := range FriendMod.Apply {
ps := G_GameLogicPtr.GetSimplePlayerByUid(k)
ps := G_GameLogicPtr.GetResSimplePlayerByUid(k)
if ps != nil {
al = append(al, &proto.ResPlayerSimple{
Uid: int32(ps.Uid),
Name: ps.Name,
Level: int32(ps.Level),
Avatar: int32(ps.Avatar),
Face: int32(ps.Face),
})
al = append(al, ps)
}
}
p.PushClientRes(&proto.ResFriendApply{
@ -268,13 +265,9 @@ func FriendLogBackData(p *Player) {
FriendMod := p.PlayMod.getFriendMod()
var log []*proto.ResFriendLog
for _, v := range FriendMod.Log {
ps := G_GameLogicPtr.GetSimplePlayerByUid(v.Uid)
ps := G_GameLogicPtr.GetResSimplePlayerByUid(v.Uid)
log = append(log, &proto.ResFriendLog{
Uid: int32(v.Uid),
Name: ps.Name,
Face: int32(ps.Face),
Avatar: int32(ps.Avatar),
Level: int32(ps.Level),
Player: ps,
Type: int32(v.Type),
Time: int32(v.Time),
})

View File

@ -20,6 +20,7 @@ import (
"server/game/mod/friend"
"server/game/mod/guild"
"server/game/mod/handbook"
"server/game/mod/invite"
"server/game/mod/limitedTimeEvent"
"server/game/mod/mail"
"server/game/mod/order"
@ -58,6 +59,7 @@ type PlayerModList struct {
Endless endless.EndlessMod `json:"endless"`
PiggyBank piggyBank.PiggyBankMod `json:"piggyBank"`
Champship champship.ChampshipMod `json:"champship"`
Invite invite.InviteMod `json:"invite"`
}
func (p *PlayerModData) LoadDataFromDB(dwUin interface{}) bool {
@ -140,6 +142,7 @@ func (p *PlayerModData) InitMod() (bool, error) {
p.ModList.Mail.InitData()
p.ModList.Charge.InitData()
p.ModList.Endless.InitData()
p.ModList.Invite.InitData()
return is_update, nil
}
@ -266,3 +269,7 @@ func (p *PlayerMod) getPiggyBankMod() *piggyBank.PiggyBankMod {
func (p *PlayerMod) getChampshipMod() *champship.ChampshipMod {
return &p.mod_list.Champship
}
func (p *PlayerMod) getInviteMod() *invite.InviteMod {
return &p.mod_list.Invite
}

View File

@ -9,14 +9,15 @@ import (
"server/db"
"server/game/internal"
"server/game/mod/card"
"server/game/mod/friend"
"server/game/mod/item"
"server/game/mod/limitedTimeEvent"
MsqMod "server/game/mod/msg"
"server/msg"
"strconv"
"time"
"server/pkg/github.com/name5566/leaf/gate"
"server/pkg/github.com/name5566/leaf/log"
"google.golang.org/protobuf/proto"
)
@ -1512,21 +1513,6 @@ func ReqAutoFBAddFriend(args []interface{}) error {
return nil
}
func ReqAutoAddInviteFriend(args []interface{}) error {
_, player, buf := ParseArgs(args)
if player.GetGameData("PlayerFriendData") == nil {
data := &PlayerFriendData{PlayerData: NewPlayerData("PlayerFriendData", player)}
ok := data.LoadDataFromDB(player.M_DwUin)
if ok {
player.playerdata["PlayerFriendData"] = data
player.playerdataIF["PlayerFriendData"] = data
}
}
player.GetIFGameData("PlayerFriendData").(*PlayerFriendData).ReqAutoAddInviteFriend(buf)
return nil
}
func ReqFriendTreasureData(args []interface{}) error {
_, player, buf := ParseArgs(args)
@ -1602,51 +1588,6 @@ func ReqDeleteFriendFunc(args []interface{}) error {
return nil
}
func ReqInviteFriendData(args []interface{}) error {
_, player, buf := ParseArgs(args)
if player.GetGameData("PlayerFriendData") == nil {
data := &PlayerFriendData{PlayerData: NewPlayerData("PlayerFriendData", player)}
ok := data.LoadDataFromDB(player.M_DwUin)
if ok {
player.playerdata["PlayerFriendData"] = data
player.playerdataIF["PlayerFriendData"] = data
}
}
player.GetIFGameData("PlayerFriendData").(*PlayerFriendData).ReqInviteFriendData(buf)
return nil
}
func ReqSelfInvited(args []interface{}) error {
_, player, buf := ParseArgs(args)
if player.GetGameData("PlayerFriendData") == nil {
data := &PlayerFriendData{PlayerData: NewPlayerData("PlayerFriendData", player)}
ok := data.LoadDataFromDB(player.M_DwUin)
if ok {
player.playerdata["PlayerFriendData"] = data
player.playerdataIF["PlayerFriendData"] = data
}
}
player.GetIFGameData("PlayerFriendData").(*PlayerFriendData).ReqSelfInvited(buf)
return nil
}
func ReqGetInviteReward(args []interface{}) error {
_, player, buf := ParseArgs(args)
if player.GetGameData("PlayerFriendData") == nil {
data := &PlayerFriendData{PlayerData: NewPlayerData("PlayerFriendData", player)}
ok := data.LoadDataFromDB(player.M_DwUin)
if ok {
player.playerdata["PlayerFriendData"] = data
player.playerdataIF["PlayerFriendData"] = data
}
}
player.GetIFGameData("PlayerFriendData").(*PlayerFriendData).ReqGetInviteReward(buf)
return nil
}
func ReqPlayerProfileDataFunc(args []interface{}) error {
G_GameLogicPtr.MPlayerProfileManager.ReqPlayerProfileData(args)
return nil
@ -2820,6 +2761,7 @@ func ReqAgreeFriend(args []interface{}) error {
Uid: req.Uid,
Player: G_GameLogicPtr.GetResSimplePlayerByUid(int(req.Uid)),
})
player.AddLog(Uid, friend.LOG_TYPE_FRIEND_BECOME, "")
FriendApplyBackData(player)
return nil
}
@ -2933,6 +2875,7 @@ func ReqCardGive(args []interface{}) error {
Type: card.TYPE_CARD_GIVE,
Status: card.STATUS_CARD_GIVE_1,
}
player.AddLog(Uid, friend.LOG_TYPE_CARD_GIVE, strconv.Itoa(CardId))
err = CardMod.AddRequestCard(CardInfo) // 添加请求卡牌
if err != nil {
player.SendErrClienRes(&msg.ResCardGive{
@ -3054,7 +2997,7 @@ func ReqCardSend(args []interface{}) error {
End: GoUtil.Now() + 86400,
Extra: CardInfo,
}
setRedisLock(CardInfo.Id, "", time.Second*86400)
player.AddLog(int(req.Uid), friend.LOG_TYPE_CARD_SEND, strconv.Itoa(CardId))
player.PushClientRes(&msg.ResCardSend{
Code: msg.RES_CODE_SUCCESS,
})
@ -3087,7 +3030,8 @@ func ReqCardExchange(args []interface{}) error {
End: GoUtil.Now() + 86400,
Extra: CardInfo,
}
setRedisLock(CardInfo.Id, "", time.Second*86400)
player.AddLog(int(req.Uid), friend.LOG_TYPE_CARD_EX_SEND, "")
player.PushClientRes(CardMod.BackData())
player.PushClientRes(&msg.ResCardExchange{
Code: msg.RES_CODE_SUCCESS,
@ -3124,6 +3068,7 @@ func ReqSelectCardExchange(args []interface{}) error {
CardInfo.ExId = CardId
CardInfo.Status = card.STATUS_CARD_EX_2
FriendMod.SetCardInfo(CardInfo)
player.AddLog(CardInfo.AUid, friend.LOG_TYPE_CARD_SELECT_SEND, fmt.Sprintf("%d", CardInfo.ExId))
err := CardMod.SubCard(CardId)
if err != nil {
player.SendErrClienRes(&msg.ResSelectCardExchange{
@ -3167,6 +3112,7 @@ func ReqAgreeCardExchange(args []interface{}) error {
CardMod.AddCard(CardInfo.ExId)
CardMod.DelExCard(CardInfo)
FriendMod.DelCardInfo(req.Id)
player.AddLog(CardInfo.BUid, friend.LOG_TYPE_CARD_EX_SUCCESS_1, fmt.Sprintf("%d_%d", CardInfo.CardId, CardInfo.ExId))
CardInfo.Status = card.STATUS_CARD_EX_3
CardInfo.EndTime = 0
player.PlayMod.save()
@ -3265,8 +3211,10 @@ func ReqGetFriendCard(args []interface{}) error {
}
FriendMod.DelCardInfo(req.Id)
CardMod.AddCard(CardInfo.CardId)
if CardInfo.ExId != 0 {
player.AddLog(CardInfo.BUid, friend.LOG_TYPE_CARD_EX_SUCCESS_2, fmt.Sprintf("%d_%d", CardInfo.ExId, CardInfo.CardId))
}
player.PlayMod.save()
// player.PushClientRes(CardMod.BackData())
player.PushClientRes(&msg.ResGetFriendCard{
Code: msg.RES_CODE_SUCCESS,
})
@ -3763,3 +3711,77 @@ func ReqMasterCard(args []interface{}) error {
player.PushClientRes(CardMod.NotifyCard())
return nil
}
func ReqSetFacebookUrl(args []interface{}) error {
_, player, buf := ParseArgs(args)
req := &msg.ReqSetFacebookUrl{}
proto.Unmarshal(buf, req)
BaseMod := player.PlayMod.getBaseMod()
BaseMod.SetFacebookUrl(req.Url)
player.PlayMod.save()
player.PushClientRes(&msg.ResSetFacebookUrl{
Code: msg.RES_CODE_SUCCESS,
})
return nil
}
func ReqInviteFriendData(args []interface{}) error {
_, player, _ := ParseArgs(args)
InviteMod := player.PlayMod.getInviteMod()
player.PushClientRes(InviteMod.BackData())
return nil
}
func ReqSelfInvited(args []interface{}) error {
_, player, buf := ParseArgs(args)
req := &msg.ReqSelfInvited{}
proto.Unmarshal(buf, req)
G_GameLogicPtr.FriendMgrSend(&MsqMod.Msg{
Type: MsqMod.HANDLE_TYPE_INVITE_FRIEND,
From: int(player.M_DwUin),
To: int(req.InviterId),
})
player.PushClientRes(&msg.ResSelfInvited{
ResultCode: 1,
})
return nil
}
func ReqGetInviteReward(args []interface{}) error {
_, player, buf := ParseArgs(args)
req := &msg.ReqGetInviteReward{}
proto.Unmarshal(buf, req)
InviteMod := player.PlayMod.getInviteMod()
Items, err := InviteMod.GetReward()
if err != nil {
log.Debug("ReqGetInviteReward err :%v", err)
return err
}
err = player.HandleItem(Items, "invite")
if err != nil {
log.Debug("ReqGetInviteReward err :%v", err)
return err
}
player.PlayMod.save()
player.PushClientRes(&msg.ResGetInviteReward{
ResultCode: 1,
})
return nil
}
func ReqAutoAddInviteFriend(args []interface{}) error {
_, player, buf := ParseArgs(args)
req := &msg.ReqAutoAddInviteFriend{}
proto.Unmarshal(buf, req)
FriendMod := player.PlayMod.getFriendMod()
FriendMod.AddFriend(int(req.Id))
player.PlayMod.save()
player.PushClientRes(&msg.ResAutoAddInviteFriend{
ResultCode: 1,
})
G_GameLogicPtr.FriendMgrSend(&MsqMod.Msg{
Type: MsqMod.HANDLE_TYPE_INVITE_ADD_FRIEND,
})
return nil
}

View File

@ -135,6 +135,7 @@ func (s *ServerMod) SaveData() {
if err != nil {
log.Debug("SaveData Marshal failed,Mod Key: %s err:%v", s.key, err)
}
log.Debug("SaveData Marshal success,Mod Key: %s", s.key)
err = db.SaveServerData(&DbData)
if err != nil {
log.Debug("SaveData sql exec ,Mod Key: %s err:%v", s.key, err)

View File

@ -11,10 +11,11 @@ const (
)
type Base struct {
EnergyMul int
IsFirstBuy bool
EnergyBuy int
NickName string
EnergyMul int
IsFirstBuy bool
EnergyBuy int
NickName string
FacebookUrl string
}
func (b *Base) InitData() {
@ -23,6 +24,14 @@ func (b *Base) InitData() {
// b.EnergyBuy = 0
}
func (b *Base) GetNickName() string {
return b.NickName
}
func (b *Base) GetFacebookUrl() string {
return b.FacebookUrl
}
func (b *Base) GetEnergyMul() int {
return b.EnergyMul
}
@ -39,6 +48,10 @@ func (b *Base) GetIsFirstBuy() bool {
return b.IsFirstBuy
}
func (b *Base) SetFacebookUrl(Url string) {
b.FacebookUrl = Url
}
func (b *Base) BuyEnergy(Energy int) []*item.Item {
if !b.IsFirstBuy {
b.IsFirstBuy = true

View File

@ -3,7 +3,6 @@ package friend
import (
"server/GoUtil"
"server/game/mod/card"
"server/game/mod/msg"
)
type FriendMod struct {
@ -11,11 +10,21 @@ type FriendMod struct {
Apply map[int]struct{} // 请求列表
Card map[string]*card.CardInfo // 收到的申请交换
Log []*LogInfo // 日志
AutoId int
}
const (
LOG_TYPE_ADD = 1
LOG_TYPE_DEL = 2
LOG_TYPE_FRIEND_APPLY = 1 // 收到申请好友
LOG_TYPE_FRIEND_BECOME = 2 // 成为好友
LOG_TYPE_CARD_EX_SEND = 3 // 发起卡牌交换申请
LOG_TYPE_CARD_SEND = 4 // 赠送卡牌
LOG_TYPE_CARD_GIVE = 5 // 请求卡牌
LOG_TYPE_CARD_SELECT_GET = 6 // 选择卡牌交换
LOG_TYPE_CARD_ACCEPT_GIVE = 7 // 接受卡牌
LOG_TYPE_CARD_EX_GET = 8 // 收到卡牌交换申请
LOG_TYPE_CARD_SELECT_SEND = 9 // 选择卡牌交换
LOG_TYPE_CARD_EX_SUCCESS_1 = 10 // 卡牌交换成功
LOG_TYPE_CARD_EX_SUCCESS_2 = 11 // 卡牌交换成功
)
const (
@ -26,9 +35,11 @@ const (
)
type LogInfo struct {
Uid int
Type int
Time int64
Id int
Uid int
Type int
Time int64
Param string
}
func (f *FriendMod) InitData() {
@ -46,7 +57,6 @@ func (f *FriendMod) InitData() {
func (f *FriendMod) AddFriend(id int) {
f.FriendList[id] = struct{}{}
delete(f.Apply, id)
f.Log = append(f.Log, &LogInfo{Uid: id, Type: LOG_TYPE_ADD, Time: GoUtil.Now()})
}
func (f *FriendMod) GetCardInfo(Id string) *card.CardInfo {
@ -67,7 +77,6 @@ func (f *FriendMod) DelCardInfo(Id string) {
func (f *FriendMod) DelFriend(id int) {
delete(f.FriendList, id)
f.Log = append(f.Log, &LogInfo{Uid: id, Type: LOG_TYPE_ADD, Time: GoUtil.Now()})
}
func (f *FriendMod) CheckFriend(Uid int) bool {
@ -79,31 +88,28 @@ func (f *FriendMod) RefuseApply(id int) {
delete(f.Apply, id)
}
func (f *FriendMod) HandleMsg(m *msg.Msg) {
switch m.Type {
case msg.HANDLE_TYPE_APPLY:
f.Apply[m.From] = struct{}{}
case msg.HADNLE_TYPE_AGREE:
f.AddFriend(m.From)
delete(f.Apply, m.From)
case msg.HANDLE_TYPE_DEL:
delete(f.FriendList, m.From)
case msg.HANDLE_TYPE_REQ_CARD:
CardInfo := m.Extra.(*card.CardInfo)
f.SetCardInfo(CardInfo)
}
}
func (f *FriendMod) CheckApply(id int) bool {
_, ok := f.Apply[id]
return ok
}
func (f *FriendMod) AddFriendApply(UId int) {
f.Apply[UId] = struct{}{}
func (f *FriendMod) AddFriendApply(Uid int) {
f.Apply[Uid] = struct{}{}
}
func (f *FriendMod) AgreeApply(UId int) {
f.AddFriend(UId)
delete(f.Apply, UId)
}
func (f *FriendMod) AddLog(Uid, Type int, Param string) int {
f.AutoId++
f.Log = append(f.Log, &LogInfo{
Id: f.AutoId,
Uid: Uid,
Type: Type,
Time: GoUtil.Now(),
Param: Param,
})
return f.AutoId
}

View File

@ -0,0 +1,50 @@
package invite
import (
"fmt"
"server/GoUtil"
inviteCfg "server/conf/invite"
"server/game/mod/item"
"server/msg"
)
type InviteMod struct {
InviteList map[int]struct{} // 邀请列表
GetIndex int
}
func (i *InviteMod) InitData() {
if i.InviteList == nil {
i.InviteList = make(map[int]struct{})
}
}
func (i *InviteMod) AddInvite(id int) {
i.InviteList[id] = struct{}{}
}
func (i *InviteMod) GetReward() ([]*item.Item, error) {
i.GetIndex++
Need, Reward := inviteCfg.GetInviteReward(i.GetIndex)
if Need == 0 {
return nil, fmt.Errorf("invite reward not found")
}
if len(i.InviteList) < Need {
return nil, fmt.Errorf("invite not enough")
}
return Reward, nil
}
func (i *InviteMod) BackData() *msg.ResInviteFriendData {
return &msg.ResInviteFriendData{
IdLists: GoUtil.MapIntToSlice(i.InviteList),
GetIndex: int32(i.GetIndex),
}
}
func (i *InviteMod) NotifySuccess() *msg.NotifyInvitedSuccess {
return &msg.NotifyInvitedSuccess{
ResultCode: 1,
IdLists: GoUtil.MapIntToSlice(i.InviteList),
}
}

View File

@ -48,6 +48,9 @@ func (l *LimitedTimeEventMod) InitData() {
if l.Triggered == nil {
l.Triggered = make(map[int]struct{})
}
if l.ProgressReward == nil {
l.ProgressReward = make(map[int]int)
}
}
// 判断限时事件是否存在
@ -203,6 +206,9 @@ func (l *LimitedTimeEventMod) GetFastProduceReward(Energy int) ([]*item.Item, er
// 增加进度
func (l *LimitedTimeEventMod) AddProgress(Lv int) {
if Lv < 4 {
return
}
l.Progress++
ProgressMax := limitedTimeEventCfg.GetProgressMax()
if l.Progress >= ProgressMax {

View File

@ -34,6 +34,9 @@ const (
HANDLE_TYPE_REFUSE_EX_CARD = 11 //A拒绝置换卡牌
HANDLE_TYPE_SEND_CARD = 15 //赠送卡牌
HANDLE_TYPE_INVITE_FRIEND = 16 //邀请好友
HANDLE_TYPE_INVITE_ADD_FRIEND = 17 //自动添加好友
// 榜单操作
HANDLE_TYPE_RANK = 101 //榜单操作
HANDLE_TYPE_RANK_INFO = 102 //榜单信息

View File

@ -16,9 +16,12 @@ require (
require (
filippo.io/edwards25519 v1.1.0 // indirect
github.com/ThinkingDataAnalytics/go-sdk v1.7.0 // indirect
github.com/ThinkingDataAnalytics/go-sdk/v2 v2.0.3 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/uuid v1.3.1 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)

View File

@ -1,5 +1,9 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/ThinkingDataAnalytics/go-sdk v1.7.0 h1:UN1zj5pr4JRipSfaKDKfHpS7pRTACECh3Ta5mmR5SCE=
github.com/ThinkingDataAnalytics/go-sdk v1.7.0/go.mod h1:LBEHgQysXYqY0aewUoWCMocxK5UM3kTQa7F6tcm7ZJ0=
github.com/ThinkingDataAnalytics/go-sdk/v2 v2.0.3 h1:+2h2cOKzZgP8DmtuvkmUhOs5WfyseFTc0KLNR3EU2eA=
github.com/ThinkingDataAnalytics/go-sdk/v2 v2.0.3/go.mod h1:uhiHUKG8fMwf4Ou3186EBBagFrBdAsAA5GHiLMWQN2A=
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
@ -12,6 +16,9 @@ github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpv
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=

File diff suppressed because it is too large Load Diff

View File

View File

@ -0,0 +1,22 @@
package telog
import (
"server/conf"
"github.com/ThinkingDataAnalytics/go-sdk/v2/src/thinkingdata"
)
var Te thinkingdata.TDAnalytics
func init() {
// 初始化
// 创建 LogConfig 配置文件
config := thinkingdata.TDLogConsumerConfig{
Directory: conf.Server.TELOGDIR, // 事件采集的文件路径
}
// 初始化 logConsumer
consumer, _ := thinkingdata.NewLogConsumerWithConfig(config)
// 创建 te 对象
Te = thinkingdata.New(consumer)
}

View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2019 thinking-analytics / data-collector / server-sdk
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,352 @@
package thinkingdata
import (
"bytes"
"compress/gzip"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strconv"
"strings"
"sync"
"time"
)
// TDBatchConsumer upload data to TE by http
type TDBatchConsumer struct {
serverUrl string // serverUrl
appId string // appId
timeout time.Duration // http timeout (mill second)
compress bool // is need compress
bufferMutex *sync.RWMutex
cacheMutex *sync.RWMutex // cache mutex
buffer []Data
batchSize int // flush event count each time
cacheBuffer [][]Data // buffer
cacheCapacity int // buffer max count
}
type TDBatchConfig struct {
ServerUrl string // serverUrl
AppId string // appId
BatchSize int // flush event count each time
Timeout int // http timeout (mill second)
Compress bool // enable compress data
AutoFlush bool // enable auto flush
Interval int // auto flush spacing (second)
CacheCapacity int // cache event count
}
const (
DefaultTimeOut = 30000
DefaultBatchSize = 20
MaxBatchSize = 200
DefaultInterval = 30
DefaultCacheCapacity = 50
)
// NewBatchConsumer create TDBatchConsumer
func NewBatchConsumer(serverUrl string, appId string) (TDConsumer, error) {
config := TDBatchConfig{
ServerUrl: serverUrl,
AppId: appId,
Compress: true,
}
return initBatchConsumer(config)
}
// NewBatchConsumerWithBatchSize create TDBatchConsumer
// serverUrl
// appId
// batchSize: flush event count each time
func NewBatchConsumerWithBatchSize(serverUrl string, appId string, batchSize int) (TDConsumer, error) {
config := TDBatchConfig{
ServerUrl: serverUrl,
AppId: appId,
Compress: true,
BatchSize: batchSize,
}
return initBatchConsumer(config)
}
// NewBatchConsumerWithCompress create TDBatchConsumer
// serverUrl
// appId
// compress: enable data compress
func NewBatchConsumerWithCompress(serverUrl string, appId string, compress bool) (TDConsumer, error) {
config := TDBatchConfig{
ServerUrl: serverUrl,
AppId: appId,
Compress: compress,
}
return initBatchConsumer(config)
}
func NewBatchConsumerWithConfig(config TDBatchConfig) (TDConsumer, error) {
return initBatchConsumer(config)
}
func initBatchConsumer(config TDBatchConfig) (TDConsumer, error) {
if config.ServerUrl == "" {
msg := fmt.Sprint("ServerUrl not be empty")
tdLogInfo(msg)
return nil, errors.New(msg)
}
u, err := url.Parse(config.ServerUrl)
if err != nil {
return nil, err
}
u.Path = "/sync_server"
var batchSize int
if config.BatchSize > MaxBatchSize {
batchSize = MaxBatchSize
} else if config.BatchSize <= 0 {
batchSize = DefaultBatchSize
} else {
batchSize = config.BatchSize
}
var cacheCapacity int
if config.CacheCapacity <= 0 {
cacheCapacity = DefaultCacheCapacity
} else {
cacheCapacity = config.CacheCapacity
}
var timeout int
if config.Timeout == 0 {
timeout = DefaultTimeOut
} else {
timeout = config.Timeout
}
c := &TDBatchConsumer{
serverUrl: u.String(),
appId: config.AppId,
timeout: time.Duration(timeout) * time.Millisecond,
compress: config.Compress,
bufferMutex: new(sync.RWMutex),
cacheMutex: new(sync.RWMutex),
batchSize: batchSize,
buffer: make([]Data, 0, batchSize),
cacheCapacity: cacheCapacity,
cacheBuffer: make([][]Data, 0, cacheCapacity),
}
var interval int
if config.Interval == 0 {
interval = DefaultInterval
} else {
interval = config.Interval
}
if config.AutoFlush {
go func() {
ticker := time.NewTicker(time.Duration(interval) * time.Second)
defer ticker.Stop()
for {
<-ticker.C
_ = c.timerFlush()
}
}()
}
tdLogInfo("Mode: batch consumer, appId: %s, serverUrl: %s", c.appId, c.serverUrl)
return c, nil
}
func (c *TDBatchConsumer) Add(d Data) error {
c.bufferMutex.Lock()
c.buffer = append(c.buffer, d)
c.bufferMutex.Unlock()
tdLogInfo("Enqueue event data: %v", d)
if c.getBufferLength() >= c.batchSize || c.getCacheLength() > 0 {
err := c.Flush()
return err
}
return nil
}
func (c *TDBatchConsumer) timerFlush() error {
tdLogInfo("timer flush data")
return c.innerFlush()
}
func (c *TDBatchConsumer) Flush() error {
tdLogInfo("flush data")
return c.innerFlush()
}
func (c *TDBatchConsumer) innerFlush() error {
c.cacheMutex.Lock()
defer c.cacheMutex.Unlock()
c.bufferMutex.Lock()
defer c.bufferMutex.Unlock()
if len(c.buffer) == 0 && len(c.cacheBuffer) == 0 {
return nil
}
defer func() {
if len(c.cacheBuffer) > c.cacheCapacity {
c.cacheBuffer = c.cacheBuffer[1:]
}
}()
if len(c.cacheBuffer) == 0 || len(c.buffer) >= c.batchSize {
c.cacheBuffer = append(c.cacheBuffer, c.buffer)
c.buffer = make([]Data, 0, c.batchSize)
}
err := c.uploadEvents()
return err
}
func (c *TDBatchConsumer) uploadEvents() error {
buffer := c.cacheBuffer[0]
jsonBytes, err := json.Marshal(buffer)
if err == nil {
params := parseTime(jsonBytes)
for i := 0; i < 3; i++ {
statusCode, code, err := c.send(params, len(buffer))
if statusCode == 200 {
c.cacheBuffer = c.cacheBuffer[1:]
switch code {
case 0:
tdLogInfo("send success %v", params)
return nil
case 1, -1:
msg := "invalid data format"
tdLogError(msg)
return fmt.Errorf(msg)
case -2:
msg := "APP ID doesn't exist"
tdLogError(msg)
return fmt.Errorf(msg)
case -3:
msg := "invalid ip transmission"
tdLogError(msg)
return fmt.Errorf(msg)
default:
msg := "unknown error"
tdLogError(msg)
return fmt.Errorf(msg)
}
}
if err != nil {
if i == 2 {
return err
}
}
}
}
return err
}
func (c *TDBatchConsumer) FlushAll() error {
for c.getCacheLength() > 0 || c.getBufferLength() > 0 {
if err := c.Flush(); err != nil {
if !strings.Contains(err.Error(), "ThinkingDataError") {
return err
}
}
}
return nil
}
func (c *TDBatchConsumer) Close() error {
tdLogInfo("batch consumer close")
return c.FlushAll()
}
func (c *TDBatchConsumer) IsStringent() bool {
return false
}
func (c *TDBatchConsumer) send(data string, size int) (statusCode int, code int, err error) {
var encodedData string
var compressType = "gzip"
if c.compress {
encodedData, err = encodeData(data)
} else {
encodedData = data
compressType = "none"
}
if err != nil {
return 0, 0, err
}
postData := bytes.NewBufferString(encodedData)
var resp *http.Response
req, _ := http.NewRequest("POST", c.serverUrl, postData)
req.Header["appid"] = []string{c.appId}
req.Header.Set("user-agent", "ta-go-sdk")
req.Header.Set("version", SdkVersion)
req.Header.Set("compress", compressType)
req.Header["TA-Integration-Type"] = []string{LibName}
req.Header["TA-Integration-Version"] = []string{SdkVersion}
req.Header["TA-Integration-Count"] = []string{strconv.Itoa(size)}
client := &http.Client{Timeout: c.timeout}
resp, err = client.Do(req)
if err != nil {
return 0, 0, err
}
defer resp.Body.Close()
if resp.StatusCode == http.StatusOK {
body, _ := ioutil.ReadAll(resp.Body)
var result struct {
Code int
}
err = json.Unmarshal(body, &result)
if err != nil {
return resp.StatusCode, 1, err
}
return resp.StatusCode, result.Code, nil
} else {
return resp.StatusCode, -1, nil
}
}
// Gzip
func encodeData(data string) (string, error) {
var buf bytes.Buffer
gw := gzip.NewWriter(&buf)
_, err := gw.Write([]byte(data))
if err != nil {
gw.Close()
return "", err
}
gw.Close()
return string(buf.Bytes()), nil
}
func (c *TDBatchConsumer) getBufferLength() int {
c.bufferMutex.RLock()
defer c.bufferMutex.RUnlock()
return len(c.buffer)
}
func (c *TDBatchConsumer) getCacheLength() int {
c.cacheMutex.RLock()
defer c.cacheMutex.RUnlock()
return len(c.cacheBuffer)
}

View File

@ -0,0 +1,120 @@
package thinkingdata
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"net/url"
)
// TDDebugConsumer The data is reported one by one, and when an error occurs, the log will be printed on the console.
type TDDebugConsumer struct {
serverUrl string // serverUrl
appId string // appId
writeData bool // is archive to TE
deviceId string // be used to debug in TE
}
// NewDebugConsumer init TDDebugConsumer
func NewDebugConsumer(serverUrl string, appId string) (TDConsumer, error) {
return NewDebugConsumerWithWriter(serverUrl, appId, true)
}
func NewDebugConsumerWithWriter(serverUrl string, appId string, writeData bool) (TDConsumer, error) {
return NewDebugConsumerWithDeviceId(serverUrl, appId, writeData, "")
}
func NewDebugConsumerWithDeviceId(serverUrl string, appId string, writeData bool, deviceId string) (TDConsumer, error) {
// enable console log
SetLogLevel(TDLogLevelDebug)
if len(serverUrl) <= 0 {
msg := fmt.Sprint("ServerUrl not be empty")
tdLogError(msg)
return nil, errors.New(msg)
}
u, err := url.Parse(serverUrl)
if err != nil {
return nil, err
}
u.Path = "/data_debug"
c := &TDDebugConsumer{serverUrl: u.String(), appId: appId, writeData: writeData, deviceId: deviceId}
tdLogInfo("Mode: debug consumer, appId: %s, serverUrl: %s", c.appId, c.serverUrl)
return c, nil
}
func (c *TDDebugConsumer) Add(d Data) error {
jsonBytes, err := json.Marshal(d)
if err != nil {
return err
}
var jsonStr string
// if properties has includes complex data, SDK need parse time with regular expression
if d.IsComplex {
jsonStr = parseTime(jsonBytes)
} else {
jsonStr = string(jsonBytes)
}
tdLogInfo("%v", jsonStr)
return c.send(jsonStr)
}
func (c *TDDebugConsumer) Flush() error {
tdLogInfo("flush data")
return nil
}
func (c *TDDebugConsumer) Close() error {
tdLogInfo("debug consumer close")
return nil
}
func (c *TDDebugConsumer) IsStringent() bool {
return true
}
func (c *TDDebugConsumer) send(data string) error {
var dryRun = "0"
if !c.writeData {
dryRun = "1"
}
postData := url.Values{"data": {data}, "appid": {c.appId}, "source": {"server"}, "dryRun": {dryRun}}
if len(c.deviceId) > 0 {
postData.Add("deviceId", c.deviceId)
}
resp, err := http.PostForm(c.serverUrl, postData)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode == http.StatusOK {
body, _ := ioutil.ReadAll(resp.Body)
result := map[string]interface{}{}
err = json.Unmarshal(body, &result)
if err != nil {
return err
}
if uint64(result["errorLevel"].(float64)) != 0 {
msg := fmt.Sprintf("send to receiver failed with return content: %s", string(body))
tdLogError(msg)
return errors.New(msg)
} else {
tdLogInfo("send success: %v", result)
}
} else {
return errors.New(fmt.Sprintf("Unexpected Status Code: %d", resp.StatusCode))
}
return nil
}

View File

@ -0,0 +1,256 @@
package thinkingdata
import (
"encoding/json"
"errors"
"fmt"
"os"
"sync"
"time"
)
type RotateMode int32
const (
DefaultChannelSize = 1000 // channel size
ROTATE_DAILY RotateMode = 0 // by the day
ROTATE_HOURLY RotateMode = 1 // by the hour
)
// TDLogConsumer write data to file, it works with LogBus
type TDLogConsumer struct {
directory string // directory of log file
dateFormat string // name format of log file
fileSize int64 // max size of single log file (MByte)
fileNamePrefix string // prefix of log file
currentFile *os.File // current file handler
wg sync.WaitGroup
ch chan []byte
mutex *sync.RWMutex
sdkClose bool
}
type TDLogConsumerConfig struct {
Directory string // directory of log file
RotateMode RotateMode // rotate mode of log file
FileSize int // max size of single log file (MByte)
FileNamePrefix string // prefix of log file
ChannelSize int
}
func NewLogConsumer(directory string, r RotateMode) (TDConsumer, error) {
return NewLogConsumerWithFileSize(directory, r, 0)
}
// NewLogConsumerWithFileSize init TDLogConsumer
// directory: directory of log file
// r: rotate mode of log file. (in days / hours)
// size: max size of single log file (MByte)
func NewLogConsumerWithFileSize(directory string, r RotateMode, size int) (TDConsumer, error) {
config := TDLogConsumerConfig{
Directory: directory,
RotateMode: r,
FileSize: size,
}
return NewLogConsumerWithConfig(config)
}
func NewLogConsumerWithConfig(config TDLogConsumerConfig) (TDConsumer, error) {
var df string
switch config.RotateMode {
case ROTATE_DAILY:
df = "2006-01-02"
case ROTATE_HOURLY:
df = "2006-01-02-15"
default:
errStr := "unknown rotate mode"
tdLogInfo(errStr)
return nil, errors.New(errStr)
}
chanSize := DefaultChannelSize
if config.ChannelSize > 0 {
chanSize = config.ChannelSize
}
c := &TDLogConsumer{
directory: config.Directory,
dateFormat: df,
fileSize: int64(config.FileSize * 1024 * 1024),
fileNamePrefix: config.FileNamePrefix,
wg: sync.WaitGroup{},
ch: make(chan []byte, chanSize),
mutex: new(sync.RWMutex),
sdkClose: false,
}
return c, c.init()
}
func (c *TDLogConsumer) Add(d Data) error {
var err error = nil
c.mutex.Lock()
defer func() {
c.mutex.Unlock()
}()
if c.sdkClose {
err = errors.New("add event failed, SDK has been closed")
tdLogError(err.Error())
} else {
jsonBytes, jsonErr := json.Marshal(d)
if jsonErr != nil {
err = jsonErr
} else {
c.ch <- jsonBytes
}
}
return err
}
func (c *TDLogConsumer) Flush() error {
tdLogInfo("flush data")
var err error = nil
c.mutex.Lock()
if c.currentFile != nil {
err = c.currentFile.Sync()
}
c.mutex.Unlock()
return err
}
func (c *TDLogConsumer) Close() error {
tdLogInfo("log consumer close")
var err error = nil
c.mutex.Lock()
if c.sdkClose {
err = errors.New("[ThinkingData][error]: SDK has been closed")
} else {
close(c.ch)
c.wg.Wait()
if c.currentFile != nil {
_ = c.currentFile.Sync()
err = c.currentFile.Close()
c.currentFile = nil
}
}
c.sdkClose = true
c.mutex.Unlock()
return err
}
func (c *TDLogConsumer) IsStringent() bool {
return false
}
func (c *TDLogConsumer) constructFileName(timeStr string, i int) string {
fileNamePrefix := ""
if len(c.fileNamePrefix) != 0 {
fileNamePrefix = c.fileNamePrefix + "."
}
// is need paging
if c.fileSize > 0 {
return fmt.Sprintf("%s/%slog.%s_%d", c.directory, fileNamePrefix, timeStr, i)
} else {
return fmt.Sprintf("%s/%slog.%s", c.directory, fileNamePrefix, timeStr)
}
}
func (c *TDLogConsumer) init() error {
fd, err := c.initLogFile()
if err != nil {
tdLogError("init log file failed: %s", err)
return err
}
c.currentFile = fd
c.wg.Add(1)
go func() {
defer func() {
c.wg.Done()
}()
for {
select {
case rec, ok := <-c.ch:
if !ok {
return
}
jsonStr := parseTime(rec)
tdLogInfo("write event data: %s", jsonStr)
c.writeToFile(jsonStr)
}
}
}()
tdLogInfo("Mode: log consumer, log path: " + c.directory)
return nil
}
func (c *TDLogConsumer) initLogFile() (*os.File, error) {
_, err := os.Stat(c.directory)
if err != nil && os.IsNotExist(err) {
e := os.MkdirAll(c.directory, os.ModePerm)
if e != nil {
return nil, e
}
}
timeStr := time.Now().Format(c.dateFormat)
return os.OpenFile(c.constructFileName(timeStr, 0), os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0664)
}
var logFileIndex = 0
func (c *TDLogConsumer) writeToFile(str string) {
timeStr := time.Now().Format(c.dateFormat)
// paging by Rotate Mode and current file size
var newName string
fName := c.constructFileName(timeStr, logFileIndex)
if c.currentFile == nil {
var openFileErr error
c.currentFile, openFileErr = os.OpenFile(fName, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0664)
if openFileErr != nil {
tdLogInfo("open log file failed: %s\n", openFileErr)
return
}
}
if c.currentFile.Name() != fName {
newName = fName
} else if c.fileSize > 0 {
stat, _ := c.currentFile.Stat()
if stat.Size() > c.fileSize {
logFileIndex++
newName = c.constructFileName(timeStr, logFileIndex)
}
}
if newName != "" {
err := c.currentFile.Close()
if err != nil {
tdLogInfo("close file failed: %s\n", err)
return
}
c.currentFile, err = os.OpenFile(fName, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0664)
if err != nil {
tdLogInfo("rotate log file failed: %s\n", err)
return
}
}
_, err := fmt.Fprintln(c.currentFile, str)
if err != nil {
tdLogInfo("LoggerWriter(%q): %s\n", c.currentFile.Name(), err)
return
}
}
// Deprecated: please use TDLogConsumer
type LogConsumer struct {
TDLogConsumer
}
// Deprecated: please use TDLogConsumerConfig
type LogConfig struct {
TDLogConsumerConfig
}

View File

@ -0,0 +1,125 @@
package thinkingdata
import (
"fmt"
"time"
)
// SDK_LOG_PREFIX const
const SDK_LOG_PREFIX = "[ThinkingData]"
var logInstance TDLogger
type TDLogLevel int32
const (
TDLogLevelOff TDLogLevel = 1
TDLogLevelError TDLogLevel = 2
TDLogLevelWarning TDLogLevel = 3
TDLogLevelInfo TDLogLevel = 4
TDLogLevelDebug TDLogLevel = 5
)
// default is TDLogLevelOff
var currentLogLevel = TDLogLevelOff
// TDLogger User-defined log classes must comply with interface
type TDLogger interface {
Print(message string)
}
// SetLogLevel Set the log output level
func SetLogLevel(level TDLogLevel) {
if level < TDLogLevelOff || level > TDLogLevelDebug {
fmt.Println(SDK_LOG_PREFIX + "log type error")
return
} else {
currentLogLevel = level
}
}
// SetCustomLogger Set a custom log input class, usually you don't need to set it up.
func SetCustomLogger(logger TDLogger) {
if logger != nil {
logInstance = logger
}
}
func tdLog(level TDLogLevel, format string, v ...interface{}) {
if level > currentLogLevel {
return
}
var modeStr string
switch level {
case TDLogLevelError:
modeStr = "[Error] "
break
case TDLogLevelWarning:
modeStr = "[Warning] "
break
case TDLogLevelInfo:
modeStr = "[Info] "
break
case TDLogLevelDebug:
modeStr = "[Debug] "
break
default:
modeStr = "[Info] "
break
}
if logInstance != nil {
msg := fmt.Sprintf(SDK_LOG_PREFIX+modeStr+format+"\n", v...)
logInstance.Print(msg)
} else {
logTime := fmt.Sprintf("[%v]", time.Now().Format("2006-01-02 15:04:05.000"))
fmt.Printf(logTime+SDK_LOG_PREFIX+modeStr+format+"\n", v...)
}
}
func tdLogDebug(format string, v ...interface{}) {
tdLog(TDLogLevelDebug, format, v...)
}
func tdLogInfo(format string, v ...interface{}) {
tdLog(TDLogLevelInfo, format, v...)
}
func tdLogError(format string, v ...interface{}) {
tdLog(TDLogLevelError, format, v...)
}
func tdLogWarning(format string, v ...interface{}) {
tdLog(TDLogLevelWarning, format, v...)
}
// Deprecated: please use thinkingdata.SetLogLevel(thinkingdata.TDLogLevelOff)
type LogType int32
// Deprecated: please use thinkingdata.SetLogLevel(thinkingdata.TDLogLevelOff)
const (
LoggerTypeOff LogType = 1 << 0 // disable log
LoggerTypePrint LogType = 1 << 1 // print on console
LoggerTypeWriteFile LogType = 1 << 2 // print to file
LoggerTypePrintAndWriteFile = LoggerTypePrint | LoggerTypeWriteFile // print both on console and file
)
// Deprecated: please use thinkingdata.SetLogLevel(thinkingdata.TDLogLevelOff)
type LoggerConfig struct {
Type LogType
Path string
}
// Deprecated: please use thinkingdata.SetLogLevel(thinkingdata.TDLogLevelOff)
func SetLoggerConfig(config LoggerConfig) {
if config.Type < LoggerTypeOff || config.Type > LoggerTypePrintAndWriteFile {
fmt.Println(SDK_LOG_PREFIX + "log type error")
return
}
if config.Type&LoggerTypeOff == LoggerTypeOff {
currentLogLevel = TDLogLevelOff
} else {
currentLogLevel = TDLogLevelInfo
}
}

View File

@ -0,0 +1,305 @@
package thinkingdata
import (
"errors"
"sync"
)
const (
Track = "track"
TrackUpdate = "track_update"
TrackOverwrite = "track_overwrite"
UserSet = "user_set"
UserUnset = "user_unset"
UserSetOnce = "user_setOnce"
UserAdd = "user_add"
UserAppend = "user_append"
UserUniqAppend = "user_uniq_append"
UserDel = "user_del"
SdkVersion = "2.0.3"
LibName = "Golang"
)
type Data struct {
IsComplex bool `json:"-"` // properties are nested or not
AccountId string `json:"#account_id,omitempty"`
DistinctId string `json:"#distinct_id,omitempty"`
Type string `json:"#type"`
Time string `json:"#time"`
EventName string `json:"#event_name,omitempty"`
EventId string `json:"#event_id,omitempty"`
FirstCheckId string `json:"#first_check_id,omitempty"`
Ip string `json:"#ip,omitempty"`
UUID string `json:"#uuid,omitempty"`
AppId string `json:"#app_id,omitempty"`
Properties map[string]interface{} `json:"properties"`
}
// TDConsumer define operation interface
type TDConsumer interface {
Add(d Data) error
Flush() error
Close() error
IsStringent() bool // check data or not.
}
type TDAnalytics struct {
consumer TDConsumer
superProperties map[string]interface{}
mutex *sync.RWMutex
dynamicSuperProperties func() map[string]interface{}
}
// New init SDK
func New(c TDConsumer) TDAnalytics {
tdLogInfo("init SDK success")
return TDAnalytics{
consumer: c,
superProperties: make(map[string]interface{}),
mutex: new(sync.RWMutex),
}
}
// GetSuperProperties get common properties
func (ta *TDAnalytics) GetSuperProperties() map[string]interface{} {
result := make(map[string]interface{})
ta.mutex.Lock()
mergeProperties(result, ta.superProperties)
ta.mutex.Unlock()
return result
}
// SetSuperProperties set common properties
func (ta *TDAnalytics) SetSuperProperties(superProperties map[string]interface{}) {
ta.mutex.Lock()
mergeProperties(ta.superProperties, superProperties)
ta.mutex.Unlock()
}
// ClearSuperProperties clear common properties
func (ta *TDAnalytics) ClearSuperProperties() {
ta.mutex.Lock()
ta.superProperties = make(map[string]interface{})
ta.mutex.Unlock()
}
// SetDynamicSuperProperties set common properties dynamically.
// not recommend to add the operation which with a lot of computation
func (ta *TDAnalytics) SetDynamicSuperProperties(action func() map[string]interface{}) {
ta.mutex.Lock()
ta.dynamicSuperProperties = action
ta.mutex.Unlock()
}
// GetDynamicSuperProperties dynamic common properties
func (ta *TDAnalytics) GetDynamicSuperProperties() map[string]interface{} {
result := make(map[string]interface{})
ta.mutex.RLock()
if ta.dynamicSuperProperties != nil {
mergeProperties(result, ta.dynamicSuperProperties())
}
ta.mutex.RUnlock()
return result
}
// Track report ordinary event
func (ta *TDAnalytics) Track(accountId, distinctId, eventName string, properties map[string]interface{}) error {
return ta.track(accountId, distinctId, Track, eventName, "", properties)
}
// TrackFirst report first event
func (ta *TDAnalytics) TrackFirst(accountId, distinctId, eventName, firstCheckId string, properties map[string]interface{}) error {
if len(firstCheckId) == 0 {
msg := "the 'firstCheckId' must be provided"
tdLogInfo(msg)
return errors.New(msg)
}
p := make(map[string]interface{})
mergeProperties(p, properties)
p["#first_check_id"] = firstCheckId
return ta.track(accountId, distinctId, Track, eventName, "", p)
}
// TrackUpdate report updatable event
func (ta *TDAnalytics) TrackUpdate(accountId, distinctId, eventName, eventId string, properties map[string]interface{}) error {
return ta.track(accountId, distinctId, TrackUpdate, eventName, eventId, properties)
}
// TrackOverwrite report overridable event
func (ta *TDAnalytics) TrackOverwrite(accountId, distinctId, eventName, eventId string, properties map[string]interface{}) error {
return ta.track(accountId, distinctId, TrackOverwrite, eventName, eventId, properties)
}
func (ta *TDAnalytics) track(accountId, distinctId, dataType, eventName, eventId string, properties map[string]interface{}) error {
defer func() {
if r := recover(); r != nil {
tdLogError("%+v\ndata: %+v", r, properties)
}
}()
if len(eventName) == 0 {
msg := "the event name must be provided"
tdLogError(msg)
return errors.New(msg)
}
// eventId not be null unless eventType is equal Track.
if len(eventId) == 0 && dataType != Track {
msg := "the event id must be provided"
tdLogError(msg)
return errors.New(msg)
}
p := ta.GetSuperProperties()
dynamicSuperProperties := ta.GetDynamicSuperProperties()
mergeProperties(p, dynamicSuperProperties)
// preset properties has the highest priority
p["#lib"] = LibName
p["#lib_version"] = SdkVersion
// custom properties
mergeProperties(p, properties)
return ta.add(accountId, distinctId, dataType, eventName, eventId, p)
}
// UserSet set user properties. would overwrite existing names.
func (ta *TDAnalytics) UserSet(accountId string, distinctId string, properties map[string]interface{}) error {
return ta.user(accountId, distinctId, UserSet, properties)
}
// UserUnset clear the user properties of users.
func (ta *TDAnalytics) UserUnset(accountId string, distinctId string, s []string) error {
if len(s) == 0 {
msg := "invalid params for UserUnset: keys is nil"
tdLogInfo(msg)
return errors.New(msg)
}
prop := make(map[string]interface{})
for _, v := range s {
prop[v] = 0
}
return ta.user(accountId, distinctId, UserUnset, prop)
}
func (ta *TDAnalytics) UserUnsetWithProperties(accountId string, distinctId string, properties map[string]interface{}) error {
if len(properties) == 0 {
msg := "invalid params for UserUnset: properties is nil"
tdLogInfo(msg)
return errors.New(msg)
}
return ta.user(accountId, distinctId, UserUnset, properties)
}
// UserSetOnce set user properties, If such property had been set before, this message would be neglected.
func (ta *TDAnalytics) UserSetOnce(accountId string, distinctId string, properties map[string]interface{}) error {
return ta.user(accountId, distinctId, UserSetOnce, properties)
}
// UserAdd to accumulate operations against the property.
func (ta *TDAnalytics) UserAdd(accountId string, distinctId string, properties map[string]interface{}) error {
return ta.user(accountId, distinctId, UserAdd, properties)
}
// UserAppend to add user properties of array type.
func (ta *TDAnalytics) UserAppend(accountId string, distinctId string, properties map[string]interface{}) error {
return ta.user(accountId, distinctId, UserAppend, properties)
}
// UserUniqAppend append user properties to array type by unique.
func (ta *TDAnalytics) UserUniqAppend(accountId string, distinctId string, properties map[string]interface{}) error {
return ta.user(accountId, distinctId, UserUniqAppend, properties)
}
// UserDelete delete a user, This operation cannot be undone.
func (ta *TDAnalytics) UserDelete(accountId string, distinctId string) error {
return ta.user(accountId, distinctId, UserDel, nil)
}
// UserDeleteWithProperties delete a user, This operation cannot be undone.
func (ta *TDAnalytics) UserDeleteWithProperties(accountId string, distinctId string, properties map[string]interface{}) error {
return ta.user(accountId, distinctId, UserDel, properties)
}
func (ta *TDAnalytics) user(accountId, distinctId, dataType string, properties map[string]interface{}) error {
defer func() {
if r := recover(); r != nil {
tdLogError("%+v\ndata: %+v", r, properties)
}
}()
if properties == nil && dataType != UserDel {
msg := "invalid params for " + dataType + ": properties is nil"
tdLogError(msg)
return errors.New(msg)
}
p := make(map[string]interface{})
mergeProperties(p, properties)
return ta.add(accountId, distinctId, dataType, "", "", p)
}
// Flush report data immediately.
func (ta *TDAnalytics) Flush() error {
return ta.consumer.Flush()
}
// Close and exit sdk
func (ta *TDAnalytics) Close() error {
err := ta.consumer.Close()
tdLogInfo("SDK close")
return err
}
func (ta *TDAnalytics) add(accountId, distinctId, dataType, eventName, eventId string, properties map[string]interface{}) error {
if len(accountId) == 0 && len(distinctId) == 0 {
msg := "invalid parameters: account_id and distinct_id cannot be empty at the same time"
tdLogError(msg)
return errors.New(msg)
}
// get "#ip" value in properties, empty string will be return when not found.
ip := extractStringProperty(properties, "#ip")
// get "#app_id" value in properties, empty string will be return when not found.
appId := extractStringProperty(properties, "#app_id")
// get "#time" value in properties, empty string will be return when not found.
eventTime := extractTime(properties)
firstCheckId := extractStringProperty(properties, "#first_check_id")
// get "#uuid" value in properties, empty string will be return when not found.
uuid := extractStringProperty(properties, "#uuid")
if len(uuid) == 0 {
uuid = generateUUID()
}
data := Data{
AccountId: accountId,
DistinctId: distinctId,
Type: dataType,
Time: eventTime,
EventName: eventName,
EventId: eventId,
FirstCheckId: firstCheckId,
Ip: ip,
UUID: uuid,
Properties: properties,
}
if len(appId) > 0 {
data.AppId = appId
}
err := formatProperties(&data, ta)
if err != nil {
return err
}
return ta.consumer.Add(data)
}
// Deprecated: please use TDConsumer
type Consumer interface {
TDConsumer
}

View File

@ -0,0 +1,143 @@
package thinkingdata
import (
"errors"
"fmt"
"github.com/google/uuid"
"os"
"reflect"
"regexp"
"time"
)
const (
DATE_FORMAT = "2006-01-02 15:04:05.000"
KEY_PATTERN = "^[a-zA-Z#][A-Za-z0-9_]{0,49}$"
)
// A string of 50 letters and digits that starts with '#' or a letter
var keyPattern, _ = regexp.Compile(KEY_PATTERN)
func mergeProperties(target, source map[string]interface{}) {
for k, v := range source {
target[k] = v
}
}
func extractTime(p map[string]interface{}) string {
if t, ok := p["#time"]; ok {
delete(p, "#time")
switch v := t.(type) {
case string:
return v
case time.Time:
return v.Format(DATE_FORMAT)
default:
return time.Now().Format(DATE_FORMAT)
}
}
return time.Now().Format(DATE_FORMAT)
}
func extractStringProperty(p map[string]interface{}, key string) string {
if t, ok := p[key]; ok {
delete(p, key)
v, ok := t.(string)
if !ok {
fmt.Fprintln(os.Stderr, "Invalid data type for "+key)
}
return v
}
return ""
}
func isNotNumber(v interface{}) bool {
switch v.(type) {
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
case float32, float64:
default:
return true
}
return false
}
func formatProperties(d *Data, ta *TDAnalytics) error {
if d.EventName != "" {
matched := checkPattern([]byte(d.EventName))
if !matched {
msg := "invalid event name: " + d.EventName
tdLogInfo(msg)
return errors.New(msg)
}
}
if d.Properties != nil {
for k, v := range d.Properties {
if ta.consumer.IsStringent() {
isMatch := checkPattern([]byte(k))
if !isMatch {
msg := "invalid property key: " + k
tdLogInfo(msg)
return errors.New(msg)
}
}
if d.Type == UserAdd && isNotNumber(v) {
msg := "invalid property value: only numbers is supported by UserAdd"
tdLogInfo(msg)
return errors.New(msg)
}
// check value
switch v.(type) {
case int:
case bool:
case float64:
case string:
case time.Time:
d.Properties[k] = v.(time.Time).Format(DATE_FORMAT)
case []string:
d.IsComplex = true
default:
d.IsComplex = true
}
}
}
return nil
}
func isNotArrayOrSlice(v interface{}) bool {
typeOf := reflect.TypeOf(v)
switch typeOf.Kind() {
case reflect.Array:
case reflect.Slice:
default:
return true
}
return false
}
func checkPattern(name []byte) bool {
return keyPattern.Match(name)
}
func parseTime(input []byte) string {
var re = regexp.MustCompile(`"((\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}:\d{2})(?:\.(\d{3}))\d*)(Z|[\+-]\d{2}:\d{2})"`)
var substitution = "\"$2 $3.$4\""
for re.Match(input) {
input = re.ReplaceAll(input, []byte(substitution))
}
return string(input)
}
func generateUUID() string {
newUUID, err := uuid.NewUUID()
if err != nil {
return ""
}
return newUUID.String()
}

10
src/server/vendor/github.com/google/uuid/CHANGELOG.md generated vendored Normal file
View File

@ -0,0 +1,10 @@
# Changelog
## [1.3.1](https://github.com/google/uuid/compare/v1.3.0...v1.3.1) (2023-08-18)
### Bug Fixes
* Use .EqualFold() to parse urn prefixed UUIDs ([#118](https://github.com/google/uuid/issues/118)) ([574e687](https://github.com/google/uuid/commit/574e6874943741fb99d41764c705173ada5293f0))
## Changelog

View File

@ -0,0 +1,26 @@
# How to contribute
We definitely welcome patches and contribution to this project!
### Tips
Commits must be formatted according to the [Conventional Commits Specification](https://www.conventionalcommits.org).
Always try to include a test case! If it is not possible or not necessary,
please explain why in the pull request description.
### Releasing
Commits that would precipitate a SemVer change, as desrcibed in the Conventional
Commits Specification, will trigger [`release-please`](https://github.com/google-github-actions/release-please-action)
to create a release candidate pull request. Once submitted, `release-please`
will create a release.
For tips on how to work with `release-please`, see its documentation.
### Legal requirements
In order to protect both you and ourselves, you will need to sign the
[Contributor License Agreement](https://cla.developers.google.com/clas).
You may have already signed it for other Google projects.

View File

@ -0,0 +1,9 @@
Paul Borman <borman@google.com>
bmatsuo
shawnps
theory
jboverfelt
dsymonds
cd1
wallclockbuilder
dansouza

27
src/server/vendor/github.com/google/uuid/LICENSE generated vendored Normal file
View File

@ -0,0 +1,27 @@
Copyright (c) 2009,2014 Google Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

21
src/server/vendor/github.com/google/uuid/README.md generated vendored Normal file
View File

@ -0,0 +1,21 @@
# uuid
The uuid package generates and inspects UUIDs based on
[RFC 4122](https://datatracker.ietf.org/doc/html/rfc4122)
and DCE 1.1: Authentication and Security Services.
This package is based on the github.com/pborman/uuid package (previously named
code.google.com/p/go-uuid). It differs from these earlier packages in that
a UUID is a 16 byte array rather than a byte slice. One loss due to this
change is the ability to represent an invalid UUID (vs a NIL UUID).
###### Install
```sh
go get github.com/google/uuid
```
###### Documentation
[![Go Reference](https://pkg.go.dev/badge/github.com/google/uuid.svg)](https://pkg.go.dev/github.com/google/uuid)
Full `go doc` style documentation for the package can be viewed online without
installing this package by using the GoDoc site here:
http://pkg.go.dev/github.com/google/uuid

80
src/server/vendor/github.com/google/uuid/dce.go generated vendored Normal file
View File

@ -0,0 +1,80 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"encoding/binary"
"fmt"
"os"
)
// A Domain represents a Version 2 domain
type Domain byte
// Domain constants for DCE Security (Version 2) UUIDs.
const (
Person = Domain(0)
Group = Domain(1)
Org = Domain(2)
)
// NewDCESecurity returns a DCE Security (Version 2) UUID.
//
// The domain should be one of Person, Group or Org.
// On a POSIX system the id should be the users UID for the Person
// domain and the users GID for the Group. The meaning of id for
// the domain Org or on non-POSIX systems is site defined.
//
// For a given domain/id pair the same token may be returned for up to
// 7 minutes and 10 seconds.
func NewDCESecurity(domain Domain, id uint32) (UUID, error) {
uuid, err := NewUUID()
if err == nil {
uuid[6] = (uuid[6] & 0x0f) | 0x20 // Version 2
uuid[9] = byte(domain)
binary.BigEndian.PutUint32(uuid[0:], id)
}
return uuid, err
}
// NewDCEPerson returns a DCE Security (Version 2) UUID in the person
// domain with the id returned by os.Getuid.
//
// NewDCESecurity(Person, uint32(os.Getuid()))
func NewDCEPerson() (UUID, error) {
return NewDCESecurity(Person, uint32(os.Getuid()))
}
// NewDCEGroup returns a DCE Security (Version 2) UUID in the group
// domain with the id returned by os.Getgid.
//
// NewDCESecurity(Group, uint32(os.Getgid()))
func NewDCEGroup() (UUID, error) {
return NewDCESecurity(Group, uint32(os.Getgid()))
}
// Domain returns the domain for a Version 2 UUID. Domains are only defined
// for Version 2 UUIDs.
func (uuid UUID) Domain() Domain {
return Domain(uuid[9])
}
// ID returns the id for a Version 2 UUID. IDs are only defined for Version 2
// UUIDs.
func (uuid UUID) ID() uint32 {
return binary.BigEndian.Uint32(uuid[0:4])
}
func (d Domain) String() string {
switch d {
case Person:
return "Person"
case Group:
return "Group"
case Org:
return "Org"
}
return fmt.Sprintf("Domain%d", int(d))
}

12
src/server/vendor/github.com/google/uuid/doc.go generated vendored Normal file
View File

@ -0,0 +1,12 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package uuid generates and inspects UUIDs.
//
// UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security
// Services.
//
// A UUID is a 16 byte (128 bit) array. UUIDs may be used as keys to
// maps or compared directly.
package uuid

53
src/server/vendor/github.com/google/uuid/hash.go generated vendored Normal file
View File

@ -0,0 +1,53 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"crypto/md5"
"crypto/sha1"
"hash"
)
// Well known namespace IDs and UUIDs
var (
NameSpaceDNS = Must(Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8"))
NameSpaceURL = Must(Parse("6ba7b811-9dad-11d1-80b4-00c04fd430c8"))
NameSpaceOID = Must(Parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8"))
NameSpaceX500 = Must(Parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8"))
Nil UUID // empty UUID, all zeros
)
// NewHash returns a new UUID derived from the hash of space concatenated with
// data generated by h. The hash should be at least 16 byte in length. The
// first 16 bytes of the hash are used to form the UUID. The version of the
// UUID will be the lower 4 bits of version. NewHash is used to implement
// NewMD5 and NewSHA1.
func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID {
h.Reset()
h.Write(space[:]) //nolint:errcheck
h.Write(data) //nolint:errcheck
s := h.Sum(nil)
var uuid UUID
copy(uuid[:], s)
uuid[6] = (uuid[6] & 0x0f) | uint8((version&0xf)<<4)
uuid[8] = (uuid[8] & 0x3f) | 0x80 // RFC 4122 variant
return uuid
}
// NewMD5 returns a new MD5 (Version 3) UUID based on the
// supplied name space and data. It is the same as calling:
//
// NewHash(md5.New(), space, data, 3)
func NewMD5(space UUID, data []byte) UUID {
return NewHash(md5.New(), space, data, 3)
}
// NewSHA1 returns a new SHA1 (Version 5) UUID based on the
// supplied name space and data. It is the same as calling:
//
// NewHash(sha1.New(), space, data, 5)
func NewSHA1(space UUID, data []byte) UUID {
return NewHash(sha1.New(), space, data, 5)
}

38
src/server/vendor/github.com/google/uuid/marshal.go generated vendored Normal file
View File

@ -0,0 +1,38 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import "fmt"
// MarshalText implements encoding.TextMarshaler.
func (uuid UUID) MarshalText() ([]byte, error) {
var js [36]byte
encodeHex(js[:], uuid)
return js[:], nil
}
// UnmarshalText implements encoding.TextUnmarshaler.
func (uuid *UUID) UnmarshalText(data []byte) error {
id, err := ParseBytes(data)
if err != nil {
return err
}
*uuid = id
return nil
}
// MarshalBinary implements encoding.BinaryMarshaler.
func (uuid UUID) MarshalBinary() ([]byte, error) {
return uuid[:], nil
}
// UnmarshalBinary implements encoding.BinaryUnmarshaler.
func (uuid *UUID) UnmarshalBinary(data []byte) error {
if len(data) != 16 {
return fmt.Errorf("invalid UUID (got %d bytes)", len(data))
}
copy(uuid[:], data)
return nil
}

90
src/server/vendor/github.com/google/uuid/node.go generated vendored Normal file
View File

@ -0,0 +1,90 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"sync"
)
var (
nodeMu sync.Mutex
ifname string // name of interface being used
nodeID [6]byte // hardware for version 1 UUIDs
zeroID [6]byte // nodeID with only 0's
)
// NodeInterface returns the name of the interface from which the NodeID was
// derived. The interface "user" is returned if the NodeID was set by
// SetNodeID.
func NodeInterface() string {
defer nodeMu.Unlock()
nodeMu.Lock()
return ifname
}
// SetNodeInterface selects the hardware address to be used for Version 1 UUIDs.
// If name is "" then the first usable interface found will be used or a random
// Node ID will be generated. If a named interface cannot be found then false
// is returned.
//
// SetNodeInterface never fails when name is "".
func SetNodeInterface(name string) bool {
defer nodeMu.Unlock()
nodeMu.Lock()
return setNodeInterface(name)
}
func setNodeInterface(name string) bool {
iname, addr := getHardwareInterface(name) // null implementation for js
if iname != "" && addr != nil {
ifname = iname
copy(nodeID[:], addr)
return true
}
// We found no interfaces with a valid hardware address. If name
// does not specify a specific interface generate a random Node ID
// (section 4.1.6)
if name == "" {
ifname = "random"
randomBits(nodeID[:])
return true
}
return false
}
// NodeID returns a slice of a copy of the current Node ID, setting the Node ID
// if not already set.
func NodeID() []byte {
defer nodeMu.Unlock()
nodeMu.Lock()
if nodeID == zeroID {
setNodeInterface("")
}
nid := nodeID
return nid[:]
}
// SetNodeID sets the Node ID to be used for Version 1 UUIDs. The first 6 bytes
// of id are used. If id is less than 6 bytes then false is returned and the
// Node ID is not set.
func SetNodeID(id []byte) bool {
if len(id) < 6 {
return false
}
defer nodeMu.Unlock()
nodeMu.Lock()
copy(nodeID[:], id)
ifname = "user"
return true
}
// NodeID returns the 6 byte node id encoded in uuid. It returns nil if uuid is
// not valid. The NodeID is only well defined for version 1 and 2 UUIDs.
func (uuid UUID) NodeID() []byte {
var node [6]byte
copy(node[:], uuid[10:])
return node[:]
}

12
src/server/vendor/github.com/google/uuid/node_js.go generated vendored Normal file
View File

@ -0,0 +1,12 @@
// Copyright 2017 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build js
package uuid
// getHardwareInterface returns nil values for the JS version of the code.
// This removes the "net" dependency, because it is not used in the browser.
// Using the "net" library inflates the size of the transpiled JS code by 673k bytes.
func getHardwareInterface(name string) (string, []byte) { return "", nil }

33
src/server/vendor/github.com/google/uuid/node_net.go generated vendored Normal file
View File

@ -0,0 +1,33 @@
// Copyright 2017 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !js
package uuid
import "net"
var interfaces []net.Interface // cached list of interfaces
// getHardwareInterface returns the name and hardware address of interface name.
// If name is "" then the name and hardware address of one of the system's
// interfaces is returned. If no interfaces are found (name does not exist or
// there are no interfaces) then "", nil is returned.
//
// Only addresses of at least 6 bytes are returned.
func getHardwareInterface(name string) (string, []byte) {
if interfaces == nil {
var err error
interfaces, err = net.Interfaces()
if err != nil {
return "", nil
}
}
for _, ifs := range interfaces {
if len(ifs.HardwareAddr) >= 6 && (name == "" || name == ifs.Name) {
return ifs.Name, ifs.HardwareAddr
}
}
return "", nil
}

118
src/server/vendor/github.com/google/uuid/null.go generated vendored Normal file
View File

@ -0,0 +1,118 @@
// Copyright 2021 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"bytes"
"database/sql/driver"
"encoding/json"
"fmt"
)
var jsonNull = []byte("null")
// NullUUID represents a UUID that may be null.
// NullUUID implements the SQL driver.Scanner interface so
// it can be used as a scan destination:
//
// var u uuid.NullUUID
// err := db.QueryRow("SELECT name FROM foo WHERE id=?", id).Scan(&u)
// ...
// if u.Valid {
// // use u.UUID
// } else {
// // NULL value
// }
//
type NullUUID struct {
UUID UUID
Valid bool // Valid is true if UUID is not NULL
}
// Scan implements the SQL driver.Scanner interface.
func (nu *NullUUID) Scan(value interface{}) error {
if value == nil {
nu.UUID, nu.Valid = Nil, false
return nil
}
err := nu.UUID.Scan(value)
if err != nil {
nu.Valid = false
return err
}
nu.Valid = true
return nil
}
// Value implements the driver Valuer interface.
func (nu NullUUID) Value() (driver.Value, error) {
if !nu.Valid {
return nil, nil
}
// Delegate to UUID Value function
return nu.UUID.Value()
}
// MarshalBinary implements encoding.BinaryMarshaler.
func (nu NullUUID) MarshalBinary() ([]byte, error) {
if nu.Valid {
return nu.UUID[:], nil
}
return []byte(nil), nil
}
// UnmarshalBinary implements encoding.BinaryUnmarshaler.
func (nu *NullUUID) UnmarshalBinary(data []byte) error {
if len(data) != 16 {
return fmt.Errorf("invalid UUID (got %d bytes)", len(data))
}
copy(nu.UUID[:], data)
nu.Valid = true
return nil
}
// MarshalText implements encoding.TextMarshaler.
func (nu NullUUID) MarshalText() ([]byte, error) {
if nu.Valid {
return nu.UUID.MarshalText()
}
return jsonNull, nil
}
// UnmarshalText implements encoding.TextUnmarshaler.
func (nu *NullUUID) UnmarshalText(data []byte) error {
id, err := ParseBytes(data)
if err != nil {
nu.Valid = false
return err
}
nu.UUID = id
nu.Valid = true
return nil
}
// MarshalJSON implements json.Marshaler.
func (nu NullUUID) MarshalJSON() ([]byte, error) {
if nu.Valid {
return json.Marshal(nu.UUID)
}
return jsonNull, nil
}
// UnmarshalJSON implements json.Unmarshaler.
func (nu *NullUUID) UnmarshalJSON(data []byte) error {
if bytes.Equal(data, jsonNull) {
*nu = NullUUID{}
return nil // valid null UUID
}
err := json.Unmarshal(data, &nu.UUID)
nu.Valid = err == nil
return err
}

59
src/server/vendor/github.com/google/uuid/sql.go generated vendored Normal file
View File

@ -0,0 +1,59 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"database/sql/driver"
"fmt"
)
// Scan implements sql.Scanner so UUIDs can be read from databases transparently.
// Currently, database types that map to string and []byte are supported. Please
// consult database-specific driver documentation for matching types.
func (uuid *UUID) Scan(src interface{}) error {
switch src := src.(type) {
case nil:
return nil
case string:
// if an empty UUID comes from a table, we return a null UUID
if src == "" {
return nil
}
// see Parse for required string format
u, err := Parse(src)
if err != nil {
return fmt.Errorf("Scan: %v", err)
}
*uuid = u
case []byte:
// if an empty UUID comes from a table, we return a null UUID
if len(src) == 0 {
return nil
}
// assumes a simple slice of bytes if 16 bytes
// otherwise attempts to parse
if len(src) != 16 {
return uuid.Scan(string(src))
}
copy((*uuid)[:], src)
default:
return fmt.Errorf("Scan: unable to scan type %T into UUID", src)
}
return nil
}
// Value implements sql.Valuer so that UUIDs can be written to databases
// transparently. Currently, UUIDs map to strings. Please consult
// database-specific driver documentation for matching types.
func (uuid UUID) Value() (driver.Value, error) {
return uuid.String(), nil
}

123
src/server/vendor/github.com/google/uuid/time.go generated vendored Normal file
View File

@ -0,0 +1,123 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"encoding/binary"
"sync"
"time"
)
// A Time represents a time as the number of 100's of nanoseconds since 15 Oct
// 1582.
type Time int64
const (
lillian = 2299160 // Julian day of 15 Oct 1582
unix = 2440587 // Julian day of 1 Jan 1970
epoch = unix - lillian // Days between epochs
g1582 = epoch * 86400 // seconds between epochs
g1582ns100 = g1582 * 10000000 // 100s of a nanoseconds between epochs
)
var (
timeMu sync.Mutex
lasttime uint64 // last time we returned
clockSeq uint16 // clock sequence for this run
timeNow = time.Now // for testing
)
// UnixTime converts t the number of seconds and nanoseconds using the Unix
// epoch of 1 Jan 1970.
func (t Time) UnixTime() (sec, nsec int64) {
sec = int64(t - g1582ns100)
nsec = (sec % 10000000) * 100
sec /= 10000000
return sec, nsec
}
// GetTime returns the current Time (100s of nanoseconds since 15 Oct 1582) and
// clock sequence as well as adjusting the clock sequence as needed. An error
// is returned if the current time cannot be determined.
func GetTime() (Time, uint16, error) {
defer timeMu.Unlock()
timeMu.Lock()
return getTime()
}
func getTime() (Time, uint16, error) {
t := timeNow()
// If we don't have a clock sequence already, set one.
if clockSeq == 0 {
setClockSequence(-1)
}
now := uint64(t.UnixNano()/100) + g1582ns100
// If time has gone backwards with this clock sequence then we
// increment the clock sequence
if now <= lasttime {
clockSeq = ((clockSeq + 1) & 0x3fff) | 0x8000
}
lasttime = now
return Time(now), clockSeq, nil
}
// ClockSequence returns the current clock sequence, generating one if not
// already set. The clock sequence is only used for Version 1 UUIDs.
//
// The uuid package does not use global static storage for the clock sequence or
// the last time a UUID was generated. Unless SetClockSequence is used, a new
// random clock sequence is generated the first time a clock sequence is
// requested by ClockSequence, GetTime, or NewUUID. (section 4.2.1.1)
func ClockSequence() int {
defer timeMu.Unlock()
timeMu.Lock()
return clockSequence()
}
func clockSequence() int {
if clockSeq == 0 {
setClockSequence(-1)
}
return int(clockSeq & 0x3fff)
}
// SetClockSequence sets the clock sequence to the lower 14 bits of seq. Setting to
// -1 causes a new sequence to be generated.
func SetClockSequence(seq int) {
defer timeMu.Unlock()
timeMu.Lock()
setClockSequence(seq)
}
func setClockSequence(seq int) {
if seq == -1 {
var b [2]byte
randomBits(b[:]) // clock sequence
seq = int(b[0])<<8 | int(b[1])
}
oldSeq := clockSeq
clockSeq = uint16(seq&0x3fff) | 0x8000 // Set our variant
if oldSeq != clockSeq {
lasttime = 0
}
}
// Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in
// uuid. The time is only defined for version 1 and 2 UUIDs.
func (uuid UUID) Time() Time {
time := int64(binary.BigEndian.Uint32(uuid[0:4]))
time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32
time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48
return Time(time)
}
// ClockSequence returns the clock sequence encoded in uuid.
// The clock sequence is only well defined for version 1 and 2 UUIDs.
func (uuid UUID) ClockSequence() int {
return int(binary.BigEndian.Uint16(uuid[8:10])) & 0x3fff
}

43
src/server/vendor/github.com/google/uuid/util.go generated vendored Normal file
View File

@ -0,0 +1,43 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"io"
)
// randomBits completely fills slice b with random data.
func randomBits(b []byte) {
if _, err := io.ReadFull(rander, b); err != nil {
panic(err.Error()) // rand should never fail
}
}
// xvalues returns the value of a byte as a hexadecimal digit or 255.
var xvalues = [256]byte{
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255,
255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
}
// xtob converts hex characters x1 and x2 into a byte.
func xtob(x1, x2 byte) (byte, bool) {
b1 := xvalues[x1]
b2 := xvalues[x2]
return (b1 << 4) | b2, b1 != 255 && b2 != 255
}

296
src/server/vendor/github.com/google/uuid/uuid.go generated vendored Normal file
View File

@ -0,0 +1,296 @@
// Copyright 2018 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"bytes"
"crypto/rand"
"encoding/hex"
"errors"
"fmt"
"io"
"strings"
"sync"
)
// A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC
// 4122.
type UUID [16]byte
// A Version represents a UUID's version.
type Version byte
// A Variant represents a UUID's variant.
type Variant byte
// Constants returned by Variant.
const (
Invalid = Variant(iota) // Invalid UUID
RFC4122 // The variant specified in RFC4122
Reserved // Reserved, NCS backward compatibility.
Microsoft // Reserved, Microsoft Corporation backward compatibility.
Future // Reserved for future definition.
)
const randPoolSize = 16 * 16
var (
rander = rand.Reader // random function
poolEnabled = false
poolMu sync.Mutex
poolPos = randPoolSize // protected with poolMu
pool [randPoolSize]byte // protected with poolMu
)
type invalidLengthError struct{ len int }
func (err invalidLengthError) Error() string {
return fmt.Sprintf("invalid UUID length: %d", err.len)
}
// IsInvalidLengthError is matcher function for custom error invalidLengthError
func IsInvalidLengthError(err error) bool {
_, ok := err.(invalidLengthError)
return ok
}
// Parse decodes s into a UUID or returns an error. Both the standard UUID
// forms of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded as well as the
// Microsoft encoding {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} and the raw hex
// encoding: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
func Parse(s string) (UUID, error) {
var uuid UUID
switch len(s) {
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
case 36:
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
case 36 + 9:
if !strings.EqualFold(s[:9], "urn:uuid:") {
return uuid, fmt.Errorf("invalid urn prefix: %q", s[:9])
}
s = s[9:]
// {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
case 36 + 2:
s = s[1:]
// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
case 32:
var ok bool
for i := range uuid {
uuid[i], ok = xtob(s[i*2], s[i*2+1])
if !ok {
return uuid, errors.New("invalid UUID format")
}
}
return uuid, nil
default:
return uuid, invalidLengthError{len(s)}
}
// s is now at least 36 bytes long
// it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
return uuid, errors.New("invalid UUID format")
}
for i, x := range [16]int{
0, 2, 4, 6,
9, 11,
14, 16,
19, 21,
24, 26, 28, 30, 32, 34,
} {
v, ok := xtob(s[x], s[x+1])
if !ok {
return uuid, errors.New("invalid UUID format")
}
uuid[i] = v
}
return uuid, nil
}
// ParseBytes is like Parse, except it parses a byte slice instead of a string.
func ParseBytes(b []byte) (UUID, error) {
var uuid UUID
switch len(b) {
case 36: // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
case 36 + 9: // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
if !bytes.EqualFold(b[:9], []byte("urn:uuid:")) {
return uuid, fmt.Errorf("invalid urn prefix: %q", b[:9])
}
b = b[9:]
case 36 + 2: // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
b = b[1:]
case 32: // xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
var ok bool
for i := 0; i < 32; i += 2 {
uuid[i/2], ok = xtob(b[i], b[i+1])
if !ok {
return uuid, errors.New("invalid UUID format")
}
}
return uuid, nil
default:
return uuid, invalidLengthError{len(b)}
}
// s is now at least 36 bytes long
// it must be of the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
if b[8] != '-' || b[13] != '-' || b[18] != '-' || b[23] != '-' {
return uuid, errors.New("invalid UUID format")
}
for i, x := range [16]int{
0, 2, 4, 6,
9, 11,
14, 16,
19, 21,
24, 26, 28, 30, 32, 34,
} {
v, ok := xtob(b[x], b[x+1])
if !ok {
return uuid, errors.New("invalid UUID format")
}
uuid[i] = v
}
return uuid, nil
}
// MustParse is like Parse but panics if the string cannot be parsed.
// It simplifies safe initialization of global variables holding compiled UUIDs.
func MustParse(s string) UUID {
uuid, err := Parse(s)
if err != nil {
panic(`uuid: Parse(` + s + `): ` + err.Error())
}
return uuid
}
// FromBytes creates a new UUID from a byte slice. Returns an error if the slice
// does not have a length of 16. The bytes are copied from the slice.
func FromBytes(b []byte) (uuid UUID, err error) {
err = uuid.UnmarshalBinary(b)
return uuid, err
}
// Must returns uuid if err is nil and panics otherwise.
func Must(uuid UUID, err error) UUID {
if err != nil {
panic(err)
}
return uuid
}
// String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
// , or "" if uuid is invalid.
func (uuid UUID) String() string {
var buf [36]byte
encodeHex(buf[:], uuid)
return string(buf[:])
}
// URN returns the RFC 2141 URN form of uuid,
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, or "" if uuid is invalid.
func (uuid UUID) URN() string {
var buf [36 + 9]byte
copy(buf[:], "urn:uuid:")
encodeHex(buf[9:], uuid)
return string(buf[:])
}
func encodeHex(dst []byte, uuid UUID) {
hex.Encode(dst, uuid[:4])
dst[8] = '-'
hex.Encode(dst[9:13], uuid[4:6])
dst[13] = '-'
hex.Encode(dst[14:18], uuid[6:8])
dst[18] = '-'
hex.Encode(dst[19:23], uuid[8:10])
dst[23] = '-'
hex.Encode(dst[24:], uuid[10:])
}
// Variant returns the variant encoded in uuid.
func (uuid UUID) Variant() Variant {
switch {
case (uuid[8] & 0xc0) == 0x80:
return RFC4122
case (uuid[8] & 0xe0) == 0xc0:
return Microsoft
case (uuid[8] & 0xe0) == 0xe0:
return Future
default:
return Reserved
}
}
// Version returns the version of uuid.
func (uuid UUID) Version() Version {
return Version(uuid[6] >> 4)
}
func (v Version) String() string {
if v > 15 {
return fmt.Sprintf("BAD_VERSION_%d", v)
}
return fmt.Sprintf("VERSION_%d", v)
}
func (v Variant) String() string {
switch v {
case RFC4122:
return "RFC4122"
case Reserved:
return "Reserved"
case Microsoft:
return "Microsoft"
case Future:
return "Future"
case Invalid:
return "Invalid"
}
return fmt.Sprintf("BadVariant%d", int(v))
}
// SetRand sets the random number generator to r, which implements io.Reader.
// If r.Read returns an error when the package requests random data then
// a panic will be issued.
//
// Calling SetRand with nil sets the random number generator to the default
// generator.
func SetRand(r io.Reader) {
if r == nil {
rander = rand.Reader
return
}
rander = r
}
// EnableRandPool enables internal randomness pool used for Random
// (Version 4) UUID generation. The pool contains random bytes read from
// the random number generator on demand in batches. Enabling the pool
// may improve the UUID generation throughput significantly.
//
// Since the pool is stored on the Go heap, this feature may be a bad fit
// for security sensitive applications.
//
// Both EnableRandPool and DisableRandPool are not thread-safe and should
// only be called when there is no possibility that New or any other
// UUID Version 4 generation function will be called concurrently.
func EnableRandPool() {
poolEnabled = true
}
// DisableRandPool disables the randomness pool if it was previously
// enabled with EnableRandPool.
//
// Both EnableRandPool and DisableRandPool are not thread-safe and should
// only be called when there is no possibility that New or any other
// UUID Version 4 generation function will be called concurrently.
func DisableRandPool() {
poolEnabled = false
defer poolMu.Unlock()
poolMu.Lock()
poolPos = randPoolSize
}

44
src/server/vendor/github.com/google/uuid/version1.go generated vendored Normal file
View File

@ -0,0 +1,44 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"encoding/binary"
)
// NewUUID returns a Version 1 UUID based on the current NodeID and clock
// sequence, and the current time. If the NodeID has not been set by SetNodeID
// or SetNodeInterface then it will be set automatically. If the NodeID cannot
// be set NewUUID returns nil. If clock sequence has not been set by
// SetClockSequence then it will be set automatically. If GetTime fails to
// return the current NewUUID returns nil and an error.
//
// In most cases, New should be used.
func NewUUID() (UUID, error) {
var uuid UUID
now, seq, err := GetTime()
if err != nil {
return uuid, err
}
timeLow := uint32(now & 0xffffffff)
timeMid := uint16((now >> 32) & 0xffff)
timeHi := uint16((now >> 48) & 0x0fff)
timeHi |= 0x1000 // Version 1
binary.BigEndian.PutUint32(uuid[0:], timeLow)
binary.BigEndian.PutUint16(uuid[4:], timeMid)
binary.BigEndian.PutUint16(uuid[6:], timeHi)
binary.BigEndian.PutUint16(uuid[8:], seq)
nodeMu.Lock()
if nodeID == zeroID {
setNodeInterface("")
}
copy(uuid[10:], nodeID[:])
nodeMu.Unlock()
return uuid, nil
}

76
src/server/vendor/github.com/google/uuid/version4.go generated vendored Normal file
View File

@ -0,0 +1,76 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import "io"
// New creates a new random UUID or panics. New is equivalent to
// the expression
//
// uuid.Must(uuid.NewRandom())
func New() UUID {
return Must(NewRandom())
}
// NewString creates a new random UUID and returns it as a string or panics.
// NewString is equivalent to the expression
//
// uuid.New().String()
func NewString() string {
return Must(NewRandom()).String()
}
// NewRandom returns a Random (Version 4) UUID.
//
// The strength of the UUIDs is based on the strength of the crypto/rand
// package.
//
// Uses the randomness pool if it was enabled with EnableRandPool.
//
// A note about uniqueness derived from the UUID Wikipedia entry:
//
// Randomly generated UUIDs have 122 random bits. One's annual risk of being
// hit by a meteorite is estimated to be one chance in 17 billion, that
// means the probability is about 0.00000000006 (6 × 1011),
// equivalent to the odds of creating a few tens of trillions of UUIDs in a
// year and having one duplicate.
func NewRandom() (UUID, error) {
if !poolEnabled {
return NewRandomFromReader(rander)
}
return newRandomFromPool()
}
// NewRandomFromReader returns a UUID based on bytes read from a given io.Reader.
func NewRandomFromReader(r io.Reader) (UUID, error) {
var uuid UUID
_, err := io.ReadFull(r, uuid[:])
if err != nil {
return Nil, err
}
uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4
uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10
return uuid, nil
}
func newRandomFromPool() (UUID, error) {
var uuid UUID
poolMu.Lock()
if poolPos == randPoolSize {
_, err := io.ReadFull(rander, pool[:])
if err != nil {
poolMu.Unlock()
return Nil, err
}
poolPos = 0
}
copy(uuid[:], pool[poolPos:(poolPos+16)])
poolPos += 16
poolMu.Unlock()
uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4
uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10
return uuid, nil
}

View File

@ -2,6 +2,11 @@
## explicit; go 1.20
filippo.io/edwards25519
filippo.io/edwards25519/field
# github.com/ThinkingDataAnalytics/go-sdk v1.7.0
## explicit; go 1.14
# github.com/ThinkingDataAnalytics/go-sdk/v2 v2.0.3
## explicit; go 1.14
github.com/ThinkingDataAnalytics/go-sdk/v2/src/thinkingdata
# github.com/cespare/xxhash/v2 v2.2.0
## explicit; go 1.11
github.com/cespare/xxhash/v2
@ -13,6 +18,9 @@ github.com/dgryski/go-rendezvous
github.com/go-sql-driver/mysql
# github.com/google/go-cmp v0.6.0
## explicit; go 1.13
# github.com/google/uuid v1.3.1
## explicit
github.com/google/uuid
# github.com/gorilla/mux v1.8.1
## explicit; go 1.20
github.com/gorilla/mux