fortune 增加设置底图并加速base64 和下载

This commit is contained in:
fumiama 2021-10-09 12:30:59 +08:00
parent 3faec79371
commit a5d0b8db8e
7 changed files with 550 additions and 79 deletions

21
data/dl.go Normal file
View File

@ -0,0 +1,21 @@
package data
import (
"io"
"net/http"
"os"
)
func DownloadTo(url, file string) error {
resp, err := http.Get(url)
if err == nil {
var f *os.File
f, err = os.Create(file)
if err == nil {
_, err = io.Copy(f, resp.Body)
resp.Body.Close()
f.Close()
}
}
return err
}

15
data/mem.go Normal file
View File

@ -0,0 +1,15 @@
package data
import "unsafe"
// Str2bytes Fast convert
func Str2bytes(s string) []byte {
x := (*[2]uintptr)(unsafe.Pointer(&s))
h := [3]uintptr{x[0], x[1], x[1]}
return *(*[]byte)(unsafe.Pointer(&h))
}
// Bytes2str Fast convert
func Bytes2str(b []byte) string {
return *(*string)(unsafe.Pointer(&b))
}

View File

@ -8,8 +8,8 @@ import (
"os" "os"
"sync" "sync"
"time" "time"
"unsafe"
"github.com/FloatTech/ZeroBot-Plugin/data"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
@ -42,7 +42,7 @@ func init() {
log.Printf("[Diana]读取%d条小作文", arrl) log.Printf("[Diana]读取%d条小作文", arrl)
md5s = make([]*[16]byte, arrl) md5s = make([]*[16]byte, arrl)
for i, t := range *Array { for i, t := range *Array {
m := md5.Sum(str2bytes(t)) m := md5.Sum(data.Str2bytes(t))
md5s[i] = &m md5s[i] = &m
} }
} else { } else {
@ -92,7 +92,7 @@ func LoadText() error {
// AddText 添加小作文 // AddText 添加小作文
func AddText(txt string) error { func AddText(txt string) error {
sum := md5.Sum(str2bytes(txt)) sum := md5.Sum(data.Str2bytes(txt))
if txt != "" && !isin(&sum) { if txt != "" && !isin(&sum) {
m.Lock() m.Lock()
defer m.Unlock() defer m.Unlock()
@ -128,10 +128,3 @@ func savecompo() error {
} }
return err return err
} }
// str2bytes Fast convert
func str2bytes(s string) []byte {
x := (*[2]uintptr)(unsafe.Pointer(&s))
h := [3]uintptr{x[0], x[1], x[1]}
return *(*[]byte)(unsafe.Pointer(&h))
}

405
plugin_fortune/cfg.pb.go Normal file
View File

@ -0,0 +1,405 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: cfg.proto
package fortune
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
io "io"
math "math"
math_bits "math/bits"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type Conf struct {
Kind map[int64]uint32 `protobuf:"bytes,1,rep,name=kind,proto3" json:"kind,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Conf) Reset() { *m = Conf{} }
func (m *Conf) String() string { return proto.CompactTextString(m) }
func (*Conf) ProtoMessage() {}
func (*Conf) Descriptor() ([]byte, []int) {
return fileDescriptor_f81ba022997f8a9d, []int{0}
}
func (m *Conf) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *Conf) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_Conf.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *Conf) XXX_Merge(src proto.Message) {
xxx_messageInfo_Conf.Merge(m, src)
}
func (m *Conf) XXX_Size() int {
return m.Size()
}
func (m *Conf) XXX_DiscardUnknown() {
xxx_messageInfo_Conf.DiscardUnknown(m)
}
var xxx_messageInfo_Conf proto.InternalMessageInfo
func (m *Conf) GetKind() map[int64]uint32 {
if m != nil {
return m.Kind
}
return nil
}
func init() {
proto.RegisterType((*Conf)(nil), "fortune.conf")
proto.RegisterMapType((map[int64]uint32)(nil), "fortune.conf.KindEntry")
}
func init() { proto.RegisterFile("cfg.proto", fileDescriptor_f81ba022997f8a9d) }
var fileDescriptor_f81ba022997f8a9d = []byte{
// 154 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4c, 0x4e, 0x4b, 0xd7,
0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x4f, 0xcb, 0x2f, 0x2a, 0x29, 0xcd, 0x4b, 0x55, 0xca,
0xe1, 0x62, 0x49, 0xce, 0xcf, 0x4b, 0x13, 0xd2, 0xe6, 0x62, 0xc9, 0xce, 0xcc, 0x4b, 0x91, 0x60,
0x54, 0x60, 0xd6, 0xe0, 0x36, 0x12, 0xd7, 0x83, 0xca, 0xeb, 0x81, 0x24, 0xf5, 0xbc, 0x33, 0xf3,
0x52, 0x5c, 0xf3, 0x4a, 0x8a, 0x2a, 0x83, 0xc0, 0x8a, 0xa4, 0xcc, 0xb9, 0x38, 0xe1, 0x42, 0x42,
0x02, 0x5c, 0xcc, 0xd9, 0xa9, 0x95, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0xcc, 0x41, 0x20, 0xa6, 0x90,
0x08, 0x17, 0x6b, 0x59, 0x62, 0x4e, 0x69, 0xaa, 0x04, 0x93, 0x02, 0xa3, 0x06, 0x6f, 0x10, 0x84,
0x63, 0xc5, 0x64, 0xc1, 0xe8, 0x24, 0x70, 0xe2, 0x91, 0x1c, 0xe3, 0x85, 0x47, 0x72, 0x8c, 0x0f,
0x1e, 0xc9, 0x31, 0xce, 0x78, 0x2c, 0xc7, 0x90, 0xc4, 0x06, 0x76, 0x8f, 0x31, 0x20, 0x00, 0x00,
0xff, 0xff, 0x8a, 0xa2, 0xbe, 0x9e, 0x9c, 0x00, 0x00, 0x00,
}
func (m *Conf) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *Conf) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *Conf) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.XXX_unrecognized != nil {
i -= len(m.XXX_unrecognized)
copy(dAtA[i:], m.XXX_unrecognized)
}
if len(m.Kind) > 0 {
for k := range m.Kind {
v := m.Kind[k]
baseI := i
i = encodeVarintCfg(dAtA, i, uint64(v))
i--
dAtA[i] = 0x10
i = encodeVarintCfg(dAtA, i, uint64(k))
i--
dAtA[i] = 0x8
i = encodeVarintCfg(dAtA, i, uint64(baseI-i))
i--
dAtA[i] = 0xa
}
}
return len(dAtA) - i, nil
}
func encodeVarintCfg(dAtA []byte, offset int, v uint64) int {
offset -= sovCfg(v)
base := offset
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return base
}
func (m *Conf) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if len(m.Kind) > 0 {
for k, v := range m.Kind {
_ = k
_ = v
mapEntrySize := 1 + sovCfg(uint64(k)) + 1 + sovCfg(uint64(v))
n += mapEntrySize + 1 + sovCfg(uint64(mapEntrySize))
}
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
return n
}
func sovCfg(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
func sozCfg(x uint64) (n int) {
return sovCfg(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *Conf) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowCfg
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: conf: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: conf: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Kind", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowCfg
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthCfg
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthCfg
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.Kind == nil {
m.Kind = make(map[int64]uint32)
}
var mapkey int64
var mapvalue uint32
for iNdEx < postIndex {
entryPreIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowCfg
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
if fieldNum == 1 {
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowCfg
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
mapkey |= int64(b&0x7F) << shift
if b < 0x80 {
break
}
}
} else if fieldNum == 2 {
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowCfg
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
mapvalue |= uint32(b&0x7F) << shift
if b < 0x80 {
break
}
}
} else {
iNdEx = entryPreIndex
skippy, err := skipCfg(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthCfg
}
if (iNdEx + skippy) > postIndex {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
m.Kind[mapkey] = mapvalue
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipCfg(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthCfg
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipCfg(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
depth := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowCfg
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowCfg
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
case 1:
iNdEx += 8
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowCfg
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if length < 0 {
return 0, ErrInvalidLengthCfg
}
iNdEx += length
case 3:
depth++
case 4:
if depth == 0 {
return 0, ErrUnexpectedEndOfGroupCfg
}
depth--
case 5:
iNdEx += 4
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
if iNdEx < 0 {
return 0, ErrInvalidLengthCfg
}
if depth == 0 {
return iNdEx, nil
}
}
return 0, io.ErrUnexpectedEOF
}
var (
ErrInvalidLengthCfg = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowCfg = fmt.Errorf("proto: integer overflow")
ErrUnexpectedEndOfGroupCfg = fmt.Errorf("proto: unexpected end of group")
)

6
plugin_fortune/cfg.proto Normal file
View File

@ -0,0 +1,6 @@
syntax = "proto3";
package fortune;
message conf {
map<int64, uint32> kind = 1;
}

51
plugin_fortune/data.go Normal file
View File

@ -0,0 +1,51 @@
package fortune
import (
io "io"
"os"
"sync"
)
var (
conf Conf
mu sync.Mutex
)
func loadcfg(name string) error {
name = base + name
if _, err := os.Stat(name); err == nil || os.IsExist(err) {
f, err := os.Open(name)
if err == nil {
defer f.Close()
data, err1 := io.ReadAll(f)
if err1 == nil {
if len(data) > 0 {
return conf.Unmarshal(data)
}
}
return err1
}
} else { // 如果没有 cfg则使用空 map
conf.Kind = make(map[int64]uint32)
}
return nil
}
func savecfg(name string) error {
name = base + name
data, err := conf.Marshal()
if err == nil {
if _, err := os.Stat(base); err == nil || os.IsExist(err) {
f, err1 := os.OpenFile(name, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
if err1 == nil {
mu.Lock()
_, err2 := f.Write(data)
f.Close()
mu.Unlock()
return err2
}
return err1
}
}
return err
}

View File

@ -6,16 +6,12 @@ import (
"bytes" "bytes"
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"errors"
"image/jpeg" "image/jpeg"
"io" "io"
"io/ioutil" "io/ioutil"
"math/rand" "math/rand"
"net/http"
"net/url"
"os" "os"
"strconv" "strconv"
"strings"
"time" "time"
"github.com/fogleman/gg" "github.com/fogleman/gg"
@ -23,6 +19,7 @@ import (
"github.com/wdvxdr1123/ZeroBot/message" "github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/control" "github.com/FloatTech/ZeroBot-Plugin/control"
"github.com/FloatTech/ZeroBot-Plugin/data"
) )
var ( var (
@ -30,27 +27,49 @@ var (
base = "data/fortune/" base = "data/fortune/"
// 素材下载网站 // 素材下载网站
site = "https://pan.dihe.moe/fortune/" site = "https://pan.dihe.moe/fortune/"
// int64 群号 string 底图类型
// 底图类型列表:车万 DC4 爱因斯坦 星空列车 樱云之恋 富婆妹 李清歌 // 底图类型列表:车万 DC4 爱因斯坦 星空列车 樱云之恋 富婆妹 李清歌
// 公主连结 原神 明日方舟 碧蓝航线 碧蓝幻想 战双 阴阳师 // 公主连结 原神 明日方舟 碧蓝航线 碧蓝幻想 战双 阴阳师
table = map[int64]string{ table = [...]string{"车万", "DC4", "爱因斯坦", "星空列车", "樱云之恋", "富婆妹", "李清歌", "公主连结", "原神", "明日方舟", "碧蓝航线", "碧蓝幻想", "战双", "阴阳师"}
0: "车万", // 映射底图与 index
1048452984: "爱因斯坦", index = make(map[string]uint32)
}
) )
func init() { func init() {
err := loadcfg("cfg.pb")
if err != nil {
panic(err)
}
for i, s := range table {
index[s] = uint32(i)
}
err = os.MkdirAll(base, 0755)
if err != nil {
panic(err)
}
// 插件主体 // 插件主体
control.Register("fortune", &control.Options{ en := control.Register("fortune", &control.Options{
DisableOnDefault: false, DisableOnDefault: false,
Help: "每日运势: \n" + Help: "每日运势: \n" +
"- 运势", "- 运势\n" +
}).OnFullMatchGroup([]string{"运势", "抽签"}).SetBlock(true).SecondPriority(). "- 设置底图[车万 DC4 爱因斯坦 星空列车 樱云之恋 富婆妹 李清歌 公主连结 原神 明日方舟 碧蓝航线 碧蓝幻想 战双 阴阳师]",
})
en.OnRegex(`^设置底图(.*)`, zero.OnlyGroup).SetBlock(true).SecondPriority().
Handle(func(ctx *zero.Ctx) {
i, ok := index[ctx.State["regex_matched"].([]string)[1]]
if ok {
conf.Kind[ctx.Event.GroupID] = i
savecfg("cfg.pb")
} else {
ctx.Send("没有这个底图哦~")
}
})
en.OnFullMatchGroup([]string{"运势", "抽签"}).SetBlock(true).SecondPriority().
Handle(func(ctx *zero.Ctx) { Handle(func(ctx *zero.Ctx) {
// 检查签文文件是否存在 // 检查签文文件是否存在
if _, err := os.Stat(base + "运势签文.json"); err != nil && !os.IsExist(err) { mikuji := base + "运势签文.json"
if _, err := os.Stat(mikuji); err != nil && !os.IsExist(err) {
ctx.SendChain(message.Text("正在下载签文文件,请稍后...")) ctx.SendChain(message.Text("正在下载签文文件,请稍后..."))
_, err := download(site+"运势签文.json", base) err := data.DownloadTo(site+"运势签文.json", mikuji)
if err != nil { if err != nil {
ctx.SendChain(message.Text("ERROR: ", err)) ctx.SendChain(message.Text("ERROR: ", err))
return return
@ -58,37 +77,40 @@ func init() {
ctx.SendChain(message.Text("下载签文文件完毕")) ctx.SendChain(message.Text("下载签文文件完毕"))
} }
// 检查字体文件是否存在 // 检查字体文件是否存在
if _, err := os.Stat(base + "sakura.ttf"); err != nil && !os.IsExist(err) { ttf := base + "sakura.ttf"
if _, err := os.Stat(ttf); err != nil && !os.IsExist(err) {
ctx.SendChain(message.Text("正在下载字体文件,请稍后...")) ctx.SendChain(message.Text("正在下载字体文件,请稍后..."))
_, err := download(site+"sakura.ttf", base) err := data.DownloadTo(site+"sakura.ttf", ttf)
if err != nil { if err != nil {
ctx.SendChain(message.Text("ERROR: ", err)) ctx.SendChain(message.Text("ERROR: ", err))
return return
} }
ctx.SendChain(message.Text("下载字体文件完毕")) ctx.SendChain(message.Text("下载字体文件完毕"))
} }
// 获取该群背景类型 // 获取该群背景类型,默认车万
var kind string kind := "车万"
if v, ok := table[ctx.Event.GroupID]; ok { if v, ok := conf.Kind[ctx.Event.GroupID]; ok {
kind = v kind = table[v]
} else {
kind = table[0]
} }
// 检查背景图片是否存在 // 检查背景图片是否存在
if _, err := os.Stat(base + kind); err != nil && !os.IsExist(err) { folder := base + kind
if _, err := os.Stat(folder); err != nil && !os.IsExist(err) {
ctx.SendChain(message.Text("正在下载背景图片,请稍后...")) ctx.SendChain(message.Text("正在下载背景图片,请稍后..."))
file, err := download(site+kind+".zip", base) zipfile := kind + ".zip"
err := data.DownloadTo(site+zipfile, zipfile)
if err != nil { if err != nil {
ctx.SendChain(message.Text("ERROR: ", err)) ctx.SendChain(message.Text("ERROR: ", err))
return return
} }
ctx.SendChain(message.Text("下载背景图片完毕")) ctx.SendChain(message.Text("下载背景图片完毕"))
err = unpack(file, base+kind+"/") err = unpack(zipfile, folder+"/")
if err != nil { if err != nil {
ctx.SendChain(message.Text("ERROR: ", err)) ctx.SendChain(message.Text("ERROR: ", err))
return return
} }
ctx.SendChain(message.Text("解压背景图片完毕")) ctx.SendChain(message.Text("解压背景图片完毕"))
// 释放空间
os.Remove(zipfile)
} }
// 生成种子 // 生成种子
t, _ := strconv.ParseInt(time.Now().Format("20060102"), 10, 64) t, _ := strconv.ParseInt(time.Now().Format("20060102"), 10, 64)
@ -106,58 +128,16 @@ func init() {
return return
} }
// 绘制背景 // 绘制背景
data, err := draw(background, title, text) d, err := draw(background, title, text)
if err != nil { if err != nil {
ctx.SendChain(message.Text("ERROR: ", err)) ctx.SendChain(message.Text("ERROR: ", err))
return return
} }
// 发送图片 // 发送图片
ctx.SendChain(message.Image("base64://" + string(data))) ctx.SendChain(message.Image("base64://" + data.Bytes2str(d)))
}) })
} }
// @function download 下载资源包
// @param link 下载链接
// @param dest 下载位置
// @return 文件路径 & 错误信息
func download(link, dest string) (string, error) {
// 路径目录不存在则创建目录
if _, err := os.Stat(dest); err != nil && !os.IsExist(err) {
if err := os.MkdirAll(dest, 0755); err != nil {
panic(err)
}
}
client := &http.Client{}
// 网络请求
request, _ := http.NewRequest("GET", link, nil)
request.Header.Set("Accept", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0")
resp, err := client.Do(request)
if err != nil {
return "", err
}
defer resp.Body.Close()
// 验证接收到的长度
length, _ := strconv.Atoi(resp.Header.Get("Content-Length"))
data, _ := ioutil.ReadAll(resp.Body)
if length > len(data) {
return "", errors.New("download not complete")
}
// 获取文件名
temp := strings.Split(resp.Header.Get("Content-Disposition"), "\"")
name, _ := url.QueryUnescape(temp[len(temp)-2])
// 写入文件
f, err := os.OpenFile(dest+name, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
if err != nil {
return "", err
}
defer f.Close()
_, err = f.Write(data)
if err != nil {
return "", err
}
return dest + name, nil
}
// @function unpack 解压资源包 // @function unpack 解压资源包
// @param tgt 压缩文件位置 // @param tgt 压缩文件位置
// @param dest 解压位置 // @param dest 解压位置