@@ -0,0 +1,8 @@ | |||||
# 默认忽略的文件 | |||||
/shelf/ | |||||
/workspace.xml | |||||
# 基于编辑器的 HTTP 客户端请求 | |||||
/httpRequests/ | |||||
# Datasource local storage ignored files | |||||
/dataSources/ | |||||
/dataSources.local.xml |
@@ -0,0 +1,8 @@ | |||||
<?xml version="1.0" encoding="UTF-8"?> | |||||
<project version="4"> | |||||
<component name="ProjectModuleManager"> | |||||
<modules> | |||||
<module fileurl="file://$PROJECT_DIR$/.idea/zyos_go_order_relate_rule.iml" filepath="$PROJECT_DIR$/.idea/zyos_go_order_relate_rule.iml" /> | |||||
</modules> | |||||
</component> | |||||
</project> |
@@ -0,0 +1,6 @@ | |||||
<?xml version="1.0" encoding="UTF-8"?> | |||||
<project version="4"> | |||||
<component name="VcsDirectoryMappings"> | |||||
<mapping directory="$PROJECT_DIR$" vcs="Git" /> | |||||
</component> | |||||
</project> |
@@ -0,0 +1,9 @@ | |||||
<?xml version="1.0" encoding="UTF-8"?> | |||||
<module type="WEB_MODULE" version="4"> | |||||
<component name="Go" enabled="true" /> | |||||
<component name="NewModuleRootManager"> | |||||
<content url="file://$MODULE_DIR$" /> | |||||
<orderEntry type="inheritedJdk" /> | |||||
<orderEntry type="sourceFolder" forTests="false" /> | |||||
</component> | |||||
</module> |
@@ -0,0 +1,57 @@ | |||||
package db | |||||
import ( | |||||
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/db/model" | |||||
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/md" | |||||
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/utils/cache" | |||||
zhios_order_relate_logx "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/utils/logx" | |||||
"fmt" | |||||
"xorm.io/xorm" | |||||
) | |||||
// 系统配置get | |||||
func SysCfgGetAll(Db *xorm.Engine) (*[]model.SysCfg, error) { | |||||
var cfgList []model.SysCfg | |||||
if err := Db.Cols("key,val,memo").Find(&cfgList); err != nil { | |||||
return nil, zhios_order_relate_logx.Error(err) | |||||
} | |||||
return &cfgList, nil | |||||
} | |||||
// 获取一条记录 | |||||
func SysCfgGetOne(Db *xorm.Engine, key string) (*model.SysCfg, error) { | |||||
var cfgList model.SysCfg | |||||
if has, err := Db.Where("`key`=?", key).Get(&cfgList); err != nil || has == false { | |||||
return nil, zhios_order_relate_logx.Error(err) | |||||
} | |||||
return &cfgList, nil | |||||
} | |||||
// 多条记录获取DB | |||||
func SysCfgFindWithDb(eg *xorm.Engine, masterId string, keys ...string) map[string]string { | |||||
res := map[string]string{} | |||||
cacheKey := fmt.Sprintf(md.AppCfgCacheKey, masterId) | |||||
err := cache.GetJson(cacheKey, &res) | |||||
if err != nil || len(res) == 0 { | |||||
cfgList, _ := SysCfgGetAll(eg) | |||||
if cfgList == nil { | |||||
return nil | |||||
} | |||||
for _, v := range *cfgList { | |||||
res[v.Key] = v.Val | |||||
} | |||||
cache.SetJson(cacheKey, res, md.CfgCacheTime) | |||||
} | |||||
if len(keys) == 0 { | |||||
return res | |||||
} | |||||
tmp := map[string]string{} | |||||
for _, v := range keys { | |||||
if val, ok := res[v]; ok { | |||||
tmp[v] = val | |||||
} else { | |||||
tmp[v] = "" | |||||
} | |||||
} | |||||
return tmp | |||||
} |
@@ -0,0 +1,17 @@ | |||||
package db | |||||
import ( | |||||
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/db/model" | |||||
zhios_order_relate_logx "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/utils/logx" | |||||
"xorm.io/xorm" | |||||
) | |||||
// UserFindByID is find user byid | |||||
func UserFindByID(Db *xorm.Engine, id interface{}) (*model.User, error) { | |||||
var m model.User | |||||
if has, err := Db.Where("uid = ?", id). | |||||
Get(&m); err != nil || has == false { | |||||
return nil, zhios_order_relate_logx.Warn(err) | |||||
} | |||||
return &m, nil | |||||
} |
@@ -0,0 +1,27 @@ | |||||
package db | |||||
import ( | |||||
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/db/model" | |||||
zhios_order_relate_logx "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/utils/logx" | |||||
"xorm.io/xorm" | |||||
) | |||||
//UserLevelInIDescByWeight is In 查询获取 权重最低 对应等级 | |||||
func UserLevelInIDescByWeightLow(Db *xorm.Engine) ([]*model.UserLevel, error) { | |||||
var ms []*model.UserLevel | |||||
if err := Db.Asc("level_weight").Limit(1).Find(&ms); err != nil { | |||||
return nil, err | |||||
} | |||||
return ms, nil | |||||
} | |||||
// UserLevlEgAll is 获取所有开启等级并且升序返回 | |||||
func UserLevlEgAll(Db *xorm.Engine) ([]*model.UserLevel, error) { | |||||
var m []*model.UserLevel | |||||
err := Db.Where("is_use = ?", 1).Asc("level_weight").Find(&m) | |||||
if err != nil { | |||||
return nil, zhios_order_relate_logx.Warn(err) | |||||
} | |||||
return m, nil | |||||
} |
@@ -0,0 +1,26 @@ | |||||
package db | |||||
import ( | |||||
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/db/model" | |||||
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/md" | |||||
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/utils/cache" | |||||
"fmt" | |||||
"xorm.io/xorm" | |||||
) | |||||
// VirtualCoinListInUse 查询正在使用中的虚拟币 | |||||
func VirtualCoinListInUse(Db *xorm.Engine, masterId string) ([]*model.VirtualCoin, error) { | |||||
var m []*model.VirtualCoin | |||||
cacheKey := fmt.Sprintf(md.VirtualCoinCfgCacheKey, masterId) | |||||
err := cache.GetJson(cacheKey, &m) | |||||
if err != nil || len(m) == 0 { | |||||
err := Db.Where("is_use=1").Find(&m) | |||||
if err != nil { | |||||
return nil, err | |||||
} | |||||
cache.SetJson(cacheKey, m, md.CfgCacheTime) | |||||
} | |||||
return m, nil | |||||
} |
@@ -0,0 +1,29 @@ | |||||
package db | |||||
import ( | |||||
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/db/model" | |||||
zhios_order_relate_logx "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/utils/logx" | |||||
"xorm.io/xorm" | |||||
) | |||||
func DbsPlanCommissionById(eg *xorm.Engine, id int) (*model.PlanCommission, error) { | |||||
var m model.PlanCommission | |||||
if isGet, err := eg.Where("id = ?", id).Get(&m); err != nil || !isGet { | |||||
return nil, zhios_order_relate_logx.Warn(err) | |||||
} | |||||
return &m, nil | |||||
} | |||||
func DbsPlanCommissionByIds(eg *xorm.Engine, ids ...int) []*model.PlanCommission { | |||||
var m []*model.PlanCommission | |||||
var err error | |||||
if len(ids) > 0 { | |||||
err = eg.In("id", ids).Find(&m) | |||||
} else { | |||||
err = eg.Find(&m) | |||||
} | |||||
if err != nil { | |||||
return nil | |||||
} | |||||
return m | |||||
} |
@@ -0,0 +1,31 @@ | |||||
package db | |||||
import ( | |||||
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/db/model" | |||||
zhios_order_relate_logx "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/utils/logx" | |||||
"xorm.io/xorm" | |||||
) | |||||
func DbsPlanRewardByPvd(eg *xorm.Engine, pvd string) (*model.PlanReward, error) { | |||||
m := &model.PlanReward{} | |||||
if isGet, err := eg.Where("pvd = ?", pvd).Get(m); err != nil || !isGet { | |||||
return nil, zhios_order_relate_logx.Warn(err) | |||||
} | |||||
return m, nil | |||||
} | |||||
func DbsPlanRewardByPvds(eg *xorm.Engine, pvds ...string) ([]*model.PlanReward, error) { | |||||
var m []*model.PlanReward | |||||
var err error | |||||
if len(pvds) > 0 { | |||||
err = eg.In("pvd", pvds).Find(&m) | |||||
} else { | |||||
err = eg.Find(&m) | |||||
} | |||||
if err != nil { | |||||
return nil, err | |||||
} | |||||
return m, nil | |||||
} |
@@ -0,0 +1,29 @@ | |||||
package db | |||||
import ( | |||||
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/db/model" | |||||
zhios_order_relate_logx "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/utils/logx" | |||||
"xorm.io/xorm" | |||||
) | |||||
func DbsUserFindByIds(eg *xorm.Engine, uid []int) (*[]model.User, error) { | |||||
var users []model.User | |||||
if err := eg.In("uid", uid).Asc("level").Find(&users); err != nil { | |||||
return nil, zhios_order_relate_logx.Error(err) | |||||
} | |||||
if len(users) == 0 { | |||||
return nil, nil | |||||
} | |||||
return &users, nil | |||||
} | |||||
func DbsUserRelate(eg *xorm.Engine, uid int) (*[]model.UserRelate, error) { | |||||
var userRelate []model.UserRelate | |||||
if err := eg.Where("uid = ?", uid).Asc("level").Find(&userRelate); err != nil { | |||||
return nil, zhios_order_relate_logx.Error(err) | |||||
} | |||||
if len(userRelate) == 0 { | |||||
return nil, nil | |||||
} | |||||
return &userRelate, nil | |||||
} |
@@ -0,0 +1,15 @@ | |||||
package model | |||||
import "time" | |||||
type PlanCommission struct { | |||||
Id int `json:"id" xorm:"not null pk autoincr comment('分佣方案ID,现在只允许1,2') INT(10)"` | |||||
PlanName string `json:"plan_name" xorm:"not null default '' comment('方案名称') VARCHAR(64)"` | |||||
Memo string `json:"memo" xorm:"not null default '' comment('备注') VARCHAR(256)"` | |||||
Mode string `json:"mode" xorm:"not null default '' comment('模式,lv_all级差按总佣金,lv_self级差按自购,lv_subsidy级差按补贴佣金') VARCHAR(16)"` | |||||
Data string `json:"data" xorm:"comment('lv级别id,subsidy_mode:0按佣金计算,1按利润计算,self_rate自购比例,team_rate团队分成比例,peer_rate同级分成比例,subsidy_enable:0不开启,1:开启,subsidy_share_rate分享补贴比例,subsidy_self_reta自购补贴比例,payMode默认0(默认内部支出)') TEXT"` | |||||
UpdateAt time.Time `json:"update_at" xorm:"default 'CURRENT_TIMESTAMP' TIMESTAMP"` | |||||
CommissionMode string `json:"commission_mode" xorm:"default 'bili' comment('佣金返佣方式 比例 bili 固定金额 money') VARCHAR(16)"` | |||||
IntegralMode string `json:"integral_mode" xorm:"default 'bili' comment('积分返佣方式 比例 bili 固定金额 money') VARCHAR(16)"` | |||||
BlockIconsMode string `json:"block_icons_mode" xorm:"default 'bili' comment('区块币返佣方式 比例 bili 固定金额 money') VARCHAR(16)"` | |||||
} |
@@ -0,0 +1,20 @@ | |||||
package model | |||||
type PlanReward struct { | |||||
Id int `json:"id" xorm:"not null pk autoincr INT(10)"` | |||||
Pvd string `json:"pvd" xorm:"not null comment('供应商') unique VARCHAR(255)"` | |||||
PvdRate float32 `json:"pvd_rate" xorm:"not null default 0.0000 comment('供应商抽成比例') FLOAT(6,4)"` | |||||
SysRate float32 `json:"sys_rate" xorm:"not null default 0.0000 comment('平台抽成比例') FLOAT(6,4)"` | |||||
RegionRate float32 `json:"region_rate" xorm:"not null default 0.0000 comment('区域代理抽成比例') FLOAT(6,4)"` | |||||
GlobalRate float32 `json:"global_rate" xorm:"not null default 0.0000 comment('全球分红抽成比例') FLOAT(6,4)"` | |||||
SettleMode int `json:"settle_mode" xorm:"not null default 1 comment('0.手动方案,1.自动方案') TINYINT(1)"` | |||||
PlanCommissionId int `json:"plan_commission_id" xorm:"not null default 0 comment('佣金方案0未设置,>0对应方案') TINYINT(3)"` | |||||
PlanSettleId int `json:"plan_settle_id" xorm:"not null default 0 comment('结算方案0未设置,>0对应方案') TINYINT(3)"` | |||||
State int `json:"state" xorm:"not null default 1 comment('0关闭,1开启') TINYINT(1)"` | |||||
SubsidyRate float32 `json:"subsidy_rate" xorm:"not null default 0.0000 comment('待删除字段') FLOAT(6,4)"` | |||||
Source int `json:"source" xorm:"not null default 1 comment('佣金来源:1联盟佣金 2补贴金额') TINYINT(1)"` | |||||
AppType int `json:"app_type" xorm:"not null default 1 comment('所属应用:1导购 2自营 4O2O') TINYINT(3)"` | |||||
MerchantRate float32 `json:"merchant_rate" xorm:"not null default 0.0000 comment('o2o商家抽成比例') FLOAT(6,4)"` | |||||
PushHandRate float32 `json:"push_hand_rate" xorm:"not null default 0.0000 comment('o2o推手抽成比例') FLOAT(6,4)"` | |||||
IntegralOpen int `json:"integral_open" xorm:"not null default 0 comment('积分抽成') TINYINT(1)"` | |||||
} |
@@ -0,0 +1,7 @@ | |||||
package model | |||||
type SysCfg struct { | |||||
Key string `json:"key" xorm:"not null pk comment('键') VARCHAR(127)"` | |||||
Val string `json:"val" xorm:"comment('值') TEXT"` | |||||
Memo string `json:"memo" xorm:"not null default '' comment('备注') VARCHAR(255)"` | |||||
} |
@@ -0,0 +1,29 @@ | |||||
package model | |||||
import ( | |||||
"time" | |||||
) | |||||
type User struct { | |||||
Uid int `json:"uid" xorm:"not null pk autoincr comment('主键ID') INT(10)"` | |||||
Username string `json:"username" xorm:"not null default '' comment('用户名') index VARCHAR(50)"` | |||||
Password string `json:"password" xorm:"not null default '' comment('密码') CHAR(32)"` | |||||
Email string `json:"email" xorm:"not null default '' comment('邮箱') VARCHAR(128)"` | |||||
Phone string `json:"phone" xorm:"not null default '' comment('联系电话') VARCHAR(20)"` | |||||
Nickname string `json:"nickname" xorm:"not null default '' comment('昵称') VARCHAR(20)"` | |||||
Level int `json:"level" xorm:"not null default 0 comment('用户等级id') INT(11)"` | |||||
InviteTotal int `json:"invite_total" xorm:"not null default 0 comment('直推邀请总人数') INT(11)"` | |||||
LevelArriveAt time.Time `json:"level_arrive_at" xorm:"not null default CURRENT_TIMESTAMP comment('到达该等级的时间') TIMESTAMP"` | |||||
LevelExpireAt time.Time `json:"level_expire_at" xorm:"not null default CURRENT_TIMESTAMP comment('该等级过期时间') TIMESTAMP"` | |||||
CreateAt time.Time `json:"create_at" xorm:"created not null default CURRENT_TIMESTAMP comment('创建时间') TIMESTAMP"` | |||||
UpdateAt time.Time `json:"update_at" xorm:"updated default CURRENT_TIMESTAMP comment('最后修改资料时间') TIMESTAMP"` | |||||
LastLoginAt time.Time `json:"last_login_at" xorm:"default CURRENT_TIMESTAMP comment('最近登录时间') TIMESTAMP"` | |||||
DeleteAt int `json:"delete_at" xorm:"not null default 0 comment('是否删除;0未删除;1已删除') TINYINT(1)"` | |||||
State int `json:"state" xorm:"not null default 1 comment('0未激活,1正常,2冻结,3删除') TINYINT(1)"` | |||||
LastLoginIp string `json:"last_login_ip" xorm:"not null default '' comment('最后登录IP') VARCHAR(64)"` | |||||
RegisterIp string `json:"register_ip" xorm:"not null default '' comment('注册IP') VARCHAR(64)"` | |||||
Zone string `json:"zone" xorm:"not null default '86' comment('区号') VARCHAR(100)"` | |||||
SalePhone string `json:"sale_phone" xorm:"not null default '' comment('') VARCHAR(100)"` | |||||
IsFake int `json:"is_fake" xorm:"not null default 0 comment('0真实 1虚拟') TINYINT(1)"` | |||||
IsMarketer int `json:"is_marketer" xorm:"not null default 0 comment('是否市商 0否 1是') TINYINT(1)"` | |||||
} |
@@ -0,0 +1,21 @@ | |||||
package model | |||||
import ( | |||||
"time" | |||||
) | |||||
type UserLevel struct { | |||||
Id int `json:"id" xorm:"not null pk autoincr comment('等级id') INT(11)"` | |||||
BenefitIds string `json:"benefit_ids" xorm:"comment('该等级拥有的权益id【json】') TEXT"` | |||||
LevelName string `json:"level_name" xorm:"not null default '' comment('等级名称') VARCHAR(255)"` | |||||
LevelWeight int `json:"level_weight" xorm:"not null default 0 comment('等级权重') INT(11)"` | |||||
LevelUpdateCondition int `json:"level_update_condition" xorm:"not null default 2 comment('2是条件升级,1是无条件升级') TINYINT(1)"` | |||||
AutoAudit int `json:"auto_audit" xorm:"not null default 0 comment('(自动审核)0关闭,1开启') TINYINT(1)"` | |||||
AutoUpdate int `json:"auto_update" xorm:"not null default 0 comment('(自动升级)0关闭,1开启') TINYINT(1)"` | |||||
LevelDate int `json:"level_date" xorm:"default 0 comment('会员有效期(0永久有效,单位月)') INT(11)"` | |||||
IsUse int `json:"is_use" xorm:"not null default 1 comment('是否开启(0否,1是)') TINYINT(1)"` | |||||
ChoosableNum int `json:"choosable_num" xorm:"default 0 comment('可选任务数量(当is_must_task为0时生效)') INT(6)"` | |||||
Memo string `json:"memo" xorm:"default '' comment('备注') VARCHAR(255)"` | |||||
CssSet string `json:"css_set" xorm:"TEXT"` | |||||
CreateAt time.Time `json:"create_at" xorm:"not null default CURRENT_TIMESTAMP TIMESTAMP"` | |||||
} |
@@ -0,0 +1,91 @@ | |||||
package model | |||||
import ( | |||||
"time" | |||||
) | |||||
type UserProfile struct { | |||||
Uid int `json:"uid" xorm:"not null pk comment('关联userID') INT(20)"` | |||||
ArkidUid int `json:"arkid_uid" xorm:"not null default 0 comment('Arkid 用户ID') INT(20)"` | |||||
ParentUid int `json:"parent_uid" xorm:"not null default 0 comment('上级ID') INT(20)"` | |||||
ArkidToken string `json:"arkid_token" xorm:"not null default '' comment('token') VARCHAR(2000)"` | |||||
AvatarUrl string `json:"avatar_url" xorm:"not null default '' comment('头像URL') VARCHAR(2000)"` | |||||
CustomInviteCode string `json:"custom_invite_code" xorm:"not null default '' comment('邀请码(自定义)') VARCHAR(16)"` | |||||
InviteCode string `json:"invite_code" xorm:"not null default '' comment('邀请码(系统)') VARCHAR(16)"` | |||||
Gender int `json:"gender" xorm:"not null default 2 comment('性别0女,1男,2未知') TINYINT(1)"` | |||||
Birthday int `json:"birthday" xorm:"not null default 0 comment('出生日期') INT(10)"` | |||||
AccWxId string `json:"acc_wx_id" xorm:"not null default '' comment('账户_微信id') VARCHAR(50)"` | |||||
AccWxOpenid string `json:"acc_wx_openid" xorm:"not null default '' comment('账户_微信openid') VARCHAR(80)"` | |||||
AccTaobaoNickname string `json:"acc_taobao_nickname" xorm:"not null default '' comment('淘宝昵称') VARCHAR(50)"` | |||||
AccTaobaoAuthTime int64 `json:"acc_taobao_auth_time" xorm:"not null default 0 comment('淘宝授权备案时间') BIGINT(11)"` | |||||
AccTaobaoShareId int64 `json:"acc_taobao_share_id" xorm:"not null default 0 comment('淘宝分享relationId,') index BIGINT(12)"` | |||||
AccTaobaoSelfId int64 `json:"acc_taobao_self_id" xorm:"not null default 0 comment('淘宝自购specialId') index BIGINT(12)"` | |||||
AccJdSelfId string `json:"acc_jd_self_id" xorm:"not null default '' comment('京东自购ID') index VARCHAR(50)"` | |||||
AccJdShareId string `json:"acc_jd_share_id" xorm:"not null default '' comment('京东分享ID') index VARCHAR(50)"` | |||||
AccJdFreeId string `json:"acc_jd_free_id" xorm:"not null default '' comment('京东新人免单ID') VARCHAR(50)"` | |||||
AccSuningSelfId string `json:"acc_suning_self_id" xorm:"not null default '' comment('苏宁自购ID') index VARCHAR(50)"` | |||||
AccSuningShareId string `json:"acc_suning_share_id" xorm:"not null default '' comment('苏宁分享ID') index VARCHAR(50)"` | |||||
AccSuningFreeId string `json:"acc_suning_free_id" xorm:"not null default '' comment('苏宁新人免单ID') VARCHAR(50)"` | |||||
AccPddSelfId string `json:"acc_pdd_self_id" xorm:"not null default '' comment('拼多多自购ID') index VARCHAR(50)"` | |||||
AccPddShareId string `json:"acc_pdd_share_id" xorm:"not null default '' comment('拼多多分享ID') index VARCHAR(50)"` | |||||
AccPddFreeId string `json:"acc_pdd_free_id" xorm:"not null default '' comment('拼多多新人免单ID') VARCHAR(50)"` | |||||
AccPddBind int `json:"acc_pdd_bind" xorm:"not null default 0 comment('拼多多是否授权绑定') TINYINT(1)"` | |||||
AccVipSelfId string `json:"acc_vip_self_id" xorm:"not null default '' comment('唯品会自购ID') index VARCHAR(50)"` | |||||
AccVipShareId string `json:"acc_vip_share_id" xorm:"not null default '' comment('唯品会分享ID') index VARCHAR(50)"` | |||||
AccVipFreeId string `json:"acc_vip_free_id" xorm:"not null default '' comment('唯品会新人免单ID') VARCHAR(50)"` | |||||
AccKaolaSelfId string `json:"acc_kaola_self_id" xorm:"not null default '' comment('考拉自购ID') index VARCHAR(50)"` | |||||
AccKaolaShareId string `json:"acc_kaola_share_id" xorm:"not null default '' comment('考拉分享ID') index VARCHAR(50)"` | |||||
AccKaolaFreeId string `json:"acc_kaola_free_id" xorm:"not null default '' comment('考拉新人免单ID') VARCHAR(50)"` | |||||
AccDuomaiShareId int64 `json:"acc_duomai_share_id" xorm:"not null pk default 0 comment('多麦联盟分享ID') BIGINT(12)"` | |||||
AccAlipay string `json:"acc_alipay" xorm:"not null default '' comment('支付宝账号') VARCHAR(50)"` | |||||
AccAlipayRealName string `json:"acc_alipay_real_name" xorm:"not null default '' comment('支付宝账号真实姓名') VARCHAR(50)"` | |||||
CertTime int `json:"cert_time" xorm:"not null default 0 comment('认证时间') INT(10)"` | |||||
CertName string `json:"cert_name" xorm:"not null default '' comment('证件上名字,也是真实姓名') VARCHAR(50)"` | |||||
CertNum string `json:"cert_num" xorm:"not null default '' comment('证件号码') VARCHAR(50)"` | |||||
CertState int `json:"cert_state" xorm:"not null default 0 comment('认证状态(0为未认证,1为认证中,2为已认证,3为认证失败)') TINYINT(1)"` | |||||
FinCommission string `json:"fin_commission" xorm:"not null default 0.0000 comment('累计佣金') DECIMAL(10,4)"` | |||||
FinValid string `json:"fin_valid" xorm:"not null default 0.0000 comment('可用余额,fin=>finance财务') DECIMAL(10,4)"` | |||||
FinInvalid string `json:"fin_invalid" xorm:"not null default 0.0000 comment('不可用余额,冻结余额') DECIMAL(10,4)"` | |||||
FinSelfOrderCount int `json:"fin_self_order_count" xorm:"not null default 0 comment('自购订单数,包括未完成') INT(11)"` | |||||
FinSelfOrderCountDone int `json:"fin_self_order_count_done" xorm:"not null default 0 comment('自购已完成订单') INT(11)"` | |||||
FinSelfRebate float32 `json:"fin_self_rebate" xorm:"not null default 0.000000 comment('累积自购获得返利金额') FLOAT(14,6)"` | |||||
FinTotal float32 `json:"fin_total" xorm:"not null default 0.000000 comment('累计总收益') FLOAT(14,6)"` | |||||
Lat float32 `json:"lat" xorm:"not null default 0.000000 comment('纬度') FLOAT(15,6)"` | |||||
Lng float32 `json:"lng" xorm:"not null default 0.000000 comment('经度') FLOAT(15,6)"` | |||||
Memo string `json:"memo" xorm:"not null default '' comment('用户简述备注') VARCHAR(2048)"` | |||||
IsNew int `json:"is_new" xorm:"not null default 1 comment('是否是新用户') TINYINT(1)"` | |||||
IsVerify int `json:"is_verify" xorm:"not null default 0 comment('是否有效会员') TINYINT(1)"` | |||||
IsOrdered int `json:"is_ordered" xorm:"not null default 0 comment('是否已完成首单(0否,1是)') TINYINT(1)"` | |||||
FromWay string `json:"from_way" xorm:"not null default '' comment('注册来源: | |||||
no_captcha_phone:免验证码手机号注册; | |||||
manual_phone:手动手机验证码注册; | |||||
wx:微信授权; | |||||
wx_mp:小程序授权; | |||||
wx_pub:公众号授权; | |||||
wx_bind_phone:微信注册绑定手机号; | |||||
admin:管理员添加;taobao_bind_phone:淘宝注册绑定手机号,apple_bind_phone:苹果注册绑定手机号') VARCHAR(16)"` | |||||
HidOrder int `json:"hid_order" xorm:"not null default 0 comment('隐藏订单') TINYINT(3)"` | |||||
HidContact int `json:"hid_contact" xorm:"not null default 0 comment('隐藏联系方式') TINYINT(4)"` | |||||
NewMsgNotice int `json:"new_msg_notice" xorm:"not null default 1 comment('新消息通知') TINYINT(1)"` | |||||
WxAccount string `json:"wx_account" xorm:"not null default '' comment('微信号') VARCHAR(100)"` | |||||
WxQrcode string `json:"wx_qrcode" xorm:"not null default '' comment('微信二维码') VARCHAR(100)"` | |||||
ThirdPartyTaobaoOid string `json:"third_party_taobao_oid" xorm:"not null default '' comment('淘宝第三方登录openID') VARCHAR(100)"` | |||||
ThirdPartyTaobaoSid string `json:"third_party_taobao_sid" xorm:"not null default '' comment('淘宝第三方登录sID') VARCHAR(255)"` | |||||
ThirdPartyTaobaoAcctoken string `json:"third_party_taobao_acctoken" xorm:"not null default '' comment('淘宝第三方登录topaccesstoken') VARCHAR(100)"` | |||||
ThirdPartyTaobaoAuthcode string `json:"third_party_taobao_authcode" xorm:"not null default '' comment('淘宝第三方登录topAuthCode') VARCHAR(100)"` | |||||
ThirdPartyAppleToken string `json:"third_party_apple_token" xorm:"not null default '' comment('苹果第三方登录token') VARCHAR(1024)"` | |||||
ThirdPartyQqAccessToken string `json:"third_party_qq_access_token" xorm:"not null default '' comment('QQ第三方登录access_token') VARCHAR(255)"` | |||||
ThirdPartyQqExpiresIn string `json:"third_party_qq_expires_in" xorm:"not null default '' comment('QQ第三方登录expires_in(剩余时长)') VARCHAR(255)"` | |||||
ThirdPartyQqOpenid string `json:"third_party_qq_openid" xorm:"not null default '' comment('QQ第三方登陆openid(不变,用于认证)') VARCHAR(255)"` | |||||
ThirdPartyQqUnionid string `json:"third_party_qq_unionid" xorm:"not null default '' comment('QQ第三方登陆unionid') VARCHAR(255)"` | |||||
ThirdPartyWechatExpiresIn string `json:"third_party_wechat_expires_in" xorm:"not null default '' comment('微信第三方登录expires_in(剩余时长)') VARCHAR(255)"` | |||||
ThirdPartyWechatOpenid string `json:"third_party_wechat_openid" xorm:"not null default '' comment('微信第三方登陆openid(不变,用于认证)') VARCHAR(255)"` | |||||
ThirdPartyWechatUnionid string `json:"third_party_wechat_unionid" xorm:"not null default '' comment('微信第三方登陆unionid') VARCHAR(255)"` | |||||
ThirdPartyWechatMiniOpenid string `json:"third_party_wechat_mini_openid" xorm:"not null default '' comment('微信小程序登录open_id') VARCHAR(255)"` | |||||
ThirdPartyWechatH5Openid string `json:"third_party_wechat_h5_openid" xorm:"not null default '' comment('微信H5登录open_id') VARCHAR(255)"` | |||||
FreeRemainTime int `json:"free_remain_time" xorm:"not null default 0 comment('免单剩余次数') INT(11)"` | |||||
FreeCumulativeTime int `json:"free_cumulative_time" xorm:"not null default 0 comment('免单累计次数') INT(11)"` | |||||
IsDelete int `json:"is_delete" xorm:"not null default 0 comment('是否已删除') TINYINT(1)"` | |||||
UpdateAt time.Time `json:"update_at" xorm:"updated not null default CURRENT_TIMESTAMP comment('更新时间') TIMESTAMP"` | |||||
SignDay int `json:"sign_day" xorm:"not null default 0 comment('签到天数') INT(11)"` | |||||
} |
@@ -0,0 +1,13 @@ | |||||
package model | |||||
import ( | |||||
"time" | |||||
) | |||||
type UserRelate struct { | |||||
Id int64 `json:"id" xorm:"pk autoincr comment('主键') BIGINT(10)"` | |||||
ParentUid int `json:"parent_uid" xorm:"not null default 0 comment('上级会员ID') unique(idx_union_u_p_id) INT(20)"` | |||||
Uid int `json:"uid" xorm:"not null default 0 comment('关联UserID') unique(idx_union_u_p_id) INT(20)"` | |||||
Level int `json:"level" xorm:"not null default 1 comment('推广等级(1直属,大于1非直属)') INT(10)"` | |||||
InviteTime time.Time `json:"invite_time" xorm:"not null default CURRENT_TIMESTAMP comment('邀请时间') TIMESTAMP"` | |||||
} |
@@ -0,0 +1,17 @@ | |||||
package model | |||||
type VirtualCoin struct { | |||||
Id int `json:"id" xorm:"not null pk autoincr INT(11)"` | |||||
Name string `json:"name" xorm:"not null default '' comment('名称') VARCHAR(255)"` | |||||
ExchangeRatio string `json:"exchange_ratio" xorm:"not null comment('兑换比例(与金额)') DECIMAL(5,2)"` | |||||
IsUse int `json:"is_use" xorm:"comment('是否开启:0否 1是') TINYINT(1)"` | |||||
CanExchange string `json:"can_exchange" xorm:"comment('能兑换的虚拟币id和手续费列表json') VARCHAR(255)"` | |||||
CanExchangeMoney int `json:"can_exchange_money" xorm:"not null default 0 comment('现金能否兑换:0否 1是') TINYINT(1)"` | |||||
IsBlock int `json:"is_block" xorm:"not null default 0 comment('是否区块币:0否 1是') TINYINT(1)"` | |||||
FunctionType string `json:"function_type" xorm:"comment('功能类型') VARCHAR(255)"` | |||||
CanCny int `json:"can_cny" xorm:"not null default 0 comment('是否能兑换余额:0否 1是') TINYINT(1)"` | |||||
CanTransfer int `json:"can_transfer" xorm:"not null default 0 comment('是否能支持转账:0否 1是') TINYINT(1)"` | |||||
CanBackout int `json:"can_backout" xorm:"not null default 0 comment('是否能支持转账撤回:0否 1是') TINYINT(1)"` | |||||
LimitLevelTransfer string `json:"limit_level_transfer" xorm:"default '' comment('能支持转账的用户等级') VARCHAR(600)"` | |||||
LimitLevelBackout string `json:"limit_level_backout" xorm:"comment('能支持撤回的用户等级') VARCHAR(600)"` | |||||
} |
@@ -0,0 +1,12 @@ | |||||
package model | |||||
type VirtualCoinRelate struct { | |||||
Id int64 `json:"id" xorm:"pk autoincr BIGINT(20)"` | |||||
Oid int64 `json:"oid" xorm:"not null default 0 comment('订单号') index unique(IDX_ORD) BIGINT(20)"` | |||||
Uid int `json:"uid" xorm:"not null default 0 comment('用户ID') unique(IDX_ORD) index INT(10)"` | |||||
CoinId int `json:"coin_id" xorm:"comment('虚拟币id') INT(11)"` | |||||
Amount string `json:"amount" xorm:"not null default 0.000000 comment('数量') DECIMAL(16,6)"` | |||||
Pvd string `json:"pvd" xorm:"not null default '' comment('供应商taobao,jd,pdd,vip,suning,kaola,mall_goods,group_buy') index VARCHAR(255)"` | |||||
CreateAt int `json:"create_at" xorm:"not null default 0 comment('订单创建时间') index INT(10)"` | |||||
Level int `json:"level" xorm:"not null default 0 comment('0自购 1直推 大于1:间推') INT(10)"` | |||||
} |
@@ -0,0 +1,13 @@ | |||||
module code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git | |||||
go 1.15 | |||||
require ( | |||||
github.com/go-redis/redis v6.15.9+incompatible | |||||
github.com/gomodule/redigo/redis v0.0.1 | |||||
github.com/syyongx/php2go v0.9.6 | |||||
go.uber.org/zap v1.13.0 | |||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f | |||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 | |||||
xorm.io/xorm v1.3.1 | |||||
) |
@@ -0,0 +1,662 @@ | |||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= | |||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= | |||||
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s= | |||||
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU= | |||||
gitee.com/travelliu/dm v1.8.11192/go.mod h1:DHTzyhCrM843x9VdKVbZ+GKXGRbKM2sJ4LxihRxShkE= | |||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= | |||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= | |||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= | |||||
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= | |||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= | |||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= | |||||
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= | |||||
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= | |||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= | |||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= | |||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= | |||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= | |||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= | |||||
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= | |||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= | |||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= | |||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= | |||||
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= | |||||
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= | |||||
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= | |||||
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= | |||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= | |||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= | |||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= | |||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= | |||||
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= | |||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= | |||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= | |||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= | |||||
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= | |||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= | |||||
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= | |||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= | |||||
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= | |||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= | |||||
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= | |||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= | |||||
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= | |||||
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= | |||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= | |||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= | |||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | |||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | |||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | |||||
github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= | |||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= | |||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= | |||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= | |||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= | |||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= | |||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= | |||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= | |||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= | |||||
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= | |||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= | |||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= | |||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= | |||||
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= | |||||
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= | |||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= | |||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= | |||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= | |||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= | |||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= | |||||
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= | |||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= | |||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= | |||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= | |||||
github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= | |||||
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= | |||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= | |||||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= | |||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= | |||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= | |||||
github.com/goccy/go-json v0.8.1 h1:4/Wjm0JIJaTDm8K1KcGrLHJoa8EsJ13YWeX+6Kfq6uI= | |||||
github.com/goccy/go-json v0.8.1/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= | |||||
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= | |||||
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= | |||||
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= | |||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= | |||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= | |||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= | |||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= | |||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= | |||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= | |||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= | |||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= | |||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | |||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | |||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= | |||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | |||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= | |||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= | |||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= | |||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= | |||||
github.com/gomodule/redigo v1.8.8 h1:f6cXq6RRfiyrOJEV7p3JhLDlmawGBVBBP1MggY8Mo4E= | |||||
github.com/gomodule/redigo/redis v0.0.1 h1:tQQSZyg4O0N0Dh2hli1pOrRdj+WHl1xf3w/x7olDgu0= | |||||
github.com/gomodule/redigo/redis v0.0.1/go.mod h1:QhGMo2EGfdSsmrYDENZq12/Y23fRP6X6nyFZ4TGSUvM= | |||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= | |||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= | |||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= | |||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= | |||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= | |||||
github.com/google/go-cmp v0.5.3 h1:x95R7cp+rSeeqAMI2knLtQ0DKlaBhv2NrtrOvafPHRo= | |||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | |||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= | |||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= | |||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | |||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= | |||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | |||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= | |||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= | |||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= | |||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= | |||||
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= | |||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= | |||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= | |||||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= | |||||
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= | |||||
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= | |||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= | |||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= | |||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= | |||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= | |||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= | |||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= | |||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= | |||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= | |||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= | |||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= | |||||
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= | |||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= | |||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= | |||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= | |||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= | |||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= | |||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= | |||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= | |||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= | |||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= | |||||
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= | |||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= | |||||
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= | |||||
github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= | |||||
github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= | |||||
github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= | |||||
github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= | |||||
github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= | |||||
github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= | |||||
github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5lahk= | |||||
github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= | |||||
github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= | |||||
github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= | |||||
github.com/jackc/pgconn v1.8.1/go.mod h1:JV6m6b6jhjdmzchES0drzCcYcAHS1OPD5xu3OZ/lE2g= | |||||
github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= | |||||
github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= | |||||
github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= | |||||
github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= | |||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= | |||||
github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= | |||||
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= | |||||
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= | |||||
github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= | |||||
github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= | |||||
github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= | |||||
github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= | |||||
github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= | |||||
github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= | |||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= | |||||
github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= | |||||
github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= | |||||
github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= | |||||
github.com/jackc/pgtype v1.2.0/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4WpC0= | |||||
github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkALtxZMCH411K+tKzNpwzCKU+AnPzBKZ+I+Po= | |||||
github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ= | |||||
github.com/jackc/pgtype v1.7.0/go.mod h1:ZnHF+rMePVqDKaOfJVI4Q8IVvAQMryDlDkZnKOI75BE= | |||||
github.com/jackc/pgtype v1.8.0/go.mod h1:PqDKcEBtllAtk/2p6z6SHdXW5UB+MhE75tUol2OKexE= | |||||
github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= | |||||
github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= | |||||
github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= | |||||
github.com/jackc/pgx/v4 v4.5.0/go.mod h1:EpAKPLdnTorwmPUUsqrPxy5fphV18j9q3wrfRXgo+kA= | |||||
github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6fOLDxqtlyhe9UWgfIi9R8+8v8GKV5TRA/o= | |||||
github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg= | |||||
github.com/jackc/pgx/v4 v4.11.0/go.mod h1:i62xJgdrtVDsnL3U8ekyrQXEwGNTRoG7/8r+CIdYfcc= | |||||
github.com/jackc/pgx/v4 v4.12.0/go.mod h1:fE547h6VulLPA3kySjfnSG/e2D861g/50JlVUa/ub60= | |||||
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= | |||||
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= | |||||
github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= | |||||
github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= | |||||
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= | |||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= | |||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= | |||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= | |||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= | |||||
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= | |||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= | |||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= | |||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= | |||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= | |||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= | |||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= | |||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= | |||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= | |||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= | |||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= | |||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= | |||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= | |||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= | |||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= | |||||
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= | |||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= | |||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= | |||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= | |||||
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= | |||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= | |||||
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= | |||||
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= | |||||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= | |||||
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= | |||||
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= | |||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= | |||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= | |||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= | |||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= | |||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= | |||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= | |||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= | |||||
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= | |||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= | |||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= | |||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= | |||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= | |||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= | |||||
github.com/mattn/go-sqlite3 v1.14.9 h1:10HX2Td0ocZpYEjhilsuo6WWtUqttj2Kb0KtD86/KYA= | |||||
github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= | |||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= | |||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= | |||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= | |||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= | |||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= | |||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= | |||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= | |||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= | |||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= | |||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= | |||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= | |||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= | |||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= | |||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= | |||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= | |||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= | |||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= | |||||
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= | |||||
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= | |||||
github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= | |||||
github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= | |||||
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= | |||||
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= | |||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= | |||||
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= | |||||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= | |||||
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= | |||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | |||||
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= | |||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | |||||
github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= | |||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= | |||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= | |||||
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= | |||||
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= | |||||
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= | |||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= | |||||
github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= | |||||
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= | |||||
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= | |||||
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= | |||||
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= | |||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= | |||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= | |||||
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= | |||||
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= | |||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= | |||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | |||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= | |||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | |||||
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= | |||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | |||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | |||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= | |||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= | |||||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= | |||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= | |||||
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= | |||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= | |||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= | |||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= | |||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= | |||||
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= | |||||
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= | |||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= | |||||
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= | |||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= | |||||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= | |||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= | |||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= | |||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= | |||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= | |||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= | |||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= | |||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= | |||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= | |||||
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= | |||||
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= | |||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= | |||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= | |||||
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= | |||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= | |||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= | |||||
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= | |||||
github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= | |||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= | |||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= | |||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= | |||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= | |||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= | |||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= | |||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= | |||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= | |||||
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= | |||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= | |||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= | |||||
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= | |||||
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= | |||||
github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= | |||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | |||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | |||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= | |||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= | |||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= | |||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= | |||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= | |||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | |||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | |||||
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= | |||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= | |||||
github.com/syyongx/php2go v0.9.6 h1:NFJlFwV5SKonYE7e/EtAcVxaJAVX9piRLpapw23HOQ8= | |||||
github.com/syyongx/php2go v0.9.6/go.mod h1:meN2eIhhUoxOd2nMxbpe8g6cFPXI5O9/UAAuz7oDdzw= | |||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= | |||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= | |||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= | |||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= | |||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | |||||
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= | |||||
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= | |||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= | |||||
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= | |||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= | |||||
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= | |||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= | |||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= | |||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= | |||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= | |||||
go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= | |||||
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= | |||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= | |||||
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= | |||||
go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= | |||||
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= | |||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= | |||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= | |||||
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= | |||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= | |||||
go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU= | |||||
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= | |||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= | |||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= | |||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | |||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | |||||
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= | |||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | |||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | |||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | |||||
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | |||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | |||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | |||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | |||||
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= | |||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= | |||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= | |||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= | |||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= | |||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= | |||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= | |||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= | |||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= | |||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= | |||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= | |||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= | |||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= | |||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | |||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | |||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | |||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | |||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | |||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | |||||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | |||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | |||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | |||||
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | |||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | |||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | |||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | |||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= | |||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | |||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | |||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | |||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= | |||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= | |||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= | |||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= | |||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= | |||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f h1:Ax0t5p6N38Ga0dThY21weqDEyz2oklo4IvDkpigvkD8= | |||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||||
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||||
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||||
golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |||||
golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac h1:oN6lz7iLW/YC7un8pq+9bOLyXrprv2+DKfkJY+2LJJw= | |||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= | |||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | |||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | |||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= | |||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | |||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | |||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= | |||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | |||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | |||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | |||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | |||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | |||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | |||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | |||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= | |||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= | |||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= | |||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= | |||||
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= | |||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= | |||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= | |||||
golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | |||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | |||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | |||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | |||||
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= | |||||
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78 h1:M8tBwCtWD/cZV9DZpFYRUgaymAYAr+aIUTWzDaM3uPs= | |||||
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= | |||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= | |||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |||||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= | |||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= | |||||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= | |||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= | |||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= | |||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= | |||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= | |||||
google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= | |||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= | |||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= | |||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= | |||||
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= | |||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= | |||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= | |||||
google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= | |||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= | |||||
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= | |||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= | |||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= | |||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | |||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= | |||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | |||||
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= | |||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= | |||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= | |||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= | |||||
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= | |||||
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= | |||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= | |||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= | |||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= | |||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= | |||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= | |||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= | |||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= | |||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | |||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= | |||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | |||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= | |||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | |||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= | |||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= | |||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= | |||||
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= | |||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= | |||||
lukechampine.com/uint128 v1.1.1 h1:pnxCASz787iMf+02ssImqk6OLt+Z5QHMoZyUXR4z6JU= | |||||
lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= | |||||
modernc.org/cc/v3 v3.33.6/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= | |||||
modernc.org/cc/v3 v3.33.9/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= | |||||
modernc.org/cc/v3 v3.33.11/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= | |||||
modernc.org/cc/v3 v3.34.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= | |||||
modernc.org/cc/v3 v3.35.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= | |||||
modernc.org/cc/v3 v3.35.4/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= | |||||
modernc.org/cc/v3 v3.35.5/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= | |||||
modernc.org/cc/v3 v3.35.7/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= | |||||
modernc.org/cc/v3 v3.35.8/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= | |||||
modernc.org/cc/v3 v3.35.10/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= | |||||
modernc.org/cc/v3 v3.35.15/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= | |||||
modernc.org/cc/v3 v3.35.16/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= | |||||
modernc.org/cc/v3 v3.35.17/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= | |||||
modernc.org/cc/v3 v3.35.18 h1:rMZhRcWrba0y3nVmdiQ7kxAgOOSq2m2f2VzjHLgEs6U= | |||||
modernc.org/cc/v3 v3.35.18/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= | |||||
modernc.org/ccgo/v3 v3.9.5/go.mod h1:umuo2EP2oDSBnD3ckjaVUXMrmeAw8C8OSICVa0iFf60= | |||||
modernc.org/ccgo/v3 v3.10.0/go.mod h1:c0yBmkRFi7uW4J7fwx/JiijwOjeAeR2NoSaRVFPmjMw= | |||||
modernc.org/ccgo/v3 v3.11.0/go.mod h1:dGNposbDp9TOZ/1KBxghxtUp/bzErD0/0QW4hhSaBMI= | |||||
modernc.org/ccgo/v3 v3.11.1/go.mod h1:lWHxfsn13L3f7hgGsGlU28D9eUOf6y3ZYHKoPaKU0ag= | |||||
modernc.org/ccgo/v3 v3.11.3/go.mod h1:0oHunRBMBiXOKdaglfMlRPBALQqsfrCKXgw9okQ3GEw= | |||||
modernc.org/ccgo/v3 v3.12.4/go.mod h1:Bk+m6m2tsooJchP/Yk5ji56cClmN6R1cqc9o/YtbgBQ= | |||||
modernc.org/ccgo/v3 v3.12.6/go.mod h1:0Ji3ruvpFPpz+yu+1m0wk68pdr/LENABhTrDkMDWH6c= | |||||
modernc.org/ccgo/v3 v3.12.8/go.mod h1:Hq9keM4ZfjCDuDXxaHptpv9N24JhgBZmUG5q60iLgUo= | |||||
modernc.org/ccgo/v3 v3.12.11/go.mod h1:0jVcmyDwDKDGWbcrzQ+xwJjbhZruHtouiBEvDfoIsdg= | |||||
modernc.org/ccgo/v3 v3.12.14/go.mod h1:GhTu1k0YCpJSuWwtRAEHAol5W7g1/RRfS4/9hc9vF5I= | |||||
modernc.org/ccgo/v3 v3.12.18/go.mod h1:jvg/xVdWWmZACSgOiAhpWpwHWylbJaSzayCqNOJKIhs= | |||||
modernc.org/ccgo/v3 v3.12.20/go.mod h1:aKEdssiu7gVgSy/jjMastnv/q6wWGRbszbheXgWRHc8= | |||||
modernc.org/ccgo/v3 v3.12.21/go.mod h1:ydgg2tEprnyMn159ZO/N4pLBqpL7NOkJ88GT5zNU2dE= | |||||
modernc.org/ccgo/v3 v3.12.22/go.mod h1:nyDVFMmMWhMsgQw+5JH6B6o4MnZ+UQNw1pp52XYFPRk= | |||||
modernc.org/ccgo/v3 v3.12.25/go.mod h1:UaLyWI26TwyIT4+ZFNjkyTbsPsY3plAEB6E7L/vZV3w= | |||||
modernc.org/ccgo/v3 v3.12.29/go.mod h1:FXVjG7YLf9FetsS2OOYcwNhcdOLGt8S9bQ48+OP75cE= | |||||
modernc.org/ccgo/v3 v3.12.36/go.mod h1:uP3/Fiezp/Ga8onfvMLpREq+KUjUmYMxXPO8tETHtA8= | |||||
modernc.org/ccgo/v3 v3.12.38/go.mod h1:93O0G7baRST1vNj4wnZ49b1kLxt0xCW5Hsa2qRaZPqc= | |||||
modernc.org/ccgo/v3 v3.12.43/go.mod h1:k+DqGXd3o7W+inNujK15S5ZYuPoWYLpF5PYougCmthU= | |||||
modernc.org/ccgo/v3 v3.12.46/go.mod h1:UZe6EvMSqOxaJ4sznY7b23/k13R8XNlyWsO5bAmSgOE= | |||||
modernc.org/ccgo/v3 v3.12.47/go.mod h1:m8d6p0zNps187fhBwzY/ii6gxfjob1VxWb919Nk1HUk= | |||||
modernc.org/ccgo/v3 v3.12.50/go.mod h1:bu9YIwtg+HXQxBhsRDE+cJjQRuINuT9PUK4orOco/JI= | |||||
modernc.org/ccgo/v3 v3.12.51/go.mod h1:gaIIlx4YpmGO2bLye04/yeblmvWEmE4BBBls4aJXFiE= | |||||
modernc.org/ccgo/v3 v3.12.53/go.mod h1:8xWGGTFkdFEWBEsUmi+DBjwu/WLy3SSOrqEmKUjMeEg= | |||||
modernc.org/ccgo/v3 v3.12.54/go.mod h1:yANKFTm9llTFVX1FqNKHE0aMcQb1fuPJx6p8AcUx+74= | |||||
modernc.org/ccgo/v3 v3.12.55/go.mod h1:rsXiIyJi9psOwiBkplOaHye5L4MOOaCjHg1Fxkj7IeU= | |||||
modernc.org/ccgo/v3 v3.12.56/go.mod h1:ljeFks3faDseCkr60JMpeDb2GSO3TKAmrzm7q9YOcMU= | |||||
modernc.org/ccgo/v3 v3.12.57/go.mod h1:hNSF4DNVgBl8wYHpMvPqQWDQx8luqxDnNGCMM4NFNMc= | |||||
modernc.org/ccgo/v3 v3.12.60/go.mod h1:k/Nn0zdO1xHVWjPYVshDeWKqbRWIfif5dtsIOCUVMqM= | |||||
modernc.org/ccgo/v3 v3.12.65/go.mod h1:D6hQtKxPNZiY6wDBtehSGKFKmyXn53F8nGTpH+POmS4= | |||||
modernc.org/ccgo/v3 v3.12.66/go.mod h1:jUuxlCFZTUZLMV08s7B1ekHX5+LIAurKTTaugUr/EhQ= | |||||
modernc.org/ccgo/v3 v3.12.67/go.mod h1:Bll3KwKvGROizP2Xj17GEGOTrlvB1XcVaBrC90ORO84= | |||||
modernc.org/ccgo/v3 v3.12.73/go.mod h1:hngkB+nUUqzOf3iqsM48Gf1FZhY599qzVg1iX+BT3cQ= | |||||
modernc.org/ccgo/v3 v3.12.81/go.mod h1:p2A1duHoBBg1mFtYvnhAnQyI6vL0uw5PGYLSIgF6rYY= | |||||
modernc.org/ccgo/v3 v3.12.82 h1:wudcnJyjLj1aQQCXF3IM9Gz2X6UNjw+afIghzdtn0v8= | |||||
modernc.org/ccgo/v3 v3.12.82/go.mod h1:ApbflUfa5BKadjHynCficldU1ghjen84tuM5jRynB7w= | |||||
modernc.org/ccorpus v1.11.1 h1:K0qPfpVG1MJh5BYazccnmhywH4zHuOgJXgbjzyp6dWA= | |||||
modernc.org/ccorpus v1.11.1/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= | |||||
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM= | |||||
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= | |||||
modernc.org/libc v1.9.8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w= | |||||
modernc.org/libc v1.9.11/go.mod h1:NyF3tsA5ArIjJ83XB0JlqhjTabTCHm9aX4XMPHyQn0Q= | |||||
modernc.org/libc v1.11.0/go.mod h1:2lOfPmj7cz+g1MrPNmX65QCzVxgNq2C5o0jdLY2gAYg= | |||||
modernc.org/libc v1.11.2/go.mod h1:ioIyrl3ETkugDO3SGZ+6EOKvlP3zSOycUETe4XM4n8M= | |||||
modernc.org/libc v1.11.5/go.mod h1:k3HDCP95A6U111Q5TmG3nAyUcp3kR5YFZTeDS9v8vSU= | |||||
modernc.org/libc v1.11.6/go.mod h1:ddqmzR6p5i4jIGK1d/EiSw97LBcE3dK24QEwCFvgNgE= | |||||
modernc.org/libc v1.11.11/go.mod h1:lXEp9QOOk4qAYOtL3BmMve99S5Owz7Qyowzvg6LiZso= | |||||
modernc.org/libc v1.11.13/go.mod h1:ZYawJWlXIzXy2Pzghaf7YfM8OKacP3eZQI81PDLFdY8= | |||||
modernc.org/libc v1.11.16/go.mod h1:+DJquzYi+DMRUtWI1YNxrlQO6TcA5+dRRiq8HWBWRC8= | |||||
modernc.org/libc v1.11.19/go.mod h1:e0dgEame6mkydy19KKaVPBeEnyJB4LGNb0bBH1EtQ3I= | |||||
modernc.org/libc v1.11.24/go.mod h1:FOSzE0UwookyT1TtCJrRkvsOrX2k38HoInhw+cSCUGk= | |||||
modernc.org/libc v1.11.26/go.mod h1:SFjnYi9OSd2W7f4ct622o/PAYqk7KHv6GS8NZULIjKY= | |||||
modernc.org/libc v1.11.27/go.mod h1:zmWm6kcFXt/jpzeCgfvUNswM0qke8qVwxqZrnddlDiE= | |||||
modernc.org/libc v1.11.28/go.mod h1:Ii4V0fTFcbq3qrv3CNn+OGHAvzqMBvC7dBNyC4vHZlg= | |||||
modernc.org/libc v1.11.31/go.mod h1:FpBncUkEAtopRNJj8aRo29qUiyx5AvAlAxzlx9GNaVM= | |||||
modernc.org/libc v1.11.34/go.mod h1:+Tzc4hnb1iaX/SKAutJmfzES6awxfU1BPvrrJO0pYLg= | |||||
modernc.org/libc v1.11.37/go.mod h1:dCQebOwoO1046yTrfUE5nX1f3YpGZQKNcITUYWlrAWo= | |||||
modernc.org/libc v1.11.39/go.mod h1:mV8lJMo2S5A31uD0k1cMu7vrJbSA3J3waQJxpV4iqx8= | |||||
modernc.org/libc v1.11.42/go.mod h1:yzrLDU+sSjLE+D4bIhS7q1L5UwXDOw99PLSX0BlZvSQ= | |||||
modernc.org/libc v1.11.44/go.mod h1:KFq33jsma7F5WXiYelU8quMJasCCTnHK0mkri4yPHgA= | |||||
modernc.org/libc v1.11.45/go.mod h1:Y192orvfVQQYFzCNsn+Xt0Hxt4DiO4USpLNXBlXg/tM= | |||||
modernc.org/libc v1.11.47/go.mod h1:tPkE4PzCTW27E6AIKIR5IwHAQKCAtudEIeAV1/SiyBg= | |||||
modernc.org/libc v1.11.49/go.mod h1:9JrJuK5WTtoTWIFQ7QjX2Mb/bagYdZdscI3xrvHbXjE= | |||||
modernc.org/libc v1.11.51/go.mod h1:R9I8u9TS+meaWLdbfQhq2kFknTW0O3aw3kEMqDDxMaM= | |||||
modernc.org/libc v1.11.53/go.mod h1:5ip5vWYPAoMulkQ5XlSJTy12Sz5U6blOQiYasilVPsU= | |||||
modernc.org/libc v1.11.54/go.mod h1:S/FVnskbzVUrjfBqlGFIPA5m7UwB3n9fojHhCNfSsnw= | |||||
modernc.org/libc v1.11.55/go.mod h1:j2A5YBRm6HjNkoSs/fzZrSxCuwWqcMYTDPLNx0URn3M= | |||||
modernc.org/libc v1.11.56/go.mod h1:pakHkg5JdMLt2OgRadpPOTnyRXm/uzu+Yyg/LSLdi18= | |||||
modernc.org/libc v1.11.58/go.mod h1:ns94Rxv0OWyoQrDqMFfWwka2BcaF6/61CqJRK9LP7S8= | |||||
modernc.org/libc v1.11.70/go.mod h1:DUOmMYe+IvKi9n6Mycyx3DbjfzSKrdr/0Vgt3j7P5gw= | |||||
modernc.org/libc v1.11.71/go.mod h1:DUOmMYe+IvKi9n6Mycyx3DbjfzSKrdr/0Vgt3j7P5gw= | |||||
modernc.org/libc v1.11.75/go.mod h1:dGRVugT6edz361wmD9gk6ax1AbDSe0x5vji0dGJiPT0= | |||||
modernc.org/libc v1.11.82/go.mod h1:NF+Ek1BOl2jeC7lw3a7Jj5PWyHPwWD4aq3wVKxqV1fI= | |||||
modernc.org/libc v1.11.86/go.mod h1:ePuYgoQLmvxdNT06RpGnaDKJmDNEkV7ZPKI2jnsvZoE= | |||||
modernc.org/libc v1.11.87 h1:PzIzOqtlzMDDcCzJ5cUP6h/Ku6Fa9iyflP2ccTY64aE= | |||||
modernc.org/libc v1.11.87/go.mod h1:Qvd5iXTeLhI5PS0XSyqMY99282y+3euapQFxM7jYnpY= | |||||
modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= | |||||
modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= | |||||
modernc.org/mathutil v1.4.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= | |||||
modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8= | |||||
modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= | |||||
modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc= | |||||
modernc.org/memory v1.0.5 h1:XRch8trV7GgvTec2i7jc33YlUI0RKVDBvZ5eZ5m8y14= | |||||
modernc.org/memory v1.0.5/go.mod h1:B7OYswTRnfGg+4tDH1t1OeUNnsy2viGTdME4tzd+IjM= | |||||
modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A= | |||||
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= | |||||
modernc.org/sqlite v1.14.2 h1:ohsW2+e+Qe2To1W6GNezzKGwjXwSax6R+CrhRxVaFbE= | |||||
modernc.org/sqlite v1.14.2/go.mod h1:yqfn85u8wVOE6ub5UT8VI9JjhrwBUUCNyTACN0h6Sx8= | |||||
modernc.org/strutil v1.1.1 h1:xv+J1BXY3Opl2ALrBwyfEikFAj8pmqcpnfmuwUwcozs= | |||||
modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= | |||||
modernc.org/tcl v1.8.13 h1:V0sTNBw0Re86PvXZxuCub3oO9WrSTqALgrwNZNvLFGw= | |||||
modernc.org/tcl v1.8.13/go.mod h1:V+q/Ef0IJaNUSECieLU4o+8IScapxnMyFV6i/7uQlAY= | |||||
modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk= | |||||
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= | |||||
modernc.org/z v1.2.19 h1:BGyRFWhDVn5LFS5OcX4Yd/MlpRTOc7hOPTdcIpCiUao= | |||||
modernc.org/z v1.2.19/go.mod h1:+ZpP0pc4zz97eukOzW3xagV/lS82IpPN9NGG5pNF9vY= | |||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= | |||||
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= | |||||
xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978 h1:bvLlAPW1ZMTWA32LuZMBEGHAUOcATZjzHcotf3SWweM= | |||||
xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE= | |||||
xorm.io/xorm v1.3.1 h1:z5egKrDoOLqZFhMjcGF4FBHiTmE5/feQoHclfhNidfM= | |||||
xorm.io/xorm v1.3.1/go.mod h1:9NbjqdnjX6eyjRRhh01GHm64r6N9shTb/8Ak3YRt8Nw= |
@@ -0,0 +1,683 @@ | |||||
package comm_plan | |||||
import ( | |||||
zhios_order_relate_utils "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/utils" | |||||
zhios_order_relate_logx "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/utils/logx" | |||||
"fmt" | |||||
) | |||||
//佣金 积分 区块币计算 | |||||
func CalReturnAmountAndRatio(level, ownbuyReturnType, peerNum int, userType string, fee, integralFee float64, opt *PlanOpt) (commission, commissionRatio float64, amountList, ratioList []*VirtualCoinCommission) { | |||||
// 佣金的比例兼容旧系统 比例独立出来的 所以这样算 | |||||
commissionRatio = getCommissionRatio(userType, level, peerNum, opt.UserRate) | |||||
commission = fee * commissionRatio | |||||
// 新版支持多种虚拟币 支持的种类id保存在ReturnType id=0代表现金佣金 其他为虚拟币 | |||||
if opt.UserRate[level].ReturnType != nil { //返佣类型 | |||||
for _, coinId := range opt.UserRate[level].ReturnType { | |||||
newFee := integralFee | |||||
if coinId == "0" { | |||||
newFee = fee | |||||
} | |||||
ratio := getVirtualCoinRatio(userType, level, peerNum, opt.UserRate, coinId) | |||||
amount := getCoinAmount(ratio, zhios_order_relate_utils.StrToInt(coinId), newFee, opt.VirtualCoinMoneyRatioList) | |||||
amountList = append(amountList, &VirtualCoinCommission{ | |||||
Cid: coinId, | |||||
Val: amount, | |||||
}) | |||||
ratioList = append(ratioList, &VirtualCoinCommission{ | |||||
Cid: coinId, | |||||
Val: zhios_order_relate_utils.AnyToFloat64(ratio), | |||||
}) | |||||
} | |||||
} | |||||
if ownbuyReturnType == 1 { //自购不返利 | |||||
commission = 0 | |||||
for i := range amountList { | |||||
amountList[i].Val = 0 | |||||
} | |||||
} | |||||
commission = zhios_order_relate_utils.FloatFormat(commission, 6) | |||||
for i, coin := range amountList { | |||||
amountList[i].Val = zhios_order_relate_utils.FloatFormat(coin.Val, 6) | |||||
} | |||||
return commission, commissionRatio, amountList, ratioList | |||||
} | |||||
//佣金 积分 区块币计算 | |||||
func CalReturnAmountAndRatioToWinery(level int, fee, integralFee float64, opt *PlanOpt) (commission, commissionRatio float64, amountList, ratioList []*VirtualCoinCommission) { | |||||
if opt.UserRate[level].ReturnType != nil { //返佣类型 | |||||
for _, coinId := range opt.UserRate[level].ReturnType { | |||||
newFee := integralFee | |||||
if coinId == "0" { | |||||
newFee = fee | |||||
} | |||||
ratio := zhios_order_relate_utils.Float64ToStrByPrec(zhios_order_relate_utils.StrToFloat64(opt.UserRate[level].BuyDeliverList[coinId])/100, 4) | |||||
amount := getCoinAmount(ratio, zhios_order_relate_utils.StrToInt(coinId), newFee, opt.VirtualCoinMoneyRatioList) | |||||
if coinId == "0" { | |||||
commission = amount | |||||
commissionRatio = zhios_order_relate_utils.StrToFloat64(ratio) | |||||
} | |||||
amountList = append(amountList, &VirtualCoinCommission{ | |||||
Cid: coinId, | |||||
Val: amount, | |||||
}) | |||||
ratioList = append(ratioList, &VirtualCoinCommission{ | |||||
Cid: coinId, | |||||
Val: zhios_order_relate_utils.AnyToFloat64(ratio), | |||||
}) | |||||
} | |||||
} | |||||
return commission, commissionRatio, amountList, ratioList | |||||
} | |||||
// 按总佣金的比例进行划分计算 | |||||
func CalcAll(opt *PlanOpt, totalAmt, integralTotalAmt float64, userList *LvUser, pvd string, sysFee float64, integralSysFee float64) error { | |||||
grade := opt.UserRate | |||||
if len(grade) == 0 { | |||||
return zhios_order_relate_logx.Warn("level grade is not set") | |||||
} | |||||
//查出用户自购佣金 | |||||
commission, commissionRatio, amountList, ratioList := CalReturnAmountAndRatio(userList.Lv, userList.OwnbuyReturnType, 0, "own", totalAmt, integralTotalAmt, opt) | |||||
userList.Profit = commission // 另外出来的佣金 兼容旧的 | |||||
userList.ProfitList = amountList // 各币种分佣 | |||||
userList.SubsidyFee = 0 | |||||
ratioListMap := convertList2Map(ratioList) | |||||
for k, v := range userList.ProfitList { | |||||
userList.ProfitList[k].Val = ratioListMap[v.Cid] * v.Val | |||||
} | |||||
// 各种币换算出总的额度 | |||||
totalAmtList := make([]*VirtualCoinCommission, 0) | |||||
for coinId, rate := range opt.VirtualCoinMoneyRatioList { | |||||
var amount float64 | |||||
if coinId == 0 { | |||||
amount = totalAmt | |||||
} else { | |||||
amount = integralTotalAmt * zhios_order_relate_utils.AnyToFloat64(rate) | |||||
} | |||||
totalAmtList = append(totalAmtList, &VirtualCoinCommission{ | |||||
Cid: zhios_order_relate_utils.AnyToString(coinId), | |||||
Val: amount, | |||||
}) | |||||
} | |||||
var ( | |||||
node = userList | |||||
maxLv = node.Lv // 当前等级 | |||||
maxLevelWeight = node.LevelWeight // 当前权重 | |||||
peerNum = 0 // 存在同级数 | |||||
peerRate float64 = 0 // 同级累计比例 | |||||
peerRateList = make([]*VirtualCoinCommission, 0) // 各虚拟币同级累计 | |||||
restAmtList = make([]*VirtualCoinCommission, 0) // 各虚拟币剩余额度 | |||||
accumulateRatioList = make([]*VirtualCoinCommission, 0) // 各虚拟币累计比例 | |||||
restAmt = totalAmt - userList.Profit // 剩余比例 | |||||
totalCommissionRatio = commissionRatio // 累计佣金比例 | |||||
) | |||||
// 计算剩余额度 | |||||
restAmtList, _ = CalVirtualCommissionMinus(totalAmtList, amountList) | |||||
// 累计比例 | |||||
accumulateRatioList = ratioList | |||||
restAmt = zhios_order_relate_utils.FloatFormat(restAmt, 6) | |||||
Loop: | |||||
for node.ParentUser != nil { //查找上级用户 | |||||
node.ParentUser.Profit = 0 | |||||
//佣金补贴奖励 | |||||
subsidyFee, subsidyRatio, isOnlySubsidyFee, subsidyFeeList, subsidyRatioList := subsidyFeeDo(opt, totalAmt, integralTotalAmt, node.ParentUser, userList.NewLv, pvd, sysFee, integralSysFee) | |||||
node.ParentUser.SubsidyFee = subsidyFee | |||||
node.ParentUser.SubsidyFeeList = subsidyFeeList // 各币种补贴 | |||||
// 如果父级比当前级别低, 跳过 | |||||
// 同级奖, 如果父级别与当前级别一致,并且设置了对应比例 | |||||
count := len(grade[maxLv].PeerRate) | |||||
if grade[maxLv].PeerRateList != nil { | |||||
count = len(grade[maxLv].PeerRateList) | |||||
} | |||||
var isBreak bool | |||||
zeroList := make(map[string]struct{}) | |||||
// 同级奖 | |||||
if node.ParentUser.LevelWeight == maxLevelWeight && count > peerNum { | |||||
//同级奖励比例 | |||||
commission, commissionRatio, amountList, ratioList := CalReturnAmountAndRatio(maxLv, userList.OwnbuyReturnType, peerNum, "same_lv", totalAmt, integralTotalAmt, opt) | |||||
//佣金 (lv, isOnlySubsidy int, restAmt, profit, peerRate, totalRatio, restRatio, subsidyFee, subsidyBili float64, opt *PlanOpt) | |||||
node.ParentUser.Profit, restAmt, totalCommissionRatio, peerRate, node.ParentUser.SubsidyFee, isBreak = sameMoney(node.Lv, isOnlySubsidyFee, restAmt, commission, peerRate, totalCommissionRatio, commissionRatio, node.ParentUser.SubsidyFee, subsidyRatio, opt) | |||||
node.ParentUser.ProfitList, restAmtList, accumulateRatioList, peerRateList, node.ParentUser.SubsidyFeeList, zeroList = sameMoneyV2(node.Lv, isOnlySubsidyFee, totalAmtList, restAmtList, amountList, peerRateList, accumulateRatioList, ratioList, node.ParentUser.SubsidyFeeList, subsidyRatioList, opt) | |||||
// 全部都没得分了 | |||||
if isBreak && len(zeroList) == len(opt.UserRate[maxLv].ReturnType) { | |||||
break Loop | |||||
} | |||||
peerNum++ | |||||
} else if node.ParentUser.LevelWeight > maxLevelWeight { | |||||
if _, ok := grade[node.Lv]; !ok { | |||||
return zhios_order_relate_logx.Warn("level grade node.Lv is not set") | |||||
} | |||||
if _, ok := grade[node.ParentUser.Lv]; !ok { | |||||
return zhios_order_relate_logx.Warn("level grade node.ParentUser.Lv is not set") | |||||
} | |||||
commission, _, amountList, teamRatioList := CalReturnAmountAndRatio(node.ParentUser.Lv, userList.OwnbuyReturnType, peerNum, "team", totalAmt, integralTotalAmt, opt) | |||||
//佣金 | |||||
node.ParentUser.Profit = commission | |||||
node.ParentUser.Profit, restAmt, totalCommissionRatio, node.ParentUser.SubsidyFee, isBreak = teamDiffMoney(node.ParentUser.Profit, grade[node.Lv].PayMode, isOnlySubsidyFee, totalAmt, restAmt, grade[node.ParentUser.Lv].TeamRate, totalCommissionRatio, peerRate, node.ParentUser.SubsidyFee, subsidyRatio) | |||||
//积分 | |||||
node.ParentUser.ProfitList = amountList | |||||
// profitList []*VirtualCoinCommission, payMode, isOnlySubsidy int, totalAmtList, restAmtList, teamRatioList, totalRatioList, peerRateList, subsidyFeeList, subsidyRatioList []*VirtualCoinCommission | |||||
node.ParentUser.ProfitList, restAmtList, accumulateRatioList, node.ParentUser.SubsidyFeeList, zeroList = teamDiffMoneyV2(node.ParentUser.ProfitList, grade[node.Lv].PayMode, isOnlySubsidyFee, totalAmtList, restAmtList, teamRatioList, accumulateRatioList, peerRateList, subsidyFeeList, subsidyRatioList) | |||||
// 没得分了 就结束 | |||||
if isBreak && len(zeroList) == len(opt.UserRate[maxLv].ReturnType) { | |||||
break Loop | |||||
} | |||||
// 等级往上升则置0 | |||||
maxLevelWeight, maxLv, peerRate, peerRateList, peerNum = node.ParentUser.LevelWeight, node.ParentUser.Lv, 0, nil, 0 | |||||
} | |||||
//如果是酒庄制度,要看这里处理 额外的补贴 | |||||
subsidyFee, subsidyRatio, isOnlySubsidyFee, subsidyFeeList, subsidyRatioList = subsidyFeeDo(opt, totalAmt, integralTotalAmt, node.ParentUser, userList.NewLv, pvd, sysFee, integralSysFee) | |||||
node.ParentUser.SubsidyFee = subsidyFee | |||||
node.ParentUser.SubsidyFeeList = subsidyFeeList // 各币种补贴 | |||||
node.Profit = zhios_order_relate_utils.StrToFloat64(fmt.Sprintf("%.4f", node.Profit)) | |||||
node = node.ParentUser | |||||
} | |||||
return nil | |||||
} | |||||
//公共处理同级计算 (只计算佣金 旧版本用) | |||||
func sameMoney(lv, isOnlySubsidy int, restAmt, profit, peerRate, totalRatio, restRatio, subsidyFee, subsidyBili float64, opt *PlanOpt) (float64, float64, float64, float64, float64, bool) { | |||||
//如果不够扣了,并且是比例返利就跳过 | |||||
if restAmt < profit { | |||||
return 0, restAmt, totalRatio, peerRate, subsidyFee, true | |||||
} | |||||
//极差返利 | |||||
if opt.UserRate[lv].PayMode == 0 && isOnlySubsidy == 0 { | |||||
restAmt -= profit // 剩余可分 | |||||
restAmt = zhios_order_relate_utils.FloatFormat(restAmt, 6) | |||||
peerRate += restRatio | |||||
totalRatio += restRatio | |||||
} else if isOnlySubsidy == 1 { //如果只返补贴 当成是极差的一部分 所以要扣 不是额外的 | |||||
profit = 0 | |||||
if opt.UserRate[lv].PayMode == 0 { | |||||
if restAmt < subsidyFee { | |||||
subsidyFee = 0 | |||||
return profit, restAmt, totalRatio, subsidyFee, peerRate, true | |||||
} | |||||
restAmt -= subsidyFee // 剩余可分 | |||||
restAmt = zhios_order_relate_utils.FloatFormat(restAmt, 6) | |||||
totalRatio += zhios_order_relate_utils.FloatFormat(subsidyBili, 6) | |||||
} | |||||
} | |||||
return profit, restAmt, totalRatio, peerRate, subsidyFee, false | |||||
} | |||||
func sameMoneyV2(lv, isOnlySubsidy int, totalAmtList, restAmtList, profitList, peerRateList, totalRatioList, restRatioList, subsidyFeeList, subsidyRatioList []*VirtualCoinCommission, opt *PlanOpt) ([]*VirtualCoinCommission, []*VirtualCoinCommission, []*VirtualCoinCommission, []*VirtualCoinCommission, []*VirtualCoinCommission, map[string]struct{}) { | |||||
restAmtMap := convertList2Map(restAmtList) | |||||
totalAmtMap := convertList2Map(totalAmtList) | |||||
//profitMap := convertList2Map(profitList) | |||||
restRatioMap := convertList2Map(restRatioList) | |||||
totalRatioMap := convertList2Map(totalRatioList) | |||||
peerRateMap := convertList2Map(peerRateList) | |||||
subsidyMap := convertList2Map(subsidyFeeList) | |||||
subsidyRatioMap := convertList2Map(subsidyRatioList) | |||||
zeroList := make(map[string]struct{}) | |||||
newProfitList := make([]*VirtualCoinCommission, 0) | |||||
newRestAmtList := make([]*VirtualCoinCommission, 0) | |||||
newTotalRatioList := make([]*VirtualCoinCommission, 0) | |||||
newPeerRateList := make([]*VirtualCoinCommission, 0) | |||||
newSubsidyFeeList := subsidyFeeList | |||||
//极差返利 | |||||
if opt.UserRate[lv].PayMode == 0 && isOnlySubsidy == 0 { | |||||
for _, coin := range profitList { | |||||
profitOne := &VirtualCoinCommission{} | |||||
profitOne.Cid = coin.Cid | |||||
profitOne.Val = totalAmtMap[coin.Cid] * restRatioMap[coin.Cid] | |||||
// 不够扣了 设为0 | |||||
if restAmtMap[coin.Cid] < profitOne.Val { | |||||
profitOne.Val = 0 | |||||
zeroList[coin.Cid] = struct{}{} | |||||
} | |||||
// 分佣 | |||||
newProfitList = append(newProfitList, profitOne) | |||||
// 剩余 | |||||
restAmtMap[coin.Cid] -= profitOne.Val | |||||
// 累计比例 | |||||
totalRatioMap[coin.Cid] += restRatioMap[coin.Cid] | |||||
// 同级累计比例 | |||||
if _, ok := peerRateMap[coin.Cid]; !ok { | |||||
peerRateMap[coin.Cid] = 0 | |||||
} | |||||
peerRateMap[coin.Cid] += restRatioMap[coin.Cid] | |||||
} | |||||
} else if isOnlySubsidy == 1 { | |||||
newSubsidyFeeList = make([]*VirtualCoinCommission, 0) | |||||
for _, coin := range profitList { | |||||
profitOne := &VirtualCoinCommission{} | |||||
subsidyFeeOne := &VirtualCoinCommission{} | |||||
profitOne.Cid = coin.Cid | |||||
profitOne.Val = 0 | |||||
newProfitList = append(newProfitList, profitOne) | |||||
if opt.UserRate[lv].PayMode == 0 { | |||||
subsidyFeeOne.Cid = coin.Cid | |||||
subsidyFeeOne.Val = subsidyMap[coin.Cid] | |||||
if restAmtMap[coin.Cid] < subsidyMap[coin.Cid] { | |||||
subsidyFeeOne.Val = 0 | |||||
zeroList[coin.Cid] = struct{}{} | |||||
} | |||||
newSubsidyFeeList = append(newSubsidyFeeList, subsidyFeeOne) | |||||
} | |||||
// 剩余额度 | |||||
restAmtMap[coin.Cid] -= subsidyFeeOne.Val | |||||
// 累计比例 | |||||
totalRatioMap[coin.Cid] += subsidyRatioMap[coin.Cid] | |||||
// 同级累计比例 | |||||
if _, ok := peerRateMap[coin.Cid]; !ok { | |||||
peerRateMap[coin.Cid] = 0 | |||||
} | |||||
peerRateMap[coin.Cid] += restRatioMap[coin.Cid] | |||||
} | |||||
} | |||||
newTotalRatioList = convertMap2List(totalRatioMap) | |||||
newPeerRateList = convertMap2List(peerRateMap) | |||||
newRestAmtList = convertMap2List(restAmtMap) | |||||
return newProfitList, newRestAmtList, newTotalRatioList, newPeerRateList, newSubsidyFeeList, zeroList | |||||
} | |||||
//公共处理下团队-上一层 (用于旧版的制度 只有佣金时) | |||||
func teamDiffMoney(profit float64, payMode, isOnlySubsidy int, totalAmt, restAmt, teamRatio, totalRatio, peerRate, subsidyFee, subsidyRatio float64) (float64, float64, float64, float64, bool) { | |||||
// 如果是团队内部支出团队比例大于同级累计比例 或站长支出 | |||||
if payMode == 1 || teamRatio > peerRate { | |||||
teamRatio = zhios_order_relate_utils.FloatFormat(teamRatio-totalRatio, 6) | |||||
} | |||||
//极差返利 | |||||
if isOnlySubsidy == 0 { | |||||
totalRatio += teamRatio | |||||
//出现负数跳过 | |||||
if teamRatio <= 0 { | |||||
profit = 0 | |||||
return profit, restAmt, totalRatio, subsidyFee, true | |||||
} | |||||
profit = zhios_order_relate_utils.FloatFormat(teamRatio*totalAmt, 6) | |||||
if restAmt < profit { | |||||
profit = 0 | |||||
return profit, restAmt, totalRatio, subsidyFee, true | |||||
} | |||||
restAmt -= profit // 剩余可分 | |||||
} else if isOnlySubsidy == 1 { //如果只返补贴 当成是极差的一部分 所以要扣 不是额外的 | |||||
totalRatio += zhios_order_relate_utils.FloatFormat(subsidyRatio, 6) | |||||
profit = 0 | |||||
if restAmt < subsidyFee { | |||||
profit = 0 | |||||
subsidyFee = 0 | |||||
return profit, restAmt, totalRatio, subsidyFee, true | |||||
} | |||||
restAmt -= subsidyFee // 剩余可分 | |||||
} | |||||
restAmt = zhios_order_relate_utils.FloatFormat(restAmt, 6) | |||||
return profit, restAmt, totalRatio, subsidyFee, false | |||||
} | |||||
// 处理多虚拟币团队的 | |||||
func teamDiffMoneyV2(profitList []*VirtualCoinCommission, payMode, isOnlySubsidy int, totalAmtList, restAmtList, teamRatioList, totalRatioList, peerRateList, subsidyFeeList, subsidyRatioList []*VirtualCoinCommission) (newProfitList, newRestAmtList, newTotalRatioList, newSubsidyFeeList []*VirtualCoinCommission, zeroList map[string]struct{}) { | |||||
restAmtMap := convertList2Map(restAmtList) | |||||
totalAmtMap := convertList2Map(totalAmtList) | |||||
profitMap := convertList2Map(profitList) | |||||
totalRatioMap := convertList2Map(totalRatioList) | |||||
peerRateMap := convertList2Map(peerRateList) | |||||
subsidyFeeMap := convertList2Map(subsidyFeeList) | |||||
subsidyRatioMap := convertList2Map(subsidyRatioList) | |||||
teamRatioMap := convertList2Map(teamRatioList) | |||||
zeroList = make(map[string]struct{}) | |||||
newProfitList = make([]*VirtualCoinCommission, 0) | |||||
for _, coin := range profitList { | |||||
// 如果是团队内部支出团队比例大于同级累计比例 或站长支出 | |||||
if payMode == 1 || teamRatioMap[coin.Cid] > peerRateMap[coin.Cid] { | |||||
teamRatioMap[coin.Cid] = zhios_order_relate_utils.FloatFormat(teamRatioMap[coin.Cid]-totalRatioMap[coin.Cid], 6) | |||||
} | |||||
if isOnlySubsidy == 0 { | |||||
totalRatioMap[coin.Cid] += teamRatioMap[coin.Cid] | |||||
profitOne := &VirtualCoinCommission{} | |||||
profitOne.Cid = coin.Cid | |||||
profitOne.Val = zhios_order_relate_utils.FloatFormat(totalAmtMap[coin.Cid]*teamRatioMap[coin.Cid], 6) | |||||
// 剩余不足或比例小于0 | |||||
if teamRatioMap[coin.Cid] < 0 || restAmtMap[coin.Cid] < profitOne.Val { | |||||
zeroList[coin.Cid] = struct{}{} | |||||
profitOne.Val = 0 | |||||
} | |||||
newProfitList = append(newProfitList, profitOne) | |||||
restAmtMap[coin.Cid] -= profitOne.Val | |||||
} else if isOnlySubsidy == 1 { //如果只返补贴 当成是极差的一部分 所以要扣 不是额外的 | |||||
totalRatioMap[coin.Cid] += zhios_order_relate_utils.FloatFormat(subsidyRatioMap[coin.Cid], 6) | |||||
profitMap[coin.Cid] = 0 | |||||
if restAmtMap[coin.Cid] < subsidyFeeMap[coin.Cid] { | |||||
subsidyFeeMap[coin.Cid] = 0 | |||||
} | |||||
restAmtMap[coin.Cid] -= subsidyFeeMap[coin.Cid] | |||||
} | |||||
} | |||||
newTotalRatioList = convertMap2List(totalRatioMap) | |||||
newRestAmtList = convertMap2List(restAmtMap) | |||||
newSubsidyFeeList = convertMap2List(subsidyFeeMap) | |||||
return newProfitList, newRestAmtList, newTotalRatioList, newSubsidyFeeList, zeroList | |||||
} | |||||
//补贴金额计算 | |||||
// types 支持的返佣类型 | |||||
func subsidyFeeDo(opt *PlanOpt, totalAmt, integralTotalAmt float64, lvuser *LvUser, newLv int, pvd string, sysFee, integralSysFee float64) (subsidyFee, subsidyRatio float64, isOnlySubsidyFee int, subsidyFeeList, subsidyRatioList []*VirtualCoinCommission) { | |||||
grade := opt.UserRate | |||||
lv := lvuser.Lv | |||||
if grade[lv].UserSubsidyType == "winery" { //酒庄模式 换一下计算基数 | |||||
commission := lvuser.Profit | |||||
amountList := lvuser.ProfitList | |||||
var baseMoney = commission | |||||
if zhios_order_relate_utils.StrToInt(grade[lv].UserSubsidyBaseCoinId) > 0 { | |||||
for _, v := range amountList { | |||||
if v.Cid == grade[lv].UserSubsidyBaseCoinId { | |||||
baseMoney = v.Val | |||||
} | |||||
} | |||||
} | |||||
totalAmt = baseMoney | |||||
integralTotalAmt = baseMoney | |||||
} | |||||
subsidyFee, subsidyRatio, isOnlySubsidyFee, subsidyFeeList, subsidyRatioList = commSubsidy(opt, totalAmt, integralTotalAmt, lvuser, newLv, pvd, sysFee, integralSysFee, grade) | |||||
return subsidyFee, subsidyRatio, isOnlySubsidyFee, subsidyFeeList, subsidyRatioList | |||||
} | |||||
func commSubsidy(opt *PlanOpt, totalAmt, integralTotalAmt float64, lvuser *LvUser, newLv int, pvd string, sysFee, integralSysFee float64, grade map[int]*LvGrade) (subsidyFee, subsidyRatio float64, isOnlySubsidyFee int, subsidyFeeList, subsidyRatioList []*VirtualCoinCommission) { | |||||
lv := lvuser.Lv | |||||
//会员费分佣只有直推的奖励 | |||||
pvdBool := zhios_order_relate_utils.InArr(pvd, []string{"user_level_up", "mall_goods_user_lv"}) | |||||
if opt.IsCanRunSubsidy == 1 { //后台推演用 | |||||
if zhios_order_relate_utils.InArr(grade[lv].UserSubsidyType, []string{"buy_goods", "winery"}) { | |||||
pvdBool = false | |||||
} else { | |||||
pvdBool = true | |||||
} | |||||
} | |||||
if pvdBool && lvuser.Diff != 1 { | |||||
return 0, 0, 0, nil, nil | |||||
} | |||||
if _, ok := grade[lv]; !ok { | |||||
return 0, 0, 0, nil, nil | |||||
} | |||||
if grade[lv].UserSubsidyType == "" { | |||||
grade[lv].UserSubsidyType = "up_lv" | |||||
} | |||||
// 各等级 各虚拟币补贴设置 | |||||
userLvUpSubsidyList := grade[lv].UserLvUpSubsidyList | |||||
if userLvUpSubsidyList == nil { | |||||
return 0, 0, 0, nil, nil | |||||
} | |||||
//只有额外补贴跟 分销补贴按钮都开启才有的分 | |||||
if grade[lv].SubsidyEnable == 1 && grade[lv].UserLvUpSubsidyEnable == 1 { | |||||
//判断有没有开启 如果不是推荐会员模式 | |||||
if pvdBool && grade[lv].UserSubsidyType != "up_lv" { // 分享会员补贴 | |||||
return 0, 0, 0, nil, nil | |||||
} | |||||
//如果不是购买商品模式 跳过 | |||||
if pvdBool == false && zhios_order_relate_utils.InArr(grade[lv].UserSubsidyType, []string{"buy_goods", "winery"}) { // 购买商品补贴 | |||||
return 0, 0, 0, nil, nil | |||||
} | |||||
//处理每个条件的返利 | |||||
if grade[lv].UserLvUpSubsidyList != nil { | |||||
fmt.Println(grade[lv].UserLvUpSubsidyList) | |||||
for k, v1 := range grade[lv].UserLvUpSubsidyList { | |||||
v, ok := v1.(map[string]interface{}) | |||||
if ok { | |||||
//如果不相等并且是会员升级的没的返 | |||||
if newLv != int(zhios_order_relate_utils.AnyToInt64(v["lv"])) && pvdBool { | |||||
continue | |||||
} | |||||
//如果层级不是当前层级 且不是会员升级 | |||||
if pvdBool == false && k+1 != lvuser.Diff { | |||||
continue | |||||
} | |||||
if pvdBool == false { //如果不是会员升级 newLv=旧的等级 | |||||
newLv = lv | |||||
} | |||||
//如果没开启与补贴共存 只能拿这个奖励 | |||||
if int(zhios_order_relate_utils.AnyToInt64(v["is_use"])) != 1 { | |||||
isOnlySubsidyFee = 1 | |||||
} | |||||
modeList := grade[lv].SubsidyModeList // 每一种币按比例还是固定金额 | |||||
if modeList == nil { | |||||
return 0, 0, 0, nil, nil | |||||
} | |||||
subsidyReturnType := grade[lv].SubsidyReturnType // 补贴支持的虚拟币 | |||||
if subsidyReturnType == nil { | |||||
return 0, 0, 0, nil, nil | |||||
} | |||||
for _, coinId := range subsidyReturnType { | |||||
ratio := GetLvUpSubsidyVirtualCoinRatio(lv, newLv, lvuser.Diff, grade, coinId) | |||||
mode := modeList[coinId] | |||||
if mode != "bili" && mode != "money" { | |||||
continue | |||||
} | |||||
modeStr := mode.(string) | |||||
subsidyMode := grade[lv].SubsidyMode | |||||
newAmt := integralTotalAmt | |||||
newSysFee := integralSysFee | |||||
var moneyRate = "" | |||||
if coinId == "0" { | |||||
newAmt = totalAmt | |||||
newSysFee = sysFee | |||||
} else if mode == "bili" { | |||||
rateList := opt.VirtualCoinMoneyRatioList | |||||
moneyRates, ok := rateList[zhios_order_relate_utils.StrToInt(coinId)] | |||||
if ok { | |||||
moneyRate = moneyRates | |||||
} | |||||
} | |||||
amount, subsidyRatio := GetSubsidyVirtualCoinAmount(ratio, moneyRate, modeStr, newAmt, newSysFee, subsidyMode) | |||||
subsidyFeeList = append(subsidyFeeList, &VirtualCoinCommission{ | |||||
Cid: coinId, | |||||
Val: amount, | |||||
}) | |||||
subsidyRatioList = append(subsidyRatioList, &VirtualCoinCommission{ | |||||
Cid: coinId, | |||||
Val: subsidyRatio, | |||||
}) | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
subsidyFee = zhios_order_relate_utils.FloatFormat(subsidyFee, 6) | |||||
for i, coin := range subsidyFeeList { | |||||
subsidyFeeList[i].Val = zhios_order_relate_utils.FloatFormat(subsidyFeeList[i].Val, 6) | |||||
if coin.Cid == "0" { | |||||
subsidyFee += coin.Val // 添加上额外补贴到外部的补贴金额 | |||||
} | |||||
} | |||||
return subsidyFee, subsidyRatio, isOnlySubsidyFee, subsidyFeeList, subsidyRatioList | |||||
} | |||||
// 获取佣金比例 | |||||
func getCommissionRatio(typ string, level, peerNum int, grade map[int]*LvGrade) (ratio float64) { | |||||
switch typ { | |||||
case "team": | |||||
ratio = grade[level].TeamRate | |||||
case "same_lv": | |||||
if len(grade[level].PeerRate) == 0 { | |||||
ratio = 0 | |||||
} else { | |||||
ratio = grade[level].PeerRate[peerNum] | |||||
} | |||||
default: | |||||
ratio = grade[level].SelfRate | |||||
} | |||||
return | |||||
} | |||||
// 获取佣金、虚拟币比例 0=佣金 | |||||
func getVirtualCoinRatio(typ string, level, peerNum int, grade map[int]*LvGrade, coinId string) (ratio string) { | |||||
ok := false | |||||
switch typ { | |||||
case "team": | |||||
ratio, ok = grade[level].TeamRateList[coinId] | |||||
case "same_lv": | |||||
ratio, ok = grade[level].PeerRateList[peerNum][coinId] | |||||
default: | |||||
ratio, ok = grade[level].SelfRateList[coinId] | |||||
} | |||||
if !ok { | |||||
ratio = "0" | |||||
} | |||||
return | |||||
} | |||||
// GetLvUpSubsidyVirtualCoinRatio 获取各币种分销补贴比例 | |||||
func GetLvUpSubsidyVirtualCoinRatio(level, newLevel, diff int, grade map[int]*LvGrade, coinId string) (ratio string) { | |||||
gradeCfg, ok := grade[level] | |||||
if !ok || gradeCfg == nil { | |||||
return "0" | |||||
} | |||||
levelSubsidyCfg := gradeCfg.UserLvUpSubsidyList | |||||
if levelSubsidyCfg == nil { | |||||
return "0" | |||||
} | |||||
// 找出对应等级的配置 | |||||
var levelRateListArr = make([]interface{}, 0) | |||||
for oneKey, oneLevel := range levelSubsidyCfg { | |||||
oneLevelMap, ok := oneLevel.(map[string]interface{}) | |||||
if !ok || oneLevelMap == nil { | |||||
continue | |||||
} | |||||
if oneLevelMap["lv"] == "" && diff == 0 { | |||||
continue | |||||
} | |||||
if oneLevelMap["lv"] == zhios_order_relate_utils.AnyToString(newLevel) || (oneKey+1 == diff && diff > 0) { | |||||
//可能不是这个类型 | |||||
jsons, ok := oneLevelMap["rate_list"].([]interface{}) | |||||
if ok { | |||||
levelRateListArr = jsons | |||||
} | |||||
} | |||||
} | |||||
if len(levelRateListArr) == 0 { | |||||
return "0" | |||||
} | |||||
// 各币种的补贴比例 | |||||
coinIdInt := zhios_order_relate_utils.StrToInt(coinId) | |||||
ratio = levelRateListArr[coinIdInt].(string) | |||||
if zhios_order_relate_utils.StrToFloat64(ratio) == 0 { | |||||
return "0" | |||||
} | |||||
return ratio | |||||
} | |||||
// GetSubsidyVirtualCoinAmount 获取各币种补贴值 | |||||
// ratio 比例 | |||||
// typ 模式 bili money | |||||
func GetSubsidyVirtualCoinAmount(ratio, moneyRate, typ string, fee, sysFee float64, subsidyMode int) (amount, subsidyRatio float64) { | |||||
ratioF := zhios_order_relate_utils.AnyToFloat64(ratio) | |||||
if typ == "money" { | |||||
amount = ratioF | |||||
subsidyRatio = ratioF / fee | |||||
} else { | |||||
subsidyRatio = ratioF / 100 | |||||
if zhios_order_relate_utils.StrToFloat64(moneyRate) > 0 { | |||||
sysFee = sysFee * zhios_order_relate_utils.StrToFloat64(moneyRate) | |||||
} | |||||
if zhios_order_relate_utils.StrToFloat64(moneyRate) > 0 { | |||||
fee = fee * zhios_order_relate_utils.StrToFloat64(moneyRate) | |||||
} | |||||
if subsidyMode == 1 { // 按利润 | |||||
amount = sysFee * subsidyRatio | |||||
} else { // 按佣金 | |||||
amount = fee * subsidyRatio | |||||
} | |||||
} | |||||
return | |||||
} | |||||
// 计算佣金、虚拟币额度 | |||||
func getCoinAmount(ratio string, coinId int, fee float64, rateList map[int]string) (amount float64) { | |||||
moneyRate, ok := rateList[coinId] | |||||
if !ok { | |||||
amount = 0.00 | |||||
return | |||||
} | |||||
if coinId == 0 { // 金额 | |||||
amount = fee * zhios_order_relate_utils.StrToFloat64(ratio) | |||||
} else { // 虚拟币 需要将金额按设置的比例兑换成虚拟币 这里不乘比例了 会影响后面的极差 | |||||
//amount = fee * zhios_order_relate_utils.AnyToFloat64(moneyRate) * zhios_order_relate_utils.StrToFloat64(ratio) | |||||
amount = fee * zhios_order_relate_utils.AnyToFloat64(moneyRate) | |||||
} | |||||
return | |||||
} | |||||
// 计算各币种数量扣除 | |||||
func CalVirtualCommissionMinus(a, b []*VirtualCoinCommission) (c []*VirtualCoinCommission, zeroList map[string]struct{}) { | |||||
var amount float64 | |||||
zeroList = make(map[string]struct{}) | |||||
for _, coinA := range a { | |||||
for _, coinB := range b { | |||||
if coinA.Cid == coinB.Cid { | |||||
amount = coinA.Val - coinB.Val | |||||
if amount < 0 { | |||||
zeroList[coinA.Cid] = struct{}{} | |||||
amount = 0 | |||||
} | |||||
c = append(c, &VirtualCoinCommission{ | |||||
Cid: coinA.Cid, | |||||
Val: amount, | |||||
}) | |||||
} | |||||
} | |||||
} | |||||
return c, zeroList | |||||
} | |||||
func convertList2Map(a []*VirtualCoinCommission) (b map[string]float64) { | |||||
b = make(map[string]float64) | |||||
for _, i := range a { | |||||
b[i.Cid] = i.Val | |||||
} | |||||
return b | |||||
} | |||||
func convertMap2List(a map[string]float64) (b []*VirtualCoinCommission) { | |||||
for cid, val := range a { | |||||
b = append(b, &VirtualCoinCommission{ | |||||
Cid: cid, | |||||
Val: val, | |||||
}) | |||||
} | |||||
return b | |||||
} |
@@ -0,0 +1,155 @@ | |||||
package comm_plan | |||||
var Fn = map[string]func(opt *PlanOpt, totalAmt, integralTotalAmt float64, userList *LvUser, pvd string, sysFee float64, integralSysFee float64) error{ | |||||
"lv_all": CalcAll, | |||||
"lv_self": CalcSelf, | |||||
"lv_subsidy": CalcAll, | |||||
"lv_price": CalcAll, | |||||
"lv_winery": CalcAll, | |||||
} | |||||
type PlanOpt struct { | |||||
IntegralOpen int | |||||
PlanCommissionId int | |||||
IsCanRunSubsidy int //用于后台判断要不要走补贴 | |||||
Pvd string // 供应商 | |||||
Mode string // 分佣方案 | |||||
CommissionMode string // 佣金返佣方式 | |||||
//IntegralMode string // 积分返佣方式 | |||||
//BlockIconsMode string // 区块币返佣方式 | |||||
SysRate float64 // 系统占佣比例 | |||||
PvdRate float64 // 供应商占佣比例 | |||||
RegionRate float64 // 区域代理占佣比例 | |||||
GlobalRate float64 // 全球分红占佣比例 | |||||
MerchantRate float64 //商家占佣比例 | |||||
PushHandRate float64 //推手占佣比例 | |||||
//IntegralBili float64 // 积分兑换比例 | |||||
//BlockIconsBili float64 // 区块币兑换比例 | |||||
UserRate map[int]*LvGrade // 供应商对应的等级比例 | |||||
VirtualCoinMoneyRatioList map[int]string // 兑换现金比例列表 | |||||
} | |||||
// 级差结构 | |||||
type LvGrade struct { | |||||
Lv int `json:"lv"` // 级别 | |||||
SubsidyMode int `json:"subsidy_mode"` // 补贴计算方式, 0按佣金计算,1按平台利润计算 | |||||
SubsidyEnable int `json:"subsidy_enable"` // 是否开启补贴计算方式 0关闭, 1开启 | |||||
SubsidySelfRate float64 `json:"subsidy_self_rate"` // 自购补贴比例 | |||||
SubsidyShareRate float64 `json:"subsidy_share_rate"` // 分享补贴比例 | |||||
PayMode int `json:"pay_mode"` // 0团队内部支出, 1平台系统支出 | |||||
SelfRate float64 `json:"self_rate"` // 自购比例 | |||||
TeamRate float64 `json:"team_rate"` // 团队分成比例 | |||||
PeerRate []float64 `json:"peer_rate"` // 同级分成比例 | |||||
UserLvUpSubsidyEnable int `json:"user_lv_up_subsidy_enable"` //分销补贴开关 | |||||
UserLvUpSubsidyMode int `json:"user_lv_up_subsidy_mode"` //补贴方式 0比例 1固定金额 | |||||
UserSubsidyType string `json:"user_subsidy_type"` // 补贴模式 up_lv 推荐会员补贴 buy_goods 购买商品 | |||||
UserSubsidyBaseCoinId string `json:"user_subsidy_base_coin_id"` // 补贴计算基数 | |||||
UserLvUpSubsidyList []interface{} `json:"user_lv_up_subsidy_list"` //会员费分销补贴相应方式的列表 | |||||
PeerRateList []map[string]string `json:"peer_rate_list"` //同级比例 | |||||
BuyDeliverList map[string]string `json:"buy_deliver_list"` //酒庄制度 | |||||
ReturnType []string `json:"return_type"` //返利类型 | |||||
SelfRateList map[string]string `json:"self_rate_list"` // 自购比例 | |||||
TeamRateList map[string]string `json:"team_rate_list"` // 团队最高比例 | |||||
SubsidyModeList map[string]interface{} `json:"subsidy_mode_list"` // 各币种返佣模式:bili:比例 money:固定金额 | |||||
//SubsidyBlockIconsMode string `json:"subsidy_block_icons_mode"` //分销 区块币返利类型 bili 比例 money 固定金额 | |||||
//SubsidyCommissionMode string `json:"subsidy_commission_mode"` //分销 佣金返利类型 bili 比例 money 固定金额 | |||||
//SubsidyIntegralMode string `json:"subsidy_integral_mode"` //分销 积分返利类型 bili 比例 money 固定金额 | |||||
SubsidyReturnType []string `json:"subsidy_return_type"` //分销 返利类型 | |||||
SubsidyOwnBiliList []map[string]string `json:"subsidy_own_bili_list"` | |||||
} | |||||
type UserLvUpSubsidyList struct { | |||||
Lv int `json:"lv"` // 等级 | |||||
//Bili float64 `json:"bili"` // 比例 | |||||
IsUse int `json:"is_use"` // 是否共存 | |||||
//BlockIcons float64 `json:"block_icons"` //区块币 | |||||
Commission float64 `json:"commission"` //佣金 (保留兼容旧版,对应在RateList里面的key为‘0’的值) | |||||
//Integral float64 `json:"integral"` //积分 | |||||
RateList map[string]interface{} // 各币种分佣设置 | |||||
} | |||||
type SettleCommissionToGuide struct { | |||||
Profit float64 `json:"profit"` | |||||
PvdFee float64 `json:"pvd_fee"` | |||||
SysFee float64 `json:"sys_fee"` | |||||
SubsidyFee float64 `json:"subsidy_fee"` | |||||
LvUser *LvUser `json:"lv_user"` | |||||
} | |||||
type SettleCommissionToAdminRes struct { | |||||
DistriCommission string `json:"distriCommission"` | |||||
PaymentCommission string `json:"paymentCommission"` | |||||
PvdCommission float64 `json:"pvdCommission"` | |||||
SubsidyCommission float64 `json:"subsidyCommission"` | |||||
Relation []*SettleCommissionToAdminLv `json:"relation"` | |||||
RemainCommission string `json:"remainCommission"` | |||||
SysCommission float64 `json:"sysCommission"` | |||||
TotalCommission string `json:"totalCommission"` | |||||
} | |||||
type SettleCommissionToAdminLv struct { | |||||
AmountCommission string `json:"amountCommission"` | |||||
Commission string `json:"commission"` | |||||
CommissionRate string `json:"commissionRate"` | |||||
GenKey string `json:"genKey"` | |||||
IsBuyer string `json:"isBuyer"` | |||||
LvID string `json:"lvId"` | |||||
LvName string `json:"lvName"` | |||||
Name string `json:"name"` | |||||
SubsidyCommission string `json:"subsidyCommission"` | |||||
SubsidyRate string `json:"subsidyRate"` | |||||
TierName string `json:"tierName"` | |||||
Weight string `json:"weight"` | |||||
} | |||||
type SettleCommissionToAdmin struct { | |||||
Commission string `json:"commission"` | |||||
ID int64 `json:"id"` | |||||
RelationList []SettleCommissionToRelationList `json:"relationList"` | |||||
} | |||||
type SettleCommissionToRelationList struct { | |||||
GenKey string `json:"genKey"` | |||||
IsBuyer string `json:"isBuyer"` | |||||
LvID string `json:"lvId"` | |||||
Name string `json:"name"` | |||||
} | |||||
type LvUser struct { | |||||
Uid int // 用户ID | |||||
Lv int // 等级 | |||||
NewLv int // 升级后等级 针对会员费分佣 | |||||
LevelWeight int // 权重 | |||||
Profit float64 // 利润(金额) | |||||
SubsidyFee float64 // 补贴(金额) | |||||
//IntegralProfit float64 // 积分利润 | |||||
//IntegralSubsidyFee float64 // 积分补贴 | |||||
//BlockIconsProfit float64 // 区块币利润 | |||||
//BlockIconsSubsidyFee float64 // 区块币补贴 | |||||
ProfitList []*VirtualCoinCommission // 各币种对用的数量 | |||||
SubsidyFeeList []*VirtualCoinCommission // 各币种对应的补贴数量 | |||||
OwnSubsidyFeeList map[string]float64 // 各币种对应的补贴数量 | |||||
OwnbuyReturnType int //0有返利 1没有返利 | |||||
Diff int // 与当前用户级别差 | |||||
OldDiff int // 旧的与当前用户级别差 | |||||
ParentUser *LvUser // 父用户 | |||||
} | |||||
// 虚拟币分佣结构体 | |||||
type VirtualCoinCommission struct { | |||||
Cid string `json:"cid"` // 虚拟币id | |||||
Val float64 `json:"val"` // 数量 | |||||
} | |||||
type VirtualCoinRateList struct { | |||||
Cid string `json:"cid"` // 虚拟币id | |||||
Val string `json:"val"` // 现金兑换比例 | |||||
} | |||||
// 初始化级差模式 | |||||
func Init(g map[int]*LvGrade) map[int]*LvGrade { | |||||
var MinLv int = -1 // 最低级别 | |||||
for k, v := range g { | |||||
if MinLv == -1 { | |||||
MinLv = v.Lv | |||||
g[k].TeamRate = v.SelfRate | |||||
} else if v.Lv < MinLv { | |||||
MinLv = v.Lv | |||||
g[k].TeamRate = v.SelfRate | |||||
} | |||||
} | |||||
return g | |||||
} |
@@ -0,0 +1,185 @@ | |||||
package comm_plan | |||||
import ( | |||||
zhios_order_relate_utils "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/utils" | |||||
zhios_order_relate_logx "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/utils/logx" | |||||
"fmt" | |||||
) | |||||
// 按自购佣金进行计算 | |||||
func CalcSelf(opt *PlanOpt, totalAmt float64, integralTotalAmt float64, userList *LvUser, pvd string, sysFee float64, integralSysFee float64) error { | |||||
grade := opt.UserRate | |||||
if len(grade) == 0 { | |||||
return zhios_order_relate_logx.Warn("level grade is not set") | |||||
} | |||||
//查出用户自购佣金 | |||||
commission, commissionRatio, amountList, ratioList := CalReturnAmountAndRatio(userList.Lv, userList.OwnbuyReturnType, 0, "own", totalAmt, integralTotalAmt, opt) | |||||
userList.Profit = commission // 另外出来的佣金 兼容旧的 | |||||
userList.ProfitList = amountList // 各币种分佣 | |||||
userList.SubsidyFee = 0 | |||||
ratioListMap := convertList2Map(ratioList) | |||||
for k, v := range userList.ProfitList { | |||||
userList.ProfitList[k].Val = ratioListMap[v.Cid] * v.Val | |||||
} | |||||
// 各种币换算出总的额度 | |||||
totalAmtList := make([]*VirtualCoinCommission, 0) | |||||
for coinId, rate := range opt.VirtualCoinMoneyRatioList { | |||||
var amount float64 | |||||
if coinId == 0 { | |||||
amount = totalAmt | |||||
} else { | |||||
amount = totalAmt * zhios_order_relate_utils.AnyToFloat64(rate) | |||||
} | |||||
totalAmtList = append(totalAmtList, &VirtualCoinCommission{ | |||||
Cid: zhios_order_relate_utils.AnyToString(coinId), | |||||
Val: amount, | |||||
}) | |||||
} | |||||
var ( | |||||
node = userList | |||||
maxLv = node.Lv // 当前等级 | |||||
maxLevelWeight = node.LevelWeight // 当前权重 | |||||
peerNum = 0 // 存在同级数 | |||||
peerRate float64 = 0 // 同级累计比例 | |||||
peerRateList = make([]*VirtualCoinCommission, 0) // 各虚拟币同级累计 | |||||
restAmtList = make([]*VirtualCoinCommission, 0) // 各虚拟币剩余额度 | |||||
accumulateRatioList = make([]*VirtualCoinCommission, 0) // 各虚拟币累计比例 | |||||
//integralPeerRate float64 = 0 // 同级累计比例 | |||||
//blockIconsPeerRate float64 = 0 // 同级累计比例 | |||||
restAmt = totalAmt - userList.Profit // 剩余比例 | |||||
//integralRestAmt = totalAmt - userList.IntegralProfit // 积分剩余比例 | |||||
//blockIconsRestAmt = totalAmt - userList.BlockIconsProfit // 区块币剩余比例 | |||||
totalCommissionRatio = commissionRatio // 累计佣金比例 | |||||
//integralBili = integralLeaveBili // 积分累计佣金比例 | |||||
//blockIconsBili = blockIconsLeaveBili // 区块币累计佣金比例 | |||||
) | |||||
// 计算剩余额度 | |||||
restAmtList, _ = CalVirtualCommissionMinus(totalAmtList, amountList) | |||||
// 累计比例 | |||||
accumulateRatioList = ratioList | |||||
// 以用户自购为基数 | |||||
totalAmt = userList.Profit | |||||
totalAmtList = amountList | |||||
Loop: | |||||
for node.ParentUser != nil { //查找上级用户 | |||||
node.ParentUser.Profit = 0 | |||||
//佣金补贴奖励 | |||||
subsidyFee, subsidyRatio, isOnlySubsidyFee, subsidyFeeList, subsidyRatioList := subsidyFeeDo(opt, totalAmt, integralTotalAmt, node.ParentUser, userList.NewLv, pvd, sysFee, integralSysFee) | |||||
node.ParentUser.SubsidyFee = subsidyFee | |||||
node.ParentUser.SubsidyFeeList = subsidyFeeList // 各币种补贴 | |||||
// 如果父级比当前级别低, 跳过 | |||||
// 同级奖, 如果父级别与当前级别一致,并且设置了对应比例 | |||||
count := len(grade[maxLv].PeerRate) | |||||
if grade[maxLv].PeerRateList != nil { | |||||
count = len(grade[maxLv].PeerRateList) | |||||
} | |||||
var isBreak bool | |||||
zeroList := make(map[string]struct{}) | |||||
// 同级奖 | |||||
if node.ParentUser.LevelWeight == maxLevelWeight && count > peerNum { | |||||
//同级奖励比例 | |||||
commission, commissionRatio, amountList, ratioList := CalReturnAmountAndRatio(maxLv, userList.OwnbuyReturnType, peerNum, "same_lv", totalAmt, integralTotalAmt, opt) | |||||
//佣金 (lv, isOnlySubsidy int, restAmt, profit, peerRate, totalRatio, restRatio, subsidyFee, subsidyBili float64, opt *PlanOpt) | |||||
node.ParentUser.Profit, restAmt, totalCommissionRatio, peerRate, node.ParentUser.SubsidyFee, isBreak = sameMoney(node.Lv, isOnlySubsidyFee, restAmt, commission, peerRate, totalCommissionRatio, commissionRatio, node.ParentUser.SubsidyFee, subsidyRatio, opt) | |||||
// 虚拟币 newProfitList, newRestAmtList, newTotalRatioList, newPeerRateList, newSubsidyFeeList, zeroList | |||||
node.ParentUser.ProfitList, restAmtList, accumulateRatioList, peerRateList, node.ParentUser.SubsidyFeeList, zeroList = sameMoneyV2(node.Lv, isOnlySubsidyFee, totalAmtList, restAmtList, amountList, peerRateList, accumulateRatioList, ratioList, node.ParentUser.SubsidyFeeList, subsidyRatioList, opt) | |||||
// 全部都没得分了 | |||||
if isBreak && len(zeroList) == len(opt.UserRate[maxLv].ReturnType) { | |||||
break Loop | |||||
} | |||||
peerNum++ | |||||
} else if node.ParentUser.LevelWeight > maxLevelWeight { | |||||
if _, ok := grade[node.Lv]; !ok { | |||||
return zhios_order_relate_logx.Warn("level grade node.Lv is not set") | |||||
} | |||||
if _, ok := grade[node.ParentUser.Lv]; !ok { | |||||
return zhios_order_relate_logx.Warn("level grade node.ParentUser.Lv is not set") | |||||
} | |||||
commission, commissionRatio, amountList, teamRatioList := CalReturnAmountAndRatio(node.ParentUser.Lv, userList.OwnbuyReturnType, peerNum, "team", totalAmt, integralTotalAmt, opt) | |||||
//佣金 | |||||
node.ParentUser.Profit = commission | |||||
node.ParentUser.Profit, restAmt, totalCommissionRatio, node.ParentUser.SubsidyFee, isBreak = teamDiffMoney(node.ParentUser.Profit, grade[node.Lv].PayMode, isOnlySubsidyFee, totalAmt, restAmt, grade[node.ParentUser.Lv].TeamRate, commissionRatio, peerRate, node.ParentUser.SubsidyFee, subsidyRatio) | |||||
//积分 | |||||
node.ParentUser.ProfitList = amountList | |||||
// profitList []*VirtualCoinCommission, payMode, isOnlySubsidy int, totalAmtList, restAmtList, teamRatioList, totalRatioList, peerRateList, subsidyFeeList, subsidyRatioList []*VirtualCoinCommission | |||||
node.ParentUser.ProfitList, restAmtList, accumulateRatioList, node.ParentUser.SubsidyFeeList, zeroList = teamDiffMoneyV2(node.ParentUser.ProfitList, grade[node.Lv].PayMode, isOnlySubsidyFee, totalAmtList, restAmtList, teamRatioList, accumulateRatioList, peerRateList, subsidyFeeList, subsidyRatioList) | |||||
// 没得分了 就结束 | |||||
if isBreak && len(zeroList) == len(opt.UserRate[maxLv].ReturnType) { | |||||
break Loop | |||||
} | |||||
// 等级往上升则置0 | |||||
maxLevelWeight, maxLv, peerRate, peerRateList, peerNum = node.ParentUser.LevelWeight, node.ParentUser.Lv, 0, nil, 0 | |||||
} | |||||
node.Profit = zhios_order_relate_utils.StrToFloat64(fmt.Sprintf("%.4f", node.Profit)) | |||||
node = node.ParentUser | |||||
} | |||||
return nil | |||||
} | |||||
/*func Test() { | |||||
g := map[int]*LvGrade{ | |||||
0: { | |||||
Lv: 0, | |||||
SelfRate: 0.4, | |||||
TeamRate: 0, | |||||
PeerRate: []float64{0.05, 0.03, 0.02}, | |||||
}, | |||||
1: {Lv: 1, | |||||
SelfRate: 0.5, | |||||
TeamRate: 0.6, | |||||
PeerRate: []float64{0.1, 0.05, 0.03}, | |||||
}, | |||||
2: { | |||||
Lv: 2, | |||||
SelfRate: 0.6, | |||||
TeamRate: 0.7, | |||||
PeerRate: []float64{}, | |||||
}, | |||||
} | |||||
Init(g) | |||||
var money float64 = 100 | |||||
u := []int{0, 0, 1, 1, 2} | |||||
var uList *LvUser | |||||
var node *LvUser | |||||
for k, v := range u { | |||||
if uList == nil { | |||||
uList = &LvUser{ | |||||
Uid: k, | |||||
Lv: v, | |||||
} | |||||
node = uList | |||||
} else { | |||||
if node != nil { | |||||
node.ParentUser = &LvUser{ | |||||
Uid: k, | |||||
Lv: v, | |||||
} | |||||
node = node.ParentUser | |||||
} | |||||
} | |||||
} | |||||
fmt.Println(u, node, uList) | |||||
CalcSelf(g, money, uList) | |||||
fmt.Println("final:", uList) | |||||
for uList.ParentUser != nil { | |||||
fmt.Printf("%#v\n", uList) | |||||
uList = uList.ParentUser | |||||
if uList.ParentUser == nil { | |||||
fmt.Printf("%#v", uList) | |||||
} | |||||
} | |||||
} | |||||
*/ |
@@ -0,0 +1,19 @@ | |||||
package md | |||||
// 缓存key统一管理, %s格式化为masterId | |||||
const ( | |||||
AppCfgCacheKey = "%s:cfg_cache:%s" // 占位符: masterId, key的第一个字母 | |||||
VirtualCoinCfgCacheKey = "%s:virtual_coin_cfg" | |||||
PlanRewardCfgCacheKey = "%s:plan_reward_cfg" | |||||
UnionSetCacheCfg = "%s:union_set_cfg:%s" // 联盟设置缓存key | |||||
UserFinValidUpdateLock = "%s:user_fin_valid_update_lock:%s" // 用户余额更新锁(能拿到锁才能更新余额) | |||||
WithdrawApplyQueueListKey = "withdraw_apply_queue" // 提现队列 | |||||
TplBottomNavRedisKey = "%s:tpl_nav_bottom_key:%s" // master_id platform | |||||
SysModByIdRedisKey = "%s:sys_mod_tpl_by_id:%s" | |||||
CfgCacheTime = 86400 | |||||
) |
@@ -0,0 +1,92 @@ | |||||
package md | |||||
// 获取用户的缓存key | |||||
const ( | |||||
KEY_SYS_CFG_CACHE = "sys_cfg_cache" | |||||
// 文件缓存的key | |||||
KEY_CFG_FILE_PVD = "file_provider" // 文件供应商 | |||||
KEY_CFG_FILE_BUCKET = "file_bucket" | |||||
KEY_CFG_FILE_REGION = "file_bucket_region" | |||||
KEY_CFG_FILE_HOST = "file_bucket_host" | |||||
KEY_CFG_FILE_SCHEME = "file_bucket_scheme" | |||||
KEY_CFG_FILE_AK = "file_access_key" | |||||
KEY_CFG_FILE_SK = "file_secret_key" | |||||
KEY_CFG_FILE_MAX_SIZE = "file_user_upload_max_size" | |||||
KEY_CFG_FILE_EXT = "file_ext" | |||||
KEY_CFG_FILE_AVATAR_THUMBNAIL = "file_avatar_thumbnail" // 默认头像缩略图参数,宽高120px,格式webp. | |||||
// 智盟 | |||||
KEY_CFG_ZM_JD_SITE_ID = "third_zm_jd_site_id" // 智盟京东联盟id | |||||
KEY_CFG_ZM_WEB_ID = "third_zm_web_id" // 智盟网站ID | |||||
KEY_CFG_ZM_AK = "third_zm_app_key" | |||||
KEY_CFG_ZM_SK = "third_zm_app_secret" | |||||
KEY_CFG_ZM_SMS_AK = "third_zm_sms_ak" | |||||
KEY_CFG_ZM_SMS_SK = "third_zm_sms_sk" | |||||
KEY_CFG_APP_NAME = "app_name" | |||||
KEY_CFG_WHITELIST = "api_cfg_whitelist" // API允许的访问的设置白名单 | |||||
// 淘宝 | |||||
KEY_CFG_TB_AUTH_AK = "third_taobao_auth_ak" | |||||
KEY_CFG_TB_AUTH_SK = "third_taobao_auth_sk" | |||||
KEY_CFG_TB_INVITER_CODE = "third_taobao_auth_inviter_code" | |||||
KEY_CFG_TB_AK = "third_taobao_ak" | |||||
KEY_CFG_TB_SK = "third_taobao_sk" | |||||
KEY_CFG_TB_PID = "third_taobao_pid" // 淘宝推广ID,如:mm_123_456_789,123是联盟ID,456是site_id,789是adzone_id | |||||
KEY_CFG_TB_SID = "third_taobao_sid" // 淘宝session id ,又称access_token | |||||
// 苏宁 | |||||
KEY_CFG_SN_AK = "third_suning_ak" | |||||
KEY_CFG_SN_SK = "third_suning_sk" | |||||
KEY_CFG_JD_AK = "" | |||||
KEY_CFG_JD_SK = "" | |||||
KEY_CFG_KL_AK = "third_kaola_ak" | |||||
KEY_CFG_KL_SK = "third_kaola_sk" | |||||
KEY_CFG_VIP_AK = "" | |||||
KEY_CFG_VIP_SK = "" | |||||
// 自动任务配置 | |||||
KEY_CFG_CRON_TB = "cron_order_taobao" | |||||
KEY_CFG_CRON_JD = "cron_order_jd" | |||||
KEY_CFG_CRON_PDD = "cron_order_pdd" | |||||
KEY_CFG_CRON_SN = "cron_order_suning" | |||||
KEY_CFG_CRON_VIP = "cron_order_vip" | |||||
KEY_CFG_CRON_KL = "cron_order_kaola" | |||||
KEY_CFG_CRON_DUOMAI = "cron_order_duomai" | |||||
KEY_CFG_CRON_HIS = "cron_order_his" // 迁移到历史订单 | |||||
KEY_CFG_CRON_SETTLE = "cron_order_settle" // 迁移到历史订单 | |||||
KEY_CFG_CRON_PUBLISHER = "cron_taobao_publisher" // 跟踪淘宝备案信息绑定会员运营id 针对小程序 | |||||
KEY_CFG_CRON_MEITUAN = "cron_order_meituan" //美团 | |||||
KEY_CFG_CRON_OILSTATION = "cron_order_oilstation" //加油 | |||||
KEY_CFG_CRON_KFC = "cron_order_kfc" //肯德基 | |||||
KEY_CFG_CRON_CINEMA = "cron_order_cinema" //电影票 | |||||
KEY_CFG_CRON_OilRequest = "cron_order_oilrequest" //加入主动请求抓单 | |||||
KEY_CFG_CRON_AGOTB = "cron_order_agotaobao" //n天前的淘宝订单 | |||||
KEY_CFG_CRON_CREDIT_CARD = "cron_order_credit_card" | |||||
KEY_CFG_CRON_ORDER_STAT = "cron_order_stat" // 订单统计任务 | |||||
KEY_CFG_CRON_CARD_UPDATE = "cron_card_update" // 权益卡更新 | |||||
KEY_CFG_CRON_USER_LV_UP_SETTLE = "cron_user_lv_up_settle" //会员费订单结算 | |||||
KEY_CFG_CRON_PRIVILEGE_CARD_SETTLE = "cron_privilege_card_settle" //权益卡订单结算 | |||||
KEY_CFG_CRON_CARD_RETURN = "cron_card_return" //权益卡退款 | |||||
KEY_CFG_CRON_PUBLISHER_RELATION = "cron_taobao_publisher_relation" //获取淘宝渠道 | |||||
KEY_CFG_CRON_DTKBRAND = "cron_dtk_brand" //大淘客品牌信息 | |||||
KEY_CFG_CRON_PUBLISHER_RELATION_BIND = "cron_taobao_publisher_relation_bind" //获取淘宝渠道绑定 | |||||
// 自动任务运行时设置 | |||||
KEY_CFG_CRON_TIME_TB = "crontab_order_time_taobao" | |||||
KEY_CFG_CRON_TIME_JD = "crontab_order_time_jd" | |||||
KEY_CFG_CRON_TIME_PDD = "crontab_order_time_pdd" | |||||
KEY_CFG_CRON_TIME_SN = "crontab_order_time_suning" | |||||
KEY_CFG_CRON_TIME_VIP = "crontab_order_time_vip" | |||||
KEY_CFG_CRON_TIME_KL = "crontab_order_time_kaola" | |||||
KEY_CFG_CRON_TIME_DUOMAI = "crontab_order_time_duomai" | |||||
KEY_CFG_CRON_TIME_PUBLISHER = "crontab_taobao_time_publisher" // 跟踪淘宝备案信息绑定会员运营id 针对小程序 | |||||
KEY_CFG_CRON_TIME_MEITUAN = "crontab_order_time_meituan" //美团 | |||||
KEY_CFG_CRON_TIME_OILSTATION = "crontab_order_time_oilstation" //加油 | |||||
KEY_CFG_CRON_TIME_KFC = "crontab_order_time_kfc" //肯德基 | |||||
KEY_CFG_CRON_TIME_CINEMA = "crontab_order_time_cinema" //电影票 | |||||
) |
@@ -0,0 +1,28 @@ | |||||
package md | |||||
// MoreDetailResponse is for response detail | |||||
type CommissionParam struct { | |||||
OldPrice string `json:"old_price"` | |||||
GoodsPrice string `json:"goods_price"` | |||||
Commission string `json:"commission"` | |||||
CommissionRate string `json:"commission_rate"` | |||||
CouponPrice string `json:"coupon_price"` | |||||
WlGoodsPrice string `json:"wl_goods_price"` //卷后价 | |||||
LowerPrice string `json:"lower_price"` | |||||
LowestCouponPrice string `json:"lowestCouponPrice"` | |||||
MinGroupPrice string `json:"min_group_price"` | |||||
PaidPrice string `json:"paid_price"` | |||||
} | |||||
type CommissionFirstParam struct { | |||||
CommissionParam CommissionParam `json:"commission_param"` | |||||
Uid string `json:"uid"` | |||||
IsShare int `json:"is_share"` | |||||
OldLv string `json:"old_lv"` //升级礼包读取的是升级前的等级 | |||||
NewLv string `json:"new_lv"` //升级礼包读取的是升级后的等级 | |||||
Provider string `json:"provider"` | |||||
IsAllLevelReturn int `json:"is_all_level_return"` // 是否返回所有层级 | |||||
GoodsId string `json:"goods_id,omitempty"` // 用于标记是哪个商品的 | |||||
OwnbuyReturnType int `json:"ownbuy_return_type"` //自购是否返利 0返利 1不返利 | |||||
Oid string `json:"oid"` | |||||
ShowLevel string `json:"show_level"` | |||||
} |
@@ -0,0 +1,143 @@ | |||||
package md | |||||
const ( | |||||
PVD_TB = "taobao" | |||||
PVD_JD = "jd" | |||||
PVD_SN = "suning" | |||||
PVD_VIP = "vip" | |||||
PVD_PDD = "pdd" | |||||
PVD_KL = "kaola" | |||||
PVD_TM = "tmall" | |||||
PVD_DTK = "dataoke" | |||||
PVD_HDK = "haodanku" | |||||
PVD_JTT = "jingtuitui" | |||||
// 特殊活动免单方案 | |||||
PVD_FREE = "free" | |||||
PVD_MEITUAN = "meituan" | |||||
PVD_OILSTATION = "oil" | |||||
PVD_KFC = "kfc" | |||||
PVD_CINEMA = "cinema" | |||||
PVD_NEW_CINEMA = "new_cinema" //新电影票 | |||||
PVD_CREDIT_CARD = "credit_card" | |||||
PVD_CARD_REFUND = "card_refund" //权益卡退款 | |||||
PVD_CARD = "privilege_card" //权益卡 | |||||
PVD_USER_LV_UP = "userlvup" //会员费用 | |||||
PVD_OPEN_CARD = "privilege_open_card" // 权益卡开卡 | |||||
PVD_DUOMAI = "duomai" // 多麦 | |||||
PVD_MALL_GOODS = "mall_goods" // 自营商品订单返佣 | |||||
PVD_MALL_GOODS_USER_LV = "mall_goods_user_lv" // 自营商品升级礼包订单返佣 | |||||
PVD_GROUP_BUY = "mall_group_buy" // 拼团未中奖返佣 | |||||
PVD_REGIONAL_AGENT_PAY = "regional_agent_pay" // 区域代理升级付款 | |||||
PVD_GUIDE = "GUIDE" //导购 | |||||
PVD_SELF_MALL = "SELF_MALL" //自营 | |||||
PVD_O2O = "O2O" //O2O | |||||
PVD_COMMON = "COMMON" //区域代理通用网点 | |||||
PVD_ORDINARY = "ordinary" //通用 | |||||
) | |||||
var PVD_LIST = map[string]string{ | |||||
PVD_TB: "淘宝", | |||||
PVD_JD: "京东", | |||||
PVD_SN: "苏宁", | |||||
PVD_VIP: "唯品会", | |||||
PVD_PDD: "拼多多", | |||||
PVD_KL: "考拉", | |||||
PVD_CREDIT_CARD: "信用卡", | |||||
PVD_TM: "天猫", | |||||
PVD_USER_LV_UP: "会员升级", | |||||
PVD_CARD_REFUND: "权益卡退款", | |||||
PVD_CARD: "权益卡", | |||||
PVD_MEITUAN: "美团", | |||||
PVD_OILSTATION: "加油", | |||||
PVD_KFC: "肯德基", | |||||
PVD_CINEMA: "电影票", | |||||
"ele": "饿了么", | |||||
"user_lv_up": "会员升级", | |||||
PVD_REGIONAL_AGENT_PAY: "区域代理升级", | |||||
PVD_GUIDE: "导购", //导购 | |||||
PVD_SELF_MALL: "自营", //自营 | |||||
PVD_O2O: "O2O", //O2O | |||||
PVD_COMMON: "区域代理通用网点", | |||||
PVD_ORDINARY: "通用", //通用 | |||||
"CARD": "权益卡", | |||||
"OIL": "加油", | |||||
} | |||||
var PVD_LIST_ICON = map[string]string{ | |||||
PVD_TB: "provider-square-icon-taobao.png", | |||||
PVD_JD: "provider-square-icon-jd.png", | |||||
PVD_SN: "provider-square-icon-suning.png", | |||||
PVD_VIP: "provider-square-icon-vip.png", | |||||
PVD_PDD: "provider-square-icon-pdd.png", | |||||
PVD_KL: "provider-square-icon-kaola.png", | |||||
} | |||||
var ZHIMENG_CFG_LIST = []string{KEY_CFG_ZM_AK, KEY_CFG_ZM_SK, KEY_CFG_ZM_WEB_ID} | |||||
var PVD_CFG_LIST = map[string][]string{ | |||||
PVD_TB: { | |||||
"third_taobao_sid", | |||||
"third_taobao_web_ak", | |||||
"third_taobao_web_sk", | |||||
"third_taobao_svc_ak", | |||||
"third_taobao_svc_sk", | |||||
"third_taobao_svc_sid", | |||||
// 推广位 | |||||
"third_taobao_share_inviter_code", | |||||
"third_taobao_share_pid_android", | |||||
"third_taobao_share_pid_ios", | |||||
"third_taobao_share_pid_web", | |||||
// 推广位 | |||||
"third_taobao_self_inviter_code", | |||||
"third_taobao_self_pid_android", | |||||
"third_taobao_self_pid_ios", | |||||
"third_taobao_self_pid_web", | |||||
}, | |||||
PVD_JD: {KEY_CFG_ZM_AK, KEY_CFG_ZM_SK, KEY_CFG_ZM_SMS_AK, KEY_CFG_ZM_SMS_SK, KEY_CFG_ZM_JD_SITE_ID, KEY_CFG_ZM_WEB_ID}, | |||||
PVD_VIP: {KEY_CFG_ZM_AK, KEY_CFG_ZM_SK, KEY_CFG_ZM_SMS_AK, KEY_CFG_ZM_SMS_SK, KEY_CFG_ZM_JD_SITE_ID, KEY_CFG_ZM_WEB_ID}, | |||||
PVD_PDD: {KEY_CFG_ZM_AK, KEY_CFG_ZM_SK, KEY_CFG_ZM_SMS_AK, KEY_CFG_ZM_SMS_SK, KEY_CFG_ZM_JD_SITE_ID, KEY_CFG_ZM_WEB_ID}, | |||||
PVD_SN: {KEY_CFG_SN_AK, KEY_CFG_SN_SK}, | |||||
PVD_KL: {KEY_CFG_KL_AK, KEY_CFG_KL_SK}, | |||||
PVD_MEITUAN: {KEY_CFG_ZM_AK, KEY_CFG_ZM_SK, KEY_CFG_ZM_SMS_AK, KEY_CFG_ZM_SMS_SK, KEY_CFG_ZM_WEB_ID}, | |||||
PVD_OILSTATION: {KEY_CFG_ZM_AK, KEY_CFG_ZM_SK, KEY_CFG_ZM_SMS_AK, KEY_CFG_ZM_SMS_SK, KEY_CFG_ZM_WEB_ID}, | |||||
PVD_KFC: {KEY_CFG_ZM_AK, KEY_CFG_ZM_SK, KEY_CFG_ZM_SMS_AK, KEY_CFG_ZM_SMS_SK, KEY_CFG_ZM_WEB_ID}, | |||||
PVD_CINEMA: {KEY_CFG_ZM_AK, KEY_CFG_ZM_SK, KEY_CFG_ZM_SMS_AK, KEY_CFG_ZM_SMS_SK, KEY_CFG_ZM_WEB_ID}, | |||||
} | |||||
var COIN_TRANSFER_TYPE = map[int]string{ | |||||
1: "全球分红", | |||||
2: "管理员修改", | |||||
3: "消费", | |||||
4: "退回", | |||||
5: "虚拟币兑换", | |||||
6: "余额充值", | |||||
} | |||||
var COMM_TASK_TYPE_NAME = map[int]string{ | |||||
1: "邀请好友", | |||||
2: "分享商品", | |||||
3: "观看视频广告", | |||||
4: "购买商品", | |||||
5: "淘宝授权", | |||||
6: "微信绑定", | |||||
7: "成为XX等级会员", | |||||
8: "填写邀请码", | |||||
9: "绑定手机号", | |||||
} | |||||
var COMM_TASK_TYPE_ONE = []string{ | |||||
"5", "6", "7", "8", "9", | |||||
} | |||||
var COMM_TASK_TYPE_MORE = []string{ | |||||
"1", "2", "3", "4", | |||||
} | |||||
var VIRTUAL_COIN_FUNCTION_TYPE = map[string]string{ | |||||
"block": "block", | |||||
"capital_pool": "capital_pool", | |||||
"super_group": "super_group", | |||||
} | |||||
var VIRTUAL_COIN_FUNCTION_TYPE_NAME = map[string]string{ | |||||
"block": "区块币", | |||||
"capital_pool": "全球分红", | |||||
"super_group": "超级拼团", | |||||
} |
@@ -0,0 +1,39 @@ | |||||
package md | |||||
import ( | |||||
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/db/model" | |||||
) | |||||
type UserInfoResponse struct { | |||||
Avatar string `json:"avatar"` | |||||
NickName string `json:"nickname"` | |||||
Gender string `json:"gender"` | |||||
Birthday string `json:"birthday"` | |||||
RegisterTime string `json:"register_time"` | |||||
FileBucketURL string `json:"file_bucket_url"` | |||||
FileFormat string `json:"file_format"` | |||||
IsNoChange string `json:"is_no_change"` | |||||
IsUpLoadWx string `json:"is_upload_wx"` | |||||
} | |||||
type User struct { | |||||
Info *model.User | |||||
Profile *model.UserProfile | |||||
Level *model.UserLevel | |||||
Tags []string | |||||
} | |||||
type UserRelation struct { | |||||
Uid int | |||||
CurUid int | |||||
Diff int // 与当前用户级别差 | |||||
Level int // 用户当前等级 | |||||
OldDiff int // 旧的级别 | |||||
} | |||||
type UserTree struct { | |||||
Uid int `json:"uid"` | |||||
Nickname string `json:"nickname"` | |||||
Phone string `json:"phone"` | |||||
Children []*UserTree `json:"children"` | |||||
} |
@@ -0,0 +1,180 @@ | |||||
package rule | |||||
import ( | |||||
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/db" | |||||
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/db/model" | |||||
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/lib/comm_plan" | |||||
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/md" | |||||
zhios_order_relate_utils "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/utils" | |||||
zhios_order_relate_logx "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/utils/logx" | |||||
"encoding/json" | |||||
"fmt" | |||||
"strings" | |||||
"xorm.io/xorm" | |||||
) | |||||
var pvdCfgList = map[string]struct { | |||||
AK string | |||||
SK string | |||||
Sid string | |||||
}{ | |||||
md.PVD_TB: {"third_taobao_svc_ak", "third_taobao_svc_sk", "third_taobao_web_sid"}, | |||||
md.PVD_KL: {md.KEY_CFG_KL_AK, md.KEY_CFG_KL_SK, ""}, | |||||
md.PVD_SN: {md.KEY_CFG_SN_AK, md.KEY_CFG_SN_SK, ""}, | |||||
md.PVD_JD: {md.KEY_CFG_ZM_AK, md.KEY_CFG_ZM_SK, md.KEY_CFG_ZM_WEB_ID}, | |||||
md.PVD_PDD: {md.KEY_CFG_ZM_AK, md.KEY_CFG_ZM_SK, md.KEY_CFG_ZM_WEB_ID}, | |||||
md.PVD_VIP: {md.KEY_CFG_ZM_AK, md.KEY_CFG_ZM_SK, md.KEY_CFG_ZM_WEB_ID}, | |||||
} | |||||
func GetPlanCfg(eg *xorm.Engine, pvd, masterId string) (*comm_plan.PlanOpt, error) { | |||||
opt := &comm_plan.PlanOpt{} | |||||
// 根据供应商 | |||||
rewardOpt, err := db.DbsPlanRewardByPvd(eg, pvd) | |||||
if err != nil { | |||||
return nil, err | |||||
} | |||||
if rewardOpt == nil { | |||||
return nil, zhios_order_relate_logx.Warn("找不到方案记录") | |||||
} | |||||
if rewardOpt.State == 0 { | |||||
return nil, zhios_order_relate_logx.Warn("抽成方案未开启") | |||||
} | |||||
if rewardOpt.PlanCommissionId == 0 { | |||||
return nil, zhios_order_relate_logx.Warn("抽成方案未设置佣金方案id") | |||||
} | |||||
fmt.Println("抽成设置:", zhios_order_relate_utils.SerializeStr(rewardOpt)) | |||||
fmt.Println("commission id:", rewardOpt.PlanCommissionId) | |||||
commissionOpt, err := db.DbsPlanCommissionById(eg, rewardOpt.PlanCommissionId) | |||||
if err != nil || commissionOpt == nil || commissionOpt.Id == 0 { | |||||
return nil, err | |||||
} | |||||
if _, ok := comm_plan.Fn[commissionOpt.Mode]; !ok { | |||||
return nil, zhios_order_relate_logx.Warn("分佣模式不存在") | |||||
} | |||||
opt.Pvd = pvd | |||||
opt.Mode = commissionOpt.Mode | |||||
opt.IntegralOpen = rewardOpt.IntegralOpen | |||||
opt.SysRate = float64(int64(rewardOpt.SysRate*1e4)) / 1e4 | |||||
opt.PvdRate = float64(int64(rewardOpt.PvdRate*1e4)) / 1e4 | |||||
opt.RegionRate = float64(int64(rewardOpt.RegionRate*1e4)) / 1e4 | |||||
opt.GlobalRate = float64(int64(rewardOpt.GlobalRate*1e4)) / 1e4 | |||||
opt.PushHandRate = float64(int64(rewardOpt.PushHandRate*1e4)) / 1e4 | |||||
opt.MerchantRate = float64(int64(rewardOpt.MerchantRate*1e4)) / 1e4 | |||||
opt.PlanCommissionId = rewardOpt.PlanCommissionId | |||||
// 兑换现金比例 | |||||
virtualCoinMoneyRate, err := GetVirtualCoinMoneyRateList(eg, masterId) | |||||
if err != nil || virtualCoinMoneyRate == nil { | |||||
opt.VirtualCoinMoneyRatioList = nil | |||||
} else { | |||||
opt.VirtualCoinMoneyRatioList = virtualCoinMoneyRate | |||||
} | |||||
if opt.SysRate >= 1 || opt.PvdRate >= 1 || opt.RegionRate >= 1 || opt.GlobalRate >= 1 || opt.PvdRate+opt.SysRate+opt.RegionRate+opt.GlobalRate >= 1 { | |||||
return nil, zhios_order_relate_logx.Warn("分佣方案数据设置总额不能大于1") | |||||
} | |||||
var subsidyTmp map[int]*comm_plan.LvGrade | |||||
commissionOpt.Data = strings.ReplaceAll(commissionOpt.Data, "\"bili\":0", "\"bili\":\"0\"") | |||||
if strings.Contains(commissionOpt.Data, "\"subsidy_mode_list\":[") { //兼容旧的方案 | |||||
tmp := strings.Split(commissionOpt.Data, "\"subsidy_mode_list\":[") | |||||
if len(tmp) > 0 { | |||||
tmp1 := strings.Split(tmp[1], "]") | |||||
if len(tmp1) > 0 { | |||||
str := "\"subsidy_mode_list\":[" + tmp1[0] + "]" | |||||
ex := strings.Split(tmp1[0], ",") | |||||
bili := "bili" | |||||
if len(ex) > 0 { | |||||
bili = strings.ReplaceAll(ex[0], "\"", "") | |||||
} | |||||
commissionOpt.Data = strings.ReplaceAll(commissionOpt.Data, str, "\"subsidy_mode_list\":{\"0\":\""+bili+"\"}") | |||||
} | |||||
} | |||||
} | |||||
if err := json.Unmarshal([]byte(commissionOpt.Data), &subsidyTmp); err != nil { | |||||
return nil, zhios_order_relate_logx.Warn(fmt.Sprintf("%s:分佣方案数据设置错误", masterId)) | |||||
} | |||||
opt.UserRate = subsidyTmp | |||||
return opt, nil | |||||
} | |||||
// 获取所有供应商对应的分佣方案, 包括免单,一元购 | |||||
func PlanOpts(eg *xorm.Engine) map[string]*comm_plan.PlanOpt { | |||||
// 获取所有佣金方案 | |||||
allCommissionPlan := db.DbsPlanCommissionByIds(eg) | |||||
if allCommissionPlan == nil { | |||||
return nil | |||||
} | |||||
commissionPlans := map[int]*model.PlanCommission{} | |||||
for _, v := range allCommissionPlan { | |||||
v.Data = strings.ReplaceAll(v.Data, "\"bili\":0", "\"bili\":\"0\"") | |||||
commissionPlans[v.Id] = v | |||||
} | |||||
// 获取所有抽成方案的计划 | |||||
allRewardPlan, err := db.DbsPlanRewardByPvds(eg) | |||||
if err != nil || allRewardPlan == nil { | |||||
return nil | |||||
} | |||||
opts := map[string]*comm_plan.PlanOpt{} | |||||
for _, v := range allRewardPlan { | |||||
if _, ok := commissionPlans[v.PlanCommissionId]; ok && v.State == 1 && v.PlanCommissionId > 0 { | |||||
var subsidyTmp map[int]*comm_plan.LvGrade | |||||
if err := json.Unmarshal([]byte(commissionPlans[v.PlanCommissionId].Data), &subsidyTmp); err != nil { | |||||
zhios_order_relate_logx.Warn("分佣方案数据设置错误 :", commissionPlans[v.PlanCommissionId]) | |||||
continue | |||||
} | |||||
opts[v.Pvd] = &comm_plan.PlanOpt{ | |||||
Pvd: v.Pvd, | |||||
PlanCommissionId: v.PlanCommissionId, | |||||
Mode: commissionPlans[v.PlanCommissionId].Mode, | |||||
CommissionMode: commissionPlans[v.PlanCommissionId].CommissionMode, | |||||
SysRate: float64(v.SysRate), | |||||
PvdRate: float64(v.PvdRate), | |||||
RegionRate: float64(v.RegionRate), | |||||
GlobalRate: float64(v.GlobalRate), | |||||
UserRate: subsidyTmp, | |||||
} | |||||
} | |||||
} | |||||
fmt.Println(opts) | |||||
if len(opts) == 0 { | |||||
return nil | |||||
} | |||||
return opts | |||||
} | |||||
func GetCreditCardRate(user *md.User, opts map[string]*comm_plan.PlanOpt) string { | |||||
opt, ok := opts[md.PVD_CREDIT_CARD] | |||||
if opts == nil || !ok { | |||||
// 方案为空写定45 | |||||
return "45" | |||||
} | |||||
userRate, ok1 := opt.UserRate[user.Info.Level] | |||||
if !ok1 { | |||||
return "35" | |||||
} | |||||
return zhios_order_relate_utils.AnyToString(((1 - opt.SysRate - opt.PvdRate) * userRate.SelfRate) * 100) | |||||
} | |||||
func GetVirtualCoinMoneyRateList(eg *xorm.Engine, masterId string) (map[int]string, error) { | |||||
m, err := db.VirtualCoinListInUse(eg, masterId) | |||||
if err != nil { | |||||
_ = zhios_order_relate_logx.Error(err) | |||||
return nil, err | |||||
} | |||||
if len(m) == 0 { | |||||
return nil, nil | |||||
} | |||||
result := make(map[int]string, 0) | |||||
result[0] = "1" // 把现金也添加进去 比例1:1 | |||||
for _, coin := range m { | |||||
result[coin.Id] = coin.ExchangeRatio | |||||
} | |||||
return result, nil | |||||
} |
@@ -0,0 +1,58 @@ | |||||
package rule | |||||
import ( | |||||
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/lib/comm_plan" | |||||
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/md" | |||||
"context" | |||||
"errors" | |||||
"golang.org/x/sync/errgroup" | |||||
"sync" | |||||
"xorm.io/xorm" | |||||
) | |||||
// BatchGetCommission 批量分佣 | |||||
func BatchGetCommission(eg *xorm.Engine, dbName string, commissionParamList []*md.CommissionFirstParam) (map[string]*comm_plan.LvUser, error) { | |||||
var ( | |||||
isShare = false | |||||
isAllLevelReturn = false | |||||
) | |||||
goodsId2lvUser := make(map[string]*comm_plan.LvUser, len(commissionParamList)) | |||||
if len(commissionParamList) == 0 { | |||||
return goodsId2lvUser, errors.New("参数错误") | |||||
} | |||||
group, _ := errgroup.WithContext(context.Background()) | |||||
var mu sync.Mutex | |||||
for _, param := range commissionParamList { | |||||
param := param // 为下面的闭包创建局部变量 | |||||
group.Go(func() error { | |||||
if param.IsShare != 0 { | |||||
isShare = true | |||||
} | |||||
if param.IsAllLevelReturn != 0 { | |||||
isAllLevelReturn = true | |||||
} | |||||
if param.GoodsId == "" { | |||||
return errors.New("商品ID缺失") | |||||
} | |||||
_, _, _, _, lvUser, err := GetRewardCommission(eg, ¶m.CommissionParam, isShare, param.Uid, param.Provider, dbName, isAllLevelReturn, map[string]string{}) | |||||
if err != nil { | |||||
return err | |||||
} | |||||
mu.Lock() | |||||
goodsId2lvUser[param.GoodsId] = lvUser | |||||
mu.Unlock() | |||||
return nil | |||||
}) | |||||
} | |||||
if err := group.Wait(); err != nil { | |||||
return goodsId2lvUser, errors.New("处理错误") | |||||
} | |||||
return goodsId2lvUser, nil | |||||
} |
@@ -0,0 +1,401 @@ | |||||
package rule | |||||
import ( | |||||
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/db" | |||||
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/lib/comm_plan" | |||||
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/md" | |||||
zhios_order_relate_utils "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/utils" | |||||
"errors" | |||||
"fmt" | |||||
"strings" | |||||
"xorm.io/xorm" | |||||
) | |||||
// getRewardCommission is 获取制度后的佣金 | |||||
// 返回:单个佣金、层级佣金、错误 | |||||
func GetRewardCommission(engine *xorm.Engine, rmd *md.CommissionParam, isShare bool, userId, provider, masterId string, returnAllLevel bool, extraData map[string]string) (float64, float64, float64, float64, *comm_plan.LvUser, error) { | |||||
virCfg := db.SysCfgFindWithDb(engine, masterId, "virtual_coin_rebate_type") | |||||
var virType = "price" | |||||
if virCfg["virtual_coin_rebate_type"] != "" { | |||||
virType = virCfg["virtual_coin_rebate_type"] | |||||
} | |||||
if virType == "commission" { | |||||
rmd.GoodsPrice = rmd.Commission | |||||
} | |||||
var ( | |||||
err error | |||||
uid = 0 | |||||
level = 0 | |||||
newLevel = 0 | |||||
) | |||||
user, _ := db.UserFindByID(engine, userId) | |||||
if user != nil { | |||||
uid = user.Uid | |||||
level = user.Level | |||||
newLevel = user.Level | |||||
} | |||||
// 获取抽成方案 | |||||
newProvider := provider | |||||
if newProvider == md.PVD_TM { //抽成方案只有淘宝的要替换回来 | |||||
newProvider = md.PVD_TB | |||||
} | |||||
if newProvider == "userlvup" { | |||||
newProvider = "user_level_up" | |||||
} | |||||
if newProvider == md.PVD_MALL_GOODS_USER_LV { //升级礼包按升级前等级计算佣金 | |||||
level = zhios_order_relate_utils.StrToInt(extraData["old_lv"]) | |||||
newLevel = zhios_order_relate_utils.StrToInt(extraData["new_lv"]) | |||||
} | |||||
if extraData["show_level"] != "" { | |||||
level = zhios_order_relate_utils.StrToInt(extraData["show_level"]) | |||||
} | |||||
ownbuyReturnType := zhios_order_relate_utils.StrToInt(extraData["ownbuy_return_type"]) | |||||
cfg, err := GetPlanCfg(engine, newProvider, masterId) | |||||
if err != nil { | |||||
return 0, 0, 0, 0, nil, err | |||||
} | |||||
if cfg == nil { | |||||
return 0, 0, 0, 0, nil, errors.New("分佣方案未设置") | |||||
} | |||||
var userRelationship *[]md.UserRelation | |||||
if returnAllLevel { | |||||
userRelationship, err = UserRelativeNetwork(engine, uid) | |||||
} else { | |||||
userRelationship = nil | |||||
} | |||||
// 获取全部佣金 | |||||
com, price := getCommission(rmd, provider) | |||||
fmt.Println(com) | |||||
fmt.Println(price) | |||||
comf := zhios_order_relate_utils.StrToFloat64(com) | |||||
if zhios_order_relate_utils.InArr(cfg.Mode, []string{"lv_price", "lv_winery"}) && zhios_order_relate_utils.StrToFloat64(rmd.OldPrice) > 0 { //价格为基数 | |||||
comf = zhios_order_relate_utils.StrToFloat64(rmd.OldPrice) | |||||
} | |||||
// userRelationship == nil 是只返回第一层 即用户自己的 | |||||
pvdFee, sysFee, subsidyFee, ulink, err := CalcCommission(uid, level, 0, ownbuyReturnType, comf, zhios_order_relate_utils.StrToFloat64(price), isShare, cfg, userRelationship, newProvider, newLevel, engine) | |||||
if err != nil { | |||||
return 0, 0, 0, 0, nil, nil | |||||
} | |||||
if ulink == nil { | |||||
return 0, 0, 0, 0, nil, nil | |||||
} | |||||
return ulink.Profit, pvdFee, sysFee, subsidyFee, ulink, nil | |||||
} | |||||
func getCommission(d *md.CommissionParam, provider string) (string, string) { | |||||
switch provider { | |||||
case md.PVD_TB, md.PVD_TM: | |||||
if zhios_order_relate_utils.StrToFloat64(d.GoodsPrice) == 0 { | |||||
//如果价格没有直接返回佣金 | |||||
return d.Commission, d.PaidPrice | |||||
} | |||||
currentPrice := currentPrice(d, provider) | |||||
currentPriceF := zhios_order_relate_utils.StrToFloat64(currentPrice) | |||||
commissionRateF := zhios_order_relate_utils.StrToFloat64(d.CommissionRate) / 100 | |||||
com := currentPriceF * commissionRateF | |||||
return zhios_order_relate_utils.Float64ToStr(com), currentPrice | |||||
case md.PVD_JD: | |||||
if zhios_order_relate_utils.StrToFloat64(d.GoodsPrice) == 0 { | |||||
//如果价格没有直接返回佣金 | |||||
return d.Commission, d.PaidPrice | |||||
} | |||||
currentPrice := currentPrice(d, provider) | |||||
currentPriceF := zhios_order_relate_utils.StrToFloat64(currentPrice) | |||||
commissionRateF := zhios_order_relate_utils.StrToFloat64(d.CommissionRate) / 100 | |||||
fmt.Println("当前劵后价格:", currentPriceF, "佣金比例:", commissionRateF) | |||||
com := currentPriceF * commissionRateF | |||||
return zhios_order_relate_utils.Float64ToStr(com), currentPrice | |||||
case md.PVD_PDD: | |||||
if zhios_order_relate_utils.StrToFloat64(d.GoodsPrice) == 0 { | |||||
//如果价格没有直接返回佣金 | |||||
return d.Commission, d.PaidPrice | |||||
} | |||||
currentPrice := currentPrice(d, provider) | |||||
currentPriceF := zhios_order_relate_utils.StrToFloat64(currentPrice) | |||||
commissionRateF := zhios_order_relate_utils.StrToFloat64(d.Commission) / 100 | |||||
com := currentPriceF * commissionRateF | |||||
return zhios_order_relate_utils.Float64ToStr(com), currentPrice | |||||
case md.PVD_VIP: | |||||
if zhios_order_relate_utils.StrToFloat64(d.GoodsPrice) == 0 { | |||||
//如果价格没有直接返回佣金 | |||||
return d.Commission, d.PaidPrice | |||||
} | |||||
currentPrice := currentPrice(d, provider) | |||||
currentPriceF := zhios_order_relate_utils.StrToFloat64(currentPrice) | |||||
commissionRateF := zhios_order_relate_utils.StrToFloat64(d.CommissionRate) / 100 | |||||
com := currentPriceF * commissionRateF | |||||
return zhios_order_relate_utils.Float64ToStr(com), currentPrice | |||||
case md.PVD_SN: | |||||
if zhios_order_relate_utils.StrToFloat64(d.GoodsPrice) == 0 { | |||||
//如果价格没有直接返回佣金 | |||||
return d.Commission, d.PaidPrice | |||||
} | |||||
currentPrice := currentPrice(d, provider) | |||||
currentPriceF := zhios_order_relate_utils.StrToFloat64(currentPrice) | |||||
commissionRateF := zhios_order_relate_utils.StrToFloat64(d.CommissionRate) / 100 | |||||
fmt.Println("当前劵后价格:", currentPriceF, "佣金比例:", commissionRateF) | |||||
com := currentPriceF * commissionRateF | |||||
return zhios_order_relate_utils.Float64ToStr(com), currentPrice | |||||
case md.PVD_KL: | |||||
if zhios_order_relate_utils.StrToFloat64(d.GoodsPrice) == 0 { | |||||
//如果价格没有直接返回佣金 | |||||
return d.Commission, d.PaidPrice | |||||
} | |||||
currentPrice := currentPrice(d, provider) | |||||
currentPriceF := zhios_order_relate_utils.StrToFloat64(currentPrice) | |||||
commissionRateF := zhios_order_relate_utils.StrToFloat64(d.CommissionRate) // TODO 先不除于100 | |||||
com := currentPriceF * commissionRateF | |||||
return zhios_order_relate_utils.Float64ToStr(com), currentPrice | |||||
default: | |||||
if zhios_order_relate_utils.StrToFloat64(d.GoodsPrice) == 0 { | |||||
//如果价格没有直接返回佣金 | |||||
return d.Commission, d.Commission | |||||
} | |||||
return d.Commission, d.GoodsPrice // 直接传过来就是总佣金了 | |||||
} | |||||
} | |||||
func currentPrice(m *md.CommissionParam, pvd string) string { | |||||
switch pvd { | |||||
case md.PVD_TB, md.PVD_TM: | |||||
if m.CouponPrice != "" { | |||||
price := zhios_order_relate_utils.StrToFloat64(m.WlGoodsPrice) - zhios_order_relate_utils.StrToFloat64(m.CouponPrice) | |||||
return zhios_order_relate_utils.Float64ToStr(price) | |||||
} | |||||
return m.WlGoodsPrice | |||||
case md.PVD_JD: | |||||
//fmt.Println(m.LowestCouponPrice, m.LowerPrice, m.WlGoodsPrice) | |||||
if m.LowestCouponPrice == "" { | |||||
if m.CouponPrice != "" { | |||||
price := zhios_order_relate_utils.StrToFloat64(m.WlGoodsPrice) - zhios_order_relate_utils.StrToFloat64(m.CouponPrice) | |||||
return zhios_order_relate_utils.Float64ToStr(price) | |||||
} | |||||
return m.LowerPrice | |||||
} | |||||
return m.LowestCouponPrice | |||||
case md.PVD_PDD: | |||||
if m.CouponPrice != "" { | |||||
price := zhios_order_relate_utils.StrToFloat64(m.MinGroupPrice) - zhios_order_relate_utils.StrToFloat64(m.CouponPrice) | |||||
return zhios_order_relate_utils.Float64ToStr(price) | |||||
} | |||||
return m.MinGroupPrice | |||||
case md.PVD_VIP: | |||||
if m.CouponPrice != "" { | |||||
price := zhios_order_relate_utils.StrToFloat64(m.GoodsPrice) - zhios_order_relate_utils.StrToFloat64(m.CouponPrice) | |||||
return zhios_order_relate_utils.Float64ToStr(price) | |||||
} | |||||
return m.GoodsPrice | |||||
case md.PVD_SN: | |||||
if m.CouponPrice != "" { | |||||
price := zhios_order_relate_utils.StrToFloat64(m.WlGoodsPrice) - zhios_order_relate_utils.StrToFloat64(m.CouponPrice) | |||||
if price < 0 { | |||||
return m.WlGoodsPrice | |||||
} | |||||
return zhios_order_relate_utils.Float64ToStr(price) | |||||
} | |||||
return m.WlGoodsPrice | |||||
case md.PVD_KL: | |||||
if m.CouponPrice != "" { | |||||
price := zhios_order_relate_utils.StrToFloat64(m.WlGoodsPrice) - zhios_order_relate_utils.StrToFloat64(m.CouponPrice) | |||||
return zhios_order_relate_utils.Float64ToStr(price) | |||||
} | |||||
return m.WlGoodsPrice | |||||
default: | |||||
return "" | |||||
} | |||||
} | |||||
func CommFee(fee float64, opt *comm_plan.PlanOpt, types string) (float64, float64, float64) { | |||||
if types == "integral" && opt.IntegralOpen == 0 || opt.Mode == "lv_winery" { //积分抽成后台没开启不用扣 | |||||
return fee, 0, 0 | |||||
} | |||||
pvdFee := fee * opt.PvdRate // 供应商联盟比例 | |||||
sysFee := fee * opt.SysRate // 平台比例 | |||||
regionFee := fee * opt.RegionRate // 区域代理比例 | |||||
globalFee := fee * opt.GlobalRate // 全球分红比例 | |||||
pushHandFee := fee * opt.PushHandRate | |||||
merchantFee := fee * opt.MerchantRate | |||||
// 剩余可分配的佣金 | |||||
fee = float64(int64(fee*1e4)-int64(pvdFee*1e4)-int64(sysFee*1e4)-int64(regionFee*1e4)-int64(globalFee*1e4)-int64(pushHandFee*1e4)-int64(merchantFee*1e4)) / 1e4 | |||||
return fee, pvdFee, sysFee | |||||
} | |||||
// 根据用户计算对应的手续费 | |||||
//ownbuyReturnType 0返利 1不返利 (免单商品是淘礼金商品的时候用的) | |||||
//pvd 只是为了判断是会员升级的订单 可不传 | |||||
func CalcCommission(uid, level, oldDiff, ownbuyReturnType int, fee, integralFee float64, isShare bool, opt *comm_plan.PlanOpt, userRelationShip *[]md.UserRelation, pvd string, newLevel int, eg *xorm.Engine) (pvdFee, sysFee, subsidyFee float64, lvUser *comm_plan.LvUser, err error) { | |||||
//佣金扣除抽成后 | |||||
fee, pvdFee, sysFee = CommFee(fee, opt, "commission") | |||||
//积分扣除抽成后 | |||||
var integralSysFee float64 = 0 | |||||
integralFee, _, integralSysFee = CommFee(integralFee, opt, "integral") | |||||
// 计算自购补贴比例 | |||||
subsidyFee = 0 | |||||
//如果没登录,要找出权重最低的那个 | |||||
if uid == 0 { | |||||
lvList, err := db.UserLevelInIDescByWeightLow(eg) | |||||
if err != nil { | |||||
fmt.Println(err) | |||||
} | |||||
if lvList != nil { | |||||
for _, v := range lvList { | |||||
level = v.Id | |||||
} | |||||
} | |||||
} | |||||
// 判断当前用户等级是否有分佣设置 | |||||
if _, ok := opt.UserRate[level]; !ok { | |||||
return 0, 0, 0, nil, errors.New("opt.UserRate[level] is nil uid=" + zhios_order_relate_utils.IntToStr(uid)) | |||||
} | |||||
// 金额的补贴 | |||||
subsidyFeeList := getOwnSubsidy(opt, level, isShare, fee, sysFee, integralFee) | |||||
subsidyFee1, ok := subsidyFeeList["0"] | |||||
if ok { | |||||
subsidyFee = subsidyFee1 | |||||
} | |||||
// 获取用户的关系网 | |||||
//userRelationShip, err := UserRelativeNetwork(eg, uid) | |||||
// 如果获取用户关系失败或者佣金方案不存在, 那么只计算当前用户的佣金, 平台佣金, 以及供应商方的佣金 | |||||
if _, ok := comm_plan.Fn[opt.Mode]; !ok || userRelationShip == nil || len(*userRelationShip) == 0 { | |||||
// 获得自购的 | |||||
commission, _, amountList, ratioList := comm_plan.CalReturnAmountAndRatio(level, ownbuyReturnType, 0, "own", fee, integralFee, opt) | |||||
if opt.Mode == "lv_winery" { | |||||
commission, _, amountList, ratioList = comm_plan.CalReturnAmountAndRatioToWinery(level, fee, integralFee, opt) | |||||
} | |||||
ratioListMap := convertList2Map(ratioList) | |||||
for k, v := range amountList { | |||||
amountList[k].Val = ratioListMap[v.Cid] * v.Val | |||||
} | |||||
//重新计算佣金 | |||||
return pvdFee, sysFee, subsidyFee, &comm_plan.LvUser{OwnSubsidyFeeList: subsidyFeeList, Uid: uid, Lv: level, OldDiff: oldDiff, Profit: commission, ProfitList: amountList, Diff: 0}, nil | |||||
} | |||||
//查出所有等级替换权重 | |||||
levelList, _ := db.UserLevlEgAll(eg) | |||||
levelWeight := 0 | |||||
for _, v1 := range levelList { | |||||
if v1.Id == level { | |||||
levelWeight = v1.LevelWeight | |||||
} | |||||
} | |||||
lvUser = &comm_plan.LvUser{OwnSubsidyFeeList: subsidyFeeList, Uid: uid, Lv: level, Diff: 0, OldDiff: oldDiff, NewLv: newLevel, LevelWeight: levelWeight, OwnbuyReturnType: ownbuyReturnType} | |||||
var node = lvUser | |||||
//关系链处理 | |||||
for _, v := range *userRelationShip { | |||||
for _, v1 := range levelList { | |||||
levelId := v.Level | |||||
if v1.Id == levelId { | |||||
levelWeight = v1.LevelWeight | |||||
} | |||||
} | |||||
node.ParentUser = &comm_plan.LvUser{Uid: v.Uid, Lv: v.Level, Diff: v.Diff, OldDiff: v.OldDiff, LevelWeight: levelWeight} | |||||
node = node.ParentUser | |||||
} | |||||
if err := comm_plan.Fn[opt.Mode](opt, fee, integralFee, lvUser, pvd, sysFee, integralSysFee); err != nil { | |||||
fmt.Println("方案有问题1") | |||||
return 0, 0, 0, nil, err | |||||
} | |||||
if opt.Mode == "lv_winery" { | |||||
commission, _, amountList, ratioList := comm_plan.CalReturnAmountAndRatioToWinery(level, fee, integralFee, opt) | |||||
lvUser.Profit = commission // 另外出来的佣金 兼容旧的 | |||||
lvUser.ProfitList = amountList // 各币种分佣 | |||||
lvUser.SubsidyFee = 0 | |||||
ratioListMap := convertList2Map(ratioList) | |||||
for k, v := range lvUser.ProfitList { | |||||
lvUser.ProfitList[k].Val = ratioListMap[v.Cid] * v.Val | |||||
} | |||||
} | |||||
return pvdFee, sysFee, subsidyFee, lvUser, nil | |||||
} | |||||
func getOwnSubsidy(opt *comm_plan.PlanOpt, level int, isShare bool, fee, sysFee, integralFee float64) map[string]float64 { | |||||
var res = make(map[string]float64) | |||||
if opt.UserRate[level].SubsidyEnable != 1 { | |||||
return res | |||||
} | |||||
if len(opt.UserRate[level].SubsidyOwnBiliList) == 0 { | |||||
var tmp = map[string]string{ | |||||
"coin_id": "0", | |||||
"self_bili": zhios_order_relate_utils.Float64ToStrByPrec(opt.UserRate[level].SubsidySelfRate*100, 6), | |||||
"share_bili": zhios_order_relate_utils.Float64ToStrByPrec(opt.UserRate[level].SubsidyShareRate*100, 6), | |||||
} | |||||
opt.UserRate[level].SubsidyOwnBiliList = append(opt.UserRate[level].SubsidyOwnBiliList, tmp) | |||||
} | |||||
for _, v := range opt.UserRate[level].SubsidyOwnBiliList { | |||||
var newFee = fee | |||||
if v["coin_id"] != "0" { //积分的 | |||||
newFee = integralFee | |||||
} | |||||
if v["coin_id"] == "0" && opt.UserRate[level].SubsidyMode == 1 { // 按佣金计算补贴 | |||||
newFee = sysFee | |||||
} | |||||
var subsidyFee float64 = 0 | |||||
subsidyFee = newFee * (zhios_order_relate_utils.StrToFloat64(v["self_bili"]) / 100) | |||||
if isShare { | |||||
subsidyFee = newFee * (zhios_order_relate_utils.StrToFloat64(v["share_bili"]) / 100) | |||||
} | |||||
subsidyFee = zhios_order_relate_utils.FloatFormat(subsidyFee, 6) | |||||
res[v["coin_id"]] = subsidyFee | |||||
} | |||||
return res | |||||
} | |||||
func getBili(eg *xorm.Engine, types string) float64 { | |||||
//读取佣金与 区块币比例 | |||||
biliList, _ := db.SysCfgGetOne(eg, types) | |||||
var bili float64 = 1 | |||||
if biliList != nil && biliList.Val != "" { | |||||
list := strings.Split(biliList.Val, ":") | |||||
if len(list) == 2 { | |||||
bili = zhios_order_relate_utils.StrToFloat64(list[0]) / zhios_order_relate_utils.StrToFloat64(list[1]) | |||||
bili = zhios_order_relate_utils.FloatFormat(bili, 6) | |||||
} | |||||
} | |||||
return bili | |||||
} | |||||
// | |||||
////分佣记录写入 | |||||
//func OrderRelateInsert(eg *xorm.Engine, userId int, oid int64, pvd string, createTime int, CommissionParam *md.CommissionParam, masterId string) { | |||||
// _, _, _, _, lvUser, _ := GetRewardCommission(eg, CommissionParam, false, zhios_order_relate_utils.IntToStr(userId), pvd, masterId, true, map[string]string{}) | |||||
// fmt.Println(lvUser) | |||||
// if lvUser == nil { | |||||
// return | |||||
// } | |||||
// level := 0 | |||||
// profit := zhios_order_relate_utils.FloatFormat(lvUser.Profit+lvUser.SubsidyFee, 6) | |||||
// //更新订单表的用户佣金 | |||||
// if pvd == "regional_agent_pay" { | |||||
// _, _ = db.RegionalAgentOrdUpdate(eg, map[string]interface{}{ | |||||
// "key": "ord_id", | |||||
// "value": oid, | |||||
// }, &model2.RegionalAgentUserOrd{UserCommission: zhios_order_relate_utils.Float64ToStr(profit)}) | |||||
// } | |||||
// if pvd == "userlvup" { | |||||
// _, _ = levelDb.UserLevelUpgradeOrdUpdate(eg, map[string]interface{}{ | |||||
// "key": "ord_id", | |||||
// "value": oid, | |||||
// }, &levelModel.UserLevelUpgradeOrd{UserCommission: zhios_order_relate_utils.Float64ToStr(profit)}) | |||||
// } | |||||
// data := []*model.OrdListRelate{{Oid: oid, Uid: lvUser.Uid, Amount: profit, Pvd: pvd, CreateAt: createTime, Level: level}} | |||||
// for lvUser.ParentUser != nil { | |||||
// lvUser = lvUser.ParentUser | |||||
// fmt.Println(lvUser) | |||||
// level = level + 1 | |||||
// profit = zhios_order_relate_utils.FloatFormat(lvUser.Profit+lvUser.SubsidyFee, 6) | |||||
// data = append(data, &model.OrdListRelate{Oid: oid, Uid: lvUser.Uid, Amount: profit, Pvd: pvd, CreateAt: createTime, Level: level}) | |||||
// } | |||||
// err := commDb.DbInsertBatch(eg, data) | |||||
// if err != nil { | |||||
// return | |||||
// } | |||||
// return | |||||
//} | |||||
func convertList2Map(a []*comm_plan.VirtualCoinCommission) (b map[string]float64) { | |||||
b = make(map[string]float64) | |||||
for _, i := range a { | |||||
b[i.Cid] = i.Val | |||||
} | |||||
return b | |||||
} |
@@ -0,0 +1,46 @@ | |||||
package rule | |||||
import ( | |||||
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/db" | |||||
"code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/md" | |||||
"xorm.io/xorm" | |||||
) | |||||
// 获取用户关系等级, 如果返回nil则没有上级用户 | |||||
func UserRelativeNetwork(eg *xorm.Engine, uid int) (*[]md.UserRelation, error) { | |||||
parent, err := db.DbsUserRelate(eg, uid) | |||||
if err != nil || parent == nil { | |||||
return nil, err | |||||
} | |||||
var uids []int | |||||
var userRelation []md.UserRelation | |||||
for _, v := range *parent { | |||||
uids = append(uids, v.ParentUid) | |||||
userRelation = append(userRelation, md.UserRelation{ | |||||
Uid: v.ParentUid, | |||||
CurUid: uid, | |||||
Diff: v.Level, | |||||
Level: 0, | |||||
}) | |||||
} | |||||
relateUsers, err := db.DbsUserFindByIds(eg, uids) | |||||
if err != nil { | |||||
return nil, err | |||||
} | |||||
if relateUsers == nil { | |||||
return nil, nil | |||||
} | |||||
tmp := map[int]int{} | |||||
for _, v := range *relateUsers { | |||||
tmp[v.Uid] = v.Level | |||||
} | |||||
for k, v := range userRelation { | |||||
if val, ok := tmp[v.Uid]; ok { | |||||
userRelation[k].Level = val | |||||
} | |||||
} | |||||
if len(userRelation) == 0 { | |||||
return nil, nil | |||||
} | |||||
return &userRelation, nil | |||||
} |
@@ -0,0 +1,421 @@ | |||||
package cache | |||||
import ( | |||||
"errors" | |||||
"fmt" | |||||
"strconv" | |||||
"time" | |||||
) | |||||
const ( | |||||
redisDialTTL = 10 * time.Second | |||||
redisReadTTL = 3 * time.Second | |||||
redisWriteTTL = 3 * time.Second | |||||
redisIdleTTL = 10 * time.Second | |||||
redisPoolTTL = 10 * time.Second | |||||
redisPoolSize int = 512 | |||||
redisMaxIdleConn int = 64 | |||||
redisMaxActive int = 512 | |||||
) | |||||
var ( | |||||
ErrNil = errors.New("nil return") | |||||
ErrWrongArgsNum = errors.New("args num error") | |||||
ErrNegativeInt = errors.New("redis cluster: unexpected value for Uint64") | |||||
) | |||||
// 以下为提供类型转换 | |||||
func Int(reply interface{}, err error) (int, error) { | |||||
if err != nil { | |||||
return 0, err | |||||
} | |||||
switch reply := reply.(type) { | |||||
case int: | |||||
return reply, nil | |||||
case int8: | |||||
return int(reply), nil | |||||
case int16: | |||||
return int(reply), nil | |||||
case int32: | |||||
return int(reply), nil | |||||
case int64: | |||||
x := int(reply) | |||||
if int64(x) != reply { | |||||
return 0, strconv.ErrRange | |||||
} | |||||
return x, nil | |||||
case uint: | |||||
n := int(reply) | |||||
if n < 0 { | |||||
return 0, strconv.ErrRange | |||||
} | |||||
return n, nil | |||||
case uint8: | |||||
return int(reply), nil | |||||
case uint16: | |||||
return int(reply), nil | |||||
case uint32: | |||||
n := int(reply) | |||||
if n < 0 { | |||||
return 0, strconv.ErrRange | |||||
} | |||||
return n, nil | |||||
case uint64: | |||||
n := int(reply) | |||||
if n < 0 { | |||||
return 0, strconv.ErrRange | |||||
} | |||||
return n, nil | |||||
case []byte: | |||||
data := string(reply) | |||||
if len(data) == 0 { | |||||
return 0, ErrNil | |||||
} | |||||
n, err := strconv.ParseInt(data, 10, 0) | |||||
return int(n), err | |||||
case string: | |||||
if len(reply) == 0 { | |||||
return 0, ErrNil | |||||
} | |||||
n, err := strconv.ParseInt(reply, 10, 0) | |||||
return int(n), err | |||||
case nil: | |||||
return 0, ErrNil | |||||
case error: | |||||
return 0, reply | |||||
} | |||||
return 0, fmt.Errorf("redis cluster: unexpected type for Int, got type %T", reply) | |||||
} | |||||
func Int64(reply interface{}, err error) (int64, error) { | |||||
if err != nil { | |||||
return 0, err | |||||
} | |||||
switch reply := reply.(type) { | |||||
case int: | |||||
return int64(reply), nil | |||||
case int8: | |||||
return int64(reply), nil | |||||
case int16: | |||||
return int64(reply), nil | |||||
case int32: | |||||
return int64(reply), nil | |||||
case int64: | |||||
return reply, nil | |||||
case uint: | |||||
n := int64(reply) | |||||
if n < 0 { | |||||
return 0, strconv.ErrRange | |||||
} | |||||
return n, nil | |||||
case uint8: | |||||
return int64(reply), nil | |||||
case uint16: | |||||
return int64(reply), nil | |||||
case uint32: | |||||
return int64(reply), nil | |||||
case uint64: | |||||
n := int64(reply) | |||||
if n < 0 { | |||||
return 0, strconv.ErrRange | |||||
} | |||||
return n, nil | |||||
case []byte: | |||||
data := string(reply) | |||||
if len(data) == 0 { | |||||
return 0, ErrNil | |||||
} | |||||
n, err := strconv.ParseInt(data, 10, 64) | |||||
return n, err | |||||
case string: | |||||
if len(reply) == 0 { | |||||
return 0, ErrNil | |||||
} | |||||
n, err := strconv.ParseInt(reply, 10, 64) | |||||
return n, err | |||||
case nil: | |||||
return 0, ErrNil | |||||
case error: | |||||
return 0, reply | |||||
} | |||||
return 0, fmt.Errorf("redis cluster: unexpected type for Int64, got type %T", reply) | |||||
} | |||||
func Uint64(reply interface{}, err error) (uint64, error) { | |||||
if err != nil { | |||||
return 0, err | |||||
} | |||||
switch reply := reply.(type) { | |||||
case uint: | |||||
return uint64(reply), nil | |||||
case uint8: | |||||
return uint64(reply), nil | |||||
case uint16: | |||||
return uint64(reply), nil | |||||
case uint32: | |||||
return uint64(reply), nil | |||||
case uint64: | |||||
return reply, nil | |||||
case int: | |||||
if reply < 0 { | |||||
return 0, ErrNegativeInt | |||||
} | |||||
return uint64(reply), nil | |||||
case int8: | |||||
if reply < 0 { | |||||
return 0, ErrNegativeInt | |||||
} | |||||
return uint64(reply), nil | |||||
case int16: | |||||
if reply < 0 { | |||||
return 0, ErrNegativeInt | |||||
} | |||||
return uint64(reply), nil | |||||
case int32: | |||||
if reply < 0 { | |||||
return 0, ErrNegativeInt | |||||
} | |||||
return uint64(reply), nil | |||||
case int64: | |||||
if reply < 0 { | |||||
return 0, ErrNegativeInt | |||||
} | |||||
return uint64(reply), nil | |||||
case []byte: | |||||
data := string(reply) | |||||
if len(data) == 0 { | |||||
return 0, ErrNil | |||||
} | |||||
n, err := strconv.ParseUint(data, 10, 64) | |||||
return n, err | |||||
case string: | |||||
if len(reply) == 0 { | |||||
return 0, ErrNil | |||||
} | |||||
n, err := strconv.ParseUint(reply, 10, 64) | |||||
return n, err | |||||
case nil: | |||||
return 0, ErrNil | |||||
case error: | |||||
return 0, reply | |||||
} | |||||
return 0, fmt.Errorf("redis cluster: unexpected type for Uint64, got type %T", reply) | |||||
} | |||||
func Float64(reply interface{}, err error) (float64, error) { | |||||
if err != nil { | |||||
return 0, err | |||||
} | |||||
var value float64 | |||||
err = nil | |||||
switch v := reply.(type) { | |||||
case float32: | |||||
value = float64(v) | |||||
case float64: | |||||
value = v | |||||
case int: | |||||
value = float64(v) | |||||
case int8: | |||||
value = float64(v) | |||||
case int16: | |||||
value = float64(v) | |||||
case int32: | |||||
value = float64(v) | |||||
case int64: | |||||
value = float64(v) | |||||
case uint: | |||||
value = float64(v) | |||||
case uint8: | |||||
value = float64(v) | |||||
case uint16: | |||||
value = float64(v) | |||||
case uint32: | |||||
value = float64(v) | |||||
case uint64: | |||||
value = float64(v) | |||||
case []byte: | |||||
data := string(v) | |||||
if len(data) == 0 { | |||||
return 0, ErrNil | |||||
} | |||||
value, err = strconv.ParseFloat(string(v), 64) | |||||
case string: | |||||
if len(v) == 0 { | |||||
return 0, ErrNil | |||||
} | |||||
value, err = strconv.ParseFloat(v, 64) | |||||
case nil: | |||||
err = ErrNil | |||||
case error: | |||||
err = v | |||||
default: | |||||
err = fmt.Errorf("redis cluster: unexpected type for Float64, got type %T", v) | |||||
} | |||||
return value, err | |||||
} | |||||
func Bool(reply interface{}, err error) (bool, error) { | |||||
if err != nil { | |||||
return false, err | |||||
} | |||||
switch reply := reply.(type) { | |||||
case bool: | |||||
return reply, nil | |||||
case int64: | |||||
return reply != 0, nil | |||||
case []byte: | |||||
data := string(reply) | |||||
if len(data) == 0 { | |||||
return false, ErrNil | |||||
} | |||||
return strconv.ParseBool(data) | |||||
case string: | |||||
if len(reply) == 0 { | |||||
return false, ErrNil | |||||
} | |||||
return strconv.ParseBool(reply) | |||||
case nil: | |||||
return false, ErrNil | |||||
case error: | |||||
return false, reply | |||||
} | |||||
return false, fmt.Errorf("redis cluster: unexpected type for Bool, got type %T", reply) | |||||
} | |||||
func Bytes(reply interface{}, err error) ([]byte, error) { | |||||
if err != nil { | |||||
return nil, err | |||||
} | |||||
switch reply := reply.(type) { | |||||
case []byte: | |||||
if len(reply) == 0 { | |||||
return nil, ErrNil | |||||
} | |||||
return reply, nil | |||||
case string: | |||||
data := []byte(reply) | |||||
if len(data) == 0 { | |||||
return nil, ErrNil | |||||
} | |||||
return data, nil | |||||
case nil: | |||||
return nil, ErrNil | |||||
case error: | |||||
return nil, reply | |||||
} | |||||
return nil, fmt.Errorf("redis cluster: unexpected type for Bytes, got type %T", reply) | |||||
} | |||||
func String(reply interface{}, err error) (string, error) { | |||||
if err != nil { | |||||
return "", err | |||||
} | |||||
value := "" | |||||
err = nil | |||||
switch v := reply.(type) { | |||||
case string: | |||||
if len(v) == 0 { | |||||
return "", ErrNil | |||||
} | |||||
value = v | |||||
case []byte: | |||||
if len(v) == 0 { | |||||
return "", ErrNil | |||||
} | |||||
value = string(v) | |||||
case int: | |||||
value = strconv.FormatInt(int64(v), 10) | |||||
case int8: | |||||
value = strconv.FormatInt(int64(v), 10) | |||||
case int16: | |||||
value = strconv.FormatInt(int64(v), 10) | |||||
case int32: | |||||
value = strconv.FormatInt(int64(v), 10) | |||||
case int64: | |||||
value = strconv.FormatInt(v, 10) | |||||
case uint: | |||||
value = strconv.FormatUint(uint64(v), 10) | |||||
case uint8: | |||||
value = strconv.FormatUint(uint64(v), 10) | |||||
case uint16: | |||||
value = strconv.FormatUint(uint64(v), 10) | |||||
case uint32: | |||||
value = strconv.FormatUint(uint64(v), 10) | |||||
case uint64: | |||||
value = strconv.FormatUint(v, 10) | |||||
case float32: | |||||
value = strconv.FormatFloat(float64(v), 'f', -1, 32) | |||||
case float64: | |||||
value = strconv.FormatFloat(v, 'f', -1, 64) | |||||
case bool: | |||||
value = strconv.FormatBool(v) | |||||
case nil: | |||||
err = ErrNil | |||||
case error: | |||||
err = v | |||||
default: | |||||
err = fmt.Errorf("redis cluster: unexpected type for String, got type %T", v) | |||||
} | |||||
return value, err | |||||
} | |||||
func Strings(reply interface{}, err error) ([]string, error) { | |||||
if err != nil { | |||||
return nil, err | |||||
} | |||||
switch reply := reply.(type) { | |||||
case []interface{}: | |||||
result := make([]string, len(reply)) | |||||
for i := range reply { | |||||
if reply[i] == nil { | |||||
continue | |||||
} | |||||
switch subReply := reply[i].(type) { | |||||
case string: | |||||
result[i] = subReply | |||||
case []byte: | |||||
result[i] = string(subReply) | |||||
default: | |||||
return nil, fmt.Errorf("redis cluster: unexpected element type for String, got type %T", reply[i]) | |||||
} | |||||
} | |||||
return result, nil | |||||
case []string: | |||||
return reply, nil | |||||
case nil: | |||||
return nil, ErrNil | |||||
case error: | |||||
return nil, reply | |||||
} | |||||
return nil, fmt.Errorf("redis cluster: unexpected type for Strings, got type %T", reply) | |||||
} | |||||
func Values(reply interface{}, err error) ([]interface{}, error) { | |||||
if err != nil { | |||||
return nil, err | |||||
} | |||||
switch reply := reply.(type) { | |||||
case []interface{}: | |||||
return reply, nil | |||||
case nil: | |||||
return nil, ErrNil | |||||
case error: | |||||
return nil, reply | |||||
} | |||||
return nil, fmt.Errorf("redis cluster: unexpected type for Values, got type %T", reply) | |||||
} |
@@ -0,0 +1,403 @@ | |||||
package cache | |||||
import ( | |||||
"encoding/json" | |||||
"errors" | |||||
"log" | |||||
"strings" | |||||
"time" | |||||
redigo "github.com/gomodule/redigo/redis" | |||||
) | |||||
// configuration | |||||
type Config struct { | |||||
Server string | |||||
Password string | |||||
MaxIdle int // Maximum number of idle connections in the pool. | |||||
// Maximum number of connections allocated by the pool at a given time. | |||||
// When zero, there is no limit on the number of connections in the pool. | |||||
MaxActive int | |||||
// Close connections after remaining idle for this duration. If the value | |||||
// is zero, then idle connections are not closed. Applications should set | |||||
// the timeout to a value less than the server's timeout. | |||||
IdleTimeout time.Duration | |||||
// If Wait is true and the pool is at the MaxActive limit, then Get() waits | |||||
// for a connection to be returned to the pool before returning. | |||||
Wait bool | |||||
KeyPrefix string // prefix to all keys; example is "dev environment name" | |||||
KeyDelimiter string // delimiter to be used while appending keys; example is ":" | |||||
KeyPlaceholder string // placeholder to be parsed using given arguments to obtain a final key; example is "?" | |||||
} | |||||
var pool *redigo.Pool | |||||
var conf *Config | |||||
func NewRedis(addr string) { | |||||
if addr == "" { | |||||
panic("\nredis connect string cannot be empty\n") | |||||
} | |||||
pool = &redigo.Pool{ | |||||
MaxIdle: redisMaxIdleConn, | |||||
IdleTimeout: redisIdleTTL, | |||||
MaxActive: redisMaxActive, | |||||
// MaxConnLifetime: redisDialTTL, | |||||
Wait: true, | |||||
Dial: func() (redigo.Conn, error) { | |||||
c, err := redigo.Dial("tcp", addr, | |||||
redigo.DialConnectTimeout(redisDialTTL), | |||||
redigo.DialReadTimeout(redisReadTTL), | |||||
redigo.DialWriteTimeout(redisWriteTTL), | |||||
) | |||||
if err != nil { | |||||
log.Println("Redis Dial failed: ", err) | |||||
return nil, err | |||||
} | |||||
return c, err | |||||
}, | |||||
TestOnBorrow: func(c redigo.Conn, t time.Time) error { | |||||
_, err := c.Do("PING") | |||||
if err != nil { | |||||
log.Println("Unable to ping to redis server:", err) | |||||
} | |||||
return err | |||||
}, | |||||
} | |||||
conn := pool.Get() | |||||
defer conn.Close() | |||||
if conn.Err() != nil { | |||||
println("\nredis connect " + addr + " error: " + conn.Err().Error()) | |||||
} else { | |||||
println("\nredis connect " + addr + " success!\n") | |||||
} | |||||
} | |||||
func Do(cmd string, args ...interface{}) (reply interface{}, err error) { | |||||
conn := pool.Get() | |||||
defer conn.Close() | |||||
return conn.Do(cmd, args...) | |||||
} | |||||
func GetPool() *redigo.Pool { | |||||
return pool | |||||
} | |||||
func ParseKey(key string, vars []string) (string, error) { | |||||
arr := strings.Split(key, conf.KeyPlaceholder) | |||||
actualKey := "" | |||||
if len(arr) != len(vars)+1 { | |||||
return "", errors.New("redis/connection.go: Insufficient arguments to parse key") | |||||
} else { | |||||
for index, val := range arr { | |||||
if index == 0 { | |||||
actualKey = arr[index] | |||||
} else { | |||||
actualKey += vars[index-1] + val | |||||
} | |||||
} | |||||
} | |||||
return getPrefixedKey(actualKey), nil | |||||
} | |||||
func getPrefixedKey(key string) string { | |||||
return conf.KeyPrefix + conf.KeyDelimiter + key | |||||
} | |||||
func StripEnvKey(key string) string { | |||||
return strings.TrimLeft(key, conf.KeyPrefix+conf.KeyDelimiter) | |||||
} | |||||
func SplitKey(key string) []string { | |||||
return strings.Split(key, conf.KeyDelimiter) | |||||
} | |||||
func Expire(key string, ttl int) (interface{}, error) { | |||||
return Do("EXPIRE", key, ttl) | |||||
} | |||||
func Persist(key string) (interface{}, error) { | |||||
return Do("PERSIST", key) | |||||
} | |||||
func Del(key string) (interface{}, error) { | |||||
return Do("DEL", key) | |||||
} | |||||
func Set(key string, data interface{}) (interface{}, error) { | |||||
// set | |||||
return Do("SET", key, data) | |||||
} | |||||
func SetNX(key string, data interface{}) (interface{}, error) { | |||||
return Do("SETNX", key, data) | |||||
} | |||||
func SetEx(key string, data interface{}, ttl int) (interface{}, error) { | |||||
return Do("SETEX", key, ttl, data) | |||||
} | |||||
func SetJson(key string, data interface{}, ttl int) bool { | |||||
c, err := json.Marshal(data) | |||||
if err != nil { | |||||
return false | |||||
} | |||||
if ttl < 1 { | |||||
_, err = Set(key, c) | |||||
} else { | |||||
_, err = SetEx(key, c, ttl) | |||||
} | |||||
if err != nil { | |||||
return false | |||||
} | |||||
return true | |||||
} | |||||
func GetJson(key string, dst interface{}) error { | |||||
b, err := GetBytes(key) | |||||
if err != nil { | |||||
return err | |||||
} | |||||
if err = json.Unmarshal(b, dst); err != nil { | |||||
return err | |||||
} | |||||
return nil | |||||
} | |||||
func Get(key string) (interface{}, error) { | |||||
// get | |||||
return Do("GET", key) | |||||
} | |||||
func GetTTL(key string) (time.Duration, error) { | |||||
ttl, err := redigo.Int64(Do("TTL", key)) | |||||
return time.Duration(ttl) * time.Second, err | |||||
} | |||||
func GetBytes(key string) ([]byte, error) { | |||||
return redigo.Bytes(Do("GET", key)) | |||||
} | |||||
func GetString(key string) (string, error) { | |||||
return redigo.String(Do("GET", key)) | |||||
} | |||||
func GetStringMap(key string) (map[string]string, error) { | |||||
return redigo.StringMap(Do("GET", key)) | |||||
} | |||||
func GetInt(key string) (int, error) { | |||||
return redigo.Int(Do("GET", key)) | |||||
} | |||||
func GetInt64(key string) (int64, error) { | |||||
return redigo.Int64(Do("GET", key)) | |||||
} | |||||
func GetStringLength(key string) (int, error) { | |||||
return redigo.Int(Do("STRLEN", key)) | |||||
} | |||||
func ZAdd(key string, score float64, data interface{}) (interface{}, error) { | |||||
return Do("ZADD", key, score, data) | |||||
} | |||||
func ZAddNX(key string, score float64, data interface{}) (interface{}, error) { | |||||
return Do("ZADD", key, "NX", score, data) | |||||
} | |||||
func ZRem(key string, data interface{}) (interface{}, error) { | |||||
return Do("ZREM", key, data) | |||||
} | |||||
func ZRange(key string, start int, end int, withScores bool) ([]interface{}, error) { | |||||
if withScores { | |||||
return redigo.Values(Do("ZRANGE", key, start, end, "WITHSCORES")) | |||||
} | |||||
return redigo.Values(Do("ZRANGE", key, start, end)) | |||||
} | |||||
func ZRemRangeByScore(key string, start int64, end int64) ([]interface{}, error) { | |||||
return redigo.Values(Do("ZREMRANGEBYSCORE", key, start, end)) | |||||
} | |||||
func ZCard(setName string) (int64, error) { | |||||
return redigo.Int64(Do("ZCARD", setName)) | |||||
} | |||||
func ZScan(setName string) (int64, error) { | |||||
return redigo.Int64(Do("ZCARD", setName)) | |||||
} | |||||
func SAdd(setName string, data interface{}) (interface{}, error) { | |||||
return Do("SADD", setName, data) | |||||
} | |||||
func SCard(setName string) (int64, error) { | |||||
return redigo.Int64(Do("SCARD", setName)) | |||||
} | |||||
func SIsMember(setName string, data interface{}) (bool, error) { | |||||
return redigo.Bool(Do("SISMEMBER", setName, data)) | |||||
} | |||||
func SMembers(setName string) ([]string, error) { | |||||
return redigo.Strings(Do("SMEMBERS", setName)) | |||||
} | |||||
func SRem(setName string, data interface{}) (interface{}, error) { | |||||
return Do("SREM", setName, data) | |||||
} | |||||
func HSet(key string, HKey string, data interface{}) (interface{}, error) { | |||||
return Do("HSET", key, HKey, data) | |||||
} | |||||
func HGet(key string, HKey string) (interface{}, error) { | |||||
return Do("HGET", key, HKey) | |||||
} | |||||
func HMGet(key string, hashKeys ...string) ([]interface{}, error) { | |||||
ret, err := Do("HMGET", key, hashKeys) | |||||
if err != nil { | |||||
return nil, err | |||||
} | |||||
reta, ok := ret.([]interface{}) | |||||
if !ok { | |||||
return nil, errors.New("result not an array") | |||||
} | |||||
return reta, nil | |||||
} | |||||
func HMSet(key string, hashKeys []string, vals []interface{}) (interface{}, error) { | |||||
if len(hashKeys) == 0 || len(hashKeys) != len(vals) { | |||||
var ret interface{} | |||||
return ret, errors.New("bad length") | |||||
} | |||||
input := []interface{}{key} | |||||
for i, v := range hashKeys { | |||||
input = append(input, v, vals[i]) | |||||
} | |||||
return Do("HMSET", input...) | |||||
} | |||||
func HGetString(key string, HKey string) (string, error) { | |||||
return redigo.String(Do("HGET", key, HKey)) | |||||
} | |||||
func HGetFloat(key string, HKey string) (float64, error) { | |||||
f, err := redigo.Float64(Do("HGET", key, HKey)) | |||||
return f, err | |||||
} | |||||
func HGetInt(key string, HKey string) (int, error) { | |||||
return redigo.Int(Do("HGET", key, HKey)) | |||||
} | |||||
func HGetInt64(key string, HKey string) (int64, error) { | |||||
return redigo.Int64(Do("HGET", key, HKey)) | |||||
} | |||||
func HGetBool(key string, HKey string) (bool, error) { | |||||
return redigo.Bool(Do("HGET", key, HKey)) | |||||
} | |||||
func HDel(key string, HKey string) (interface{}, error) { | |||||
return Do("HDEL", key, HKey) | |||||
} | |||||
func HGetAll(key string) (map[string]interface{}, error) { | |||||
vals, err := redigo.Values(Do("HGETALL", key)) | |||||
if err != nil { | |||||
return nil, err | |||||
} | |||||
num := len(vals) / 2 | |||||
result := make(map[string]interface{}, num) | |||||
for i := 0; i < num; i++ { | |||||
key, _ := redigo.String(vals[2*i], nil) | |||||
result[key] = vals[2*i+1] | |||||
} | |||||
return result, nil | |||||
} | |||||
func FlushAll() bool { | |||||
res, _ := redigo.String(Do("FLUSHALL")) | |||||
if res == "" { | |||||
return false | |||||
} | |||||
return true | |||||
} | |||||
// NOTE: Use this in production environment with extreme care. | |||||
// Read more here:https://redigo.io/commands/keys | |||||
func Keys(pattern string) ([]string, error) { | |||||
return redigo.Strings(Do("KEYS", pattern)) | |||||
} | |||||
func HKeys(key string) ([]string, error) { | |||||
return redigo.Strings(Do("HKEYS", key)) | |||||
} | |||||
func Exists(key string) bool { | |||||
count, err := redigo.Int(Do("EXISTS", key)) | |||||
if count == 0 || err != nil { | |||||
return false | |||||
} | |||||
return true | |||||
} | |||||
func Incr(key string) (int64, error) { | |||||
return redigo.Int64(Do("INCR", key)) | |||||
} | |||||
func Decr(key string) (int64, error) { | |||||
return redigo.Int64(Do("DECR", key)) | |||||
} | |||||
func IncrBy(key string, incBy int64) (int64, error) { | |||||
return redigo.Int64(Do("INCRBY", key, incBy)) | |||||
} | |||||
func DecrBy(key string, decrBy int64) (int64, error) { | |||||
return redigo.Int64(Do("DECRBY", key)) | |||||
} | |||||
func IncrByFloat(key string, incBy float64) (float64, error) { | |||||
return redigo.Float64(Do("INCRBYFLOAT", key, incBy)) | |||||
} | |||||
func DecrByFloat(key string, decrBy float64) (float64, error) { | |||||
return redigo.Float64(Do("DECRBYFLOAT", key, decrBy)) | |||||
} | |||||
// use for message queue | |||||
func LPush(key string, data interface{}) (interface{}, error) { | |||||
// set | |||||
return Do("LPUSH", key, data) | |||||
} | |||||
func LPop(key string) (interface{}, error) { | |||||
return Do("LPOP", key) | |||||
} | |||||
func LPopString(key string) (string, error) { | |||||
return redigo.String(Do("LPOP", key)) | |||||
} | |||||
func LPopFloat(key string) (float64, error) { | |||||
f, err := redigo.Float64(Do("LPOP", key)) | |||||
return f, err | |||||
} | |||||
func LPopInt(key string) (int, error) { | |||||
return redigo.Int(Do("LPOP", key)) | |||||
} | |||||
func LPopInt64(key string) (int64, error) { | |||||
return redigo.Int64(Do("LPOP", key)) | |||||
} | |||||
func RPush(key string, data interface{}) (interface{}, error) { | |||||
// set | |||||
return Do("RPUSH", key, data) | |||||
} | |||||
func RPop(key string) (interface{}, error) { | |||||
return Do("RPOP", key) | |||||
} | |||||
func RPopString(key string) (string, error) { | |||||
return redigo.String(Do("RPOP", key)) | |||||
} | |||||
func RPopFloat(key string) (float64, error) { | |||||
f, err := redigo.Float64(Do("RPOP", key)) | |||||
return f, err | |||||
} | |||||
func RPopInt(key string) (int, error) { | |||||
return redigo.Int(Do("RPOP", key)) | |||||
} | |||||
func RPopInt64(key string) (int64, error) { | |||||
return redigo.Int64(Do("RPOP", key)) | |||||
} | |||||
func Scan(cursor int64, pattern string, count int64) (int64, []string, error) { | |||||
var items []string | |||||
var newCursor int64 | |||||
values, err := redigo.Values(Do("SCAN", cursor, "MATCH", pattern, "COUNT", count)) | |||||
if err != nil { | |||||
return 0, nil, err | |||||
} | |||||
values, err = redigo.Scan(values, &newCursor, &items) | |||||
if err != nil { | |||||
return 0, nil, err | |||||
} | |||||
return newCursor, items, nil | |||||
} |
@@ -0,0 +1,622 @@ | |||||
package cache | |||||
import ( | |||||
"strconv" | |||||
"time" | |||||
"github.com/go-redis/redis" | |||||
) | |||||
var pools *redis.ClusterClient | |||||
func NewRedisCluster(addrs []string) error { | |||||
opt := &redis.ClusterOptions{ | |||||
Addrs: addrs, | |||||
PoolSize: redisPoolSize, | |||||
PoolTimeout: redisPoolTTL, | |||||
IdleTimeout: redisIdleTTL, | |||||
DialTimeout: redisDialTTL, | |||||
ReadTimeout: redisReadTTL, | |||||
WriteTimeout: redisWriteTTL, | |||||
} | |||||
pools = redis.NewClusterClient(opt) | |||||
if err := pools.Ping().Err(); err != nil { | |||||
return err | |||||
} | |||||
return nil | |||||
} | |||||
func RCGet(key string) (interface{}, error) { | |||||
res, err := pools.Get(key).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
return []byte(res), nil | |||||
} | |||||
func RCSet(key string, value interface{}) error { | |||||
err := pools.Set(key, value, 0).Err() | |||||
return convertError(err) | |||||
} | |||||
func RCGetSet(key string, value interface{}) (interface{}, error) { | |||||
res, err := pools.GetSet(key, value).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
return []byte(res), nil | |||||
} | |||||
func RCSetNx(key string, value interface{}) (int64, error) { | |||||
res, err := pools.SetNX(key, value, 0).Result() | |||||
if err != nil { | |||||
return 0, convertError(err) | |||||
} | |||||
if res { | |||||
return 1, nil | |||||
} | |||||
return 0, nil | |||||
} | |||||
func RCSetEx(key string, value interface{}, timeout int64) error { | |||||
_, err := pools.Set(key, value, time.Duration(timeout)*time.Second).Result() | |||||
if err != nil { | |||||
return convertError(err) | |||||
} | |||||
return nil | |||||
} | |||||
// nil表示成功,ErrNil表示数据库内已经存在这个key,其他表示数据库发生错误 | |||||
func RCSetNxEx(key string, value interface{}, timeout int64) error { | |||||
res, err := pools.SetNX(key, value, time.Duration(timeout)*time.Second).Result() | |||||
if err != nil { | |||||
return convertError(err) | |||||
} | |||||
if res { | |||||
return nil | |||||
} | |||||
return ErrNil | |||||
} | |||||
func RCMGet(keys ...string) ([]interface{}, error) { | |||||
res, err := pools.MGet(keys...).Result() | |||||
return res, convertError(err) | |||||
} | |||||
// 为确保多个key映射到同一个slot,每个key最好加上hash tag,如:{test} | |||||
func RCMSet(kvs map[string]interface{}) error { | |||||
pairs := make([]string, 0, len(kvs)*2) | |||||
for k, v := range kvs { | |||||
val, err := String(v, nil) | |||||
if err != nil { | |||||
return err | |||||
} | |||||
pairs = append(pairs, k, val) | |||||
} | |||||
return convertError(pools.MSet(pairs).Err()) | |||||
} | |||||
// 为确保多个key映射到同一个slot,每个key最好加上hash tag,如:{test} | |||||
func RCMSetNX(kvs map[string]interface{}) (bool, error) { | |||||
pairs := make([]string, 0, len(kvs)*2) | |||||
for k, v := range kvs { | |||||
val, err := String(v, nil) | |||||
if err != nil { | |||||
return false, err | |||||
} | |||||
pairs = append(pairs, k, val) | |||||
} | |||||
res, err := pools.MSetNX(pairs).Result() | |||||
return res, convertError(err) | |||||
} | |||||
func RCExpireAt(key string, timestamp int64) (int64, error) { | |||||
res, err := pools.ExpireAt(key, time.Unix(timestamp, 0)).Result() | |||||
if err != nil { | |||||
return 0, convertError(err) | |||||
} | |||||
if res { | |||||
return 1, nil | |||||
} | |||||
return 0, nil | |||||
} | |||||
func RCDel(keys ...string) (int64, error) { | |||||
args := make([]interface{}, 0, len(keys)) | |||||
for _, key := range keys { | |||||
args = append(args, key) | |||||
} | |||||
res, err := pools.Del(keys...).Result() | |||||
if err != nil { | |||||
return res, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func RCIncr(key string) (int64, error) { | |||||
res, err := pools.Incr(key).Result() | |||||
if err != nil { | |||||
return res, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func RCIncrBy(key string, delta int64) (int64, error) { | |||||
res, err := pools.IncrBy(key, delta).Result() | |||||
if err != nil { | |||||
return res, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func RCExpire(key string, duration int64) (int64, error) { | |||||
res, err := pools.Expire(key, time.Duration(duration)*time.Second).Result() | |||||
if err != nil { | |||||
return 0, convertError(err) | |||||
} | |||||
if res { | |||||
return 1, nil | |||||
} | |||||
return 0, nil | |||||
} | |||||
func RCExists(key string) (bool, error) { | |||||
res, err := pools.Exists(key).Result() | |||||
if err != nil { | |||||
return false, convertError(err) | |||||
} | |||||
if res > 0 { | |||||
return true, nil | |||||
} | |||||
return false, nil | |||||
} | |||||
func RCHGet(key string, field string) (interface{}, error) { | |||||
res, err := pools.HGet(key, field).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
return []byte(res), nil | |||||
} | |||||
func RCHLen(key string) (int64, error) { | |||||
res, err := pools.HLen(key).Result() | |||||
if err != nil { | |||||
return res, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func RCHSet(key string, field string, val interface{}) error { | |||||
value, err := String(val, nil) | |||||
if err != nil && err != ErrNil { | |||||
return err | |||||
} | |||||
_, err = pools.HSet(key, field, value).Result() | |||||
if err != nil { | |||||
return convertError(err) | |||||
} | |||||
return nil | |||||
} | |||||
func RCHDel(key string, fields ...string) (int64, error) { | |||||
args := make([]interface{}, 0, len(fields)+1) | |||||
args = append(args, key) | |||||
for _, field := range fields { | |||||
args = append(args, field) | |||||
} | |||||
res, err := pools.HDel(key, fields...).Result() | |||||
if err != nil { | |||||
return 0, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func RCHMGet(key string, fields ...string) (interface{}, error) { | |||||
args := make([]interface{}, 0, len(fields)+1) | |||||
args = append(args, key) | |||||
for _, field := range fields { | |||||
args = append(args, field) | |||||
} | |||||
if len(fields) == 0 { | |||||
return nil, ErrNil | |||||
} | |||||
res, err := pools.HMGet(key, fields...).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func RCHMSet(key string, kvs ...interface{}) error { | |||||
if len(kvs) == 0 { | |||||
return nil | |||||
} | |||||
if len(kvs)%2 != 0 { | |||||
return ErrWrongArgsNum | |||||
} | |||||
var err error | |||||
v := map[string]interface{}{} // todo change | |||||
v["field"], err = String(kvs[0], nil) | |||||
if err != nil && err != ErrNil { | |||||
return err | |||||
} | |||||
v["value"], err = String(kvs[1], nil) | |||||
if err != nil && err != ErrNil { | |||||
return err | |||||
} | |||||
pairs := make([]string, 0, len(kvs)-2) | |||||
if len(kvs) > 2 { | |||||
for _, kv := range kvs[2:] { | |||||
kvString, err := String(kv, nil) | |||||
if err != nil && err != ErrNil { | |||||
return err | |||||
} | |||||
pairs = append(pairs, kvString) | |||||
} | |||||
} | |||||
v["paris"] = pairs | |||||
_, err = pools.HMSet(key, v).Result() | |||||
if err != nil { | |||||
return convertError(err) | |||||
} | |||||
return nil | |||||
} | |||||
func RCHKeys(key string) ([]string, error) { | |||||
res, err := pools.HKeys(key).Result() | |||||
if err != nil { | |||||
return res, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func RCHVals(key string) ([]interface{}, error) { | |||||
res, err := pools.HVals(key).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
rs := make([]interface{}, 0, len(res)) | |||||
for _, res := range res { | |||||
rs = append(rs, res) | |||||
} | |||||
return rs, nil | |||||
} | |||||
func RCHGetAll(key string) (map[string]string, error) { | |||||
vals, err := pools.HGetAll(key).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
return vals, nil | |||||
} | |||||
func RCHIncrBy(key, field string, delta int64) (int64, error) { | |||||
res, err := pools.HIncrBy(key, field, delta).Result() | |||||
if err != nil { | |||||
return res, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func RCZAdd(key string, kvs ...interface{}) (int64, error) { | |||||
args := make([]interface{}, 0, len(kvs)+1) | |||||
args = append(args, key) | |||||
args = append(args, kvs...) | |||||
if len(kvs) == 0 { | |||||
return 0, nil | |||||
} | |||||
if len(kvs)%2 != 0 { | |||||
return 0, ErrWrongArgsNum | |||||
} | |||||
zs := make([]redis.Z, len(kvs)/2) | |||||
for i := 0; i < len(kvs); i += 2 { | |||||
idx := i / 2 | |||||
score, err := Float64(kvs[i], nil) | |||||
if err != nil && err != ErrNil { | |||||
return 0, err | |||||
} | |||||
zs[idx].Score = score | |||||
zs[idx].Member = kvs[i+1] | |||||
} | |||||
res, err := pools.ZAdd(key, zs...).Result() | |||||
if err != nil { | |||||
return res, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func RCZRem(key string, members ...string) (int64, error) { | |||||
args := make([]interface{}, 0, len(members)) | |||||
args = append(args, key) | |||||
for _, member := range members { | |||||
args = append(args, member) | |||||
} | |||||
res, err := pools.ZRem(key, members).Result() | |||||
if err != nil { | |||||
return res, convertError(err) | |||||
} | |||||
return res, err | |||||
} | |||||
func RCZRange(key string, min, max int64, withScores bool) (interface{}, error) { | |||||
res := make([]interface{}, 0) | |||||
if withScores { | |||||
zs, err := pools.ZRangeWithScores(key, min, max).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
for _, z := range zs { | |||||
res = append(res, z.Member, strconv.FormatFloat(z.Score, 'f', -1, 64)) | |||||
} | |||||
} else { | |||||
ms, err := pools.ZRange(key, min, max).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
for _, m := range ms { | |||||
res = append(res, m) | |||||
} | |||||
} | |||||
return res, nil | |||||
} | |||||
func RCZRangeByScoreWithScore(key string, min, max int64) (map[string]int64, error) { | |||||
opt := new(redis.ZRangeBy) | |||||
opt.Min = strconv.FormatInt(int64(min), 10) | |||||
opt.Max = strconv.FormatInt(int64(max), 10) | |||||
opt.Count = -1 | |||||
opt.Offset = 0 | |||||
vals, err := pools.ZRangeByScoreWithScores(key, *opt).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
res := make(map[string]int64, len(vals)) | |||||
for _, val := range vals { | |||||
key, err := String(val.Member, nil) | |||||
if err != nil && err != ErrNil { | |||||
return nil, err | |||||
} | |||||
res[key] = int64(val.Score) | |||||
} | |||||
return res, nil | |||||
} | |||||
func RCLRange(key string, start, stop int64) (interface{}, error) { | |||||
res, err := pools.LRange(key, start, stop).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func RCLSet(key string, index int, value interface{}) error { | |||||
err := pools.LSet(key, int64(index), value).Err() | |||||
return convertError(err) | |||||
} | |||||
func RCLLen(key string) (int64, error) { | |||||
res, err := pools.LLen(key).Result() | |||||
if err != nil { | |||||
return res, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func RCLRem(key string, count int, value interface{}) (int, error) { | |||||
val, _ := value.(string) | |||||
res, err := pools.LRem(key, int64(count), val).Result() | |||||
if err != nil { | |||||
return int(res), convertError(err) | |||||
} | |||||
return int(res), nil | |||||
} | |||||
func RCTTl(key string) (int64, error) { | |||||
duration, err := pools.TTL(key).Result() | |||||
if err != nil { | |||||
return int64(duration.Seconds()), convertError(err) | |||||
} | |||||
return int64(duration.Seconds()), nil | |||||
} | |||||
func RCLPop(key string) (interface{}, error) { | |||||
res, err := pools.LPop(key).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func RCRPop(key string) (interface{}, error) { | |||||
res, err := pools.RPop(key).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func RCBLPop(key string, timeout int) (interface{}, error) { | |||||
res, err := pools.BLPop(time.Duration(timeout)*time.Second, key).Result() | |||||
if err != nil { | |||||
// 兼容redis 2.x | |||||
if err == redis.Nil { | |||||
return nil, ErrNil | |||||
} | |||||
return nil, err | |||||
} | |||||
return res[1], nil | |||||
} | |||||
func RCBRPop(key string, timeout int) (interface{}, error) { | |||||
res, err := pools.BRPop(time.Duration(timeout)*time.Second, key).Result() | |||||
if err != nil { | |||||
// 兼容redis 2.x | |||||
if err == redis.Nil { | |||||
return nil, ErrNil | |||||
} | |||||
return nil, convertError(err) | |||||
} | |||||
return res[1], nil | |||||
} | |||||
func RCLPush(key string, value ...interface{}) error { | |||||
args := make([]interface{}, 0, len(value)+1) | |||||
args = append(args, key) | |||||
args = append(args, value...) | |||||
vals := make([]string, 0, len(value)) | |||||
for _, v := range value { | |||||
val, err := String(v, nil) | |||||
if err != nil && err != ErrNil { | |||||
return err | |||||
} | |||||
vals = append(vals, val) | |||||
} | |||||
_, err := pools.LPush(key, vals).Result() // todo ... | |||||
if err != nil { | |||||
return convertError(err) | |||||
} | |||||
return nil | |||||
} | |||||
func RCRPush(key string, value ...interface{}) error { | |||||
args := make([]interface{}, 0, len(value)+1) | |||||
args = append(args, key) | |||||
args = append(args, value...) | |||||
vals := make([]string, 0, len(value)) | |||||
for _, v := range value { | |||||
val, err := String(v, nil) | |||||
if err != nil && err != ErrNil { | |||||
if err == ErrNil { | |||||
continue | |||||
} | |||||
return err | |||||
} | |||||
if val == "" { | |||||
continue | |||||
} | |||||
vals = append(vals, val) | |||||
} | |||||
_, err := pools.RPush(key, vals).Result() // todo ... | |||||
if err != nil { | |||||
return convertError(err) | |||||
} | |||||
return nil | |||||
} | |||||
// 为确保srcKey跟destKey映射到同一个slot,srcKey和destKey需要加上hash tag,如:{test} | |||||
func RCBRPopLPush(srcKey string, destKey string, timeout int) (interface{}, error) { | |||||
res, err := pools.BRPopLPush(srcKey, destKey, time.Duration(timeout)*time.Second).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
// 为确保srcKey跟destKey映射到同一个slot,srcKey和destKey需要加上hash tag,如:{test} | |||||
func RCRPopLPush(srcKey string, destKey string) (interface{}, error) { | |||||
res, err := pools.RPopLPush(srcKey, destKey).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func RCSAdd(key string, members ...interface{}) (int64, error) { | |||||
args := make([]interface{}, 0, len(members)+1) | |||||
args = append(args, key) | |||||
args = append(args, members...) | |||||
ms := make([]string, 0, len(members)) | |||||
for _, member := range members { | |||||
m, err := String(member, nil) | |||||
if err != nil && err != ErrNil { | |||||
return 0, err | |||||
} | |||||
ms = append(ms, m) | |||||
} | |||||
res, err := pools.SAdd(key, ms).Result() // todo ... | |||||
if err != nil { | |||||
return res, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func RCSPop(key string) ([]byte, error) { | |||||
res, err := pools.SPop(key).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
return []byte(res), nil | |||||
} | |||||
func RCSIsMember(key string, member interface{}) (bool, error) { | |||||
m, _ := member.(string) | |||||
res, err := pools.SIsMember(key, m).Result() | |||||
if err != nil { | |||||
return res, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func RCSRem(key string, members ...interface{}) (int64, error) { | |||||
args := make([]interface{}, 0, len(members)+1) | |||||
args = append(args, key) | |||||
args = append(args, members...) | |||||
ms := make([]string, 0, len(members)) | |||||
for _, member := range members { | |||||
m, err := String(member, nil) | |||||
if err != nil && err != ErrNil { | |||||
return 0, err | |||||
} | |||||
ms = append(ms, m) | |||||
} | |||||
res, err := pools.SRem(key, ms).Result() // todo ... | |||||
if err != nil { | |||||
return res, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func RCSMembers(key string) ([]string, error) { | |||||
res, err := pools.SMembers(key).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func RCScriptLoad(luaScript string) (interface{}, error) { | |||||
res, err := pools.ScriptLoad(luaScript).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func RCEvalSha(sha1 string, numberKeys int, keysArgs ...interface{}) (interface{}, error) { | |||||
vals := make([]interface{}, 0, len(keysArgs)+2) | |||||
vals = append(vals, sha1, numberKeys) | |||||
vals = append(vals, keysArgs...) | |||||
keys := make([]string, 0, numberKeys) | |||||
args := make([]string, 0, len(keysArgs)-numberKeys) | |||||
for i, value := range keysArgs { | |||||
val, err := String(value, nil) | |||||
if err != nil && err != ErrNil { | |||||
return nil, err | |||||
} | |||||
if i < numberKeys { | |||||
keys = append(keys, val) | |||||
} else { | |||||
args = append(args, val) | |||||
} | |||||
} | |||||
res, err := pools.EvalSha(sha1, keys, args).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func RCEval(luaScript string, numberKeys int, keysArgs ...interface{}) (interface{}, error) { | |||||
vals := make([]interface{}, 0, len(keysArgs)+2) | |||||
vals = append(vals, luaScript, numberKeys) | |||||
vals = append(vals, keysArgs...) | |||||
keys := make([]string, 0, numberKeys) | |||||
args := make([]string, 0, len(keysArgs)-numberKeys) | |||||
for i, value := range keysArgs { | |||||
val, err := String(value, nil) | |||||
if err != nil && err != ErrNil { | |||||
return nil, err | |||||
} | |||||
if i < numberKeys { | |||||
keys = append(keys, val) | |||||
} else { | |||||
args = append(args, val) | |||||
} | |||||
} | |||||
res, err := pools.Eval(luaScript, keys, args).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func RCGetBit(key string, offset int64) (int64, error) { | |||||
res, err := pools.GetBit(key, offset).Result() | |||||
if err != nil { | |||||
return res, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func RCSetBit(key string, offset uint32, value int) (int, error) { | |||||
res, err := pools.SetBit(key, int64(offset), value).Result() | |||||
return int(res), convertError(err) | |||||
} | |||||
func RCGetClient() *redis.ClusterClient { | |||||
return pools | |||||
} | |||||
func convertError(err error) error { | |||||
if err == redis.Nil { | |||||
// 为了兼容redis 2.x,这里不返回 ErrNil,ErrNil在调用redis_cluster_reply函数时才返回 | |||||
return nil | |||||
} | |||||
return err | |||||
} |
@@ -0,0 +1,324 @@ | |||||
package cache | |||||
import ( | |||||
"errors" | |||||
"log" | |||||
"strings" | |||||
"time" | |||||
redigo "github.com/gomodule/redigo/redis" | |||||
) | |||||
type RedisPool struct { | |||||
*redigo.Pool | |||||
} | |||||
func NewRedisPool(cfg *Config) *RedisPool { | |||||
return &RedisPool{&redigo.Pool{ | |||||
MaxIdle: cfg.MaxIdle, | |||||
IdleTimeout: cfg.IdleTimeout, | |||||
MaxActive: cfg.MaxActive, | |||||
Wait: cfg.Wait, | |||||
Dial: func() (redigo.Conn, error) { | |||||
c, err := redigo.Dial("tcp", cfg.Server) | |||||
if err != nil { | |||||
log.Println("Redis Dial failed: ", err) | |||||
return nil, err | |||||
} | |||||
if cfg.Password != "" { | |||||
if _, err := c.Do("AUTH", cfg.Password); err != nil { | |||||
c.Close() | |||||
log.Println("Redis AUTH failed: ", err) | |||||
return nil, err | |||||
} | |||||
} | |||||
return c, err | |||||
}, | |||||
TestOnBorrow: func(c redigo.Conn, t time.Time) error { | |||||
_, err := c.Do("PING") | |||||
if err != nil { | |||||
log.Println("Unable to ping to redis server:", err) | |||||
} | |||||
return err | |||||
}, | |||||
}} | |||||
} | |||||
func (p *RedisPool) Do(cmd string, args ...interface{}) (reply interface{}, err error) { | |||||
conn := pool.Get() | |||||
defer conn.Close() | |||||
return conn.Do(cmd, args...) | |||||
} | |||||
func (p *RedisPool) GetPool() *redigo.Pool { | |||||
return pool | |||||
} | |||||
func (p *RedisPool) ParseKey(key string, vars []string) (string, error) { | |||||
arr := strings.Split(key, conf.KeyPlaceholder) | |||||
actualKey := "" | |||||
if len(arr) != len(vars)+1 { | |||||
return "", errors.New("redis/connection.go: Insufficient arguments to parse key") | |||||
} else { | |||||
for index, val := range arr { | |||||
if index == 0 { | |||||
actualKey = arr[index] | |||||
} else { | |||||
actualKey += vars[index-1] + val | |||||
} | |||||
} | |||||
} | |||||
return getPrefixedKey(actualKey), nil | |||||
} | |||||
func (p *RedisPool) getPrefixedKey(key string) string { | |||||
return conf.KeyPrefix + conf.KeyDelimiter + key | |||||
} | |||||
func (p *RedisPool) StripEnvKey(key string) string { | |||||
return strings.TrimLeft(key, conf.KeyPrefix+conf.KeyDelimiter) | |||||
} | |||||
func (p *RedisPool) SplitKey(key string) []string { | |||||
return strings.Split(key, conf.KeyDelimiter) | |||||
} | |||||
func (p *RedisPool) Expire(key string, ttl int) (interface{}, error) { | |||||
return Do("EXPIRE", key, ttl) | |||||
} | |||||
func (p *RedisPool) Persist(key string) (interface{}, error) { | |||||
return Do("PERSIST", key) | |||||
} | |||||
func (p *RedisPool) Del(key string) (interface{}, error) { | |||||
return Do("DEL", key) | |||||
} | |||||
func (p *RedisPool) Set(key string, data interface{}) (interface{}, error) { | |||||
// set | |||||
return Do("SET", key, data) | |||||
} | |||||
func (p *RedisPool) SetNX(key string, data interface{}) (interface{}, error) { | |||||
return Do("SETNX", key, data) | |||||
} | |||||
func (p *RedisPool) SetEx(key string, data interface{}, ttl int) (interface{}, error) { | |||||
return Do("SETEX", key, ttl, data) | |||||
} | |||||
func (p *RedisPool) Get(key string) (interface{}, error) { | |||||
// get | |||||
return Do("GET", key) | |||||
} | |||||
func (p *RedisPool) GetStringMap(key string) (map[string]string, error) { | |||||
// get | |||||
return redigo.StringMap(Do("GET", key)) | |||||
} | |||||
func (p *RedisPool) GetTTL(key string) (time.Duration, error) { | |||||
ttl, err := redigo.Int64(Do("TTL", key)) | |||||
return time.Duration(ttl) * time.Second, err | |||||
} | |||||
func (p *RedisPool) GetBytes(key string) ([]byte, error) { | |||||
return redigo.Bytes(Do("GET", key)) | |||||
} | |||||
func (p *RedisPool) GetString(key string) (string, error) { | |||||
return redigo.String(Do("GET", key)) | |||||
} | |||||
func (p *RedisPool) GetInt(key string) (int, error) { | |||||
return redigo.Int(Do("GET", key)) | |||||
} | |||||
func (p *RedisPool) GetStringLength(key string) (int, error) { | |||||
return redigo.Int(Do("STRLEN", key)) | |||||
} | |||||
func (p *RedisPool) ZAdd(key string, score float64, data interface{}) (interface{}, error) { | |||||
return Do("ZADD", key, score, data) | |||||
} | |||||
func (p *RedisPool) ZRem(key string, data interface{}) (interface{}, error) { | |||||
return Do("ZREM", key, data) | |||||
} | |||||
func (p *RedisPool) ZRange(key string, start int, end int, withScores bool) ([]interface{}, error) { | |||||
if withScores { | |||||
return redigo.Values(Do("ZRANGE", key, start, end, "WITHSCORES")) | |||||
} | |||||
return redigo.Values(Do("ZRANGE", key, start, end)) | |||||
} | |||||
func (p *RedisPool) SAdd(setName string, data interface{}) (interface{}, error) { | |||||
return Do("SADD", setName, data) | |||||
} | |||||
func (p *RedisPool) SCard(setName string) (int64, error) { | |||||
return redigo.Int64(Do("SCARD", setName)) | |||||
} | |||||
func (p *RedisPool) SIsMember(setName string, data interface{}) (bool, error) { | |||||
return redigo.Bool(Do("SISMEMBER", setName, data)) | |||||
} | |||||
func (p *RedisPool) SMembers(setName string) ([]string, error) { | |||||
return redigo.Strings(Do("SMEMBERS", setName)) | |||||
} | |||||
func (p *RedisPool) SRem(setName string, data interface{}) (interface{}, error) { | |||||
return Do("SREM", setName, data) | |||||
} | |||||
func (p *RedisPool) HSet(key string, HKey string, data interface{}) (interface{}, error) { | |||||
return Do("HSET", key, HKey, data) | |||||
} | |||||
func (p *RedisPool) HGet(key string, HKey string) (interface{}, error) { | |||||
return Do("HGET", key, HKey) | |||||
} | |||||
func (p *RedisPool) HMGet(key string, hashKeys ...string) ([]interface{}, error) { | |||||
ret, err := Do("HMGET", key, hashKeys) | |||||
if err != nil { | |||||
return nil, err | |||||
} | |||||
reta, ok := ret.([]interface{}) | |||||
if !ok { | |||||
return nil, errors.New("result not an array") | |||||
} | |||||
return reta, nil | |||||
} | |||||
func (p *RedisPool) HMSet(key string, hashKeys []string, vals []interface{}) (interface{}, error) { | |||||
if len(hashKeys) == 0 || len(hashKeys) != len(vals) { | |||||
var ret interface{} | |||||
return ret, errors.New("bad length") | |||||
} | |||||
input := []interface{}{key} | |||||
for i, v := range hashKeys { | |||||
input = append(input, v, vals[i]) | |||||
} | |||||
return Do("HMSET", input...) | |||||
} | |||||
func (p *RedisPool) HGetString(key string, HKey string) (string, error) { | |||||
return redigo.String(Do("HGET", key, HKey)) | |||||
} | |||||
func (p *RedisPool) HGetFloat(key string, HKey string) (float64, error) { | |||||
f, err := redigo.Float64(Do("HGET", key, HKey)) | |||||
return float64(f), err | |||||
} | |||||
func (p *RedisPool) HGetInt(key string, HKey string) (int, error) { | |||||
return redigo.Int(Do("HGET", key, HKey)) | |||||
} | |||||
func (p *RedisPool) HGetInt64(key string, HKey string) (int64, error) { | |||||
return redigo.Int64(Do("HGET", key, HKey)) | |||||
} | |||||
func (p *RedisPool) HGetBool(key string, HKey string) (bool, error) { | |||||
return redigo.Bool(Do("HGET", key, HKey)) | |||||
} | |||||
func (p *RedisPool) HDel(key string, HKey string) (interface{}, error) { | |||||
return Do("HDEL", key, HKey) | |||||
} | |||||
func (p *RedisPool) HGetAll(key string) (map[string]interface{}, error) { | |||||
vals, err := redigo.Values(Do("HGETALL", key)) | |||||
if err != nil { | |||||
return nil, err | |||||
} | |||||
num := len(vals) / 2 | |||||
result := make(map[string]interface{}, num) | |||||
for i := 0; i < num; i++ { | |||||
key, _ := redigo.String(vals[2*i], nil) | |||||
result[key] = vals[2*i+1] | |||||
} | |||||
return result, nil | |||||
} | |||||
// NOTE: Use this in production environment with extreme care. | |||||
// Read more here:https://redigo.io/commands/keys | |||||
func (p *RedisPool) Keys(pattern string) ([]string, error) { | |||||
return redigo.Strings(Do("KEYS", pattern)) | |||||
} | |||||
func (p *RedisPool) HKeys(key string) ([]string, error) { | |||||
return redigo.Strings(Do("HKEYS", key)) | |||||
} | |||||
func (p *RedisPool) Exists(key string) (bool, error) { | |||||
count, err := redigo.Int(Do("EXISTS", key)) | |||||
if count == 0 { | |||||
return false, err | |||||
} else { | |||||
return true, err | |||||
} | |||||
} | |||||
func (p *RedisPool) Incr(key string) (int64, error) { | |||||
return redigo.Int64(Do("INCR", key)) | |||||
} | |||||
func (p *RedisPool) Decr(key string) (int64, error) { | |||||
return redigo.Int64(Do("DECR", key)) | |||||
} | |||||
func (p *RedisPool) IncrBy(key string, incBy int64) (int64, error) { | |||||
return redigo.Int64(Do("INCRBY", key, incBy)) | |||||
} | |||||
func (p *RedisPool) DecrBy(key string, decrBy int64) (int64, error) { | |||||
return redigo.Int64(Do("DECRBY", key)) | |||||
} | |||||
func (p *RedisPool) IncrByFloat(key string, incBy float64) (float64, error) { | |||||
return redigo.Float64(Do("INCRBYFLOAT", key, incBy)) | |||||
} | |||||
func (p *RedisPool) DecrByFloat(key string, decrBy float64) (float64, error) { | |||||
return redigo.Float64(Do("DECRBYFLOAT", key, decrBy)) | |||||
} | |||||
// use for message queue | |||||
func (p *RedisPool) LPush(key string, data interface{}) (interface{}, error) { | |||||
// set | |||||
return Do("LPUSH", key, data) | |||||
} | |||||
func (p *RedisPool) LPop(key string) (interface{}, error) { | |||||
return Do("LPOP", key) | |||||
} | |||||
func (p *RedisPool) LPopString(key string) (string, error) { | |||||
return redigo.String(Do("LPOP", key)) | |||||
} | |||||
func (p *RedisPool) LPopFloat(key string) (float64, error) { | |||||
f, err := redigo.Float64(Do("LPOP", key)) | |||||
return float64(f), err | |||||
} | |||||
func (p *RedisPool) LPopInt(key string) (int, error) { | |||||
return redigo.Int(Do("LPOP", key)) | |||||
} | |||||
func (p *RedisPool) LPopInt64(key string) (int64, error) { | |||||
return redigo.Int64(Do("LPOP", key)) | |||||
} | |||||
func (p *RedisPool) RPush(key string, data interface{}) (interface{}, error) { | |||||
// set | |||||
return Do("RPUSH", key, data) | |||||
} | |||||
func (p *RedisPool) RPop(key string) (interface{}, error) { | |||||
return Do("RPOP", key) | |||||
} | |||||
func (p *RedisPool) RPopString(key string) (string, error) { | |||||
return redigo.String(Do("RPOP", key)) | |||||
} | |||||
func (p *RedisPool) RPopFloat(key string) (float64, error) { | |||||
f, err := redigo.Float64(Do("RPOP", key)) | |||||
return float64(f), err | |||||
} | |||||
func (p *RedisPool) RPopInt(key string) (int, error) { | |||||
return redigo.Int(Do("RPOP", key)) | |||||
} | |||||
func (p *RedisPool) RPopInt64(key string) (int64, error) { | |||||
return redigo.Int64(Do("RPOP", key)) | |||||
} | |||||
func (p *RedisPool) Scan(cursor int64, pattern string, count int64) (int64, []string, error) { | |||||
var items []string | |||||
var newCursor int64 | |||||
values, err := redigo.Values(Do("SCAN", cursor, "MATCH", pattern, "COUNT", count)) | |||||
if err != nil { | |||||
return 0, nil, err | |||||
} | |||||
values, err = redigo.Scan(values, &newCursor, &items) | |||||
if err != nil { | |||||
return 0, nil, err | |||||
} | |||||
return newCursor, items, nil | |||||
} |
@@ -0,0 +1,617 @@ | |||||
package cache | |||||
import ( | |||||
"strconv" | |||||
"time" | |||||
"github.com/go-redis/redis" | |||||
) | |||||
type RedisClusterPool struct { | |||||
client *redis.ClusterClient | |||||
} | |||||
func NewRedisClusterPool(addrs []string) (*RedisClusterPool, error) { | |||||
opt := &redis.ClusterOptions{ | |||||
Addrs: addrs, | |||||
PoolSize: 512, | |||||
PoolTimeout: 10 * time.Second, | |||||
IdleTimeout: 10 * time.Second, | |||||
DialTimeout: 10 * time.Second, | |||||
ReadTimeout: 3 * time.Second, | |||||
WriteTimeout: 3 * time.Second, | |||||
} | |||||
c := redis.NewClusterClient(opt) | |||||
if err := c.Ping().Err(); err != nil { | |||||
return nil, err | |||||
} | |||||
return &RedisClusterPool{client: c}, nil | |||||
} | |||||
func (p *RedisClusterPool) Get(key string) (interface{}, error) { | |||||
res, err := p.client.Get(key).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
return []byte(res), nil | |||||
} | |||||
func (p *RedisClusterPool) Set(key string, value interface{}) error { | |||||
err := p.client.Set(key, value, 0).Err() | |||||
return convertError(err) | |||||
} | |||||
func (p *RedisClusterPool) GetSet(key string, value interface{}) (interface{}, error) { | |||||
res, err := p.client.GetSet(key, value).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
return []byte(res), nil | |||||
} | |||||
func (p *RedisClusterPool) SetNx(key string, value interface{}) (int64, error) { | |||||
res, err := p.client.SetNX(key, value, 0).Result() | |||||
if err != nil { | |||||
return 0, convertError(err) | |||||
} | |||||
if res { | |||||
return 1, nil | |||||
} | |||||
return 0, nil | |||||
} | |||||
func (p *RedisClusterPool) SetEx(key string, value interface{}, timeout int64) error { | |||||
_, err := p.client.Set(key, value, time.Duration(timeout)*time.Second).Result() | |||||
if err != nil { | |||||
return convertError(err) | |||||
} | |||||
return nil | |||||
} | |||||
// nil表示成功,ErrNil表示数据库内已经存在这个key,其他表示数据库发生错误 | |||||
func (p *RedisClusterPool) SetNxEx(key string, value interface{}, timeout int64) error { | |||||
res, err := p.client.SetNX(key, value, time.Duration(timeout)*time.Second).Result() | |||||
if err != nil { | |||||
return convertError(err) | |||||
} | |||||
if res { | |||||
return nil | |||||
} | |||||
return ErrNil | |||||
} | |||||
func (p *RedisClusterPool) MGet(keys ...string) ([]interface{}, error) { | |||||
res, err := p.client.MGet(keys...).Result() | |||||
return res, convertError(err) | |||||
} | |||||
// 为确保多个key映射到同一个slot,每个key最好加上hash tag,如:{test} | |||||
func (p *RedisClusterPool) MSet(kvs map[string]interface{}) error { | |||||
pairs := make([]string, 0, len(kvs)*2) | |||||
for k, v := range kvs { | |||||
val, err := String(v, nil) | |||||
if err != nil { | |||||
return err | |||||
} | |||||
pairs = append(pairs, k, val) | |||||
} | |||||
return convertError(p.client.MSet(pairs).Err()) | |||||
} | |||||
// 为确保多个key映射到同一个slot,每个key最好加上hash tag,如:{test} | |||||
func (p *RedisClusterPool) MSetNX(kvs map[string]interface{}) (bool, error) { | |||||
pairs := make([]string, 0, len(kvs)*2) | |||||
for k, v := range kvs { | |||||
val, err := String(v, nil) | |||||
if err != nil { | |||||
return false, err | |||||
} | |||||
pairs = append(pairs, k, val) | |||||
} | |||||
res, err := p.client.MSetNX(pairs).Result() | |||||
return res, convertError(err) | |||||
} | |||||
func (p *RedisClusterPool) ExpireAt(key string, timestamp int64) (int64, error) { | |||||
res, err := p.client.ExpireAt(key, time.Unix(timestamp, 0)).Result() | |||||
if err != nil { | |||||
return 0, convertError(err) | |||||
} | |||||
if res { | |||||
return 1, nil | |||||
} | |||||
return 0, nil | |||||
} | |||||
func (p *RedisClusterPool) Del(keys ...string) (int64, error) { | |||||
args := make([]interface{}, 0, len(keys)) | |||||
for _, key := range keys { | |||||
args = append(args, key) | |||||
} | |||||
res, err := p.client.Del(keys...).Result() | |||||
if err != nil { | |||||
return res, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func (p *RedisClusterPool) Incr(key string) (int64, error) { | |||||
res, err := p.client.Incr(key).Result() | |||||
if err != nil { | |||||
return res, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func (p *RedisClusterPool) IncrBy(key string, delta int64) (int64, error) { | |||||
res, err := p.client.IncrBy(key, delta).Result() | |||||
if err != nil { | |||||
return res, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func (p *RedisClusterPool) Expire(key string, duration int64) (int64, error) { | |||||
res, err := p.client.Expire(key, time.Duration(duration)*time.Second).Result() | |||||
if err != nil { | |||||
return 0, convertError(err) | |||||
} | |||||
if res { | |||||
return 1, nil | |||||
} | |||||
return 0, nil | |||||
} | |||||
func (p *RedisClusterPool) Exists(key string) (bool, error) { // todo (bool, error) | |||||
res, err := p.client.Exists(key).Result() | |||||
if err != nil { | |||||
return false, convertError(err) | |||||
} | |||||
if res > 0 { | |||||
return true, nil | |||||
} | |||||
return false, nil | |||||
} | |||||
func (p *RedisClusterPool) HGet(key string, field string) (interface{}, error) { | |||||
res, err := p.client.HGet(key, field).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
return []byte(res), nil | |||||
} | |||||
func (p *RedisClusterPool) HLen(key string) (int64, error) { | |||||
res, err := p.client.HLen(key).Result() | |||||
if err != nil { | |||||
return res, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func (p *RedisClusterPool) HSet(key string, field string, val interface{}) error { | |||||
value, err := String(val, nil) | |||||
if err != nil && err != ErrNil { | |||||
return err | |||||
} | |||||
_, err = p.client.HSet(key, field, value).Result() | |||||
if err != nil { | |||||
return convertError(err) | |||||
} | |||||
return nil | |||||
} | |||||
func (p *RedisClusterPool) HDel(key string, fields ...string) (int64, error) { | |||||
args := make([]interface{}, 0, len(fields)+1) | |||||
args = append(args, key) | |||||
for _, field := range fields { | |||||
args = append(args, field) | |||||
} | |||||
res, err := p.client.HDel(key, fields...).Result() | |||||
if err != nil { | |||||
return 0, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func (p *RedisClusterPool) HMGet(key string, fields ...string) (interface{}, error) { | |||||
args := make([]interface{}, 0, len(fields)+1) | |||||
args = append(args, key) | |||||
for _, field := range fields { | |||||
args = append(args, field) | |||||
} | |||||
if len(fields) == 0 { | |||||
return nil, ErrNil | |||||
} | |||||
res, err := p.client.HMGet(key, fields...).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func (p *RedisClusterPool) HMSet(key string, kvs ...interface{}) error { | |||||
if len(kvs) == 0 { | |||||
return nil | |||||
} | |||||
if len(kvs)%2 != 0 { | |||||
return ErrWrongArgsNum | |||||
} | |||||
var err error | |||||
v := map[string]interface{}{} // todo change | |||||
v["field"], err = String(kvs[0], nil) | |||||
if err != nil && err != ErrNil { | |||||
return err | |||||
} | |||||
v["value"], err = String(kvs[1], nil) | |||||
if err != nil && err != ErrNil { | |||||
return err | |||||
} | |||||
pairs := make([]string, 0, len(kvs)-2) | |||||
if len(kvs) > 2 { | |||||
for _, kv := range kvs[2:] { | |||||
kvString, err := String(kv, nil) | |||||
if err != nil && err != ErrNil { | |||||
return err | |||||
} | |||||
pairs = append(pairs, kvString) | |||||
} | |||||
} | |||||
v["paris"] = pairs | |||||
_, err = p.client.HMSet(key, v).Result() | |||||
if err != nil { | |||||
return convertError(err) | |||||
} | |||||
return nil | |||||
} | |||||
func (p *RedisClusterPool) HKeys(key string) ([]string, error) { | |||||
res, err := p.client.HKeys(key).Result() | |||||
if err != nil { | |||||
return res, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func (p *RedisClusterPool) HVals(key string) ([]interface{}, error) { | |||||
res, err := p.client.HVals(key).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
rs := make([]interface{}, 0, len(res)) | |||||
for _, res := range res { | |||||
rs = append(rs, res) | |||||
} | |||||
return rs, nil | |||||
} | |||||
func (p *RedisClusterPool) HGetAll(key string) (map[string]string, error) { | |||||
vals, err := p.client.HGetAll(key).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
return vals, nil | |||||
} | |||||
func (p *RedisClusterPool) HIncrBy(key, field string, delta int64) (int64, error) { | |||||
res, err := p.client.HIncrBy(key, field, delta).Result() | |||||
if err != nil { | |||||
return res, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func (p *RedisClusterPool) ZAdd(key string, kvs ...interface{}) (int64, error) { | |||||
args := make([]interface{}, 0, len(kvs)+1) | |||||
args = append(args, key) | |||||
args = append(args, kvs...) | |||||
if len(kvs) == 0 { | |||||
return 0, nil | |||||
} | |||||
if len(kvs)%2 != 0 { | |||||
return 0, ErrWrongArgsNum | |||||
} | |||||
zs := make([]redis.Z, len(kvs)/2) | |||||
for i := 0; i < len(kvs); i += 2 { | |||||
idx := i / 2 | |||||
score, err := Float64(kvs[i], nil) | |||||
if err != nil && err != ErrNil { | |||||
return 0, err | |||||
} | |||||
zs[idx].Score = score | |||||
zs[idx].Member = kvs[i+1] | |||||
} | |||||
res, err := p.client.ZAdd(key, zs...).Result() | |||||
if err != nil { | |||||
return res, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func (p *RedisClusterPool) ZRem(key string, members ...string) (int64, error) { | |||||
args := make([]interface{}, 0, len(members)) | |||||
args = append(args, key) | |||||
for _, member := range members { | |||||
args = append(args, member) | |||||
} | |||||
res, err := p.client.ZRem(key, members).Result() | |||||
if err != nil { | |||||
return res, convertError(err) | |||||
} | |||||
return res, err | |||||
} | |||||
func (p *RedisClusterPool) ZRange(key string, min, max int64, withScores bool) (interface{}, error) { | |||||
res := make([]interface{}, 0) | |||||
if withScores { | |||||
zs, err := p.client.ZRangeWithScores(key, min, max).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
for _, z := range zs { | |||||
res = append(res, z.Member, strconv.FormatFloat(z.Score, 'f', -1, 64)) | |||||
} | |||||
} else { | |||||
ms, err := p.client.ZRange(key, min, max).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
for _, m := range ms { | |||||
res = append(res, m) | |||||
} | |||||
} | |||||
return res, nil | |||||
} | |||||
func (p *RedisClusterPool) ZRangeByScoreWithScore(key string, min, max int64) (map[string]int64, error) { | |||||
opt := new(redis.ZRangeBy) | |||||
opt.Min = strconv.FormatInt(int64(min), 10) | |||||
opt.Max = strconv.FormatInt(int64(max), 10) | |||||
opt.Count = -1 | |||||
opt.Offset = 0 | |||||
vals, err := p.client.ZRangeByScoreWithScores(key, *opt).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
res := make(map[string]int64, len(vals)) | |||||
for _, val := range vals { | |||||
key, err := String(val.Member, nil) | |||||
if err != nil && err != ErrNil { | |||||
return nil, err | |||||
} | |||||
res[key] = int64(val.Score) | |||||
} | |||||
return res, nil | |||||
} | |||||
func (p *RedisClusterPool) LRange(key string, start, stop int64) (interface{}, error) { | |||||
res, err := p.client.LRange(key, start, stop).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func (p *RedisClusterPool) LSet(key string, index int, value interface{}) error { | |||||
err := p.client.LSet(key, int64(index), value).Err() | |||||
return convertError(err) | |||||
} | |||||
func (p *RedisClusterPool) LLen(key string) (int64, error) { | |||||
res, err := p.client.LLen(key).Result() | |||||
if err != nil { | |||||
return res, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func (p *RedisClusterPool) LRem(key string, count int, value interface{}) (int, error) { | |||||
val, _ := value.(string) | |||||
res, err := p.client.LRem(key, int64(count), val).Result() | |||||
if err != nil { | |||||
return int(res), convertError(err) | |||||
} | |||||
return int(res), nil | |||||
} | |||||
func (p *RedisClusterPool) TTl(key string) (int64, error) { | |||||
duration, err := p.client.TTL(key).Result() | |||||
if err != nil { | |||||
return int64(duration.Seconds()), convertError(err) | |||||
} | |||||
return int64(duration.Seconds()), nil | |||||
} | |||||
func (p *RedisClusterPool) LPop(key string) (interface{}, error) { | |||||
res, err := p.client.LPop(key).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func (p *RedisClusterPool) RPop(key string) (interface{}, error) { | |||||
res, err := p.client.RPop(key).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func (p *RedisClusterPool) BLPop(key string, timeout int) (interface{}, error) { | |||||
res, err := p.client.BLPop(time.Duration(timeout)*time.Second, key).Result() | |||||
if err != nil { | |||||
// 兼容redis 2.x | |||||
if err == redis.Nil { | |||||
return nil, ErrNil | |||||
} | |||||
return nil, err | |||||
} | |||||
return res[1], nil | |||||
} | |||||
func (p *RedisClusterPool) BRPop(key string, timeout int) (interface{}, error) { | |||||
res, err := p.client.BRPop(time.Duration(timeout)*time.Second, key).Result() | |||||
if err != nil { | |||||
// 兼容redis 2.x | |||||
if err == redis.Nil { | |||||
return nil, ErrNil | |||||
} | |||||
return nil, convertError(err) | |||||
} | |||||
return res[1], nil | |||||
} | |||||
func (p *RedisClusterPool) LPush(key string, value ...interface{}) error { | |||||
args := make([]interface{}, 0, len(value)+1) | |||||
args = append(args, key) | |||||
args = append(args, value...) | |||||
vals := make([]string, 0, len(value)) | |||||
for _, v := range value { | |||||
val, err := String(v, nil) | |||||
if err != nil && err != ErrNil { | |||||
return err | |||||
} | |||||
vals = append(vals, val) | |||||
} | |||||
_, err := p.client.LPush(key, vals).Result() // todo ... | |||||
if err != nil { | |||||
return convertError(err) | |||||
} | |||||
return nil | |||||
} | |||||
func (p *RedisClusterPool) RPush(key string, value ...interface{}) error { | |||||
args := make([]interface{}, 0, len(value)+1) | |||||
args = append(args, key) | |||||
args = append(args, value...) | |||||
vals := make([]string, 0, len(value)) | |||||
for _, v := range value { | |||||
val, err := String(v, nil) | |||||
if err != nil && err != ErrNil { | |||||
if err == ErrNil { | |||||
continue | |||||
} | |||||
return err | |||||
} | |||||
if val == "" { | |||||
continue | |||||
} | |||||
vals = append(vals, val) | |||||
} | |||||
_, err := p.client.RPush(key, vals).Result() // todo ... | |||||
if err != nil { | |||||
return convertError(err) | |||||
} | |||||
return nil | |||||
} | |||||
// 为确保srcKey跟destKey映射到同一个slot,srcKey和destKey需要加上hash tag,如:{test} | |||||
func (p *RedisClusterPool) BRPopLPush(srcKey string, destKey string, timeout int) (interface{}, error) { | |||||
res, err := p.client.BRPopLPush(srcKey, destKey, time.Duration(timeout)*time.Second).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
// 为确保srcKey跟destKey映射到同一个slot,srcKey和destKey需要加上hash tag,如:{test} | |||||
func (p *RedisClusterPool) RPopLPush(srcKey string, destKey string) (interface{}, error) { | |||||
res, err := p.client.RPopLPush(srcKey, destKey).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func (p *RedisClusterPool) SAdd(key string, members ...interface{}) (int64, error) { | |||||
args := make([]interface{}, 0, len(members)+1) | |||||
args = append(args, key) | |||||
args = append(args, members...) | |||||
ms := make([]string, 0, len(members)) | |||||
for _, member := range members { | |||||
m, err := String(member, nil) | |||||
if err != nil && err != ErrNil { | |||||
return 0, err | |||||
} | |||||
ms = append(ms, m) | |||||
} | |||||
res, err := p.client.SAdd(key, ms).Result() // todo ... | |||||
if err != nil { | |||||
return res, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func (p *RedisClusterPool) SPop(key string) ([]byte, error) { | |||||
res, err := p.client.SPop(key).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
return []byte(res), nil | |||||
} | |||||
func (p *RedisClusterPool) SIsMember(key string, member interface{}) (bool, error) { | |||||
m, _ := member.(string) | |||||
res, err := p.client.SIsMember(key, m).Result() | |||||
if err != nil { | |||||
return res, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func (p *RedisClusterPool) SRem(key string, members ...interface{}) (int64, error) { | |||||
args := make([]interface{}, 0, len(members)+1) | |||||
args = append(args, key) | |||||
args = append(args, members...) | |||||
ms := make([]string, 0, len(members)) | |||||
for _, member := range members { | |||||
m, err := String(member, nil) | |||||
if err != nil && err != ErrNil { | |||||
return 0, err | |||||
} | |||||
ms = append(ms, m) | |||||
} | |||||
res, err := p.client.SRem(key, ms).Result() // todo ... | |||||
if err != nil { | |||||
return res, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func (p *RedisClusterPool) SMembers(key string) ([]string, error) { | |||||
res, err := p.client.SMembers(key).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func (p *RedisClusterPool) ScriptLoad(luaScript string) (interface{}, error) { | |||||
res, err := p.client.ScriptLoad(luaScript).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func (p *RedisClusterPool) EvalSha(sha1 string, numberKeys int, keysArgs ...interface{}) (interface{}, error) { | |||||
vals := make([]interface{}, 0, len(keysArgs)+2) | |||||
vals = append(vals, sha1, numberKeys) | |||||
vals = append(vals, keysArgs...) | |||||
keys := make([]string, 0, numberKeys) | |||||
args := make([]string, 0, len(keysArgs)-numberKeys) | |||||
for i, value := range keysArgs { | |||||
val, err := String(value, nil) | |||||
if err != nil && err != ErrNil { | |||||
return nil, err | |||||
} | |||||
if i < numberKeys { | |||||
keys = append(keys, val) | |||||
} else { | |||||
args = append(args, val) | |||||
} | |||||
} | |||||
res, err := p.client.EvalSha(sha1, keys, args).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func (p *RedisClusterPool) Eval(luaScript string, numberKeys int, keysArgs ...interface{}) (interface{}, error) { | |||||
vals := make([]interface{}, 0, len(keysArgs)+2) | |||||
vals = append(vals, luaScript, numberKeys) | |||||
vals = append(vals, keysArgs...) | |||||
keys := make([]string, 0, numberKeys) | |||||
args := make([]string, 0, len(keysArgs)-numberKeys) | |||||
for i, value := range keysArgs { | |||||
val, err := String(value, nil) | |||||
if err != nil && err != ErrNil { | |||||
return nil, err | |||||
} | |||||
if i < numberKeys { | |||||
keys = append(keys, val) | |||||
} else { | |||||
args = append(args, val) | |||||
} | |||||
} | |||||
res, err := p.client.Eval(luaScript, keys, args).Result() | |||||
if err != nil { | |||||
return nil, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func (p *RedisClusterPool) GetBit(key string, offset int64) (int64, error) { | |||||
res, err := p.client.GetBit(key, offset).Result() | |||||
if err != nil { | |||||
return res, convertError(err) | |||||
} | |||||
return res, nil | |||||
} | |||||
func (p *RedisClusterPool) SetBit(key string, offset uint32, value int) (int, error) { | |||||
res, err := p.client.SetBit(key, int64(offset), value).Result() | |||||
return int(res), convertError(err) | |||||
} | |||||
func (p *RedisClusterPool) GetClient() *redis.ClusterClient { | |||||
return pools | |||||
} |
@@ -0,0 +1,366 @@ | |||||
package zhios_order_relate_utils | |||||
import ( | |||||
"encoding/binary" | |||||
"encoding/json" | |||||
"fmt" | |||||
"math" | |||||
"strconv" | |||||
"strings" | |||||
) | |||||
func ToString(raw interface{}, e error) (res string) { | |||||
if e != nil { | |||||
return "" | |||||
} | |||||
return AnyToString(raw) | |||||
} | |||||
func ToInt64(raw interface{}, e error) int64 { | |||||
if e != nil { | |||||
return 0 | |||||
} | |||||
return AnyToInt64(raw) | |||||
} | |||||
func AnyToBool(raw interface{}) bool { | |||||
switch i := raw.(type) { | |||||
case float32, float64, int, int64, uint, uint8, uint16, uint32, uint64, int8, int16, int32: | |||||
return i != 0 | |||||
case []byte: | |||||
return i != nil | |||||
case string: | |||||
if i == "false" { | |||||
return false | |||||
} | |||||
return i != "" | |||||
case error: | |||||
return false | |||||
case nil: | |||||
return true | |||||
} | |||||
val := fmt.Sprint(raw) | |||||
val = strings.TrimLeft(val, "&") | |||||
if strings.TrimLeft(val, "{}") == "" { | |||||
return false | |||||
} | |||||
if strings.TrimLeft(val, "[]") == "" { | |||||
return false | |||||
} | |||||
// ptr type | |||||
b, err := json.Marshal(raw) | |||||
if err != nil { | |||||
return false | |||||
} | |||||
if strings.TrimLeft(string(b), "\"\"") == "" { | |||||
return false | |||||
} | |||||
if strings.TrimLeft(string(b), "{}") == "" { | |||||
return false | |||||
} | |||||
return true | |||||
} | |||||
func AnyToInt64(raw interface{}) int64 { | |||||
switch i := raw.(type) { | |||||
case string: | |||||
res, _ := strconv.ParseInt(i, 10, 64) | |||||
return res | |||||
case []byte: | |||||
return BytesToInt64(i) | |||||
case int: | |||||
return int64(i) | |||||
case int64: | |||||
return i | |||||
case uint: | |||||
return int64(i) | |||||
case uint8: | |||||
return int64(i) | |||||
case uint16: | |||||
return int64(i) | |||||
case uint32: | |||||
return int64(i) | |||||
case uint64: | |||||
return int64(i) | |||||
case int8: | |||||
return int64(i) | |||||
case int16: | |||||
return int64(i) | |||||
case int32: | |||||
return int64(i) | |||||
case float32: | |||||
return int64(i) | |||||
case float64: | |||||
return int64(i) | |||||
case error: | |||||
return 0 | |||||
case bool: | |||||
if i { | |||||
return 1 | |||||
} | |||||
return 0 | |||||
} | |||||
return 0 | |||||
} | |||||
func AnyToString(raw interface{}) string { | |||||
switch i := raw.(type) { | |||||
case []byte: | |||||
return string(i) | |||||
case int: | |||||
return strconv.FormatInt(int64(i), 10) | |||||
case int64: | |||||
return strconv.FormatInt(i, 10) | |||||
case float32: | |||||
return Float64ToStr(float64(i)) | |||||
case float64: | |||||
return Float64ToStr(i) | |||||
case uint: | |||||
return strconv.FormatInt(int64(i), 10) | |||||
case uint8: | |||||
return strconv.FormatInt(int64(i), 10) | |||||
case uint16: | |||||
return strconv.FormatInt(int64(i), 10) | |||||
case uint32: | |||||
return strconv.FormatInt(int64(i), 10) | |||||
case uint64: | |||||
return strconv.FormatInt(int64(i), 10) | |||||
case int8: | |||||
return strconv.FormatInt(int64(i), 10) | |||||
case int16: | |||||
return strconv.FormatInt(int64(i), 10) | |||||
case int32: | |||||
return strconv.FormatInt(int64(i), 10) | |||||
case string: | |||||
return i | |||||
case error: | |||||
return i.Error() | |||||
case bool: | |||||
return strconv.FormatBool(i) | |||||
} | |||||
return fmt.Sprintf("%#v", raw) | |||||
} | |||||
func AnyToFloat64(raw interface{}) float64 { | |||||
switch i := raw.(type) { | |||||
case []byte: | |||||
f, _ := strconv.ParseFloat(string(i), 64) | |||||
return f | |||||
case int: | |||||
return float64(i) | |||||
case int64: | |||||
return float64(i) | |||||
case float32: | |||||
return float64(i) | |||||
case float64: | |||||
return i | |||||
case uint: | |||||
return float64(i) | |||||
case uint8: | |||||
return float64(i) | |||||
case uint16: | |||||
return float64(i) | |||||
case uint32: | |||||
return float64(i) | |||||
case uint64: | |||||
return float64(i) | |||||
case int8: | |||||
return float64(i) | |||||
case int16: | |||||
return float64(i) | |||||
case int32: | |||||
return float64(i) | |||||
case string: | |||||
f, _ := strconv.ParseFloat(i, 64) | |||||
return f | |||||
case bool: | |||||
if i { | |||||
return 1 | |||||
} | |||||
} | |||||
return 0 | |||||
} | |||||
func ToByte(raw interface{}, e error) []byte { | |||||
if e != nil { | |||||
return []byte{} | |||||
} | |||||
switch i := raw.(type) { | |||||
case string: | |||||
return []byte(i) | |||||
case int: | |||||
return Int64ToBytes(int64(i)) | |||||
case int64: | |||||
return Int64ToBytes(i) | |||||
case float32: | |||||
return Float32ToByte(i) | |||||
case float64: | |||||
return Float64ToByte(i) | |||||
case uint: | |||||
return Int64ToBytes(int64(i)) | |||||
case uint8: | |||||
return Int64ToBytes(int64(i)) | |||||
case uint16: | |||||
return Int64ToBytes(int64(i)) | |||||
case uint32: | |||||
return Int64ToBytes(int64(i)) | |||||
case uint64: | |||||
return Int64ToBytes(int64(i)) | |||||
case int8: | |||||
return Int64ToBytes(int64(i)) | |||||
case int16: | |||||
return Int64ToBytes(int64(i)) | |||||
case int32: | |||||
return Int64ToBytes(int64(i)) | |||||
case []byte: | |||||
return i | |||||
case error: | |||||
return []byte(i.Error()) | |||||
case bool: | |||||
if i { | |||||
return []byte("true") | |||||
} | |||||
return []byte("false") | |||||
} | |||||
return []byte(fmt.Sprintf("%#v", raw)) | |||||
} | |||||
func Int64ToBytes(i int64) []byte { | |||||
var buf = make([]byte, 8) | |||||
binary.BigEndian.PutUint64(buf, uint64(i)) | |||||
return buf | |||||
} | |||||
func BytesToInt64(buf []byte) int64 { | |||||
return int64(binary.BigEndian.Uint64(buf)) | |||||
} | |||||
func StrToInt(s string) int { | |||||
res, _ := strconv.Atoi(s) | |||||
return res | |||||
} | |||||
func StrToInt64(s string) int64 { | |||||
res, _ := strconv.ParseInt(s, 10, 64) | |||||
return res | |||||
} | |||||
func Float32ToByte(float float32) []byte { | |||||
bits := math.Float32bits(float) | |||||
bytes := make([]byte, 4) | |||||
binary.LittleEndian.PutUint32(bytes, bits) | |||||
return bytes | |||||
} | |||||
func ByteToFloat32(bytes []byte) float32 { | |||||
bits := binary.LittleEndian.Uint32(bytes) | |||||
return math.Float32frombits(bits) | |||||
} | |||||
func Float64ToByte(float float64) []byte { | |||||
bits := math.Float64bits(float) | |||||
bytes := make([]byte, 8) | |||||
binary.LittleEndian.PutUint64(bytes, bits) | |||||
return bytes | |||||
} | |||||
func ByteToFloat64(bytes []byte) float64 { | |||||
bits := binary.LittleEndian.Uint64(bytes) | |||||
return math.Float64frombits(bits) | |||||
} | |||||
func Float64ToStr(f float64) string { | |||||
return strconv.FormatFloat(f, 'f', 2, 64) | |||||
} | |||||
func Float64ToStrPrec1(f float64) string { | |||||
return strconv.FormatFloat(f, 'f', 1, 64) | |||||
} | |||||
func Float64ToStrByPrec(f float64, prec int) string { | |||||
return strconv.FormatFloat(f, 'f', prec, 64) | |||||
} | |||||
func Float32ToStr(f float32) string { | |||||
return Float64ToStr(float64(f)) | |||||
} | |||||
func StrToFloat64(s string) float64 { | |||||
res, err := strconv.ParseFloat(s, 64) | |||||
if err != nil { | |||||
return 0 | |||||
} | |||||
return res | |||||
} | |||||
func StrToFormat(s string, prec int) string { | |||||
ex := strings.Split(s, ".") | |||||
if len(ex) == 2 { | |||||
if StrToFloat64(ex[1]) == 0 { //小数点后面为空就是不要小数点了 | |||||
return ex[0] | |||||
} | |||||
//看取多少位 | |||||
str := ex[1] | |||||
str1 := str | |||||
if prec < len(str) { | |||||
str1 = str[0:prec] | |||||
} else { | |||||
for i := 0; i < prec-len(str); i++ { | |||||
str1 += "0" | |||||
} | |||||
} | |||||
if prec > 0 { | |||||
return ex[0] + "." + str1 | |||||
} else { | |||||
return ex[0] | |||||
} | |||||
} | |||||
return s | |||||
} | |||||
func StrToFloat32(s string) float32 { | |||||
res, err := strconv.ParseFloat(s, 32) | |||||
if err != nil { | |||||
return 0 | |||||
} | |||||
return float32(res) | |||||
} | |||||
func StrToBool(s string) bool { | |||||
b, _ := strconv.ParseBool(s) | |||||
return b | |||||
} | |||||
func BoolToStr(b bool) string { | |||||
if b { | |||||
return "true" | |||||
} | |||||
return "false" | |||||
} | |||||
func FloatToInt64(f float64) int64 { | |||||
return int64(f) | |||||
} | |||||
func IntToStr(i int) string { | |||||
return strconv.Itoa(i) | |||||
} | |||||
func Int64ToStr(i int64) string { | |||||
return strconv.FormatInt(i, 10) | |||||
} | |||||
func IntToFloat64(i int) float64 { | |||||
s := strconv.Itoa(i) | |||||
res, err := strconv.ParseFloat(s, 64) | |||||
if err != nil { | |||||
return 0 | |||||
} | |||||
return res | |||||
} | |||||
func Int64ToFloat64(i int64) float64 { | |||||
s := strconv.FormatInt(i, 10) | |||||
res, err := strconv.ParseFloat(s, 64) | |||||
if err != nil { | |||||
return 0 | |||||
} | |||||
return res | |||||
} |
@@ -0,0 +1,209 @@ | |||||
package zhios_order_relate_utils | |||||
import ( | |||||
"bytes" | |||||
"crypto/tls" | |||||
"fmt" | |||||
"io" | |||||
"io/ioutil" | |||||
"net/http" | |||||
"net/url" | |||||
"sort" | |||||
"strings" | |||||
"time" | |||||
) | |||||
var CurlDebug bool | |||||
func CurlGet(router string, header map[string]string) ([]byte, error) { | |||||
return curl(http.MethodGet, router, nil, header) | |||||
} | |||||
func CurlGetJson(router string, body interface{}, header map[string]string) ([]byte, error) { | |||||
return curl_new(http.MethodGet, router, body, header) | |||||
} | |||||
// 只支持form 与json 提交, 请留意body的类型, 支持string, []byte, map[string]string | |||||
func CurlPost(router string, body interface{}, header map[string]string) ([]byte, error) { | |||||
return curl(http.MethodPost, router, body, header) | |||||
} | |||||
func CurlPut(router string, body interface{}, header map[string]string) ([]byte, error) { | |||||
return curl(http.MethodPut, router, body, header) | |||||
} | |||||
// 只支持form 与json 提交, 请留意body的类型, 支持string, []byte, map[string]string | |||||
func CurlPatch(router string, body interface{}, header map[string]string) ([]byte, error) { | |||||
return curl(http.MethodPatch, router, body, header) | |||||
} | |||||
// CurlDelete is curl delete | |||||
func CurlDelete(router string, body interface{}, header map[string]string) ([]byte, error) { | |||||
return curl(http.MethodDelete, router, body, header) | |||||
} | |||||
func curl(method, router string, body interface{}, header map[string]string) ([]byte, error) { | |||||
var reqBody io.Reader | |||||
contentType := "application/json" | |||||
switch v := body.(type) { | |||||
case string: | |||||
reqBody = strings.NewReader(v) | |||||
case []byte: | |||||
reqBody = bytes.NewReader(v) | |||||
case map[string]string: | |||||
val := url.Values{} | |||||
for k, v := range v { | |||||
val.Set(k, v) | |||||
} | |||||
reqBody = strings.NewReader(val.Encode()) | |||||
contentType = "application/x-www-form-urlencoded" | |||||
case map[string]interface{}: | |||||
val := url.Values{} | |||||
for k, v := range v { | |||||
val.Set(k, v.(string)) | |||||
} | |||||
reqBody = strings.NewReader(val.Encode()) | |||||
contentType = "application/x-www-form-urlencoded" | |||||
} | |||||
if header == nil { | |||||
header = map[string]string{"Content-Type": contentType} | |||||
} | |||||
if _, ok := header["Content-Type"]; !ok { | |||||
header["Content-Type"] = contentType | |||||
} | |||||
resp, er := CurlReq(method, router, reqBody, header) | |||||
if er != nil { | |||||
return nil, er | |||||
} | |||||
res, err := ioutil.ReadAll(resp.Body) | |||||
if CurlDebug { | |||||
blob := SerializeStr(body) | |||||
if contentType != "application/json" { | |||||
blob = HttpBuild(body) | |||||
} | |||||
fmt.Printf("\n\n=====================\n[url]: %s\n[time]: %s\n[method]: %s\n[content-type]: %v\n[req_header]: %s\n[req_body]: %#v\n[resp_err]: %v\n[resp_header]: %v\n[resp_body]: %v\n=====================\n\n", | |||||
router, | |||||
time.Now().Format("2006-01-02 15:04:05.000"), | |||||
method, | |||||
contentType, | |||||
HttpBuildQuery(header), | |||||
blob, | |||||
err, | |||||
SerializeStr(resp.Header), | |||||
string(res), | |||||
) | |||||
} | |||||
resp.Body.Close() | |||||
return res, err | |||||
} | |||||
func curl_new(method, router string, body interface{}, header map[string]string) ([]byte, error) { | |||||
var reqBody io.Reader | |||||
contentType := "application/json" | |||||
if header == nil { | |||||
header = map[string]string{"Content-Type": contentType} | |||||
} | |||||
if _, ok := header["Content-Type"]; !ok { | |||||
header["Content-Type"] = contentType | |||||
} | |||||
resp, er := CurlReq(method, router, reqBody, header) | |||||
if er != nil { | |||||
return nil, er | |||||
} | |||||
res, err := ioutil.ReadAll(resp.Body) | |||||
if CurlDebug { | |||||
blob := SerializeStr(body) | |||||
if contentType != "application/json" { | |||||
blob = HttpBuild(body) | |||||
} | |||||
fmt.Printf("\n\n=====================\n[url]: %s\n[time]: %s\n[method]: %s\n[content-type]: %v\n[req_header]: %s\n[req_body]: %#v\n[resp_err]: %v\n[resp_header]: %v\n[resp_body]: %v\n=====================\n\n", | |||||
router, | |||||
time.Now().Format("2006-01-02 15:04:05.000"), | |||||
method, | |||||
contentType, | |||||
HttpBuildQuery(header), | |||||
blob, | |||||
err, | |||||
SerializeStr(resp.Header), | |||||
string(res), | |||||
) | |||||
} | |||||
resp.Body.Close() | |||||
return res, err | |||||
} | |||||
func CurlReq(method, router string, reqBody io.Reader, header map[string]string) (*http.Response, error) { | |||||
req, _ := http.NewRequest(method, router, reqBody) | |||||
if header != nil { | |||||
for k, v := range header { | |||||
req.Header.Set(k, v) | |||||
} | |||||
} | |||||
// 绕过github等可能因为特征码返回503问题 | |||||
// https://www.imwzk.com/posts/2021-03-14-why-i-always-get-503-with-golang/ | |||||
defaultCipherSuites := []uint16{0xc02f, 0xc030, 0xc02b, 0xc02c, 0xcca8, 0xcca9, 0xc013, 0xc009, | |||||
0xc014, 0xc00a, 0x009c, 0x009d, 0x002f, 0x0035, 0xc012, 0x000a} | |||||
client := &http.Client{ | |||||
Transport: &http.Transport{ | |||||
TLSClientConfig: &tls.Config{ | |||||
InsecureSkipVerify: true, | |||||
CipherSuites: append(defaultCipherSuites[8:], defaultCipherSuites[:8]...), | |||||
}, | |||||
}, | |||||
// 获取301重定向 | |||||
CheckRedirect: func(req *http.Request, via []*http.Request) error { | |||||
return http.ErrUseLastResponse | |||||
}, | |||||
} | |||||
return client.Do(req) | |||||
} | |||||
// 组建get请求参数,sortAsc true为小到大,false为大到小,nil不排序 a=123&b=321 | |||||
func HttpBuildQuery(args map[string]string, sortAsc ...bool) string { | |||||
str := "" | |||||
if len(args) == 0 { | |||||
return str | |||||
} | |||||
if len(sortAsc) > 0 { | |||||
keys := make([]string, 0, len(args)) | |||||
for k := range args { | |||||
keys = append(keys, k) | |||||
} | |||||
if sortAsc[0] { | |||||
sort.Strings(keys) | |||||
} else { | |||||
sort.Sort(sort.Reverse(sort.StringSlice(keys))) | |||||
} | |||||
for _, k := range keys { | |||||
str += "&" + k + "=" + args[k] | |||||
} | |||||
} else { | |||||
for k, v := range args { | |||||
str += "&" + k + "=" + v | |||||
} | |||||
} | |||||
return str[1:] | |||||
} | |||||
func HttpBuild(body interface{}, sortAsc ...bool) string { | |||||
params := map[string]string{} | |||||
if args, ok := body.(map[string]interface{}); ok { | |||||
for k, v := range args { | |||||
params[k] = AnyToString(v) | |||||
} | |||||
return HttpBuildQuery(params, sortAsc...) | |||||
} | |||||
if args, ok := body.(map[string]string); ok { | |||||
for k, v := range args { | |||||
params[k] = AnyToString(v) | |||||
} | |||||
return HttpBuildQuery(params, sortAsc...) | |||||
} | |||||
if args, ok := body.(map[string]int); ok { | |||||
for k, v := range args { | |||||
params[k] = AnyToString(v) | |||||
} | |||||
return HttpBuildQuery(params, sortAsc...) | |||||
} | |||||
return AnyToString(body) | |||||
} |
@@ -0,0 +1,22 @@ | |||||
package zhios_order_relate_utils | |||||
import ( | |||||
"os" | |||||
"path" | |||||
"strings" | |||||
"time" | |||||
) | |||||
// 获取文件后缀 | |||||
func FileExt(fname string) string { | |||||
return strings.ToLower(strings.TrimLeft(path.Ext(fname), ".")) | |||||
} | |||||
func FilePutContents(fileName string, content string) { | |||||
fd, _ := os.OpenFile("./tmp/"+fileName+".logs", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644) | |||||
fd_time := time.Now().Format("2006-01-02 15:04:05") | |||||
fd_content := strings.Join([]string{"[", fd_time, "] ", content, "\n"}, "") | |||||
buf := []byte(fd_content) | |||||
fd.Write(buf) | |||||
fd.Close() | |||||
} |
@@ -0,0 +1,59 @@ | |||||
package zhios_order_relate_utils | |||||
import ( | |||||
"math" | |||||
) | |||||
func CouponFormat(data string) string { | |||||
switch data { | |||||
case "0.00", "0", "": | |||||
return "" | |||||
default: | |||||
return Int64ToStr(FloatToInt64(StrToFloat64(data))) | |||||
} | |||||
} | |||||
func CommissionFormat(data string) string { | |||||
if data != "" && data != "0" { | |||||
return data | |||||
} | |||||
return "" | |||||
} | |||||
func HideString(src string, hLen int) string { | |||||
str := []rune(src) | |||||
if hLen == 0 { | |||||
hLen = 4 | |||||
} | |||||
hideStr := "" | |||||
for i := 0; i < hLen; i++ { | |||||
hideStr += "*" | |||||
} | |||||
hideLen := len(str) / 2 | |||||
showLen := len(str) - hideLen | |||||
if hideLen == 0 || showLen == 0 { | |||||
return hideStr | |||||
} | |||||
subLen := showLen / 2 | |||||
if subLen == 0 { | |||||
return string(str[:showLen]) + hideStr | |||||
} | |||||
s := string(str[:subLen]) | |||||
s += hideStr | |||||
s += string(str[len(str)-subLen:]) | |||||
return s | |||||
} | |||||
//SaleCountFormat is 格式化销量 | |||||
func SaleCountFormat(s string) string { | |||||
return s + "已售" | |||||
} | |||||
// 小数格式化 | |||||
func FloatFormat(f float64, i int) float64 { | |||||
if i > 14 { | |||||
return f | |||||
} | |||||
p := math.Pow10(i) | |||||
return float64(int64((f+0.000000000000009)*p)) / p | |||||
} |
@@ -0,0 +1,245 @@ | |||||
package zhios_order_relate_logx | |||||
import ( | |||||
"os" | |||||
"strings" | |||||
"time" | |||||
"go.uber.org/zap" | |||||
"go.uber.org/zap/zapcore" | |||||
) | |||||
type LogConfig struct { | |||||
AppName string `yaml:"app_name" json:"app_name" toml:"app_name"` | |||||
Level string `yaml:"level" json:"level" toml:"level"` | |||||
StacktraceLevel string `yaml:"stacktrace_level" json:"stacktrace_level" toml:"stacktrace_level"` | |||||
IsStdOut bool `yaml:"is_stdout" json:"is_stdout" toml:"is_stdout"` | |||||
TimeFormat string `yaml:"time_format" json:"time_format" toml:"time_format"` // second, milli, nano, standard, iso, | |||||
Encoding string `yaml:"encoding" json:"encoding" toml:"encoding"` // console, json | |||||
Skip int `yaml:"skip" json:"skip" toml:"skip"` | |||||
IsFileOut bool `yaml:"is_file_out" json:"is_file_out" toml:"is_file_out"` | |||||
FileDir string `yaml:"file_dir" json:"file_dir" toml:"file_dir"` | |||||
FileName string `yaml:"file_name" json:"file_name" toml:"file_name"` | |||||
FileMaxSize int `yaml:"file_max_size" json:"file_max_size" toml:"file_max_size"` | |||||
FileMaxAge int `yaml:"file_max_age" json:"file_max_age" toml:"file_max_age"` | |||||
} | |||||
var ( | |||||
l *LogX = defaultLogger() | |||||
conf *LogConfig | |||||
) | |||||
// default logger setting | |||||
func defaultLogger() *LogX { | |||||
conf = &LogConfig{ | |||||
Level: "debug", | |||||
StacktraceLevel: "error", | |||||
IsStdOut: true, | |||||
TimeFormat: "standard", | |||||
Encoding: "console", | |||||
Skip: 2, | |||||
} | |||||
writers := []zapcore.WriteSyncer{os.Stdout} | |||||
lg, lv := newZapLogger(setLogLevel(conf.Level), setLogLevel(conf.StacktraceLevel), conf.Encoding, conf.TimeFormat, conf.Skip, zapcore.NewMultiWriteSyncer(writers...)) | |||||
zap.RedirectStdLog(lg) | |||||
return &LogX{logger: lg, atomLevel: lv} | |||||
} | |||||
// initial standard log, if you don't init, it will use default logger setting | |||||
func InitDefaultLogger(cfg *LogConfig) { | |||||
var writers []zapcore.WriteSyncer | |||||
if cfg.IsStdOut || (!cfg.IsStdOut && !cfg.IsFileOut) { | |||||
writers = append(writers, os.Stdout) | |||||
} | |||||
if cfg.IsFileOut { | |||||
writers = append(writers, NewRollingFile(cfg.FileDir, cfg.FileName, cfg.FileMaxSize, cfg.FileMaxAge)) | |||||
} | |||||
lg, lv := newZapLogger(setLogLevel(cfg.Level), setLogLevel(cfg.StacktraceLevel), cfg.Encoding, cfg.TimeFormat, cfg.Skip, zapcore.NewMultiWriteSyncer(writers...)) | |||||
zap.RedirectStdLog(lg) | |||||
if cfg.AppName != "" { | |||||
lg = lg.With(zap.String("app", cfg.AppName)) // 加上应用名称 | |||||
} | |||||
l = &LogX{logger: lg, atomLevel: lv} | |||||
} | |||||
// create a new logger | |||||
func NewLogger(cfg *LogConfig) *LogX { | |||||
var writers []zapcore.WriteSyncer | |||||
if cfg.IsStdOut || (!cfg.IsStdOut && !cfg.IsFileOut) { | |||||
writers = append(writers, os.Stdout) | |||||
} | |||||
if cfg.IsFileOut { | |||||
writers = append(writers, NewRollingFile(cfg.FileDir, cfg.FileName, cfg.FileMaxSize, cfg.FileMaxAge)) | |||||
} | |||||
lg, lv := newZapLogger(setLogLevel(cfg.Level), setLogLevel(cfg.StacktraceLevel), cfg.Encoding, cfg.TimeFormat, cfg.Skip, zapcore.NewMultiWriteSyncer(writers...)) | |||||
zap.RedirectStdLog(lg) | |||||
if cfg.AppName != "" { | |||||
lg = lg.With(zap.String("app", cfg.AppName)) // 加上应用名称 | |||||
} | |||||
return &LogX{logger: lg, atomLevel: lv} | |||||
} | |||||
// create a new zaplog logger | |||||
func newZapLogger(level, stacktrace zapcore.Level, encoding, timeType string, skip int, output zapcore.WriteSyncer) (*zap.Logger, *zap.AtomicLevel) { | |||||
encCfg := zapcore.EncoderConfig{ | |||||
TimeKey: "T", | |||||
LevelKey: "L", | |||||
NameKey: "N", | |||||
CallerKey: "C", | |||||
MessageKey: "M", | |||||
StacktraceKey: "S", | |||||
LineEnding: zapcore.DefaultLineEnding, | |||||
EncodeCaller: zapcore.ShortCallerEncoder, | |||||
EncodeDuration: zapcore.NanosDurationEncoder, | |||||
EncodeLevel: zapcore.LowercaseLevelEncoder, | |||||
} | |||||
setTimeFormat(timeType, &encCfg) // set time type | |||||
atmLvl := zap.NewAtomicLevel() // set level | |||||
atmLvl.SetLevel(level) | |||||
encoder := zapcore.NewJSONEncoder(encCfg) // 确定encoder格式 | |||||
if encoding == "console" { | |||||
encoder = zapcore.NewConsoleEncoder(encCfg) | |||||
} | |||||
return zap.New(zapcore.NewCore(encoder, output, atmLvl), zap.AddCaller(), zap.AddStacktrace(stacktrace), zap.AddCallerSkip(skip)), &atmLvl | |||||
} | |||||
// set log level | |||||
func setLogLevel(lvl string) zapcore.Level { | |||||
switch strings.ToLower(lvl) { | |||||
case "panic": | |||||
return zapcore.PanicLevel | |||||
case "fatal": | |||||
return zapcore.FatalLevel | |||||
case "error": | |||||
return zapcore.ErrorLevel | |||||
case "warn", "warning": | |||||
return zapcore.WarnLevel | |||||
case "info": | |||||
return zapcore.InfoLevel | |||||
default: | |||||
return zapcore.DebugLevel | |||||
} | |||||
} | |||||
// set time format | |||||
func setTimeFormat(timeType string, z *zapcore.EncoderConfig) { | |||||
switch strings.ToLower(timeType) { | |||||
case "iso": // iso8601 standard | |||||
z.EncodeTime = zapcore.ISO8601TimeEncoder | |||||
case "sec": // only for unix second, without millisecond | |||||
z.EncodeTime = func(t time.Time, enc zapcore.PrimitiveArrayEncoder) { | |||||
enc.AppendInt64(t.Unix()) | |||||
} | |||||
case "second": // unix second, with millisecond | |||||
z.EncodeTime = zapcore.EpochTimeEncoder | |||||
case "milli", "millisecond": // millisecond | |||||
z.EncodeTime = zapcore.EpochMillisTimeEncoder | |||||
case "nano", "nanosecond": // nanosecond | |||||
z.EncodeTime = zapcore.EpochNanosTimeEncoder | |||||
default: // standard format | |||||
z.EncodeTime = func(t time.Time, enc zapcore.PrimitiveArrayEncoder) { | |||||
enc.AppendString(t.Format("2006-01-02 15:04:05.000")) | |||||
} | |||||
} | |||||
} | |||||
func GetLevel() string { | |||||
switch l.atomLevel.Level() { | |||||
case zapcore.PanicLevel: | |||||
return "panic" | |||||
case zapcore.FatalLevel: | |||||
return "fatal" | |||||
case zapcore.ErrorLevel: | |||||
return "error" | |||||
case zapcore.WarnLevel: | |||||
return "warn" | |||||
case zapcore.InfoLevel: | |||||
return "info" | |||||
default: | |||||
return "debug" | |||||
} | |||||
} | |||||
func SetLevel(lvl string) { | |||||
l.atomLevel.SetLevel(setLogLevel(lvl)) | |||||
} | |||||
// temporary add call skip | |||||
func AddCallerSkip(skip int) *LogX { | |||||
l.logger.WithOptions(zap.AddCallerSkip(skip)) | |||||
return l | |||||
} | |||||
// permanent add call skip | |||||
func AddDepth(skip int) *LogX { | |||||
l.logger = l.logger.WithOptions(zap.AddCallerSkip(skip)) | |||||
return l | |||||
} | |||||
// permanent add options | |||||
func AddOptions(opts ...zap.Option) *LogX { | |||||
l.logger = l.logger.WithOptions(opts...) | |||||
return l | |||||
} | |||||
func AddField(k string, v interface{}) { | |||||
l.logger.With(zap.Any(k, v)) | |||||
} | |||||
func AddFields(fields map[string]interface{}) *LogX { | |||||
for k, v := range fields { | |||||
l.logger.With(zap.Any(k, v)) | |||||
} | |||||
return l | |||||
} | |||||
// Normal log | |||||
func Debug(e interface{}, args ...interface{}) error { | |||||
return l.Debug(e, args...) | |||||
} | |||||
func Info(e interface{}, args ...interface{}) error { | |||||
return l.Info(e, args...) | |||||
} | |||||
func Warn(e interface{}, args ...interface{}) error { | |||||
return l.Warn(e, args...) | |||||
} | |||||
func Error(e interface{}, args ...interface{}) error { | |||||
return l.Error(e, args...) | |||||
} | |||||
func Panic(e interface{}, args ...interface{}) error { | |||||
return l.Panic(e, args...) | |||||
} | |||||
func Fatal(e interface{}, args ...interface{}) error { | |||||
return l.Fatal(e, args...) | |||||
} | |||||
// Format logs | |||||
func Debugf(format string, args ...interface{}) error { | |||||
return l.Debugf(format, args...) | |||||
} | |||||
func Infof(format string, args ...interface{}) error { | |||||
return l.Infof(format, args...) | |||||
} | |||||
func Warnf(format string, args ...interface{}) error { | |||||
return l.Warnf(format, args...) | |||||
} | |||||
func Errorf(format string, args ...interface{}) error { | |||||
return l.Errorf(format, args...) | |||||
} | |||||
func Panicf(format string, args ...interface{}) error { | |||||
return l.Panicf(format, args...) | |||||
} | |||||
func Fatalf(format string, args ...interface{}) error { | |||||
return l.Fatalf(format, args...) | |||||
} | |||||
func formatFieldMap(m FieldMap) []Field { | |||||
var res []Field | |||||
for k, v := range m { | |||||
res = append(res, zap.Any(k, v)) | |||||
} | |||||
return res | |||||
} |
@@ -0,0 +1,105 @@ | |||||
package zhios_order_relate_logx | |||||
import ( | |||||
"bytes" | |||||
"io" | |||||
"os" | |||||
"path/filepath" | |||||
"time" | |||||
"gopkg.in/natefinch/lumberjack.v2" | |||||
) | |||||
// output interface | |||||
type WriteSyncer interface { | |||||
io.Writer | |||||
Sync() error | |||||
} | |||||
// split writer | |||||
func NewRollingFile(dir, filename string, maxSize, MaxAge int) WriteSyncer { | |||||
s, err := os.Stat(dir) | |||||
if err != nil || !s.IsDir() { | |||||
os.RemoveAll(dir) | |||||
if err := os.MkdirAll(dir, 0766); err != nil { | |||||
panic(err) | |||||
} | |||||
} | |||||
return newLumberjackWriteSyncer(&lumberjack.Logger{ | |||||
Filename: filepath.Join(dir, filename), | |||||
MaxSize: maxSize, // megabytes, MB | |||||
MaxAge: MaxAge, // days | |||||
LocalTime: true, | |||||
Compress: false, | |||||
}) | |||||
} | |||||
type lumberjackWriteSyncer struct { | |||||
*lumberjack.Logger | |||||
buf *bytes.Buffer | |||||
logChan chan []byte | |||||
closeChan chan interface{} | |||||
maxSize int | |||||
} | |||||
func newLumberjackWriteSyncer(l *lumberjack.Logger) *lumberjackWriteSyncer { | |||||
ws := &lumberjackWriteSyncer{ | |||||
Logger: l, | |||||
buf: bytes.NewBuffer([]byte{}), | |||||
logChan: make(chan []byte, 5000), | |||||
closeChan: make(chan interface{}), | |||||
maxSize: 1024, | |||||
} | |||||
go ws.run() | |||||
return ws | |||||
} | |||||
func (l *lumberjackWriteSyncer) run() { | |||||
ticker := time.NewTicker(1 * time.Second) | |||||
for { | |||||
select { | |||||
case <-ticker.C: | |||||
if l.buf.Len() > 0 { | |||||
l.sync() | |||||
} | |||||
case bs := <-l.logChan: | |||||
_, err := l.buf.Write(bs) | |||||
if err != nil { | |||||
continue | |||||
} | |||||
if l.buf.Len() > l.maxSize { | |||||
l.sync() | |||||
} | |||||
case <-l.closeChan: | |||||
l.sync() | |||||
return | |||||
} | |||||
} | |||||
} | |||||
func (l *lumberjackWriteSyncer) Stop() { | |||||
close(l.closeChan) | |||||
} | |||||
func (l *lumberjackWriteSyncer) Write(bs []byte) (int, error) { | |||||
b := make([]byte, len(bs)) | |||||
for i, c := range bs { | |||||
b[i] = c | |||||
} | |||||
l.logChan <- b | |||||
return 0, nil | |||||
} | |||||
func (l *lumberjackWriteSyncer) Sync() error { | |||||
return nil | |||||
} | |||||
func (l *lumberjackWriteSyncer) sync() error { | |||||
defer l.buf.Reset() | |||||
_, err := l.Logger.Write(l.buf.Bytes()) | |||||
if err != nil { | |||||
return err | |||||
} | |||||
return nil | |||||
} |
@@ -0,0 +1,192 @@ | |||||
package zhios_order_relate_logx | |||||
import ( | |||||
"errors" | |||||
"fmt" | |||||
"strconv" | |||||
"go.uber.org/zap" | |||||
) | |||||
type LogX struct { | |||||
logger *zap.Logger | |||||
atomLevel *zap.AtomicLevel | |||||
} | |||||
type Field = zap.Field | |||||
type FieldMap map[string]interface{} | |||||
// 判断其他类型--start | |||||
func getFields(msg string, format bool, args ...interface{}) (string, []Field) { | |||||
var str []interface{} | |||||
var fields []zap.Field | |||||
if len(args) > 0 { | |||||
for _, v := range args { | |||||
if f, ok := v.(Field); ok { | |||||
fields = append(fields, f) | |||||
} else if f, ok := v.(FieldMap); ok { | |||||
fields = append(fields, formatFieldMap(f)...) | |||||
} else { | |||||
str = append(str, AnyToString(v)) | |||||
} | |||||
} | |||||
if format { | |||||
return fmt.Sprintf(msg, str...), fields | |||||
} | |||||
str = append([]interface{}{msg}, str...) | |||||
return fmt.Sprintln(str...), fields | |||||
} | |||||
return msg, []Field{} | |||||
} | |||||
func (l *LogX) Debug(s interface{}, args ...interface{}) error { | |||||
es, e := checkErr(s) | |||||
if es != "" { | |||||
msg, field := getFields(es, false, args...) | |||||
l.logger.Debug(msg, field...) | |||||
} | |||||
return e | |||||
} | |||||
func (l *LogX) Info(s interface{}, args ...interface{}) error { | |||||
es, e := checkErr(s) | |||||
if es != "" { | |||||
msg, field := getFields(es, false, args...) | |||||
l.logger.Info(msg, field...) | |||||
} | |||||
return e | |||||
} | |||||
func (l *LogX) Warn(s interface{}, args ...interface{}) error { | |||||
es, e := checkErr(s) | |||||
if es != "" { | |||||
msg, field := getFields(es, false, args...) | |||||
l.logger.Warn(msg, field...) | |||||
} | |||||
return e | |||||
} | |||||
func (l *LogX) Error(s interface{}, args ...interface{}) error { | |||||
es, e := checkErr(s) | |||||
if es != "" { | |||||
msg, field := getFields(es, false, args...) | |||||
l.logger.Error(msg, field...) | |||||
} | |||||
return e | |||||
} | |||||
func (l *LogX) DPanic(s interface{}, args ...interface{}) error { | |||||
es, e := checkErr(s) | |||||
if es != "" { | |||||
msg, field := getFields(es, false, args...) | |||||
l.logger.DPanic(msg, field...) | |||||
} | |||||
return e | |||||
} | |||||
func (l *LogX) Panic(s interface{}, args ...interface{}) error { | |||||
es, e := checkErr(s) | |||||
if es != "" { | |||||
msg, field := getFields(es, false, args...) | |||||
l.logger.Panic(msg, field...) | |||||
} | |||||
return e | |||||
} | |||||
func (l *LogX) Fatal(s interface{}, args ...interface{}) error { | |||||
es, e := checkErr(s) | |||||
if es != "" { | |||||
msg, field := getFields(es, false, args...) | |||||
l.logger.Fatal(msg, field...) | |||||
} | |||||
return e | |||||
} | |||||
func checkErr(s interface{}) (string, error) { | |||||
switch e := s.(type) { | |||||
case error: | |||||
return e.Error(), e | |||||
case string: | |||||
return e, errors.New(e) | |||||
case []byte: | |||||
return string(e), nil | |||||
default: | |||||
return "", nil | |||||
} | |||||
} | |||||
func (l *LogX) LogError(err error) error { | |||||
return l.Error(err.Error()) | |||||
} | |||||
func (l *LogX) Debugf(msg string, args ...interface{}) error { | |||||
s, f := getFields(msg, true, args...) | |||||
l.logger.Debug(s, f...) | |||||
return errors.New(s) | |||||
} | |||||
func (l *LogX) Infof(msg string, args ...interface{}) error { | |||||
s, f := getFields(msg, true, args...) | |||||
l.logger.Info(s, f...) | |||||
return errors.New(s) | |||||
} | |||||
func (l *LogX) Warnf(msg string, args ...interface{}) error { | |||||
s, f := getFields(msg, true, args...) | |||||
l.logger.Warn(s, f...) | |||||
return errors.New(s) | |||||
} | |||||
func (l *LogX) Errorf(msg string, args ...interface{}) error { | |||||
s, f := getFields(msg, true, args...) | |||||
l.logger.Error(s, f...) | |||||
return errors.New(s) | |||||
} | |||||
func (l *LogX) DPanicf(msg string, args ...interface{}) error { | |||||
s, f := getFields(msg, true, args...) | |||||
l.logger.DPanic(s, f...) | |||||
return errors.New(s) | |||||
} | |||||
func (l *LogX) Panicf(msg string, args ...interface{}) error { | |||||
s, f := getFields(msg, true, args...) | |||||
l.logger.Panic(s, f...) | |||||
return errors.New(s) | |||||
} | |||||
func (l *LogX) Fatalf(msg string, args ...interface{}) error { | |||||
s, f := getFields(msg, true, args...) | |||||
l.logger.Fatal(s, f...) | |||||
return errors.New(s) | |||||
} | |||||
func AnyToString(raw interface{}) string { | |||||
switch i := raw.(type) { | |||||
case []byte: | |||||
return string(i) | |||||
case int: | |||||
return strconv.FormatInt(int64(i), 10) | |||||
case int64: | |||||
return strconv.FormatInt(i, 10) | |||||
case float32: | |||||
return strconv.FormatFloat(float64(i), 'f', 2, 64) | |||||
case float64: | |||||
return strconv.FormatFloat(i, 'f', 2, 64) | |||||
case uint: | |||||
return strconv.FormatInt(int64(i), 10) | |||||
case uint8: | |||||
return strconv.FormatInt(int64(i), 10) | |||||
case uint16: | |||||
return strconv.FormatInt(int64(i), 10) | |||||
case uint32: | |||||
return strconv.FormatInt(int64(i), 10) | |||||
case uint64: | |||||
return strconv.FormatInt(int64(i), 10) | |||||
case int8: | |||||
return strconv.FormatInt(int64(i), 10) | |||||
case int16: | |||||
return strconv.FormatInt(int64(i), 10) | |||||
case int32: | |||||
return strconv.FormatInt(int64(i), 10) | |||||
case string: | |||||
return i | |||||
case error: | |||||
return i.Error() | |||||
} | |||||
return fmt.Sprintf("%#v", raw) | |||||
} |
@@ -0,0 +1,23 @@ | |||||
package zhios_order_relate_utils | |||||
import ( | |||||
"encoding/json" | |||||
) | |||||
func Serialize(data interface{}) []byte { | |||||
res, err := json.Marshal(data) | |||||
if err != nil { | |||||
return []byte{} | |||||
} | |||||
return res | |||||
} | |||||
func Unserialize(b []byte, dst interface{}) { | |||||
if err := json.Unmarshal(b, dst); err != nil { | |||||
dst = nil | |||||
} | |||||
} | |||||
func SerializeStr(data interface{}, arg ...interface{}) string { | |||||
return string(Serialize(data)) | |||||
} |
@@ -0,0 +1,203 @@ | |||||
package zhios_order_relate_utils | |||||
import ( | |||||
"fmt" | |||||
"github.com/syyongx/php2go" | |||||
"math/rand" | |||||
"reflect" | |||||
"sort" | |||||
"strings" | |||||
"time" | |||||
) | |||||
func Implode(glue string, args ...interface{}) string { | |||||
data := make([]string, len(args)) | |||||
for i, s := range args { | |||||
data[i] = fmt.Sprint(s) | |||||
} | |||||
return strings.Join(data, glue) | |||||
} | |||||
//字符串是否在数组里 | |||||
func InArr(target string, str_array []string) bool { | |||||
for _, element := range str_array { | |||||
if target == element { | |||||
return true | |||||
} | |||||
} | |||||
return false | |||||
} | |||||
func InArrToInt(target int, str_array []int) bool { | |||||
for _, element := range str_array { | |||||
if target == element { | |||||
return true | |||||
} | |||||
} | |||||
return false | |||||
} | |||||
//把数组的值放到key里 | |||||
func ArrayColumn(array interface{}, key string) (result map[string]interface{}, err error) { | |||||
result = make(map[string]interface{}) | |||||
t := reflect.TypeOf(array) | |||||
v := reflect.ValueOf(array) | |||||
if t.Kind() != reflect.Slice { | |||||
return nil, nil | |||||
} | |||||
if v.Len() == 0 { | |||||
return nil, nil | |||||
} | |||||
for i := 0; i < v.Len(); i++ { | |||||
indexv := v.Index(i) | |||||
if indexv.Type().Kind() != reflect.Struct { | |||||
return nil, nil | |||||
} | |||||
mapKeyInterface := indexv.FieldByName(key) | |||||
if mapKeyInterface.Kind() == reflect.Invalid { | |||||
return nil, nil | |||||
} | |||||
mapKeyString, err := InterfaceToString(mapKeyInterface.Interface()) | |||||
if err != nil { | |||||
return nil, err | |||||
} | |||||
result[mapKeyString] = indexv.Interface() | |||||
} | |||||
return result, err | |||||
} | |||||
//转string | |||||
func InterfaceToString(v interface{}) (result string, err error) { | |||||
switch reflect.TypeOf(v).Kind() { | |||||
case reflect.Int64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32: | |||||
result = fmt.Sprintf("%v", v) | |||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | |||||
result = fmt.Sprintf("%v", v) | |||||
case reflect.String: | |||||
result = v.(string) | |||||
default: | |||||
err = nil | |||||
} | |||||
return result, err | |||||
} | |||||
func HideTrueName(name string) string { | |||||
res := "**" | |||||
if name != "" { | |||||
runs := []rune(name) | |||||
leng := len(runs) | |||||
if leng <= 3 { | |||||
res = string(runs[0:1]) + res | |||||
} else if leng < 5 { | |||||
res = string(runs[0:2]) + res | |||||
} else if leng < 10 { | |||||
res = string(runs[0:2]) + "***" + string(runs[leng-2:leng]) | |||||
} else if leng < 16 { | |||||
res = string(runs[0:3]) + "****" + string(runs[leng-3:leng]) | |||||
} else { | |||||
res = string(runs[0:4]) + "*****" + string(runs[leng-4:leng]) | |||||
} | |||||
} | |||||
return res | |||||
} | |||||
func GetQueryParam(uri string) map[string]string { | |||||
//根据问号分割路由还是query参数 | |||||
uriList := strings.Split(uri, "?") | |||||
var query = make(map[string]string, 0) | |||||
//有参数才处理 | |||||
if len(uriList) == 2 { | |||||
//分割query参数 | |||||
var queryList = strings.Split(uriList[1], "&") | |||||
if len(queryList) > 0 { | |||||
//key value 分别赋值 | |||||
for _, v := range queryList { | |||||
var valueList = strings.Split(v, "=") | |||||
if len(valueList) == 2 { | |||||
value, _ := php2go.URLDecode(valueList[1]) | |||||
if value == "" { | |||||
value = valueList[1] | |||||
} | |||||
query[valueList[0]] = value | |||||
} | |||||
} | |||||
} | |||||
} | |||||
return query | |||||
} | |||||
//JoinStringsInASCII 按照规则,参数名ASCII码从小到大排序后拼接 | |||||
//data 待拼接的数据 | |||||
//sep 连接符 | |||||
//onlyValues 是否只包含参数值,true则不包含参数名,否则参数名和参数值均有 | |||||
//includeEmpty 是否包含空值,true则包含空值,否则不包含,注意此参数不影响参数名的存在 | |||||
//exceptKeys 被排除的参数名,不参与排序及拼接 | |||||
func JoinStringsInASCII(data map[string]string, sep string, onlyValues, includeEmpty bool, exceptKeys ...string) string { | |||||
var list []string | |||||
var keyList []string | |||||
m := make(map[string]int) | |||||
if len(exceptKeys) > 0 { | |||||
for _, except := range exceptKeys { | |||||
m[except] = 1 | |||||
} | |||||
} | |||||
for k := range data { | |||||
if _, ok := m[k]; ok { | |||||
continue | |||||
} | |||||
value := data[k] | |||||
if !includeEmpty && value == "" { | |||||
continue | |||||
} | |||||
if onlyValues { | |||||
keyList = append(keyList, k) | |||||
} else { | |||||
list = append(list, fmt.Sprintf("%s=%s", k, value)) | |||||
} | |||||
} | |||||
if onlyValues { | |||||
sort.Strings(keyList) | |||||
for _, v := range keyList { | |||||
list = append(list, AnyToString(data[v])) | |||||
} | |||||
} else { | |||||
sort.Strings(list) | |||||
} | |||||
return strings.Join(list, sep) | |||||
} | |||||
//x的y次方 | |||||
func RandPow(l int) string { | |||||
var i = "1" | |||||
for j := 0; j < l; j++ { | |||||
i += "0" | |||||
} | |||||
k := StrToInt64(i) | |||||
n := rand.New(rand.NewSource(time.Now().UnixNano())).Int63n(k) | |||||
ls := "%0" + IntToStr(l) + "v" | |||||
str := fmt.Sprintf(ls, n) | |||||
//min := int(math.Pow10(l - 1)) | |||||
//max := int(math.Pow10(l) - 1) | |||||
return str | |||||
} | |||||
//根据显示长度截取字符串 | |||||
func ShowSubstr(s string, l int) string { | |||||
if len(s) <= l { | |||||
return s | |||||
} | |||||
ss, sl, rl, rs := "", 0, 0, []rune(s) | |||||
for _, r := range rs { | |||||
rint := int(r) | |||||
if rint < 128 { | |||||
rl = 1 | |||||
} else { | |||||
rl = 2 | |||||
} | |||||
if sl+rl > l { | |||||
break | |||||
} | |||||
sl += rl | |||||
ss += string(r) | |||||
} | |||||
return ss | |||||
} |