Skip to content

Commit 1a07118

Browse files
committed
init
1 parent d9f5ac3 commit 1a07118

File tree

11 files changed

+881
-0
lines changed

11 files changed

+881
-0
lines changed

.github/workflows/release.yml

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
name: 稳定版
2+
on:
3+
push:
4+
tags:
5+
- v*
6+
7+
env:
8+
GITHUB_TOKEN: ${{ github.token }}
9+
10+
jobs:
11+
my-job:
12+
name: Build gocq-sqlite3-migrate on Push Tag 🚀
13+
runs-on: ubuntu-latest
14+
steps:
15+
16+
- name: Set up Go
17+
uses: actions/setup-go@v2
18+
with:
19+
go-version: 1.19
20+
21+
- name: Check out code into the Go module directory
22+
uses: actions/checkout@v2
23+
24+
- name: Cache Go
25+
id: cache
26+
uses: actions/cache@v2
27+
with:
28+
# A list of files, directories, and wildcard patterns to cache and restore
29+
path: ~/go/pkg/mod
30+
key: ${{ runner.os }}-build-${{ hashFiles('**/go.sum') }}
31+
32+
- name: Tidy Go modules
33+
run: go mod tidy
34+
35+
- name: Build linux-x64
36+
run: CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o artifacts/gocq-sqlite3-migrate-linux-x64
37+
- name: Build linux-x86
38+
run: CGO_ENABLED=0 GOOS=linux GOARCH=386 go build -ldflags="-s -w" -o artifacts/gocq-sqlite3-migrate-linux-x86
39+
- name: Build windows-x64
40+
run: CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags="-s -w" -o artifacts/gocq-sqlite3-migrate-x64.exe
41+
- name: Build windows-x86
42+
run: CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags="-s -w" -o artifacts/gocq-sqlite3-migrate-x86.exe
43+
- name: Build arm64
44+
run: CGO_ENABLED=0 GOOS=linux GOARCH=arm64 GOARM=7 go build -ldflags="-s -w" -o artifacts/gocq-sqlite3-migrate-linux-arm64
45+
- name: Build armv6
46+
run: CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=6 go build -ldflags="-s -w" -o artifacts/gocq-sqlite3-migrate-linux-armv6
47+
- name: Build darwin amd64
48+
run: CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags="-s -w" -o artifacts/gocq-sqlite3-migrate-darwin-amd64
49+
- name: Build darwin arm64
50+
run: CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -ldflags="-s -w" -o artifacts/gocq-sqlite3-migrate-darwin-arm64
51+
52+
- name: Upload binaries to release
53+
uses: svenstaro/upload-release-action@v2
54+
with:
55+
repo_token: ${{ secrets.GITHUB_TOKEN }}
56+
file: artifacts/gocq-sqlite3-migrate-*
57+
tag: ${{ github.ref }}
58+
overwrite: true
59+
file_glob: true

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@
1313

