@@ -0,0 +1,7 @@
|
|||||||
|
honoka-chan
|
||||||
|
honoka-chan.exe
|
||||||
|
privatekey.pem
|
||||||
|
publickey.pem
|
||||||
|
|
||||||
|
data
|
||||||
|
logs
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
app_name: LL! SIF Private Server
|
||||||
|
server:
|
||||||
|
powered_by: KLab Native APP Platform
|
||||||
|
version_date: "20120129"
|
||||||
|
version_number: 97.4.6
|
||||||
|
version_up: "0"
|
||||||
|
log:
|
||||||
|
log_dir: logs
|
||||||
|
log_level: 5
|
||||||
|
log_save: true
|
||||||
|
redis:
|
||||||
|
host: 192.168.1.9
|
||||||
|
port: "6379"
|
||||||
|
pass: "klsbgames"
|
||||||
|
db: 5
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// Copyright (C) 2021 YumeMichi
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
package config
|
||||||
|
|
||||||
|
var (
|
||||||
|
ConfName = "config.yml"
|
||||||
|
Conf = &AppConfigs{}
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
Conf = Load(ConfName)
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
// Copyright (C) 2021-2022 YumeMichi
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"honoka-chan/utils"
|
||||||
|
"honoka-chan/xclog"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AppConfigs struct {
|
||||||
|
AppName string `yaml:"app_name"`
|
||||||
|
Server ServerConfigs `yaml:"server"`
|
||||||
|
Log LogConfigs `yaml:"log"`
|
||||||
|
Redis RedisConfigs `yaml:"redis"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServerConfigs struct {
|
||||||
|
PoweredBy string `yaml:"powered_by"`
|
||||||
|
VersionDate string `yaml:"version_date"`
|
||||||
|
VersionNumber string `yaml:"version_number"`
|
||||||
|
VersionUp string `yaml:"version_up"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LogConfigs struct {
|
||||||
|
LogDir string `yaml:"log_dir"`
|
||||||
|
LogLevel int `yaml:"log_level"`
|
||||||
|
LogSave bool `yaml:"log_save"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RedisConfigs struct {
|
||||||
|
Host string `yaml:"host"`
|
||||||
|
Port string `yaml:"port"`
|
||||||
|
Pass string `yaml:"pass"`
|
||||||
|
Db int `yaml:"db"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func DefaultConfigs() *AppConfigs {
|
||||||
|
return &AppConfigs{
|
||||||
|
AppName: "LL! SIF Private Server",
|
||||||
|
Server: ServerConfigs{
|
||||||
|
PoweredBy: "KLab Native APP Platform",
|
||||||
|
VersionDate: "20120129",
|
||||||
|
VersionNumber: "97.4.6",
|
||||||
|
VersionUp: "0",
|
||||||
|
},
|
||||||
|
Log: LogConfigs{
|
||||||
|
LogDir: "logs",
|
||||||
|
LogLevel: 5,
|
||||||
|
LogSave: true,
|
||||||
|
},
|
||||||
|
Redis: RedisConfigs{
|
||||||
|
Host: "127.0.0.1",
|
||||||
|
Port: "6379",
|
||||||
|
Pass: "",
|
||||||
|
Db: 0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Load(p string) *AppConfigs {
|
||||||
|
if !utils.PathExists(p) {
|
||||||
|
_ = DefaultConfigs().Save(p)
|
||||||
|
}
|
||||||
|
c := AppConfigs{}
|
||||||
|
err := yaml.Unmarshal([]byte(utils.ReadAllText(p)), &c)
|
||||||
|
if err != nil {
|
||||||
|
xclog.Error("Failed to load " + ConfName + ": " + err.Error())
|
||||||
|
_ = os.Rename(p, p+".backup"+strconv.FormatInt(time.Now().Unix(), 10))
|
||||||
|
_ = DefaultConfigs().Save(p)
|
||||||
|
}
|
||||||
|
c = AppConfigs{}
|
||||||
|
_ = yaml.Unmarshal([]byte(utils.ReadAllText(p)), &c)
|
||||||
|
xclog.Info(ConfName + " loaded!")
|
||||||
|
return &c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *AppConfigs) Save(p string) error {
|
||||||
|
data, err := yaml.Marshal(c)
|
||||||
|
if err != nil {
|
||||||
|
xclog.Error("Failed to save " + ConfName + ": " + err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
utils.WriteAllText(p, string(data))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package encrypt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/aes"
|
||||||
|
"crypto/cipher"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
iv = []byte("12345678abcdefgh")
|
||||||
|
)
|
||||||
|
|
||||||
|
func Padding(plainText []byte, blockSize int) []byte {
|
||||||
|
n := blockSize - len(plainText)%blockSize
|
||||||
|
temp := bytes.Repeat([]byte{byte(n)}, n)
|
||||||
|
plainText = append(plainText, temp...)
|
||||||
|
return plainText
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnPadding(cipherText []byte) []byte {
|
||||||
|
end := cipherText[len(cipherText)-1]
|
||||||
|
cipherText = cipherText[:len(cipherText)-int(end)]
|
||||||
|
return cipherText
|
||||||
|
}
|
||||||
|
|
||||||
|
func AES_CBC_Encrypt(plainText []byte, key []byte) []byte {
|
||||||
|
block, err := aes.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
plainText = Padding(plainText, block.BlockSize())
|
||||||
|
blockMode := cipher.NewCBCEncrypter(block, iv)
|
||||||
|
cipherText := make([]byte, len(plainText))
|
||||||
|
blockMode.CryptBlocks(cipherText, plainText)
|
||||||
|
return cipherText
|
||||||
|
}
|
||||||
|
|
||||||
|
func AES_CBC_Decrypt(cipherText []byte, key []byte) []byte {
|
||||||
|
block, err := aes.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
plainText := make([]byte, len(cipherText))
|
||||||
|
blockMode := cipher.NewCBCDecrypter(block, iv)
|
||||||
|
blockMode.CryptBlocks(plainText, cipherText)
|
||||||
|
plainText = UnPadding(plainText)
|
||||||
|
return plainText
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package encrypt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/hmac"
|
||||||
|
"crypto/sha1"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func HMAC_SHA1_Encrypt(plainText []byte, key []byte) string {
|
||||||
|
mac := hmac.New(sha1.New, key)
|
||||||
|
mac.Write(plainText)
|
||||||
|
cipherText := fmt.Sprintf("%x", mac.Sum(nil))
|
||||||
|
return cipherText
|
||||||
|
}
|
||||||
+172
@@ -0,0 +1,172 @@
|
|||||||
|
package encrypt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/rsa"
|
||||||
|
"crypto/sha1"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/pem"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RSA_Gen(bits int) {
|
||||||
|
//get current path
|
||||||
|
_, currentpath, _, _ := runtime.Caller(0)
|
||||||
|
currentpath = filepath.Dir(currentpath)
|
||||||
|
|
||||||
|
//----------------------------------------------private key
|
||||||
|
|
||||||
|
// GenerateKey generates an RSA keypair of the given bit size using the
|
||||||
|
// random source random (for example, crypto/rand.Reader).
|
||||||
|
privateKey, err := rsa.GenerateKey(rand.Reader, bits)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
//serialize privatekey to ASN.1 der by x509.MarshalPKCS8PrivateKey
|
||||||
|
x509privatekey, err := x509.MarshalPKCS8PrivateKey(privateKey)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
//encode x509 to pem and save to file
|
||||||
|
//1. create privatefile
|
||||||
|
privatekeyfile, err := os.Create(currentpath + "/privatekey.pem")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer privatekeyfile.Close()
|
||||||
|
//2. new a pem block struct object
|
||||||
|
privatekeyblock := pem.Block{
|
||||||
|
Type: "PRIVATE KEY",
|
||||||
|
Headers: nil,
|
||||||
|
Bytes: x509privatekey,
|
||||||
|
}
|
||||||
|
//3. save to file
|
||||||
|
pem.Encode(privatekeyfile, &privatekeyblock)
|
||||||
|
|
||||||
|
//----------------------------------------------public key
|
||||||
|
|
||||||
|
//get public key
|
||||||
|
publickey := privateKey.PublicKey
|
||||||
|
//serialize publickey to ASN.1 der by x509.MarshalPKCS8PublicKey
|
||||||
|
x509publickey, _ := x509.MarshalPKIXPublicKey(&publickey)
|
||||||
|
|
||||||
|
//encode x509 to pem and save to file
|
||||||
|
//1. create publickeyfile
|
||||||
|
publickeyfile, err := os.Create(currentpath + "/publickey.pem")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer publickeyfile.Close()
|
||||||
|
|
||||||
|
//2. new a pem block struct object
|
||||||
|
publickeyblock := pem.Block{
|
||||||
|
Type: "PUBLIC KEY",
|
||||||
|
Headers: nil,
|
||||||
|
Bytes: x509publickey,
|
||||||
|
}
|
||||||
|
|
||||||
|
//3. save to file
|
||||||
|
pem.Encode(publickeyfile, &publickeyblock)
|
||||||
|
}
|
||||||
|
func RSA_Encrypt(plainText []byte, publickeypath string) []byte {
|
||||||
|
//open publickeyfile
|
||||||
|
publickeyfile, err := os.Open(publickeypath)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer publickeyfile.Close()
|
||||||
|
|
||||||
|
//get publickeyfile info
|
||||||
|
publickeyfileInfo, _ := publickeyfile.Stat()
|
||||||
|
|
||||||
|
//read publickeyfile content
|
||||||
|
//1. make size
|
||||||
|
buf := make([]byte, publickeyfileInfo.Size())
|
||||||
|
//2. read file to buf
|
||||||
|
publickeyfile.Read(buf)
|
||||||
|
//3. decode pem
|
||||||
|
publickeyDecodeBlock, _ := pem.Decode(buf)
|
||||||
|
//4. x509 decode
|
||||||
|
publicKeyInterface, err := x509.ParsePKIXPublicKey(publickeyDecodeBlock.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
//assert
|
||||||
|
publicKey := publicKeyInterface.(*rsa.PublicKey)
|
||||||
|
|
||||||
|
//encrypt plainText
|
||||||
|
cipherText, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, plainText)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return cipherText
|
||||||
|
}
|
||||||
|
|
||||||
|
func RSA_Decrypt(cipherText []byte, privatekeypath string) []byte {
|
||||||
|
//open privatekeyfile
|
||||||
|
privatekeyfile, err := os.Open(privatekeypath)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer privatekeyfile.Close()
|
||||||
|
//get privatekeyfile content
|
||||||
|
privatekeyinfo, _ := privatekeyfile.Stat()
|
||||||
|
buf := make([]byte, privatekeyinfo.Size())
|
||||||
|
privatekeyfile.Read(buf)
|
||||||
|
//pem decode
|
||||||
|
privatekeyblock, _ := pem.Decode(buf)
|
||||||
|
//X509 decode
|
||||||
|
parseKey, err := x509.ParsePKCS8PrivateKey(privatekeyblock.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
privateKey := parseKey.(*rsa.PrivateKey)
|
||||||
|
//decrypt the cipher
|
||||||
|
plainText, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, cipherText)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return plainText
|
||||||
|
}
|
||||||
|
|
||||||
|
func RSA_Sign_SHA1(cipherText []byte, privatekeypath string) []byte {
|
||||||
|
//open privatekeyfile
|
||||||
|
privatekeyfile, err := os.Open(privatekeypath)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer privatekeyfile.Close()
|
||||||
|
//get privatekeyfile content
|
||||||
|
privatekeyinfo, _ := privatekeyfile.Stat()
|
||||||
|
buf := make([]byte, privatekeyinfo.Size())
|
||||||
|
privatekeyfile.Read(buf)
|
||||||
|
//pem decode
|
||||||
|
privatekeyblock, _ := pem.Decode(buf)
|
||||||
|
//X509 decode
|
||||||
|
parseKey, err := x509.ParsePKCS8PrivateKey(privatekeyblock.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
privateKey := parseKey.(*rsa.PrivateKey)
|
||||||
|
|
||||||
|
msgHash := sha1.New()
|
||||||
|
_, err = msgHash.Write(cipherText)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
msgHashSum := msgHash.Sum(nil)
|
||||||
|
|
||||||
|
signature, err := rsa.SignPSS(rand.Reader, privateKey, crypto.SHA1, msgHashSum, nil)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return signature
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
module honoka-chan
|
||||||
|
|
||||||
|
go 1.19
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/gin-gonic/gin v1.8.2
|
||||||
|
github.com/redis/go-redis/v9 v9.0.2
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||||
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||||
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
|
github.com/go-playground/locales v0.14.0 // indirect
|
||||||
|
github.com/go-playground/universal-translator v0.18.0 // indirect
|
||||||
|
github.com/go-playground/validator/v10 v10.11.1 // indirect
|
||||||
|
github.com/goccy/go-json v0.9.11 // indirect
|
||||||
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
|
github.com/leodido/go-urn v1.2.1 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
|
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
|
||||||
|
github.com/ugorji/go/codec v1.2.7 // indirect
|
||||||
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect
|
||||||
|
golang.org/x/net v0.4.0 // indirect
|
||||||
|
golang.org/x/sys v0.3.0 // indirect
|
||||||
|
golang.org/x/text v0.5.0 // indirect
|
||||||
|
google.golang.org/protobuf v1.28.1 // indirect
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
|
)
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
github.com/bsm/ginkgo/v2 v2.5.0 h1:aOAnND1T40wEdAtkGSkvSICWeQ8L3UASX7YVCqQx+eQ=
|
||||||
|
github.com/bsm/gomega v1.20.0 h1:JhAwLmtRzXFTx2AkALSLa8ijZafntmhSoU63Ok18Uq8=
|
||||||
|
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||||
|
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
|
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/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||||
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||||
|
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||||
|
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||||
|
github.com/gin-gonic/gin v1.8.2 h1:UzKToD9/PoFj/V4rvlKqTRKnQYyz8Sc1MJlv4JHPtvY=
|
||||||
|
github.com/gin-gonic/gin v1.8.2/go.mod h1:qw5AYuDrzRTnhvusDsrov+fDIxp9Dleuu12h8nfB398=
|
||||||
|
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
||||||
|
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
|
github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
|
||||||
|
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
|
||||||
|
github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
|
||||||
|
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
||||||
|
github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ=
|
||||||
|
github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
|
||||||
|
github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk=
|
||||||
|
github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||||
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
|
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||||
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
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/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
|
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||||
|
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
|
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
||||||
|
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||||
|
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
|
||||||
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
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/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
|
||||||
|
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
|
||||||
|
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||||
|
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/redis/go-redis/v9 v9.0.2 h1:BA426Zqe/7r56kCcvxYLWe1mkaz71LKF77GwgFzSxfE=
|
||||||
|
github.com/redis/go-redis/v9 v9.0.2/go.mod h1:/xDTe9EF1LM61hek62Poq2nzQSGj0xSrEtEHbBQevps=
|
||||||
|
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||||
|
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
|
||||||
|
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||||
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
|
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
|
||||||
|
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
|
||||||
|
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
|
||||||
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
|
||||||
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
|
||||||
|
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/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-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
|
||||||
|
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
|
||||||
|
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
|
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||||
|
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"honoka-chan/config"
|
||||||
|
"honoka-chan/resp"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func AnnounceIndexHandler(ctx *gin.Context) {
|
||||||
|
ctx.String(http.StatusOK, "Hello, world!")
|
||||||
|
}
|
||||||
|
|
||||||
|
func AnnounceCheckStateHandler(ctx *gin.Context) {
|
||||||
|
ctx.Header("Server-Version", config.Conf.Server.VersionNumber)
|
||||||
|
ctx.Header("user_id", "5802913")
|
||||||
|
ctx.Header("authorize", "consumerKey=lovelive_test&timeStamp=1678640534&version=1.1&token=bS5G6TKTsw0aGxVQz8JWJTx8Tf73H0bF9Bq1PEw3UaxoEoUG8GcrrzaEbjOwEQJTrThgHpBlbwnMRl9ITGw1&nonce=11&requestTimeStamp=1678640534")
|
||||||
|
ctx.Header("X-Message-Sign", "vP/1uPKsGnArUaIL7lPDgZC4lGPjwVZDvFWiGXFfxrRzq6wQ8Veq3623KCl05/2hTTQnOm3L6bNu377s//R/7SieeQ7L7FNWLptTHoyyqgjZe16CJzyqFGbmm9pxxZDttJ74zkuBO1astYBPxh2+qws4LduZUS0c0VklzP5nNoY=")
|
||||||
|
ctx.String(http.StatusOK, resp.AnnounceState)
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"honoka-chan/model"
|
||||||
|
"honoka-chan/resp"
|
||||||
|
"honoka-chan/utils"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ApiHandler(ctx *gin.Context) {
|
||||||
|
// fmt.Println(c.PostForm("request_data"))
|
||||||
|
var formdata []model.SifApi
|
||||||
|
err := json.Unmarshal([]byte(ctx.PostForm("request_data")), &formdata)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
v1 := false
|
||||||
|
for _, v := range formdata {
|
||||||
|
// fmt.Println(v)
|
||||||
|
if v.Module == "live" {
|
||||||
|
v1 = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx.Header("Server-Version", "97.4.6")
|
||||||
|
ctx.Header("user_id", "5802913")
|
||||||
|
if v1 {
|
||||||
|
// 登录后第一次请求API
|
||||||
|
ctx.Header("authorize", "consumerKey=lovelive_test&timeStamp=1678640521&version=1.1&token=bS5G6TKTsw0aGxVQz8JWJTx8Tf73H0bF9Bq1PEw3UaxoEoUG8GcrrzaEbjOwEQJTrThgHpBlbwnMRl9ITGw1&nonce=9&requestTimeStamp=1678640521")
|
||||||
|
// ctx.Header("X-Message-Sign", "bNuSClKqt20FoGduZJI4pB1Y8xUwrrarvfsq0soqU5U97x7kGLESNoXSQVZcFfa1Eo4kgntEktokmDHzCbxpsYFvrD1mhbn++UOmcwXXCQRdxbbfhTt7MVfXbcqXAuFKAfkE37n9dkn1U0RnNt5U4m3mbRhLYT5B16ZcPGIPn/E=")
|
||||||
|
ctx.String(http.StatusOK, utils.ReadAllText("data/test2.json"))
|
||||||
|
} else {
|
||||||
|
// 登录后第二次请求API
|
||||||
|
ctx.Header("authorize", "consumerKey=lovelive_test&timeStamp=1678640523&version=1.1&token=bS5G6TKTsw0aGxVQz8JWJTx8Tf73H0bF9Bq1PEw3UaxoEoUG8GcrrzaEbjOwEQJTrThgHpBlbwnMRl9ITGw1&nonce=10&requestTimeStamp=1678640523")
|
||||||
|
// ctx.Header("X-Message-Sign", "w6+DlFx4DcmaoNXoLu71PH9sOOQeGFX/x0aDayt0qpHa+Uw+MeA0EJossW3/OgZvZgcFxBK2tKrHZJxRrguwCp0lpaI6/onWrYhK9xZeAW33nrsuWWT52v4wyNPY236xGecrDrs9R0nmTOuxElQEKqdFeZYL/JZiuuxvUbwxMy8=")
|
||||||
|
ctx.String(http.StatusOK, resp.Api2)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"honoka-chan/resp"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func DownloadEventHandler(ctx *gin.Context) {
|
||||||
|
ctx.Header("user_id", "5802913")
|
||||||
|
ctx.Header("authorize", "consumerKey=lovelive_test&timeStamp=1678640521&version=1.1&token=bS5G6TKTsw0aGxVQz8JWJTx8Tf73H0bF9Bq1PEw3UaxoEoUG8GcrrzaEbjOwEQJTrThgHpBlbwnMRl9ITGw1&nonce=7&requestTimeStamp=1678640521")
|
||||||
|
ctx.Header("X-Message-Sign", "anBqaPYp7nEprAbxhOouwx8e1dCn1PbmXNplSVtGT3QWNvS+bcMYnqr8QxluM5SIGi3esO8tzHsDzn+Z7tdohFtpkT1zdYQ5qK07eZ8VtyckaRnmx5QLzn7MMflFWr3P/HONS04QwLakoeZyNDCBmxjqOy6QzNsf6e4o9D+21AM=")
|
||||||
|
ctx.String(http.StatusOK, resp.Event)
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"honoka-chan/resp"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GdprHandler(ctx *gin.Context) {
|
||||||
|
ctx.Header("Server-Version", "97.4.6")
|
||||||
|
ctx.Header("user_id", "5802913")
|
||||||
|
ctx.Header("authorize", "consumerKey=lovelive_test&timeStamp=1678640520&version=1.1&token=bS5G6TKTsw0aGxVQz8JWJTx8Tf73H0bF9Bq1PEw3UaxoEoUG8GcrrzaEbjOwEQJTrThgHpBlbwnMRl9ITGw1&nonce=4&requestTimeStamp=1678640520")
|
||||||
|
ctx.Header("X-Message-Sign", "nGH0cQ34z9D3QnTGFDe2r2WMBGfTzYx+5oaJJbvYCqMESTDAQWlxq8X73OBLgdCkEIMuIAiRyF0z+0MQEVohDL4l6nDgcVDDJztCXP/W5ZXZh1wNgGhHZIDrwboNjsg1acq0+phBAiBEQQt6HipEdGRQh5fhAhhA717ns/C4iUI=")
|
||||||
|
ctx.String(http.StatusOK, resp.Gdpr)
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"honoka-chan/config"
|
||||||
|
|
||||||
|
"github.com/redis/go-redis/v9"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
nonce = 0
|
||||||
|
|
||||||
|
redisCli *redis.Client
|
||||||
|
redisCtx = context.Background()
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
redisCli = redis.NewClient(&redis.Options{
|
||||||
|
Addr: config.Conf.Redis.Host + ":" + config.Conf.Redis.Port,
|
||||||
|
Password: config.Conf.Redis.Pass,
|
||||||
|
DB: config.Conf.Redis.Db,
|
||||||
|
})
|
||||||
|
|
||||||
|
_, err := redisCli.Ping(redisCtx).Result()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"honoka-chan/resp"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func LBonusExecuteHandler(ctx *gin.Context) {
|
||||||
|
ctx.Header("Server-Version", "97.4.6")
|
||||||
|
ctx.Header("user_id", "5802913")
|
||||||
|
ctx.Header("authorize", "consumerKey=lovelive_test&timeStamp=1678640521&version=1.1&token=bS5G6TKTsw0aGxVQz8JWJTx8Tf73H0bF9Bq1PEw3UaxoEoUG8GcrrzaEbjOwEQJTrThgHpBlbwnMRl9ITGw1&nonce=8&requestTimeStamp=1678640521")
|
||||||
|
ctx.Header("X-Message-Sign", "2UDMPncUOcUnQdLPCSuZIrRWK9yRgASUzCL3YiMpox/IUDNrHn7BRr/eo6iMQ1TlDTnNqzHj/ZP/8m4rpgvlDFHg16nlPUQJe0hqF9Ck3tjeHfT7wbwV75deoqIlPNONS5u3eCI8ZlhRf9VeDUBxRoVDRiq4xqiwjOILvmPAb1w=")
|
||||||
|
ctx.String(http.StatusOK, resp.LBonus)
|
||||||
|
}
|
||||||
@@ -0,0 +1,167 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"honoka-chan/encrypt"
|
||||||
|
"honoka-chan/model"
|
||||||
|
"honoka-chan/utils"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func AuthKeyHandler(ctx *gin.Context) {
|
||||||
|
reqTime := time.Now().Unix()
|
||||||
|
authReq := model.AuthKeyReq{}
|
||||||
|
err := json.Unmarshal([]byte(ctx.PostForm("request_data")), &authReq)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
dummyToken64, err := base64.StdEncoding.DecodeString(authReq.DummyToken)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
dummyTokenDecrypted := encrypt.RSA_Decrypt(dummyToken64, "privatekey.pem")
|
||||||
|
clientToken := base64.RawStdEncoding.EncodeToString(dummyTokenDecrypted)
|
||||||
|
aesKey := dummyTokenDecrypted[0:16]
|
||||||
|
data64, err := base64.StdEncoding.DecodeString(authReq.AuthData)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
dataDecrypted := utils.Sub16(encrypt.AES_CBC_Decrypt(data64, aesKey))
|
||||||
|
fmt.Println(string(dataDecrypted))
|
||||||
|
|
||||||
|
mRandStr := utils.RandomStr(32)
|
||||||
|
serverToken := base64.RawStdEncoding.EncodeToString([]byte(mRandStr))
|
||||||
|
|
||||||
|
authorizeToken := utils.RandomBase64Token(32)
|
||||||
|
|
||||||
|
nonce++
|
||||||
|
|
||||||
|
authData := map[string]interface{}{
|
||||||
|
"client_token": clientToken,
|
||||||
|
"server_token": serverToken,
|
||||||
|
"nonce": nonce,
|
||||||
|
}
|
||||||
|
_, err = redisCli.HSet(redisCtx, authorizeToken, authData).Result()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
authResp := model.AuthKeyResp{}
|
||||||
|
authResp.ResponseData.DummyToken = serverToken
|
||||||
|
authResp.ResponseData.AuthorizeToken = authorizeToken
|
||||||
|
authResp.StatusCode = 200
|
||||||
|
resp, err := json.Marshal(authResp)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Println(string(resp))
|
||||||
|
|
||||||
|
respTime := time.Now().Unix()
|
||||||
|
authorizeStr := fmt.Sprintf("consumerKey=lovelive_test&timeStamp=%d&version=1.1&nonce=%d&requestTimeStamp=%d", respTime, nonce, reqTime)
|
||||||
|
fmt.Println(authorizeStr)
|
||||||
|
|
||||||
|
xms := encrypt.RSA_Sign_SHA1(resp, "privatekey.pem")
|
||||||
|
xms64 := base64.RawStdEncoding.EncodeToString(xms)
|
||||||
|
|
||||||
|
ctx.Header("user_id", "")
|
||||||
|
ctx.Header("authorize", authorizeStr)
|
||||||
|
ctx.Header("X-Message-Sign", xms64)
|
||||||
|
ctx.JSON(http.StatusOK, authResp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoginHandler(ctx *gin.Context) {
|
||||||
|
reqTime := time.Now().Unix()
|
||||||
|
authorizeStr := ctx.Request.Header["Authorize"]
|
||||||
|
if len(authorizeStr) == 0 {
|
||||||
|
ctx.String(http.StatusForbidden, "Fuck you!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println(authorizeStr[0])
|
||||||
|
urlParams, err := url.ParseQuery(authorizeStr[0])
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Println(urlParams)
|
||||||
|
authToken := urlParams["token"]
|
||||||
|
if len(authToken) == 0 {
|
||||||
|
ctx.String(http.StatusForbidden, "Fuck you!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
authData, err := redisCli.HGetAll(redisCtx, authToken[0]).Result()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Println(authData)
|
||||||
|
clientToken, serverToken, clientNonce := authData["client_token"], authData["server_token"], authData["nonce"]
|
||||||
|
fmt.Println(clientToken)
|
||||||
|
clientToken64, err := base64.RawStdEncoding.DecodeString(clientToken)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
serverToken64, err := base64.RawStdEncoding.DecodeString(serverToken)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
xmcKey := utils.SliceXor([]byte(clientToken64), []byte(serverToken64))
|
||||||
|
fmt.Println(xmcKey)
|
||||||
|
aesKey := xmcKey[0:16]
|
||||||
|
loginReq := model.LoginReq{}
|
||||||
|
err = json.Unmarshal([]byte(ctx.PostForm("request_data")), &loginReq)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
key64, err := base64.StdEncoding.DecodeString(loginReq.LoginKey)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
pass64, err := base64.StdEncoding.DecodeString(loginReq.LoginPasswd)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
keyDescrypted := utils.Sub16(encrypt.AES_CBC_Decrypt(key64, aesKey))
|
||||||
|
fmt.Println(string(keyDescrypted))
|
||||||
|
passDescrypted := utils.Sub16(encrypt.AES_CBC_Decrypt(pass64, aesKey))
|
||||||
|
fmt.Println(string(passDescrypted))
|
||||||
|
|
||||||
|
nonce, _ = strconv.Atoi(clientNonce)
|
||||||
|
nonce++
|
||||||
|
|
||||||
|
authorizeToken := utils.RandomBase64Token(32)
|
||||||
|
uid, err := redisCli.HGet(redisCtx, "login_key_uid", string(keyDescrypted)).Result()
|
||||||
|
if err != nil {
|
||||||
|
ctx.String(http.StatusForbidden, "Fuck you!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
userId, _ := strconv.Atoi(uid)
|
||||||
|
|
||||||
|
loginResp := model.LoginResp{}
|
||||||
|
loginResp.ResponseData.AuthorizeToken = authorizeToken
|
||||||
|
loginResp.ResponseData.UserId = userId
|
||||||
|
loginResp.ResponseData.ServerTimestamp = time.Now().Unix()
|
||||||
|
loginResp.ResponseData.AdultFlag = 2
|
||||||
|
loginResp.StatusCode = 200
|
||||||
|
resp, err := json.Marshal(loginResp)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Println(string(resp))
|
||||||
|
|
||||||
|
respTime := time.Now().Unix()
|
||||||
|
newAuthorizeStr := fmt.Sprintf("consumerKey=lovelive_test&timeStamp=%d&version=1.1&token=%s&nonce=%d&user_id=%d&requestTimeStamp=%d", respTime, authorizeToken, nonce, userId, reqTime)
|
||||||
|
fmt.Println(newAuthorizeStr)
|
||||||
|
|
||||||
|
xms := encrypt.RSA_Sign_SHA1(resp, "privatekey.pem")
|
||||||
|
xms64 := base64.RawStdEncoding.EncodeToString(xms)
|
||||||
|
|
||||||
|
ctx.Header("user_id", "")
|
||||||
|
ctx.Header("authorize", newAuthorizeStr)
|
||||||
|
ctx.Header("X-Message-Sign", xms64)
|
||||||
|
ctx.JSON(http.StatusOK, loginResp)
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"honoka-chan/resp"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func PersonalNoticeHandler(ctx *gin.Context) {
|
||||||
|
ctx.Header("Server-Version", "97.4.6")
|
||||||
|
ctx.Header("user_id", "5802913")
|
||||||
|
ctx.Header("authorize", "consumerKey=lovelive_test&timeStamp=1678640520&version=1.1&token=bS5G6TKTsw0aGxVQz8JWJTx8Tf73H0bF9Bq1PEw3UaxoEoUG8GcrrzaEbjOwEQJTrThgHpBlbwnMRl9ITGw1&nonce=5&requestTimeStamp=1678640520")
|
||||||
|
ctx.Header("X-Message-Sign", "c/J6CJPZZeGk44VLWkgCfamhFFKlLheu4e2ga2KrEl6DkVyotQTDte39RGMJS+kd5qRg/nSh/QdRGEfMLIeXB2xj3TT/UB1a03wV6slr39B+Xd2ip8BiuDKxmqpw3ESdK25WdlY+fMXbXc4RkkrleqElME7jw+VZ2SiwIgiedNg=")
|
||||||
|
ctx.String(http.StatusOK, resp.Gdpr)
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ScenarioStartupHandler(ctx *gin.Context) {
|
||||||
|
ctx.Header("Content-Type", "application/json")
|
||||||
|
ctx.Header("X-Powered-By", "KLab Native APP Platform")
|
||||||
|
ctx.Header("server_version", "20120129")
|
||||||
|
ctx.Header("Server-Version", "97.4.6")
|
||||||
|
ctx.Header("user_id", "5802913")
|
||||||
|
ctx.Header("version_up", "0")
|
||||||
|
ctx.Header("status_code", "200")
|
||||||
|
ctx.Header("authorize", "consumerKey=lovelive_test&timeStamp=1678786443&version=1.1&token=2gjbstqCHAlIv600Pk0AJN5uvfPYgLvfSKB418sMIoclOy1M9UP7LUC1CG14tPicVzOq2MBOXLvpmNRwyWIi9Qf&nonce=17&requestTimeStamp=1678786443")
|
||||||
|
ctx.Header("X-Message-Sign", "L+cK2fiaDxkRwJCmT6lpMu9RM/emmUye32RtS8C36I7OpBhGiZLbiPN30dPXITWDIUjUyPsVCqvLVzEy484Q+NHvQfDEUuS5SnKOtoNxW9Zk6kjyckjJKFIbsdH61cbb4pfzmSptcaByZ6ieNIpbHTzsvpu54JFOXb84g859Pxs=")
|
||||||
|
|
||||||
|
res := `{"response_data":{"scenario_id":1,"scenario_adjustment":50,"server_timestamp":1678785161},"release_info":[],"status_code":200}`
|
||||||
|
ctx.String(http.StatusOK, res)
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"honoka-chan/resp"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TosCheckHandler(ctx *gin.Context) {
|
||||||
|
ctx.Header("user_id", "5802913")
|
||||||
|
ctx.Header("authorize", "consumerKey=lovelive_test&timeStamp=1678640520&version=1.1&token=bS5G6TKTsw0aGxVQz8JWJTx8Tf73H0bF9Bq1PEw3UaxoEoUG8GcrrzaEbjOwEQJTrThgHpBlbwnMRl9ITGw1&nonce=6&requestTimeStamp=1678640520")
|
||||||
|
ctx.Header("X-Message-Sign", "lHGAUrSt27AAUkeB+WJCSLjs9xZdyNnDRlZVZ0VRXFhqDnVBag0lwSQEUQoedh3/FyIHazbfjuTJw9REsgSJwX05I7GW7KoqPIYNoRLiLgjM6Y7MOZWrpVdipWl0q7IPS3mKyL8ye6sRZ8TfWx8cFfnohp3U7FnvrAEWdh1h71I=")
|
||||||
|
ctx.String(http.StatusOK, resp.TosCheck)
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"honoka-chan/resp"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func SetNotificationTokenHandler(ctx *gin.Context) {
|
||||||
|
ctx.Header("Server-Version", "97.4.6")
|
||||||
|
ctx.Header("user_id", "5802913")
|
||||||
|
ctx.Header("authorize", "consumerKey=lovelive_test&timeStamp=1678891478&version=1.1&token=cTMEyAfIDErcKUyCgBM6ZuJv8UBRgSzG4z4MfqYhR7xSHBYhIA9ofaVKtSefeiP2LTKIfbnCfE5dppYw8Af&nonce=18&requestTimeStamp=1678891478")
|
||||||
|
ctx.Header("X-Message-Sign", "bNZj/YjRADDccb5vcF/NHI9Kin3bkM3ECBQdxttXvCBqzoSBX6yWuEn9Fsjx+Yp3g2D9CcONZzqJlAvXbatGHJkbClSXuomLXVOcNmQYgidjyUvC7CceoSvCbL8U4Ge12tyGd8V2EMHVZfxqPKdHsJSGaOFbUpmo7wAhKVfuEjg=")
|
||||||
|
ctx.String(http.StatusOK, resp.NotificationToken)
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"honoka-chan/resp"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func UserInfoHandler(ctx *gin.Context) {
|
||||||
|
ctx.Header("Server-Version", "97.4.6")
|
||||||
|
ctx.Header("user_id", "5802913")
|
||||||
|
ctx.Header("authorize", "consumerKey=lovelive_test&timeStamp=1678640520&version=1.1&token=bS5G6TKTsw0aGxVQz8JWJTx8Tf73H0bF9Bq1PEw3UaxoEoUG8GcrrzaEbjOwEQJTrThgHpBlbwnMRl9ITGw1&nonce=3&requestTimeStamp=1678640520")
|
||||||
|
ctx.Header("X-Message-Sign", "oa9sisoLJILWOKto4CAfb1jJwzoozpkpIAhnXl3s6m5jy75Zyb8tM+Jds6rqytnJt/labC/hFH0dhna/qqGbnTeLq6zUwHrTf8crz4uwtVi8qOBwvSbtA1dgbiKJr9raAflgJOQj6cft7XGP4bdkYfbuNxPS9gFhK+MG7b8S3Z8=")
|
||||||
|
ctx.String(http.StatusOK, resp.UserInfo)
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"honoka-chan/config"
|
||||||
|
"honoka-chan/handler"
|
||||||
|
"honoka-chan/middleware"
|
||||||
|
"honoka-chan/xclog"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
xclog.Init(config.Conf.Log.LogDir, "", config.Conf.Log.LogLevel, config.Conf.Log.LogSave)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// test
|
||||||
|
// apiData := utils.ReadAllText("data/api1.json")
|
||||||
|
// var obj model.Response
|
||||||
|
// err := json.Unmarshal([]byte(apiData), &obj)
|
||||||
|
// if err != nil {
|
||||||
|
// panic(err)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// var data interface{}
|
||||||
|
// err = json.Unmarshal(obj.ResponseData, &data)
|
||||||
|
// if err != nil {
|
||||||
|
// panic(err)
|
||||||
|
// }
|
||||||
|
// resultType := reflect.TypeOf(data)
|
||||||
|
// // fmt.Println(resultType.Kind())
|
||||||
|
// if resultType.Kind() == reflect.Map {
|
||||||
|
// data = data.(map[string]interface{})
|
||||||
|
// }
|
||||||
|
// result := data.([]interface{})
|
||||||
|
// for k, v := range result {
|
||||||
|
// m, err := json.Marshal(v)
|
||||||
|
// if err != nil {
|
||||||
|
// panic(err)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// switch k {
|
||||||
|
// case 0:
|
||||||
|
// res := model.LiveStatusResp{}
|
||||||
|
// err = json.Unmarshal(m, &res)
|
||||||
|
// if err != nil {
|
||||||
|
// panic(err)
|
||||||
|
// }
|
||||||
|
// // fmt.Println(res.Result.NormalLiveStatusList[0].HiScore)
|
||||||
|
// case 1:
|
||||||
|
// res := model.LiveScheduleResp{}
|
||||||
|
// err = json.Unmarshal(m, &res)
|
||||||
|
// if err != nil {
|
||||||
|
// panic(err)
|
||||||
|
// }
|
||||||
|
// // fmt.Println(res.Result.LiveList[0].StartDate)
|
||||||
|
// case 2:
|
||||||
|
// res := model.UnitAllResp{}
|
||||||
|
// err = json.Unmarshal(m, &res)
|
||||||
|
// if err != nil {
|
||||||
|
// panic(err)
|
||||||
|
// }
|
||||||
|
// for _, vv := range res.Result.Active {
|
||||||
|
// if vv.MaxLevel == 120 {
|
||||||
|
// fmt.Println(vv)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// router
|
||||||
|
r := gin.Default()
|
||||||
|
r.Use(middleware.KlabHeader)
|
||||||
|
|
||||||
|
r.GET("/webview.php/announce/index", handler.AnnounceIndexHandler)
|
||||||
|
|
||||||
|
r.POST("/main.php/login/authkey", handler.AuthKeyHandler)
|
||||||
|
r.POST("/main.php/login/login", handler.LoginHandler)
|
||||||
|
r.POST("/main.php/user/userInfo", handler.UserInfoHandler)
|
||||||
|
r.POST("/main.php/gdpr/get", handler.GdprHandler)
|
||||||
|
r.POST("/main.php/personalnotice/get", handler.PersonalNoticeHandler)
|
||||||
|
r.POST("/main.php/tos/tosCheck", handler.TosCheckHandler)
|
||||||
|
r.POST("/main.php/download/event", handler.DownloadEventHandler)
|
||||||
|
r.POST("/main.php/lbonus/execute", handler.LBonusExecuteHandler)
|
||||||
|
r.POST("/main.php/api", handler.ApiHandler)
|
||||||
|
r.POST("/main.php/announce/checkState", handler.AnnounceCheckStateHandler)
|
||||||
|
r.POST("/main.php/scenario/startup", handler.ScenarioStartupHandler)
|
||||||
|
r.POST("/main.php/user/setNotificationToken", handler.SetNotificationTokenHandler)
|
||||||
|
|
||||||
|
r.Run(":8080") // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"honoka-chan/config"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func KlabHeader(ctx *gin.Context) {
|
||||||
|
ctx.Header("Content-Type", "application/json; charset=utf-8")
|
||||||
|
ctx.Header("X-Powered-By", config.Conf.Server.PoweredBy)
|
||||||
|
ctx.Header("server_version", config.Conf.Server.VersionDate)
|
||||||
|
ctx.Header("version_up", config.Conf.Server.VersionUp)
|
||||||
|
ctx.Header("status_code", "200")
|
||||||
|
}
|
||||||
+518
@@ -0,0 +1,518 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import "encoding/json"
|
||||||
|
|
||||||
|
// module: live, action: liveStatus
|
||||||
|
type NormalLiveStatusList struct {
|
||||||
|
LiveDifficultyID int `json:"live_difficulty_id"`
|
||||||
|
Status int `json:"status"`
|
||||||
|
HiScore int `json:"hi_score"`
|
||||||
|
HiComboCount int `json:"hi_combo_count"`
|
||||||
|
ClearCnt int `json:"clear_cnt"`
|
||||||
|
AchievedGoalIDList []int `json:"achieved_goal_id_list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SpecialLiveStatusList struct {
|
||||||
|
LiveDifficultyID int `json:"live_difficulty_id"`
|
||||||
|
Status int `json:"status"`
|
||||||
|
HiScore int `json:"hi_score"`
|
||||||
|
HiComboCount int `json:"hi_combo_count"`
|
||||||
|
ClearCnt int `json:"clear_cnt"`
|
||||||
|
AchievedGoalIDList []int `json:"achieved_goal_id_list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TrainingLiveStatusList struct {
|
||||||
|
LiveDifficultyID int `json:"live_difficulty_id"`
|
||||||
|
Status int `json:"status"`
|
||||||
|
HiScore int `json:"hi_score"`
|
||||||
|
HiComboCount int `json:"hi_combo_count"`
|
||||||
|
ClearCnt int `json:"clear_cnt"`
|
||||||
|
AchievedGoalIDList []int `json:"achieved_goal_id_list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LiveStatusResult struct {
|
||||||
|
NormalLiveStatusList []NormalLiveStatusList `json:"normal_live_status_list"`
|
||||||
|
SpecialLiveStatusList []SpecialLiveStatusList `json:"special_live_status_list"`
|
||||||
|
TrainingLiveStatusList []TrainingLiveStatusList `json:"training_live_status_list"`
|
||||||
|
MarathonLiveStatusList []interface{} `json:"marathon_live_status_list"`
|
||||||
|
FreeLiveStatusList []interface{} `json:"free_live_status_list"`
|
||||||
|
CanResumeLive bool `json:"can_resume_live"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LiveStatusResp struct {
|
||||||
|
Result LiveStatusResult `json:"result"`
|
||||||
|
Status int `json:"status"`
|
||||||
|
CommandNum bool `json:"commandNum"`
|
||||||
|
TimeStamp int64 `json:"timeStamp"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// module: live, action: schedule
|
||||||
|
type LiveList struct {
|
||||||
|
LiveDifficultyID int `json:"live_difficulty_id"`
|
||||||
|
StartDate string `json:"start_date"`
|
||||||
|
EndDate string `json:"end_date"`
|
||||||
|
IsRandom bool `json:"is_random"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LimitedBonusCommonList struct {
|
||||||
|
LiveType int `json:"live_type"`
|
||||||
|
LimitedBonusType int `json:"limited_bonus_type"`
|
||||||
|
LimitedBonusValue int `json:"limited_bonus_value"`
|
||||||
|
StartDate string `json:"start_date"`
|
||||||
|
EndDate string `json:"end_date"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RandomLiveList struct {
|
||||||
|
AttributeID int `json:"attribute_id"`
|
||||||
|
StartDate string `json:"start_date"`
|
||||||
|
EndDate string `json:"end_date"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TrainingLiveList struct {
|
||||||
|
LiveDifficultyID int `json:"live_difficulty_id"`
|
||||||
|
StartDate string `json:"start_date"`
|
||||||
|
IsRandom bool `json:"is_random"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LiveScheduleResult struct {
|
||||||
|
EventList []interface{} `json:"event_list"`
|
||||||
|
LiveList []LiveList `json:"live_list"`
|
||||||
|
LimitedBonusList []interface{} `json:"limited_bonus_list"`
|
||||||
|
LimitedBonusCommonList []LimitedBonusCommonList `json:"limited_bonus_common_list"`
|
||||||
|
RandomLiveList []RandomLiveList `json:"random_live_list"`
|
||||||
|
FreeLiveList []interface{} `json:"free_live_list"`
|
||||||
|
TrainingLiveList []TrainingLiveList `json:"training_live_list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LiveScheduleResp struct {
|
||||||
|
Result LiveScheduleResult `json:"result"`
|
||||||
|
Status int `json:"status"`
|
||||||
|
CommandNum bool `json:"commandNum"`
|
||||||
|
TimeStamp int64 `json:"timeStamp"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// module: unit, action: unitAll
|
||||||
|
type Costume struct {
|
||||||
|
UnitID int `json:"unit_id"`
|
||||||
|
IsRankMax bool `json:"is_rank_max"`
|
||||||
|
IsSigned bool `json:"is_signed"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Active struct {
|
||||||
|
UnitOwningUserID int `json:"unit_owning_user_id"`
|
||||||
|
UnitID int `json:"unit_id"`
|
||||||
|
Exp int `json:"exp"`
|
||||||
|
NextExp int `json:"next_exp"`
|
||||||
|
Level int `json:"level"`
|
||||||
|
MaxLevel int `json:"max_level"`
|
||||||
|
LevelLimitID int `json:"level_limit_id"`
|
||||||
|
Rank int `json:"rank"`
|
||||||
|
MaxRank int `json:"max_rank"`
|
||||||
|
Love int `json:"love"`
|
||||||
|
MaxLove int `json:"max_love"`
|
||||||
|
UnitSkillExp int `json:"unit_skill_exp"`
|
||||||
|
UnitSkillLevel int `json:"unit_skill_level"`
|
||||||
|
MaxHp int `json:"max_hp"`
|
||||||
|
UnitRemovableSkillCapacity int `json:"unit_removable_skill_capacity"`
|
||||||
|
FavoriteFlag bool `json:"favorite_flag"`
|
||||||
|
DisplayRank int `json:"display_rank"`
|
||||||
|
IsRankMax bool `json:"is_rank_max"`
|
||||||
|
IsLoveMax bool `json:"is_love_max"`
|
||||||
|
IsLevelMax bool `json:"is_level_max"`
|
||||||
|
IsSigned bool `json:"is_signed"`
|
||||||
|
IsSkillLevelMax bool `json:"is_skill_level_max"`
|
||||||
|
IsRemovableSkillCapacityMax bool `json:"is_removable_skill_capacity_max"`
|
||||||
|
InsertDate string `json:"insert_date"`
|
||||||
|
Costume Costume `json:"costume,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Waiting struct {
|
||||||
|
UnitOwningUserID int64 `json:"unit_owning_user_id"`
|
||||||
|
UnitID int `json:"unit_id"`
|
||||||
|
Exp int `json:"exp"`
|
||||||
|
NextExp int `json:"next_exp"`
|
||||||
|
Level int `json:"level"`
|
||||||
|
MaxLevel int `json:"max_level"`
|
||||||
|
LevelLimitID int `json:"level_limit_id"`
|
||||||
|
Rank int `json:"rank"`
|
||||||
|
MaxRank int `json:"max_rank"`
|
||||||
|
Love int `json:"love"`
|
||||||
|
MaxLove int `json:"max_love"`
|
||||||
|
UnitSkillExp int `json:"unit_skill_exp"`
|
||||||
|
UnitSkillLevel int `json:"unit_skill_level"`
|
||||||
|
MaxHp int `json:"max_hp"`
|
||||||
|
UnitRemovableSkillCapacity int `json:"unit_removable_skill_capacity"`
|
||||||
|
FavoriteFlag bool `json:"favorite_flag"`
|
||||||
|
DisplayRank int `json:"display_rank"`
|
||||||
|
IsRankMax bool `json:"is_rank_max"`
|
||||||
|
IsLoveMax bool `json:"is_love_max"`
|
||||||
|
IsLevelMax bool `json:"is_level_max"`
|
||||||
|
IsSigned bool `json:"is_signed"`
|
||||||
|
IsSkillLevelMax bool `json:"is_skill_level_max"`
|
||||||
|
IsRemovableSkillCapacityMax bool `json:"is_removable_skill_capacity_max"`
|
||||||
|
InsertDate string `json:"insert_date"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UnitAllResult struct {
|
||||||
|
Active []Active `json:"active"`
|
||||||
|
Waiting []Waiting `json:"waiting"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UnitAllResp struct {
|
||||||
|
Result UnitAllResult `json:"result"`
|
||||||
|
Status int `json:"status"`
|
||||||
|
CommandNum bool `json:"commandNum"`
|
||||||
|
TimeStamp int64 `json:"timeStamp"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// module: unit, action: deckInfo
|
||||||
|
type UnitOwningUserIds struct {
|
||||||
|
Position int `json:"position"`
|
||||||
|
UnitOwningUserID int64 `json:"unit_owning_user_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UnitDeckInfo struct {
|
||||||
|
UnitDeckID int `json:"unit_deck_id"`
|
||||||
|
MainFlag bool `json:"main_flag"`
|
||||||
|
DeckName string `json:"deck_name"`
|
||||||
|
UnitOwningUserIds []UnitOwningUserIds `json:"unit_owning_user_ids"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UnitDeckInfoResult struct {
|
||||||
|
UnitDeckInfo []UnitDeckInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
// module: unit, action: supporterAll
|
||||||
|
type UnitSupportList struct {
|
||||||
|
UnitID int `json:"unit_id"`
|
||||||
|
Amount int `json:"amount"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UnitSupporterAllResult struct {
|
||||||
|
UnitSupportList []UnitSupportList `json:"unit_support_list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// module: unit, action: removableSkillInfo
|
||||||
|
|
||||||
|
// module: costume, action: costumeList
|
||||||
|
type CostumeList struct {
|
||||||
|
UnitID int `json:"unit_id"`
|
||||||
|
IsRankMax bool `json:"is_rank_max"`
|
||||||
|
IsSigned bool `json:"is_signed"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CostumeListResult struct {
|
||||||
|
CostumeList []CostumeList `json:"costume_list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// module: album, action: albumAll
|
||||||
|
type AlbumAll struct {
|
||||||
|
UnitID int `json:"unit_id"`
|
||||||
|
RankMaxFlag bool `json:"rank_max_flag"`
|
||||||
|
LoveMaxFlag bool `json:"love_max_flag"`
|
||||||
|
RankLevelMaxFlag bool `json:"rank_level_max_flag"`
|
||||||
|
AllMaxFlag bool `json:"all_max_flag"`
|
||||||
|
HighestLovePerUnit int `json:"highest_love_per_unit"`
|
||||||
|
TotalLove int `json:"total_love"`
|
||||||
|
FavoritePoint int `json:"favorite_point"`
|
||||||
|
SignFlag bool `json:"sign_flag"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AlbumAllResult struct {
|
||||||
|
AlbumAll []AlbumAll
|
||||||
|
}
|
||||||
|
|
||||||
|
// module: scenario, action: scenarioStatus
|
||||||
|
type ScenarioStatusList struct {
|
||||||
|
ScenarioID int `json:"scenario_id"`
|
||||||
|
Status int `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ScenarioStatusResult struct {
|
||||||
|
ScenarioStatusList []ScenarioStatusList `json:"scenario_status_list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// module: subscenario, action: subscenarioStatus
|
||||||
|
type SubscenarioStatusList struct {
|
||||||
|
SubscenarioID int `json:"subscenario_id"`
|
||||||
|
Status int `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SubscenarioStatusResult struct {
|
||||||
|
SubscenarioStatusList []SubscenarioStatusList `json:"subscenario_status_list"`
|
||||||
|
UnlockedSubscenarioIds []interface{} `json:"unlocked_subscenario_ids"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// module: eventscenario, action: status
|
||||||
|
type EventScenarioChapterList struct {
|
||||||
|
EventScenarioID int `json:"event_scenario_id"`
|
||||||
|
Chapter int `json:"chapter"`
|
||||||
|
ChapterAsset string `json:"chapter_asset"`
|
||||||
|
Status int `json:"status"`
|
||||||
|
OpenFlashFlag int `json:"open_flash_flag"`
|
||||||
|
IsReward bool `json:"is_reward"`
|
||||||
|
CostType int `json:"cost_type"`
|
||||||
|
ItemID int `json:"item_id"`
|
||||||
|
Amount int `json:"amount"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type EventScenarioList struct {
|
||||||
|
EventID int `json:"event_id"`
|
||||||
|
EventScenarioBtnAsset string `json:"event_scenario_btn_asset"`
|
||||||
|
OpenDate string `json:"open_date"`
|
||||||
|
ChapterList []EventScenarioChapterList `json:"chapter_list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type EventScenarioStatusResult struct {
|
||||||
|
EventScenarioList []EventScenarioList `json:"event_scenario_list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// module: multiunit, action: multiunitscenarioStatus
|
||||||
|
type MultiUnitScenarioChapterList struct {
|
||||||
|
MultiUnitScenarioID int `json:"multi_unit_scenario_id"`
|
||||||
|
Chapter int `json:"chapter"`
|
||||||
|
Status int `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MultiUnitScenarioStatusList struct {
|
||||||
|
MultiUnitID int `json:"multi_unit_id"`
|
||||||
|
Status int `json:"status"`
|
||||||
|
MultiUnitScenarioBtnAsset string `json:"multi_unit_scenario_btn_asset"`
|
||||||
|
OpenDate string `json:"open_date"`
|
||||||
|
ChapterList []MultiUnitScenarioChapterList `json:"chapter_list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MultiUnitScenarioStatusResult struct {
|
||||||
|
MultiUnitScenarioStatusList []MultiUnitScenarioStatusList `json:"multi_unit_scenario_status_list"`
|
||||||
|
UnlockedMultiUnitScenarioIds []interface{} `json:"unlocked_multi_unit_scenario_ids"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// module: payment, action: productList
|
||||||
|
type RestrictionInfo struct {
|
||||||
|
Restricted bool `json:"restricted"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UnderAgeInfo struct {
|
||||||
|
BirthSet bool `json:"birth_set"`
|
||||||
|
HasLimit bool `json:"has_limit"`
|
||||||
|
LimitAmount interface{} `json:"limit_amount"`
|
||||||
|
MonthUsed int `json:"month_used"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SnsProductItemList struct {
|
||||||
|
ItemID int `json:"item_id"`
|
||||||
|
AddType int `json:"add_type"`
|
||||||
|
Amount int `json:"amount"`
|
||||||
|
IsFreebie bool `json:"is_freebie"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SnsProductList struct {
|
||||||
|
ProductID string `json:"product_id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Price int `json:"price"`
|
||||||
|
CanBuy bool `json:"can_buy"`
|
||||||
|
ProductType int `json:"product_type"`
|
||||||
|
ItemList []SnsProductItemList `json:"item_list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProductItemList struct {
|
||||||
|
ItemID int `json:"item_id"`
|
||||||
|
AddType int `json:"add_type"`
|
||||||
|
Amount int `json:"amount"`
|
||||||
|
IsFreebie bool `json:"is_freebie"`
|
||||||
|
IsRankMax bool `json:"is_rank_max,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LimitStatus struct {
|
||||||
|
TermStartDate string `json:"term_start_date"`
|
||||||
|
RemainingTime string `json:"remaining_time"`
|
||||||
|
RemainingCount int `json:"remaining_count"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProductList struct {
|
||||||
|
ProductID string `json:"product_id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
BannerImgAsset string `json:"banner_img_asset"`
|
||||||
|
Price int `json:"price"`
|
||||||
|
CanBuy bool `json:"can_buy"`
|
||||||
|
ProductType int `json:"product_type"`
|
||||||
|
AnnounceURL string `json:"announce_url"`
|
||||||
|
ConfirmURL string `json:"confirm_url"`
|
||||||
|
ItemList []ProductItemList `json:"item_list"`
|
||||||
|
LimitStatus LimitStatus `json:"limit_status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SubscriptionItemList struct {
|
||||||
|
ItemID int `json:"item_id"`
|
||||||
|
AddType int `json:"add_type"`
|
||||||
|
Amount int `json:"amount"`
|
||||||
|
IsFreebie bool `json:"is_freebie"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RewardList struct {
|
||||||
|
ItemID int `json:"item_id"`
|
||||||
|
AddType int `json:"add_type"`
|
||||||
|
Amount int `json:"amount"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Items struct {
|
||||||
|
Seq int `json:"seq"`
|
||||||
|
RewardList []RewardList `json:"reward_list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LicenseInfo struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Items []Items `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserStatus struct {
|
||||||
|
IsLicensed bool `json:"is_licensed"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SubscriptionStatus struct {
|
||||||
|
LicenseID int `json:"license_id"`
|
||||||
|
LicenseType int `json:"license_type"`
|
||||||
|
LicenseInfo LicenseInfo `json:"license_info,omitempty"`
|
||||||
|
UserStatus UserStatus `json:"user_status"`
|
||||||
|
PurchaseCount int `json:"purchase_count"`
|
||||||
|
BadgeFlag bool `json:"badge_flag"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SubscriptionList struct {
|
||||||
|
ProductID string `json:"product_id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
BannerImgAsset string `json:"banner_img_asset"`
|
||||||
|
Price int `json:"price"`
|
||||||
|
CanBuy bool `json:"can_buy"`
|
||||||
|
ProductType int `json:"product_type"`
|
||||||
|
ProductURL string `json:"product_url"`
|
||||||
|
ItemList []SubscriptionItemList `json:"item_list"`
|
||||||
|
LimitStatus LimitStatus `json:"limit_status"`
|
||||||
|
SubscriptionStatus SubscriptionStatus `json:"subscription_status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProductListResult struct {
|
||||||
|
RestrictionInfo RestrictionInfo `json:"restriction_info"`
|
||||||
|
UnderAgeInfo UnderAgeInfo `json:"under_age_info"`
|
||||||
|
SnsProductList []SnsProductList `json:"sns_product_list"`
|
||||||
|
ProductList []ProductList `json:"product_list"`
|
||||||
|
SubscriptionList []SubscriptionList `json:"subscription_list"`
|
||||||
|
ShowPointShop bool `json:"show_point_shop"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// module: banner, action: bannerList
|
||||||
|
type BannerList struct {
|
||||||
|
BannerType int `json:"banner_type"`
|
||||||
|
TargetID int `json:"target_id"`
|
||||||
|
AssetPath string `json:"asset_path"`
|
||||||
|
FixedFlag bool `json:"fixed_flag"`
|
||||||
|
BackSide bool `json:"back_side"`
|
||||||
|
BannerID int `json:"banner_id"`
|
||||||
|
StartDate string `json:"start_date"`
|
||||||
|
EndDate string `json:"end_date"`
|
||||||
|
AddUnitStartDate string `json:"add_unit_start_date,omitempty"`
|
||||||
|
WebviewURL string `json:"webview_url,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type BannerListResult struct {
|
||||||
|
TimeLimit string `json:"time_limit"`
|
||||||
|
BannerList []BannerList `json:"banner_list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// module: notice, action: noticeMarquee
|
||||||
|
type NoticeMarqueeResult struct {
|
||||||
|
ItemCount int `json:"item_count"`
|
||||||
|
MarqueeList []interface{} `json:"marquee_list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// module: user, action: getNavi
|
||||||
|
type User struct {
|
||||||
|
UserID int `json:"user_id"`
|
||||||
|
UnitOwningUserID int64 `json:"unit_owning_user_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserNaviResult struct {
|
||||||
|
User User `json:"user"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// module: navigation, action: specialCutin
|
||||||
|
type SpecialCutinResult struct {
|
||||||
|
SpecialCutinList []interface{} `json:"special_cutin_list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// module: award, action: awardInfo
|
||||||
|
type AwardInfo struct {
|
||||||
|
AwardID int `json:"award_id"`
|
||||||
|
IsSet bool `json:"is_set"`
|
||||||
|
InsertDate string `json:"insert_date"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AwardInfoResult struct {
|
||||||
|
AwardInfo []AwardInfo `json:"award_info"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// module: background, action: backgroundInfo
|
||||||
|
type BackgroundInfo struct {
|
||||||
|
BackgroundID int `json:"background_id"`
|
||||||
|
IsSet bool `json:"is_set"`
|
||||||
|
InsertDate string `json:"insert_date"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type BackgroundInfoResult struct {
|
||||||
|
BackgroundInfo []BackgroundInfo `json:"background_info"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// module: stamp, action: stampInfo
|
||||||
|
type StampList struct {
|
||||||
|
Position int `json:"position"`
|
||||||
|
StampID int `json:"stamp_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type SettingList struct {
|
||||||
|
StampSettingID int `json:"stamp_setting_id"`
|
||||||
|
MainFlag int `json:"main_flag"`
|
||||||
|
StampList []StampList `json:"stamp_list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type StampSetting struct {
|
||||||
|
StampType int `json:"stamp_type"`
|
||||||
|
SettingList []SettingList `json:"setting_list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type StampInfoResult struct {
|
||||||
|
OwningStampIds []int `json:"owning_stamp_ids"`
|
||||||
|
StampSetting []StampSetting `json:"stamp_setting"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// module: exchange, action: owningPoint
|
||||||
|
type ExchangePointList struct {
|
||||||
|
Rarity int `json:"rarity"`
|
||||||
|
ExchangePoint int `json:"exchange_point"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type OwningPointResult struct {
|
||||||
|
ExchangePointList []ExchangePointList `json:"exchange_point_list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// module: livese, action: liveseInfo
|
||||||
|
type LiveSeInfoResult struct {
|
||||||
|
LiveSeList []int `json:"live_se_list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// module: liveicon, action: liveiconInfo
|
||||||
|
type LiveIconInfoResult struct {
|
||||||
|
LiveNotesIconList []int `json:"live_notes_icon_list"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// module: item, action: list
|
||||||
|
|
||||||
|
// module: marathon, action: marathonInfo
|
||||||
|
|
||||||
|
// module: challenge, action: challengeInfo
|
||||||
|
|
||||||
|
// response_data
|
||||||
|
type Response struct {
|
||||||
|
ResponseData json.RawMessage `json:"response_data"`
|
||||||
|
ReleaseInfo []interface{} `json:"release_info"`
|
||||||
|
StatusCode int `json:"status_code"`
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
type SifApi struct {
|
||||||
|
Module string `json:"module"`
|
||||||
|
Action string `json:"action"`
|
||||||
|
Timestamp int64 `json:"timeStamp"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AuthKeyReq struct {
|
||||||
|
DummyToken string `json:"dummy_token"`
|
||||||
|
AuthData string `json:"auth_data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AuthKeyResp struct {
|
||||||
|
ResponseData struct {
|
||||||
|
AuthorizeToken string `json:"authorize_token"`
|
||||||
|
DummyToken string `json:"dummy_token"`
|
||||||
|
} `json:"response_data"`
|
||||||
|
ReleaseInfo [0]interface{} `json:"release_info"`
|
||||||
|
StatusCode int `json:"status_code"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoginReq struct {
|
||||||
|
LoginKey string `json:"login_key"`
|
||||||
|
LoginPasswd string `json:"login_passwd"`
|
||||||
|
DevToken string `json:"devtoken"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoginResp struct {
|
||||||
|
ResponseData struct {
|
||||||
|
AuthorizeToken string `json:"authorize_token"`
|
||||||
|
UserId int `json:"user_id"`
|
||||||
|
ReviewVersion string `json:"review_version"`
|
||||||
|
ServerTimestamp int64 `json:"server_timestamp"`
|
||||||
|
IdfaEnabled bool `json:"idfa_enabled"`
|
||||||
|
SkipLoginNews bool `json:"skip_login_news"`
|
||||||
|
AdultFlag int `json:"adult_flag"`
|
||||||
|
} `json:"response_data"`
|
||||||
|
ReleaseInfo [0]interface{} `json:"release_info"`
|
||||||
|
StatusCode int `json:"status_code"`
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,60 @@
|
|||||||
|
// Copyright (C) 2021-2023 YumeMichi
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/hex"
|
||||||
|
"math/rand"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func PathExists(path string) bool {
|
||||||
|
_, err := os.Stat(path)
|
||||||
|
return err == nil || os.IsExist(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadAllText(path string) string {
|
||||||
|
b, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteAllText(path, text string) {
|
||||||
|
_ = os.WriteFile(path, []byte(text), 0644)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SliceXor(s1, s2 []byte) (res []byte) {
|
||||||
|
for k, b := range s1 {
|
||||||
|
newBt := b ^ s2[k]
|
||||||
|
res = append(res, newBt)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func Sub16(str []byte) []byte {
|
||||||
|
return str[16:]
|
||||||
|
}
|
||||||
|
|
||||||
|
func RandomStr(len int) string {
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
mRand := make([]byte, len)
|
||||||
|
rand.Read(mRand)
|
||||||
|
mRandStr := hex.EncodeToString(mRand)[0:len]
|
||||||
|
|
||||||
|
return mRandStr
|
||||||
|
}
|
||||||
|
|
||||||
|
func RandomBase64Token(len int) string {
|
||||||
|
rand.NewSource(time.Now().UnixNano())
|
||||||
|
mRand := make([]byte, len)
|
||||||
|
rand.Read(mRand)
|
||||||
|
mRandStr := hex.EncodeToString(mRand)[0:len]
|
||||||
|
|
||||||
|
return base64.RawStdEncoding.EncodeToString([]byte(mRandStr))
|
||||||
|
}
|
||||||
+257
@@ -0,0 +1,257 @@
|
|||||||
|
// Copyright (C) 2022 YumeMichi
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
package xclog
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Logg 日志
|
||||||
|
type Logg struct {
|
||||||
|
fileDir string
|
||||||
|
fileName string
|
||||||
|
filePre string
|
||||||
|
saveFile bool
|
||||||
|
level int
|
||||||
|
date string
|
||||||
|
log *log.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
// LogConf config struct of log
|
||||||
|
type LogConf struct {
|
||||||
|
FileDir string `json:"file_dir"`
|
||||||
|
FilePre string `json:"file_pre"`
|
||||||
|
Level int `json:"level"`
|
||||||
|
SaveFile bool `json:"save_file"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
lgg *Logg
|
||||||
|
levelLinePre = map[int]string{
|
||||||
|
1: "[F]",
|
||||||
|
2: "[E]",
|
||||||
|
3: "[W]",
|
||||||
|
4: "[I]",
|
||||||
|
5: "[D]",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// 为防止未初始化调用奔溃,使用init默认参数初始化
|
||||||
|
func init() {
|
||||||
|
lgg, _ = New("./", "", "", 5, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init 使用参数初始化
|
||||||
|
func Init(fileDir, filePre string, level int, saveFile bool) (*Logg, error) {
|
||||||
|
var fileName string
|
||||||
|
|
||||||
|
if level > 5 || level < 1 {
|
||||||
|
level = 5
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.HasSuffix(fileDir, "/") {
|
||||||
|
fileDir = fileDir + "/"
|
||||||
|
} else if fileDir == "" {
|
||||||
|
fileDir = "./"
|
||||||
|
}
|
||||||
|
|
||||||
|
date := getNowDate()
|
||||||
|
|
||||||
|
if filePre != "" {
|
||||||
|
filePre = filePre + "_"
|
||||||
|
}
|
||||||
|
stat, err := os.Stat(fileDir)
|
||||||
|
if err != nil && os.IsNotExist(err) {
|
||||||
|
os.MkdirAll(fileDir, 0777)
|
||||||
|
} else if err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if !stat.IsDir() {
|
||||||
|
return nil, errors.New("log_dir is not dir:" + fileDir)
|
||||||
|
}
|
||||||
|
fileName = fileDir + filePre + date + ".log"
|
||||||
|
newLogg, err := New(fileDir, filePre, fileName, level, saveFile)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Init log error:", err.Error())
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
lgg = newLogg
|
||||||
|
return lgg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// InitByLogConf
|
||||||
|
func InitByLogConf(lc LogConf) (*Logg, error) {
|
||||||
|
return Init(lc.FileDir, lc.FilePre, lc.Level, lc.SaveFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
// New 返回一个日志实体,与默认不同的独立的日志,通过返回的Logg调用方法
|
||||||
|
func New(fileDir, filePre, fileName string, level int, saveFile bool) (*Logg, error) {
|
||||||
|
// file, err := os.Create(fileName)
|
||||||
|
var newLogg = &Logg{
|
||||||
|
fileDir: fileDir,
|
||||||
|
filePre: filePre,
|
||||||
|
date: getNowDate(),
|
||||||
|
level: level,
|
||||||
|
fileName: fileName,
|
||||||
|
saveFile: saveFile,
|
||||||
|
}
|
||||||
|
|
||||||
|
if saveFile {
|
||||||
|
file, err := os.OpenFile(fileName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, os.ModeAppend)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
os.Chmod(fileName, 0777)
|
||||||
|
newLogg.log = log.New(file, "", 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return newLogg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getNowDate() string {
|
||||||
|
return time.Now().Format("2006-01-02")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug Debug
|
||||||
|
func Debug(args ...interface{}) {
|
||||||
|
lgg.Debug(args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debugf Debugf
|
||||||
|
func Debugf(format string, args ...interface{}) {
|
||||||
|
lgg.Debugf(format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug Debug
|
||||||
|
func (lg *Logg) Debug(args ...interface{}) {
|
||||||
|
lg.writeLine(5, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debugf format debug
|
||||||
|
func (lg *Logg) Debugf(format string, args ...interface{}) {
|
||||||
|
lg.writeLine(5, fmt.Sprintf(format, args...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Info Info
|
||||||
|
func Info(args ...interface{}) {
|
||||||
|
lgg.Info(args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Infof Infof
|
||||||
|
func Infof(format string, args ...interface{}) {
|
||||||
|
lgg.Infof(format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Info Info
|
||||||
|
func (lg *Logg) Info(args ...interface{}) {
|
||||||
|
lg.writeLine(4, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Infof format debug
|
||||||
|
func (lg *Logg) Infof(format string, args ...interface{}) {
|
||||||
|
lg.writeLine(4, fmt.Sprintf(format, args...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warn Warn
|
||||||
|
func Warn(args ...interface{}) {
|
||||||
|
lgg.Warn(args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warnf Warnf
|
||||||
|
func Warnf(format string, args ...interface{}) {
|
||||||
|
lgg.Warnf(format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warn Warn
|
||||||
|
func (lg *Logg) Warn(args ...interface{}) {
|
||||||
|
lg.writeLine(3, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warnf format debug
|
||||||
|
func (lg *Logg) Warnf(format string, args ...interface{}) {
|
||||||
|
lg.writeLine(3, fmt.Sprintf(format, args...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error Error
|
||||||
|
func Error(args ...interface{}) {
|
||||||
|
lgg.Error(args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errorf Errorf
|
||||||
|
func Errorf(format string, args ...interface{}) {
|
||||||
|
lgg.Errorf(format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error Error
|
||||||
|
func (lg *Logg) Error(args ...interface{}) {
|
||||||
|
lg.writeLine(2, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errorf format debug
|
||||||
|
func (lg *Logg) Errorf(format string, args ...interface{}) {
|
||||||
|
lg.writeLine(2, fmt.Sprintf(format, args...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fatal Fatal
|
||||||
|
func Fatal(args ...interface{}) {
|
||||||
|
lgg.Fatal(args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fatalf Fatalf
|
||||||
|
func Fatalf(format string, args ...interface{}) {
|
||||||
|
lgg.Fatalf(format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fatal Fatal
|
||||||
|
func (lg *Logg) Fatal(args ...interface{}) {
|
||||||
|
lg.writeLine(1, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fatalf format debug
|
||||||
|
func (lg *Logg) Fatalf(format string, args ...interface{}) {
|
||||||
|
lg.writeLine(1, fmt.Sprintf(format, args...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeLine ...
|
||||||
|
func (lg *Logg) writeLine(level int, args ...interface{}) {
|
||||||
|
_, file, line, _ := runtime.Caller(3)
|
||||||
|
fileArr := strings.Split(file, "/")
|
||||||
|
a := []interface{}{time.Now().Format("2006/01/02 15:04:05"), fileArr[len(fileArr)-1] + ":" + strconv.Itoa(line) + ":", levelLinePre[level]}
|
||||||
|
a = append(a, args...)
|
||||||
|
if !lg.saveFile {
|
||||||
|
fmt.Println(a...)
|
||||||
|
if level == 1 {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
nowDate := getNowDate()
|
||||||
|
if nowDate != lg.date {
|
||||||
|
// 切割日志文件
|
||||||
|
newFile := lg.fileDir + lg.filePre + nowDate + ".log"
|
||||||
|
f, err := os.OpenFile(newFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, os.ModeAppend)
|
||||||
|
if err != nil {
|
||||||
|
lg.log.Println("[E]", "create new log file:", err.Error())
|
||||||
|
} else {
|
||||||
|
lg.log.SetOutput(f)
|
||||||
|
lg.date = nowDate
|
||||||
|
lg.fileName = newFile
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if level == 1 {
|
||||||
|
lg.log.Fatal(a...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if level <= lg.level {
|
||||||
|
lg.log.Println(a...)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user