Create & Init Project...

This commit is contained in:
2019-04-22 18:49:16 +08:00
commit fc4fa37393
25440 changed files with 4054998 additions and 0 deletions

View File

@@ -0,0 +1,89 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
load(
"@io_bazel_rules_go//proto:def.bzl",
"go_proto_library",
)
proto_library(
name = "model_proto",
srcs = ["member.proto"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = ["@gogo_special_proto//github.com/gogo/protobuf/gogoproto"],
)
go_proto_library(
name = "model_go_proto",
compilers = ["@io_bazel_rules_go//proto:gogofast_proto"],
importpath = "go-common/app/job/main/member/model",
proto = ":model_proto",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/time:go_default_library",
"@com_github_gogo_protobuf//gogoproto:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = ["model_test.go"],
embed = [
":go_default_library",
],
rundir = ".",
tags = ["automanaged"],
deps = [
"//library/time:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"base.go",
"model.go",
"moral.go",
"notify.go",
"official.go",
"old_account.go",
"realname.go",
],
embed = [":model_go_proto"],
importpath = "go-common/app/job/main/member/model",
tags = ["automanaged"],
deps = [
"//app/job/main/member/conf:go_default_library",
"//library/log:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
"//vendor/github.com/satori/go.uuid:go_default_library",
"@com_github_gogo_protobuf//gogoproto:go_default_library",
"@com_github_gogo_protobuf//proto:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/job/main/member/model/block:all-srcs",
"//app/job/main/member/model/queue:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,30 @@
package model
import (
"fmt"
"math/rand"
)
const (
//CacheKeyBase is.
CacheKeyBase = "bs_%d" // key of baseInfo
//CacheKeyMoral is.
CacheKeyMoral = "moral_%d" // key of detail
//CacheKeyInfo is.
CacheKeyInfo = "i_"
//URLNoFace is.
URLNoFace = "http://static.hdslb.com/images/member/noface.gif"
//TableExpLog is.
TableExpLog = "ugc:ExpLog"
//TableMoralLog is.
TableMoralLog = "ugc:MoralLog"
)
// RandFaceURL get face URL
func (b *BaseInfo) RandFaceURL() {
if b.Face == "" {
b.Face = URLNoFace
return
}
b.Face = fmt.Sprintf("http://i%d.hdslb.com%s", rand.Int63n(3), b.Face)
}

View File

@@ -0,0 +1,34 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"blackhouse.go",
"dao.go",
"model.go",
"msg.go",
"notify.go",
],
importpath = "go-common/app/job/main/member/model/block",
tags = ["automanaged"],
deps = ["//library/time:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,11 @@
package block
import (
xtime "go-common/library/time"
)
// CreditAnswerMSG param struct
type CreditAnswerMSG struct {
MID int64 `json:"mid"`
MTime xtime.Time `json:"mtime"`
}

View File

@@ -0,0 +1,57 @@
package block
import (
"time"
)
// DBUser .
type DBUser struct {
ID int64
MID int64
Status BlockStatus
CTime time.Time
MTime time.Time
}
// DBUserDetail .
type DBUserDetail struct {
ID int64
MID int64
BlockCount int
CTime time.Time
MTime time.Time
}
// DBHistory .
type DBHistory struct {
ID int64
MID int64
AdminID int64
AdminName string
Source BlockSource
Area BlockArea
Reason string
Comment string
Action BlockAction
StartTime time.Time
Duration int64
Notify bool
CTime time.Time
MTime time.Time
}
// DBExtra .
type DBExtra struct {
ID int64
MID int64
CreditAnswerFlag bool
ActionTime time.Time
CTime time.Time
MTime time.Time
}
// MCBlockInfo .
type MCBlockInfo struct {
// BlockStatus is.
BlockStatus BlockStatus `json:"bs"`
}

View File

@@ -0,0 +1,184 @@
package block
import (
"time"
)
// BlockStatus 封禁状态 0. 未封禁 1. 永久封禁 2. 限时封禁
type BlockStatus uint8
const (
// BlockStatusFalse 未封禁
BlockStatusFalse BlockStatus = iota
// BlockStatusForever 永久封禁
BlockStatusForever
// BlockStatusLimit 限时封禁
BlockStatusLimit
// BlockStatusCredit 小黑屋封禁
BlockStatusCredit
)
// BlockSource 封禁来源 1. 小黑屋(小黑屋和manager后台封禁) 2. 系统封禁(反作弊及监控系统上报) 3.解封 (所有后台,用户前台自助的解封)
type BlockSource uint8
const (
// BlockSourceCredit 小黑屋封禁
BlockSourceCredit BlockSource = iota + 1
// BlockSourceSys 系统封禁
BlockSourceSys
// BlockSourceRemove 解封
BlockSourceRemove
)
// String .
func (b BlockSource) String() string {
switch b {
case BlockSourceCredit:
return "小黑屋封禁"
case BlockSourceSys:
return "系统封禁"
case BlockSourceRemove:
return "解封"
default:
return ""
}
}
const (
// BlockLogBizID 用户审核日志
BlockLogBizID = 122
// BlockJOBManagerID blockjob manager uid
BlockJOBManagerID = 1493
// BlockJOBManagerName blockjob manager name
BlockJOBManagerName = "blockjob"
)
// BlockArea 封禁业务
type BlockArea uint8
// const .
const (
BlockAreaNone BlockArea = iota
BlockAreaReply
BlockAreaDanmaku
BlockAreaMessage
BlockAreaTag
BlockAreaProfile // 个人资料
BlockAreaArchive
BlockAreaMusic
BlockAreaArticle
BlockAreaSpaceBanner // 空间头图
BlockAreaDynamic // 动态
BlockAreaAlbum // 相册
BlockAreaQuickVideo //小视频
)
// String .
func (b BlockArea) String() string {
switch b {
case BlockAreaReply:
return "评论"
case BlockAreaDanmaku:
return "弹幕"
case BlockAreaMessage:
return "私信"
case BlockAreaTag:
return "标签"
case BlockAreaProfile:
return "个人资料"
case BlockAreaArchive:
return "投稿"
case BlockAreaMusic:
return "音频"
case BlockAreaArticle:
return "专栏"
case BlockAreaSpaceBanner:
return "空间头图"
case BlockAreaDynamic:
return "动态"
case BlockAreaAlbum:
return "相册"
case BlockAreaQuickVideo:
return "小视频"
default:
return ""
}
}
// BlockAction .
type BlockAction uint8
const (
// BlockActionLimit 限时封禁
BlockActionLimit BlockAction = iota + 1
// BlockActionForever 永久封禁
BlockActionForever
// BlockActionAdminRemove 后台解封
BlockActionAdminRemove
// BlockActionSelfRemove 自助解封
BlockActionSelfRemove
)
// String .
func (b BlockAction) String() string {
switch b {
case BlockActionLimit:
return "限时封禁"
case BlockActionForever:
return "永久封禁"
case BlockActionAdminRemove:
return "后台解封"
case BlockActionSelfRemove:
return "自动解封"
default:
return ""
}
}
// BlockInfo 封禁信息
type BlockInfo struct {
MID int64 `json:"mid"`
BlockStatus BlockStatus `json:"block_status"` // blockStatus 封禁状态 0. 未封禁 1. 永久封禁 2. 限时封禁
// EndTime int64 `json:"end_time"` // 结束封禁时间 unix time 永久封禁为0
}
// ParseDB .
func (b *BlockInfo) ParseDB(data *DBUser) {
b.MID = data.MID
b.BlockStatus = data.Status
}
// ParseMC .
func (b *BlockInfo) ParseMC(data *MCBlockInfo, mid int64) {
b.MID = mid
b.BlockStatus = data.BlockStatus
}
// BlockHistory 封禁历史
type BlockHistory struct {
Area BlockArea `json:"type"`
Operator string `json:"operator"` // 操作人
Reason string `json:"reason"` // 封禁原因
Action BlockAction `json:"action"` // 操作类型
ActionTime int64 `json:"action_time"` // 操作时间
RemoveTime int64 `json:"remove_time"` // 解封时间
Comment string `json:"comment"`
}
// ParseDB .
func (b *BlockHistory) ParseDB(data *DBHistory) {
b.Area = data.Area
b.Operator = data.AdminName
b.Reason = data.Reason
b.Action = data.Action
b.ActionTime = data.StartTime.Unix()
b.RemoveTime = data.StartTime.Add(time.Second * time.Duration(data.Duration)).Unix()
b.Comment = data.Comment
}
// BlockMessage 通知消息体
type BlockMessage struct {
MID int64 `json:"mid"` // 用户mid
Area BlockArea `json:"area"` // BlockArea 封禁类型 1. 小黑屋(小黑屋和manager后台封禁) 2. 系统封禁(反作弊及监控系统上报) 3.解封 (所有后台,用户前台自助的解封)
Status BlockStatus `json:"status"` // blockStatus 封禁状态 0. 未封禁 1. 永久封禁 2. 限时封禁
}

View File

@@ -0,0 +1,8 @@
package block
// MSG .
type MSG struct {
Code string
Title string
Content string
}

View File

@@ -0,0 +1,8 @@
package block
// AccountNotify .
type AccountNotify struct {
UID int64 `json:"mid"`
Type string `json:"type"`
Action string `json:"action"`
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,50 @@
syntax = "proto3";
package model;
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
message LevelInfo {
int32 Cur = 1 [(gogoproto.jsontag) = "current_level"];
int32 Min = 2 [(gogoproto.jsontag) = "current_min"];
int32 NowExp = 3 [(gogoproto.jsontag) = "current_exp,omitempty"];
int32 NextExp = 4 [(gogoproto.jsontag) = "next_exp"];
}
message PendantInfo {
int32 Pid = 1 [(gogoproto.jsontag) = "pid",(gogoproto.casttype) = "int"];
string Name = 2 [(gogoproto.jsontag) = "name"];
string Image = 3 [(gogoproto.jsontag) = "image"];
int64 Expire = 4 [(gogoproto.jsontag) = "expire",(gogoproto.casttype) = "int"];
}
message NameplateInfo {
int32 Nid = 1 [(gogoproto.jsontag) = "nid",(gogoproto.casttype) = "int"];
string Name = 2 [(gogoproto.jsontag) = "name"];
string Image = 3 [(gogoproto.jsontag) = "image"];
string ImageSmall = 4 [(gogoproto.jsontag) = "image_small"];
string Level = 5 [(gogoproto.jsontag) = "level"];
string Condition = 6 [(gogoproto.jsontag) = "condition"];
}
message OfficialInfo {
int32 Type = 7 [(gogoproto.jsontag) = "type",(gogoproto.casttype) = "int8"];
string Desc = 8 [(gogoproto.jsontag) = "desc"];
}
message BaseInfo {
int64 Mid = 1 [(gogoproto.jsontag) = "mid"];
string Name = 2 [(gogoproto.jsontag) = "name"];
int64 Sex = 3 [(gogoproto.jsontag) = "sex"];
string Face = 4 [(gogoproto.jsontag) = "face"];
string Sign = 5 [(gogoproto.jsontag) = "sign"];
int64 Rank = 8 [(gogoproto.jsontag) = "rank"];
int64 Birthday = 9 [(gogoproto.jsontag) = "birthday", (gogoproto.casttype) = "go-common/library/time.Time"];
int64 CTime = 10 [(gogoproto.jsontag) = "ctime", (gogoproto.casttype) = "go-common/library/time.Time"];
int64 MTime = 11 [(gogoproto.jsontag) = "mtime", (gogoproto.casttype) = "go-common/library/time.Time"];
}
message Detail {
int64 Mid = 1 [(gogoproto.jsontag) = "mid"];
int64 Birthday = 2 [(gogoproto.jsontag) = "birthday", (gogoproto.casttype) = "go-common/library/time.Time"];
int64 Place = 3 [(gogoproto.jsontag) = "place"];
int64 Marital = 4 [(gogoproto.jsontag) = "marital"];
int64 Dating = 5 [(gogoproto.jsontag) = "dating"];
string Tags = 6 [(gogoproto.jsontag) = "tags"];
int64 CTime = 7 [(gogoproto.jsontag) = "ctime", (gogoproto.casttype) = "go-common/library/time.Time"];
int64 MTime = 8 [(gogoproto.jsontag) = "mtime", (gogoproto.casttype) = "go-common/library/time.Time"];
}

View File

@@ -0,0 +1,200 @@
package model
import (
"encoding/json"
"fmt"
"time"
xtime "go-common/library/time"
"github.com/satori/go.uuid"
)
const (
// FlagNo 否
FlagNo = int32(0)
// FlagYes 是
FlagYes = int32(1)
// ExpFlagOnLogin 每日登录经验
ExpFlagOnLogin = int32(1)
// ExpFlagOnShare 每日分享经验
ExpFlagOnShare = int32(2)
// ExpFlagOnView 每日播放经验
ExpFlagOnView = int32(4)
// ExpFlagOnEmail 一次性绑定邮箱
ExpFlagOnEmail = int32(8)
// ExpFlagOnPhone 一次性绑定手机
ExpFlagOnPhone = int32(16)
// ExpFlagOnSafe 一次性绑定密保
ExpFlagOnSafe = int32(32)
// ExpFlagOnIdentify 一次性实名认证
ExpFlagOnIdentify = int32(64)
// ExpActOnCoin 投币奖励动作
ExpActOnCoin = int64(1)
// ExpActOnLogin 登录奖励动作
ExpActOnLogin = int64(2)
// ExpActOnView 播放奖励动作
ExpActOnView = int64(3)
// ExpActOnShare 分享奖励动作
ExpActOnShare = int64(4)
// ExpActOnEmail 绑定邮箱动作
ExpActOnEmail = int64(5)
// ExpActOnPhone 绑定手机动作
ExpActOnPhone = int64(6)
// ExpActOnSafe 绑定密保动作
ExpActOnSafe = int64(7)
// ExpActOnIdentify 实名认证动作
ExpActOnIdentify = int64(8)
)
var (
login = &ExpOper{ExpFlagOnLogin, 5, "login", "登录奖励"}
share = &ExpOper{ExpFlagOnShare, 5, "shareClick", "分享视频奖励"}
view = &ExpOper{ExpFlagOnView, 5, "watch", "观看视频奖励"}
email = &ExpOper{ExpFlagOnEmail, 20, "bindEmail", "绑定邮箱奖励"}
safe = &ExpOper{ExpFlagOnSafe, 30, "pwdPro", "设置密保奖励"}
phone = &ExpOper{ExpFlagOnPhone, 100, "bindPhone", "绑定手机奖励"}
identify = &ExpOper{ExpFlagOnIdentify, 50, "realIdentity", "实名认证奖励"}
// ExpFlagOper exp flag map for oper
ExpFlagOper = map[string]*ExpOper{"login": login, "share": share, "view": view, "email": email, "phone": phone, "safe": safe, "identify": identify}
)
// Exp userexp for mysql scan.
type Exp struct {
Mid int64 `json:"mid"`
Exp float32 `json:"exp"`
Mtime xtime.Time `json:"modify_time"`
}
// ExpLog user exp log for mysql
type ExpLog struct {
Mid int64 `json:"mid"`
FromExp float32 `json:"from_exp"`
ToExp float32 `json:"to_exp"`
Operater string `json:"operater"`
Reason string `json:"reason"`
Action int64 `json:"actin_id"`
Mtime xtime.Time `json:"modify_time"`
}
// NewExp userexp for mysql scan.
type NewExp struct {
Mid int64 `json:"mid"`
Exp int64 `json:"exp"`
Flag int32 `json:"flag"`
Addtime xtime.Time `json:"addtime"`
Mtime xtime.Time `json:"mtime"`
}
// ExpOper exp operation
type ExpOper struct {
Flag int32
Count int64
Oper string
Reason string
}
// Message binlog databus msg.
type Message struct {
Action string `json:"action"`
Table string `json:"table"`
New json.RawMessage `json:"new"`
Old json.RawMessage `json:"old"`
}
//Flag is.
type Flag struct {
Mid int64 `json:"mid,omitempty"`
Flag int64 `json:"finish_action"`
Exp int64 `json:"modify_exp"`
}
// UserLog user log.
type UserLog struct {
Mid int64 `json:"mid"`
IP string `json:"ip"`
TS int64 `json:"ts"`
LogID string `json:"log_id"`
Content map[string]string `json:"content"`
}
// AddExp databus add exp arg.
type AddExp struct {
Event string `json:"event,omitempty"`
Mid int64 `json:"mid,omitempty"`
IP string `json:"ip,omitempty"`
Ts int64 `json:"ts,omitempty"`
}
// LoginLog user login log.
type LoginLog struct {
Mid int64 `json:"mid,omitempty"`
Loginip int64 `json:"loginip,omitempty"`
Timestamp int64 `json:"timestamp,omitempty"`
}
// LoginLogIPString user login log message with string ip.
type LoginLogIPString struct {
Mid int64 `json:"mid,omitempty"`
Loginip string `json:"loginip,omitempty"`
Timestamp int64 `json:"timestamp,omitempty"`
}
// FaceCheckRes face check result.
type FaceCheckRes struct {
FileName string `json:"file_name,omitempty"`
Bucket string `json:"bucket,omitempty"`
Sex float64 `json:"sex,omitempty"`
Politics float64 `json:"politics,omitempty"`
}
// FacePath is
func (fcr *FaceCheckRes) FacePath() string {
return fmt.Sprintf("/bfs/%s/%s", fcr.Bucket, fcr.FileName)
}
//String is.
func (fcr *FaceCheckRes) String() string {
return fmt.Sprintf("Sex: %.4f, Politics: %.4f", fcr.Sex, fcr.Politics)
}
// MemberMid member mid
type MemberMid struct {
Mid int64 `json:"mid"`
}
// MemberAso member aso
type MemberAso struct {
Email string `json:"email"`
Telphone string `json:"telphone"`
SafeQs int8 `json:"safe_question"`
Spacesta int8 `json:"spacesta"`
}
// ExpMessage exp msg
type ExpMessage struct {
Mid int64 `json:"mid"`
Exp int64 `json:"exp"`
}
// FlagDailyReset reset daily flag with ts.
func (e *NewExp) FlagDailyReset(now time.Time) {
e.Flag = e.Flag & ^0x7
e.Addtime = RestrictDate(xtime.Time(now.Unix()))
}
// RestrictDate restric user brithday
func RestrictDate(xt xtime.Time) xtime.Time {
t := xt.Time()
year := t.Year()
if year < 0 {
year = 0
}
return xtime.Time(time.Date(year, t.Month(), t.Day(), 0, 0, 0, 0, t.Location()).Unix())
}
// UUID4 is generate uuid
func UUID4() string {
return uuid.NewV4().String()
}

View File

@@ -0,0 +1,42 @@
package model
import (
xtime "go-common/library/time"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestRestrictDate(t *testing.T) {
xt1 := xtime.Time(-62169580800)
t1 := xt1.Time()
assert.True(t, t1.Year() < 0)
xt2 := RestrictDate(xt1)
t2 := xt2.Time()
assert.Equal(t, 0, t2.Year())
assert.Equal(t, t1.Month(), t2.Month())
assert.Equal(t, t1.Day(), t2.Day())
}
func TestRealname(t *testing.T) {
realnameIMG := RealnameApplyImgMessage{
AddTimeStr: "2018-05-11 15:07:00",
AddTimeDB: time.Now(),
}
t.Log("addtime", realnameIMG.AddTime().Local())
realnameApply := RealnameApplyMessage{
CardDataCanal: "dGMyNUhTcXN1NS9MYkF1bGdoKzNkTGs0eHI5UlM4SS9NY2VQa25xV3czU2grY1Q3R0JiSjlaQWhPZ294TTlEQVV0ZFhuYzIrUnlXTVN3NWk5THFWdkpmTEJaYXJhSlFHWUQ3bVlWZ3liNU1IS1hQTXZ0RE9pR1d6UnpYcUtRUEFYTHZCcXIzZVFoVURwT3VieXJzV0c1Z0dJS2dQNEdYbUV0T1B3MXV6bEE4PQ==",
}
t.Log("card data", realnameApply.CardData())
var (
card = "340702199110120012"
)
md5 := cardMD5(card, 0, 0)
t.Log("card md5", md5)
}

View File

@@ -0,0 +1,19 @@
package model
import (
"go-common/library/time"
)
//MoralLog is.
type MoralLog struct {
Mid int64 `json:"mid"`
IP int64 `json:"ip"`
Operater string `json:"operater"`
Origin int8 `json:"origin"`
Reason string `json:"reason"`
Remark string `json:"remark"`
Status int8 `json:"status"`
FromMoral int64 `json:"from_moral"`
ToMoral int64 `json:"to_moral"`
ModifyTime time.Time `json:"modify_time"`
}

View File

@@ -0,0 +1,19 @@
package model
// consts
const (
ActUpdateExp = "updateExp"
ActUpdateLevel = "updateLevel"
ActUpdateFace = "updateFace"
ActUpdateMoral = "updateMoral"
ActUpdateUname = "updateUname"
)
// NotifyInfo notify info.
type NotifyInfo struct {
Uname string `json:"uname"`
Mid int64 `json:"mid"`
Type string `json:"type"`
NewName string `json:"newName"`
Action string `json:"action"`
}

View File

@@ -0,0 +1,37 @@
package model
// official role const.
const (
OfficialRoleUnauth = iota
OfficialRoleUp
OfficialRoleIdentify
OfficialRoleBusiness
OfficialRoleGov
OfficialRoleMedia
OfficialRoleOther
)
// Official is.
type Official struct {
Role int8 `json:"role"`
Title string `json:"title"`
Desc string `json:"desc"`
}
// FromCert is.
func FromCert(v *MemberVerify) Official {
of := Official{}
switch v.Type {
case -1:
of.Role = 0
of.Title = ""
case 0:
of.Role = 2
of.Title = v.Desc
case 1:
of.Role = 3
of.Title = v.Desc
}
of.Desc = ""
return of
}

View File

@@ -0,0 +1,21 @@
package model
import (
"go-common/library/time"
)
//MemberVerify is.
type MemberVerify struct {
Mid int64 `json:"mid"`
Type int64 `json:"type"`
Desc string `json:"desc"`
}
//AccountInfo is.
type AccountInfo struct {
Mid int64 `json:"mid"`
Name string `json:"name"`
Cert int64 `json:"cert"`
CertDesc string `json:"certdesc"`
Ts time.Time `json:"ts"`
}

View File

@@ -0,0 +1,7 @@
#! /bin/sh
# proto.sh
gopath=$GOPATH/src
gogopath=$GOPATH/src/go-common/vendor/github.com/gogo/protobuf
protoc --gofast_out=. --proto_path=$gopath:$gogopath:. *.proto

View File

@@ -0,0 +1,33 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"error.go",
"priority_queue.go",
"queue.go",
"ring.go",
],
importpath = "go-common/app/job/main/member/model/queue",
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,32 @@
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package queue
import "errors"
var (
// ErrDisposed is returned when an operation is performed on a disposed
// queue.
ErrDisposed = errors.New(`queue: disposed`)
// ErrTimeout is returned when an applicable queue operation times out.
ErrTimeout = errors.New(`queue: poll timed out`)
// ErrEmptyQueue is returned when an non-applicable queue operation was called
// due to the queue's empty item state
ErrEmptyQueue = errors.New(`queue: empty queue`)
)

View File

@@ -0,0 +1,267 @@
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
The priority queue is almost a spitting image of the logic
used for a regular queue. In order to keep the logic fast,
this code is repeated instead of using casts to cast to interface{}
back and forth. If Go had inheritance and generics, this problem
would be easier to solve.
*/
package queue
import "sync"
// Item is an item that can be added to the priority queue.
type Item interface {
// Compare returns a bool that can be used to determine
// ordering in the priority queue. Assuming the queue
// is in ascending order, this should return > logic.
// Return 1 to indicate this object is greater than the
// the other logic, 0 to indicate equality, and -1 to indicate
// less than other.
Compare(other Item) int
HashCode() int64
}
type priorityItems []Item
func (items *priorityItems) swap(i, j int) {
(*items)[i], (*items)[j] = (*items)[j], (*items)[i]
}
func (items *priorityItems) pop() Item {
size := len(*items)
// Move last leaf to root, and 'pop' the last item.
items.swap(size-1, 0)
item := (*items)[size-1] // Item to return.
(*items)[size-1], *items = nil, (*items)[:size-1]
// 'Bubble down' to restore heap property.
index := 0
childL, childR := 2*index+1, 2*index+2
for len(*items) > childL {
child := childL
if len(*items) > childR && (*items)[childR].Compare((*items)[childL]) < 0 {
child = childR
}
if (*items)[child].Compare((*items)[index]) < 0 {
items.swap(index, child)
index = child
childL, childR = 2*index+1, 2*index+2
} else {
break
}
}
return item
}
func (items *priorityItems) get(number int) []Item {
returnItems := make([]Item, 0, number)
for i := 0; i < number; i++ {
if len(*items) == 0 {
break
}
returnItems = append(returnItems, items.pop())
}
return returnItems
}
func (items *priorityItems) push(item Item) {
// Stick the item as the end of the last level.
*items = append(*items, item)
// 'Bubble up' to restore heap property.
index := len(*items) - 1
parent := int((index - 1) / 2)
for parent >= 0 && (*items)[parent].Compare(item) > 0 {
items.swap(index, parent)
index = parent
parent = int((index - 1) / 2)
}
}
// PriorityQueue is similar to queue except that it takes
// items that implement the Item interface and adds them
// to the queue in priority order.
type PriorityQueue struct {
waiters waiters
items priorityItems
itemMap map[int64]struct{}
lock sync.Mutex
disposeLock sync.Mutex
disposed bool
allowDuplicates bool
}
// Put adds items to the queue.
func (pq *PriorityQueue) Put(items ...Item) error {
if len(items) == 0 {
return nil
}
pq.lock.Lock()
defer pq.lock.Unlock()
if pq.disposed {
return ErrDisposed
}
for _, item := range items {
if pq.allowDuplicates {
pq.items.push(item)
} else if _, ok := pq.itemMap[item.HashCode()]; !ok {
pq.itemMap[item.HashCode()] = struct{}{}
pq.items.push(item)
}
}
for {
sema := pq.waiters.get()
if sema == nil {
break
}
sema.response.Add(1)
sema.ready <- true
sema.response.Wait()
if len(pq.items) == 0 {
break
}
}
return nil
}
// Get retrieves items from the queue. If the queue is empty,
// this call blocks until the next item is added to the queue. This
// will attempt to retrieve number of items.
func (pq *PriorityQueue) Get(number int) ([]Item, error) {
if number < 1 {
return nil, nil
}
pq.lock.Lock()
if pq.disposed {
pq.lock.Unlock()
return nil, ErrDisposed
}
var items []Item
// Remove references to popped items.
deleteItems := func(items []Item) {
for _, item := range items {
delete(pq.itemMap, item.HashCode())
}
}
if len(pq.items) == 0 {
sema := newSema()
pq.waiters.put(sema)
pq.lock.Unlock()
<-sema.ready
if pq.Disposed() {
return nil, ErrDisposed
}
items = pq.items.get(number)
if !pq.allowDuplicates {
deleteItems(items)
}
sema.response.Done()
return items, nil
}
items = pq.items.get(number)
deleteItems(items)
pq.lock.Unlock()
return items, nil
}
// Peek will look at the next item without removing it from the queue.
func (pq *PriorityQueue) Peek() Item {
pq.lock.Lock()
defer pq.lock.Unlock()
if len(pq.items) > 0 {
return pq.items[0]
}
return nil
}
// Empty returns a bool indicating if there are any items left
// in the queue.
func (pq *PriorityQueue) Empty() bool {
pq.lock.Lock()
defer pq.lock.Unlock()
return len(pq.items) == 0
}
// Len returns a number indicating how many items are in the queue.
func (pq *PriorityQueue) Len() int {
pq.lock.Lock()
defer pq.lock.Unlock()
return len(pq.items)
}
// Disposed returns a bool indicating if this queue has been disposed.
func (pq *PriorityQueue) Disposed() bool {
pq.disposeLock.Lock()
defer pq.disposeLock.Unlock()
return pq.disposed
}
// Dispose will prevent any further reads/writes to this queue
// and frees available resources.
func (pq *PriorityQueue) Dispose() {
pq.lock.Lock()
defer pq.lock.Unlock()
pq.disposeLock.Lock()
defer pq.disposeLock.Unlock()
pq.disposed = true
for _, waiter := range pq.waiters {
waiter.response.Add(1)
waiter.ready <- true
}
pq.items = nil
pq.waiters = nil
}
// NewPriorityQueue is the constructor for a priority queue.
func NewPriorityQueue(hint int, allowDuplicates bool) *PriorityQueue {
return &PriorityQueue{
items: make(priorityItems, 0, hint),
itemMap: make(map[int64]struct{}, hint),
allowDuplicates: allowDuplicates,
}
}

View File

@@ -0,0 +1,411 @@
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Package queue includes a regular queue and a priority queue.
These queues rely on waitgroups to pause listening threads
on empty queues until a message is received. If any thread
calls Dispose on the queue, any listeners are immediately returned
with an error. Any subsequent put to the queue will return an error
as opposed to panicking as with channels. Queues will grow with unbounded
behavior as opposed to channels which can be buffered but will pause
while a thread attempts to put to a full channel.
Recently added is a lockless ring buffer using the same basic C design as
found here:
http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue
Modified for use with Go with the addition of some dispose semantics providing
the capability to release blocked threads. This works for both puts
and gets, either will return an error if they are blocked and the buffer
is disposed. This could serve as a signal to kill a goroutine. All threadsafety
is acheived using CAS operations, making this buffer pretty quick.
Benchmarks:
BenchmarkPriorityQueue-8 2000000 782 ns/op
BenchmarkQueue-8 2000000 671 ns/op
BenchmarkChannel-8 1000000 2083 ns/op
BenchmarkQueuePut-8 20000 84299 ns/op
BenchmarkQueueGet-8 20000 80753 ns/op
BenchmarkExecuteInParallel-8 20000 68891 ns/op
BenchmarkRBLifeCycle-8 10000000 177 ns/op
BenchmarkRBPut-8 30000000 58.1 ns/op
BenchmarkRBGet-8 50000000 26.8 ns/op
TODO: We really need a Fibonacci heap for the priority queue.
TODO: Unify the types of queue to the same interface.
*/
package queue
import (
"runtime"
"sync"
"sync/atomic"
"time"
)
type waiters []*sema
func (w *waiters) get() *sema {
if len(*w) == 0 {
return nil
}
sema := (*w)[0]
copy((*w)[0:], (*w)[1:])
(*w)[len(*w)-1] = nil // or the zero value of T
*w = (*w)[:len(*w)-1]
return sema
}
func (w *waiters) put(sema *sema) {
*w = append(*w, sema)
}
func (w *waiters) remove(sema *sema) {
if len(*w) == 0 {
return
}
// build new slice, copy all except sema
ws := *w
newWs := make(waiters, 0, len(*w))
for i := range ws {
if ws[i] != sema {
newWs = append(newWs, ws[i])
}
}
*w = newWs
}
type items []interface{}
func (items *items) get(number int64) []interface{} {
returnItems := make([]interface{}, 0, number)
index := int64(0)
for i := int64(0); i < number; i++ {
if i >= int64(len(*items)) {
break
}
returnItems = append(returnItems, (*items)[i])
(*items)[i] = nil
index++
}
*items = (*items)[index:]
return returnItems
}
func (items *items) peek() (interface{}, bool) {
length := len(*items)
if length == 0 {
return nil, false
}
return (*items)[0], true
}
func (items *items) getUntil(checker func(item interface{}) bool) []interface{} {
length := len(*items)
if len(*items) == 0 {
// returning nil here actually wraps that nil in a list
// of interfaces... thanks go
return []interface{}{}
}
returnItems := make([]interface{}, 0, length)
index := -1
for i, item := range *items {
if !checker(item) {
break
}
returnItems = append(returnItems, item)
index = i
(*items)[i] = nil // prevent memory leak
}
*items = (*items)[index+1:]
return returnItems
}
type sema struct {
ready chan bool
response *sync.WaitGroup
}
func newSema() *sema {
return &sema{
ready: make(chan bool, 1),
response: &sync.WaitGroup{},
}
}
// Queue is the struct responsible for tracking the state
// of the queue.
type Queue struct {
waiters waiters
items items
lock sync.Mutex
disposed bool
}
// Put will add the specified items to the queue.
func (q *Queue) Put(items ...interface{}) error {
if len(items) == 0 {
return nil
}
q.lock.Lock()
if q.disposed {
q.lock.Unlock()
return ErrDisposed
}
q.items = append(q.items, items...)
for {
sema := q.waiters.get()
if sema == nil {
break
}
sema.response.Add(1)
select {
case sema.ready <- true:
sema.response.Wait()
default:
// This semaphore timed out.
}
if len(q.items) == 0 {
break
}
}
q.lock.Unlock()
return nil
}
// Get retrieves items from the queue. If there are some items in the
// queue, get will return a number UP TO the number passed in as a
// parameter. If no items are in the queue, this method will pause
// until items are added to the queue.
func (q *Queue) Get(number int64) ([]interface{}, error) {
return q.Poll(number, 0)
}
// Poll retrieves items from the queue. If there are some items in the queue,
// Poll will return a number UP TO the number passed in as a parameter. If no
// items are in the queue, this method will pause until items are added to the
// queue or the provided timeout is reached. A non-positive timeout will block
// until items are added. If a timeout occurs, ErrTimeout is returned.
func (q *Queue) Poll(number int64, timeout time.Duration) ([]interface{}, error) {
if number < 1 {
// thanks again go
return []interface{}{}, nil
}
q.lock.Lock()
if q.disposed {
q.lock.Unlock()
return nil, ErrDisposed
}
var items []interface{}
if len(q.items) == 0 {
sema := newSema()
q.waiters.put(sema)
q.lock.Unlock()
var timeoutC <-chan time.Time
if timeout > 0 {
timeoutC = time.After(timeout)
}
select {
case <-sema.ready:
// we are now inside the put's lock
if q.disposed {
return nil, ErrDisposed
}
items = q.items.get(number)
sema.response.Done()
return items, nil
case <-timeoutC:
// cleanup the sema that was added to waiters
select {
case sema.ready <- true:
// we called this before Put() could
// Remove sema from waiters.
q.lock.Lock()
q.waiters.remove(sema)
q.lock.Unlock()
default:
// Put() got it already, we need to call Done() so Put() can move on
sema.response.Done()
}
return nil, ErrTimeout
}
}
items = q.items.get(number)
q.lock.Unlock()
return items, nil
}
// Peek returns a the first item in the queue by value
// without modifying the queue.
func (q *Queue) Peek() (interface{}, error) {
q.lock.Lock()
defer q.lock.Unlock()
if q.disposed {
return nil, ErrDisposed
}
peekItem, ok := q.items.peek()
if !ok {
return nil, ErrEmptyQueue
}
return peekItem, nil
}
// TakeUntil takes a function and returns a list of items that
// match the checker until the checker returns false. This does not
// wait if there are no items in the queue.
func (q *Queue) TakeUntil(checker func(item interface{}) bool) ([]interface{}, error) {
if checker == nil {
return nil, nil
}
q.lock.Lock()
if q.disposed {
q.lock.Unlock()
return nil, ErrDisposed
}
result := q.items.getUntil(checker)
q.lock.Unlock()
return result, nil
}
// Empty returns a bool indicating if this bool is empty.
func (q *Queue) Empty() bool {
q.lock.Lock()
defer q.lock.Unlock()
return len(q.items) == 0
}
// Len returns the number of items in this queue.
func (q *Queue) Len() int64 {
q.lock.Lock()
defer q.lock.Unlock()
return int64(len(q.items))
}
// Disposed returns a bool indicating if this queue
// has had disposed called on it.
func (q *Queue) Disposed() bool {
q.lock.Lock()
defer q.lock.Unlock()
return q.disposed
}
// Dispose will dispose of this queue and returns
// the items disposed. Any subsequent calls to Get
// or Put will return an error.
func (q *Queue) Dispose() []interface{} {
q.lock.Lock()
defer q.lock.Unlock()
q.disposed = true
for _, waiter := range q.waiters {
waiter.response.Add(1)
select {
case waiter.ready <- true:
// release Poll immediately
default:
// ignore if it's a timeout or in the get
}
}
disposedItems := q.items
q.items = nil
q.waiters = nil
return disposedItems
}
// New is a constructor for a new threadsafe queue.
func New(hint int64) *Queue {
return &Queue{
items: make([]interface{}, 0, hint),
}
}
// ExecuteInParallel will (in parallel) call the provided function
// with each item in the queue until the queue is exhausted. When the queue
// is exhausted execution is complete and all goroutines will be killed.
// This means that the queue will be disposed so cannot be used again.
func ExecuteInParallel(q *Queue, fn func(interface{})) {
if q == nil {
return
}
q.lock.Lock() // so no one touches anything in the middle
// of this process
todo, done := uint64(len(q.items)), int64(-1)
// this is important or we might face an infinite loop
if todo == 0 {
return
}
numCPU := 1
if runtime.NumCPU() > 1 {
numCPU = runtime.NumCPU() - 1
}
var wg sync.WaitGroup
wg.Add(numCPU)
items := q.items
for i := 0; i < numCPU; i++ {
go func() {
for {
index := atomic.AddInt64(&done, 1)
if index >= int64(todo) {
wg.Done()
break
}
fn(items[index])
items[index] = 0
}
}()
}
wg.Wait()
q.lock.Unlock()
q.Dispose()
}

View File

@@ -0,0 +1,203 @@
/*
Copyright 2014 Workiva, LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package queue
import (
"runtime"
"sync/atomic"
"time"
)
// roundUp takes a uint64 greater than 0 and rounds it up to the next
// power of 2.
func roundUp(v uint64) uint64 {
v--
v |= v >> 1
v |= v >> 2
v |= v >> 4
v |= v >> 8
v |= v >> 16
v |= v >> 32
v++
return v
}
type node struct {
position uint64
data interface{}
}
type nodes []*node
// RingBuffer is a MPMC buffer that achieves threadsafety with CAS operations
// only. A put on full or get on empty call will block until an item
// is put or retrieved. Calling Dispose on the RingBuffer will unblock
// any blocked threads with an error. This buffer is similar to the buffer
// described here: http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue
// with some minor additions.
type RingBuffer struct {
_padding0 [8]uint64
queue uint64
_padding1 [8]uint64
dequeue uint64
_padding2 [8]uint64
mask, disposed uint64
_padding3 [8]uint64
nodes nodes
}
func (rb *RingBuffer) init(size uint64) {
size = roundUp(size)
rb.nodes = make(nodes, size)
for i := uint64(0); i < size; i++ {
rb.nodes[i] = &node{position: i}
}
rb.mask = size - 1 // so we don't have to do this with every put/get operation
}
// Put adds the provided item to the queue. If the queue is full, this
// call will block until an item is added to the queue or Dispose is called
// on the queue. An error will be returned if the queue is disposed.
func (rb *RingBuffer) Put(item interface{}) error {
_, err := rb.put(item, false)
return err
}
// Offer adds the provided item to the queue if there is space. If the queue
// is full, this call will return false. An error will be returned if the
// queue is disposed.
func (rb *RingBuffer) Offer(item interface{}) (bool, error) {
return rb.put(item, true)
}
func (rb *RingBuffer) put(item interface{}, offer bool) (bool, error) {
var n *node
pos := atomic.LoadUint64(&rb.queue)
L:
for {
if atomic.LoadUint64(&rb.disposed) == 1 {
return false, ErrDisposed
}
n = rb.nodes[pos&rb.mask]
seq := atomic.LoadUint64(&n.position)
switch dif := seq - pos; {
case dif == 0:
if atomic.CompareAndSwapUint64(&rb.queue, pos, pos+1) {
break L
}
// case dif < 0:
// panic(`Ring buffer in a compromised state during a put operation.`)
default:
pos = atomic.LoadUint64(&rb.queue)
}
if offer {
return false, nil
}
runtime.Gosched() // free up the cpu before the next iteration
}
n.data = item
atomic.StoreUint64(&n.position, pos+1)
return true, nil
}
// Get will return the next item in the queue. This call will block
// if the queue is empty. This call will unblock when an item is added
// to the queue or Dispose is called on the queue. An error will be returned
// if the queue is disposed.
func (rb *RingBuffer) Get() (interface{}, error) {
return rb.Poll(0)
}
// Poll will return the next item in the queue. This call will block
// if the queue is empty. This call will unblock when an item is added
// to the queue, Dispose is called on the queue, or the timeout is reached. An
// error will be returned if the queue is disposed or a timeout occurs. A
// non-positive timeout will block indefinitely.
func (rb *RingBuffer) Poll(timeout time.Duration) (interface{}, error) {
var (
n *node
pos = atomic.LoadUint64(&rb.dequeue)
start time.Time
)
if timeout > 0 {
start = time.Now()
}
L:
for {
if atomic.LoadUint64(&rb.disposed) == 1 {
return nil, ErrDisposed
}
n = rb.nodes[pos&rb.mask]
seq := atomic.LoadUint64(&n.position)
switch dif := seq - (pos + 1); {
case dif == 0:
if atomic.CompareAndSwapUint64(&rb.dequeue, pos, pos+1) {
break L
}
// case dif < 0:
// panic(`Ring buffer in compromised state during a get operation.`)
default:
pos = atomic.LoadUint64(&rb.dequeue)
}
if timeout > 0 && time.Since(start) >= timeout {
return nil, ErrTimeout
}
runtime.Gosched() // free up the cpu before the next iteration
}
data := n.data
n.data = nil
atomic.StoreUint64(&n.position, pos+rb.mask+1)
return data, nil
}
// Len returns the number of items in the queue.
func (rb *RingBuffer) Len() uint64 {
return atomic.LoadUint64(&rb.queue) - atomic.LoadUint64(&rb.dequeue)
}
// Cap returns the capacity of this ring buffer.
func (rb *RingBuffer) Cap() uint64 {
return uint64(len(rb.nodes))
}
// Dispose will dispose of this queue and free any blocked threads
// in the Put and/or Get methods. Calling those methods on a disposed
// queue will return an error.
func (rb *RingBuffer) Dispose() {
atomic.CompareAndSwapUint64(&rb.disposed, 0, 1)
}
// IsDisposed will return a bool indicating if this queue has been
// disposed.
func (rb *RingBuffer) IsDisposed() bool {
return atomic.LoadUint64(&rb.disposed) == 1
}
// NewRingBuffer will allocate, initialize, and return a ring buffer
// with the specified size.
func NewRingBuffer(size uint64) *RingBuffer {
rb := &RingBuffer{}
rb.init(size)
return rb
}

View File

@@ -0,0 +1,273 @@
package model
import (
"crypto/md5"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"fmt"
"strings"
"time"
"go-common/app/job/main/member/conf"
"go-common/library/log"
"github.com/pkg/errors"
)
var (
realnameSalt = "biliidentification@#$%^&*()(*&^%$#"
)
//RealnamePersonMessage is.
type RealnamePersonMessage struct {
MID int64 `json:"mid"`
Realname string `json:"realname"`
IdentifyCard string `json:"identify_card"`
}
//RealnameApplyMessage is.
type RealnameApplyMessage struct {
ID int `json:"id"`
MID int64 `json:"mid"`
Realname string `json:"realname"`
Type int `json:"type"`
CardDataCanal string `json:"card_data"`
CardForSearch string `json:"card_for_search"`
FrontIMG int `json:"front_img"`
BackIMG int `json:"back_img"`
FrontIMG2 int `json:"front_img2"`
ApplyTimeUnix int64 `json:"apply_time"`
Operater string `json:"operater"`
OperaterTimeUnix int64 `json:"operater_time"`
Status int8 `json:"status"`
Remark string `json:"remark"`
RemarkStatus int8 `json:"remark_status"`
}
// CardMD5 is.
func (r *RealnameApplyMessage) CardMD5() (res string) {
return cardReMD5(r.CardData(), r.CardType(), r.Country())
}
// cardReMD5 is.
func cardReMD5(encrypedCard string, cardType int, country int) (res string) {
card, err := cardDecrypt([]byte(encrypedCard))
if err != nil {
log.Error("cardNewMD5 decrypt err : %+v", err)
return
}
return cardMD5(string(card), cardType, country)
}
func cardMD5(card string, cardType int, country int) (res string) {
var (
lowerCode = strings.ToLower(card)
key = fmt.Sprintf("%s_%s_%d_%d", realnameSalt, lowerCode, cardType, country)
)
return fmt.Sprintf("%x", md5.Sum([]byte(key)))
}
func cardDecrypt(data []byte) (text []byte, err error) {
var (
decryptedData []byte
size int
)
decryptedData = make([]byte, base64.StdEncoding.DecodedLen(len(data)))
if size, err = base64.StdEncoding.Decode(decryptedData, data); err != nil {
err = errors.Wrapf(err, "base decode %s", data)
return
}
if text, err = rsaDecrypt(decryptedData[:size]); err != nil {
err = errors.Wrapf(err, "rsa decrypt %s , data : %s", decryptedData, data)
return
}
return
}
func rsaDecrypt(text []byte) (content []byte, err error) {
block, _ := pem.Decode(conf.Conf.RealnameRsaPriv)
if block == nil {
err = errors.New("private key error")
return
}
var (
privateKey *rsa.PrivateKey
)
if privateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes); err != nil {
err = errors.WithStack(err)
return
}
if content, err = rsa.DecryptPKCS1v15(rand.Reader, privateKey, text); err != nil {
err = errors.WithStack(err)
return
}
return
}
//ApplyTime is.
func (r *RealnameApplyMessage) ApplyTime() (t time.Time) {
t = time.Unix(r.ApplyTimeUnix, 0)
return
}
//OperaterTime is.
func (r *RealnameApplyMessage) OperaterTime() (t time.Time) {
t = time.Unix(r.OperaterTimeUnix, 0)
return
}
//CardType is.
func (r *RealnameApplyMessage) CardType() (t int) {
if r.Type > 6 {
return 6
}
return r.Type
}
//Country is.
func (r *RealnameApplyMessage) Country() (t int) {
if r.Type > 6 {
return r.Type
}
return 0
}
//CardData is.
func (r *RealnameApplyMessage) CardData() (data string) {
if r.CardDataCanal == "" {
log.Warn("card data empty (+v)", r)
return ""
}
bytes, err := base64.StdEncoding.DecodeString(r.CardDataCanal)
if err != nil {
err = errors.Wrapf(err, "decode (%+v) failed", r)
log.Error("+v", err)
return ""
}
return string(bytes)
}
//RealnameApplyImgMessage is.
type RealnameApplyImgMessage struct {
ID int `json:"id"`
IMGData string `json:"img_data"`
AddTimeStr string `json:"add_time"`
AddTimeDB time.Time
}
//AddTime is.
func (r *RealnameApplyImgMessage) AddTime() (t time.Time) {
if r.AddTimeDB.IsZero() {
var err error
if t, err = time.ParseInLocation("2006-01-02 15:04:05", r.AddTimeStr, time.Local); err != nil {
log.Error("%+v", err)
t = time.Now()
}
return
}
return r.AddTimeDB
}
// RealnameApplyStatus is.
type RealnameApplyStatus int8
const (
// RealnameApplyStatusPending is.
RealnameApplyStatusPending RealnameApplyStatus = iota
// RealnameApplyStatusPass is.
RealnameApplyStatusPass
// RealnameApplyStatusBack is.
RealnameApplyStatusBack
// RealnameApplyStatusNone is.
RealnameApplyStatusNone
)
// IsPass return is apply passed
func (r RealnameApplyStatus) IsPass() bool {
switch r {
case RealnameApplyStatusPass:
return true
default:
return false
}
}
// RealnameChannel is
type RealnameChannel int8
// RealnameChannel enum
const (
RealnameChannelMain RealnameChannel = iota
RealnameChannelAlipay
)
const (
// RealnameCountryChina is.
RealnameCountryChina = 0
// RealnameCardTypeIdentity is.
RealnameCardTypeIdentity = 0
)
// RealnameInfo is user realname status info
type RealnameInfo struct {
ID int64 `json:"id"`
MID int64 `json:"mid"`
Channel RealnameChannel `json:"channel"`
Realname string `json:"realname"`
Country int `json:"country"`
CardType int `json:"card_type"`
Card string `json:"card"`
CardMD5 string `json:"card_md5"`
Status RealnameApplyStatus `json:"status"`
Reason string `json:"reason"`
CTime time.Time `json:"ctime"`
MTime time.Time `json:"mtime"`
}
// DecryptedCard is
func (r *RealnameInfo) DecryptedCard() (string, error) {
raw, err := cardDecrypt([]byte(r.Card))
if err != nil {
return "", err
}
return string(raw), nil
}
// RealnameApply is user realname apply info from default channel.
type RealnameApply struct {
ID int `json:"id"`
MID int64 `json:"mid"`
Realname string `json:"realname"`
Country int16 `json:"country"`
CardType int8 `json:"card_type"`
CardNum string `json:"card_num"`
CardMD5 string `json:"card_md5"`
HandIMG int `json:"hand_img"`
FrontIMG int `json:"front_img"`
BackIMG int `json:"back_img"`
Status int `json:"status"`
Operator string `json:"operator"`
OperatorID int64 `json:"operator_id"`
OperatorTime time.Time `json:"operator_time"`
Remark string `json:"remark"`
RemarkStatus int8 `json:"remark_status"`
CTime time.Time `json:"ctime"`
MTime time.Time `json:"mtime"`
}
// RealnameAlipayApply is user alipay apply info from alipay channle.
type RealnameAlipayApply struct {
ID int64 `json:"id"`
MID int64 `json:"mid"`
Realname string `json:"realname"`
Card string `json:"card"`
IMG string `json:"img"`
Status RealnameApplyStatus `json:"status"`
Reason string `json:"reason"`
Bizno string `json:"bizno"`
CTime time.Time `json:"ctime"`
MTime time.Time `json:"mtime"`
}