1414
# Dependency directories (remove the comment below to include it)
1515
# vendor/
16+
17+
/data
18+
go.sum

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,20 @@
11
# gocq-sqlite3-migrate
22
go-cqhttp leveldb v3 到 sqlite3 迁移工具
3+
4+
## 安装
5+
6+
你可以下载 [已经编译好的二进制文件](https://github.com/RomiChan/gocq-sqlite3-migrate/releases).
7+
8+
从源码安装:
9+
```bash
10+
$ go install github.com/RomiChan/gocq-sqlite3-migrate@latest
11+
```
12+
13+
## 使用方法
14+
15+
```bash
16+
./gocq-sqlite3-migrate -from xxx -to yyy
17+
```
18+
默认值:
19+
* from: `data/leveldb-v3`
20+
* to: `data/sqlite3/msg.db`

go.mod

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
module github.com/RomiChan/gocq-sqlite3-migrate
2+
3+
go 1.19
4+
5+
require (
6+
github.com/FloatTech/sqlite v0.5.0
7+
github.com/Mrs4s/MiraiGo v0.0.0-20220828090150-a3c348100dfe
8+
github.com/Mrs4s/go-cqhttp v1.0.0-rc3.0.20221109121432-fa267b6a2d47
9+
github.com/pkg/errors v0.9.1
10+
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
11+
)
12+
13+
require (
14+
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b // indirect
15+
github.com/Microsoft/go-winio v0.5.1 // indirect
16+
github.com/fumiama/go-base16384 v1.5.2 // indirect
17+
github.com/fumiama/sqlite3 v1.14.6 // indirect
18+
github.com/golang/snappy v0.0.4 // indirect
19+
github.com/google/uuid v1.3.0 // indirect
20+
github.com/kr/text v0.2.0 // indirect
21+
github.com/mattn/go-colorable v0.1.12 // indirect
22+
github.com/mattn/go-isatty v0.0.14 // indirect
23+
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
24+
github.com/segmentio/asm v1.1.3 // indirect
25+
github.com/sirupsen/logrus v1.8.1 // indirect
26+
github.com/tidwall/gjson v1.14.3 // indirect
27+
github.com/tidwall/match v1.1.1 // indirect
28+
github.com/tidwall/pretty v1.2.0 // indirect
29+
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect
30+
golang.org/x/text v0.3.7 // indirect
31+
gopkg.in/yaml.v3 v3.0.1 // indirect
32+
modernc.org/libc v1.14.6 // indirect
33+
modernc.org/mathutil v1.4.1 // indirect
34+
modernc.org/memory v1.0.5 // indirect
35+
)

leveldb/const.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package leveldb
2+
3+
const dataVersion = 1
4+
5+
const (
6+
group = 0x0
7+
private = 0x1
8+
guildChannel = 0x2
9+
)
10+
11+
type coder byte
12+
13+
const (
14+
coderNil coder = iota
15+
coderInt
16+
coderUint
17+
coderInt32
18+
coderUint32
19+
coderInt64
20+
coderUint64
21+
coderString
22+
coderMSG // global.MSG
23+
coderArrayMSG // []global.MSG
24+
coderStruct // struct{}
25+
)

leveldb/leveldb.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package leveldb
2+
3+
import (
4+
"strconv"
5+
6+
"github.com/Mrs4s/MiraiGo/utils"
7+
"github.com/pkg/errors"
8+
"github.com/syndtr/goleveldb/leveldb"
9+
"github.com/syndtr/goleveldb/leveldb/opt"
10+
)
11+
12+
type Database struct {
13+
db *leveldb.DB
14+
}
15+
16+
func Open(dbpath string) (ldb *Database, err error) {
17+
d, err := leveldb.OpenFile(dbpath, &opt.Options{
18+
WriteBuffer: 32 * opt.KiB,
19+
})
20+
if err != nil {
21+
return nil, errors.Wrap(err, "open leveldb error")
22+
}
23+
return &Database{db: d}, nil
24+
}
25+
26+
func (ldb *Database) Close() error {
27+
return ldb.db.Close()
28+
}
29+
30+
func (ldb *Database) ForEach(f func(x any) error) (errs []error) {
31+
iter := ldb.db.NewIterator(nil, nil)
32+
for iter.Next() {
33+
value := iter.Value()
34+
if len(value) == 0 {
35+
continue
36+
}
37+
r, err := newReader(utils.B2S(value))
38+
if err != nil {
39+
errs = append(errs, errors.Wrap(err, "new reader failed"))
40+
continue
41+
}
42+
flg := r.uvarint()
43+
switch flg {
44+
case group:
45+
err = f(r.readStoredGroupMessage())
46+
if err != nil {
47+
errs = append(errs, errors.Wrap(err, "decode group message callback failed"))
48+
}
49+
case private:
50+
err = f(r.readStoredPrivateMessage())
51+
if err != nil {
52+
errs = append(errs, errors.Wrap(err, "decode private message callback failed"))
53+
}
54+
case guildChannel:
55+
err = f(r.readStoredGuildChannelMessage())
56+
if err != nil {
57+
errs = append(errs, errors.Wrap(err, "decode guild channel message callback failed"))
58+
}
59+
default:
60+
errs = append(errs, errors.New("unknown message flag "+strconv.Itoa(int(flg))))
61+
}
62+
63+
}
64+
iter.Release()
65+
return
66+
}

leveldb/reader.go

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package leveldb
2+
3+
import (
4+
"encoding/binary"
5+
"io"
6+
"strconv"
7+
"strings"
8+
9+
"github.com/pkg/errors"
10+
11+
"github.com/Mrs4s/go-cqhttp/global"
12+
)
13+
14+
type intReader struct {
15+
data string
16+
*strings.Reader
17+
}
18+
19+
func newIntReader(s string) intReader {
20+
return intReader{
21+
data: s,
22+
Reader: strings.NewReader(s),
23+
}
24+
}
25+
26+
func (r *intReader) varint() int64 {
27+
i, _ := binary.ReadVarint(r)
28+
return i
29+
}
30+
31+
func (r *intReader) uvarint() uint64 {
32+
i, _ := binary.ReadUvarint(r)
33+
return i
34+
}
35+
36+
// reader implements the index read.
37+
// data format is the same as the writer's
38+
type reader struct {
39+
data intReader
40+
strings intReader
41+
stringIndex map[uint64]string
42+
}
43+
44+
func (r *reader) coder() coder { o, _ := r.data.ReadByte(); return coder(o) }
45+
func (r *reader) varint() int64 { return r.data.varint() }
46+
func (r *reader) uvarint() uint64 { return r.data.uvarint() }
47+
func (r *reader) int32() int32 { return int32(r.varint()) }
48+
func (r *reader) int64() int64 { return r.varint() }
49+
func (r *reader) uint64() uint64 { return r.uvarint() }
50+
51+
// func (r *reader) uint32() uint32 { return uint32(r.uvarint()) }
52+
// func (r *reader) int() int { return int(r.varint()) }
53+
// func (r *reader) uint() uint { return uint(r.uvarint()) }
54+
55+
func (r *reader) string() string {
56+
off := r.data.uvarint()
57+
if s, ok := r.stringIndex[off]; ok {
58+
return s
59+
}
60+
_, _ = r.strings.Seek(int64(off), io.SeekStart)
61+
l := int64(r.strings.uvarint())
62+
whence, _ := r.strings.Seek(0, io.SeekCurrent)
63+
s := r.strings.data[whence : whence+l]
64+
r.stringIndex[off] = s
65+
return s
66+
}
67+
68+
func (r *reader) msg() global.MSG {
69+
length := r.uvarint()
70+
msg := make(global.MSG, length)
71+
for i := uint64(0); i < length; i++ {
72+
s := r.string()
73+
msg[s] = r.obj()
74+
}
75+
return msg
76+
}
77+
78+
func (r *reader) arrayMsg() []global.MSG {
79+
length := r.uvarint()
80+
msgs := make([]global.MSG, length)
81+
for i := range msgs {
82+
msgs[i] = r.msg()
83+
}
84+
return msgs
85+
}
86+
87+
func (r *reader) obj() interface{} {
88+
switch coder := r.coder(); coder {
89+
case coderNil:
90+
return nil
91+
case coderInt:
92+
return int(r.varint())
93+
case coderUint:
94+
return uint(r.uvarint())
95+
case coderInt32:
96+
return int32(r.varint())
97+
case coderUint32:
98+
return uint32(r.uvarint())
99+
case coderInt64:
100+
return r.varint()
101+
case coderUint64:
102+
return r.uvarint()
103+
case coderString:
104+
return r.string()
105+
case coderMSG:
106+
return r.msg()
107+
case coderArrayMSG:
108+
return r.arrayMsg()
109+
default:
110+
panic("db/leveldb: invalid coder " + strconv.Itoa(int(coder)))
111+
}
112+
}
113+
114+
func newReader(data string) (*reader, error) {
115+
in := newIntReader(data)
116+
v := in.uvarint()
117+
if v != dataVersion {
118+
return nil, errors.Errorf("db/leveldb: invalid data version %d", v)
119+
}
120+
sl := int64(in.uvarint())
121+
dl := int64(in.uvarint())
122+
whence, _ := in.Seek(0, io.SeekCurrent)
123+
sData := data[whence : whence+sl]
124+
dData := data[whence+sl : whence+sl+dl]
125+
r := reader{
126+
data: newIntReader(dData),
127+
strings: newIntReader(sData),
128+
stringIndex: make(map[uint64]string),
129+
}
130+
return &r, nil
131+
}

0 commit comments

Comments
 (0)