2022-09-06 09:30:45 +02:00
|
|
|
package meowlib
|
|
|
|
|
|
|
|
import (
|
2022-10-22 14:41:48 +02:00
|
|
|
"bytes"
|
|
|
|
"compress/gzip"
|
2022-09-06 09:30:45 +02:00
|
|
|
"fmt"
|
|
|
|
"image"
|
|
|
|
"image/color"
|
|
|
|
"image/png"
|
2022-12-19 12:15:10 +01:00
|
|
|
"io"
|
2022-09-06 09:30:45 +02:00
|
|
|
"log"
|
|
|
|
"math"
|
|
|
|
"os"
|
|
|
|
|
|
|
|
"github.com/makiuchi-d/gozxing"
|
|
|
|
"github.com/makiuchi-d/gozxing/qrcode"
|
2022-09-19 14:09:32 +02:00
|
|
|
"google.golang.org/protobuf/proto"
|
2022-09-06 09:30:45 +02:00
|
|
|
)
|
|
|
|
|
2023-11-08 21:52:09 +01:00
|
|
|
func ServerFromUrl(url string) *ServerCard {
|
|
|
|
var s ServerCard
|
2022-09-06 09:30:45 +02:00
|
|
|
s.Url = url
|
|
|
|
return &s
|
|
|
|
}
|
|
|
|
|
2022-09-06 17:07:35 +02:00
|
|
|
func (Contact *ContactCard) AddUrls(urls []string) {
|
2022-09-06 09:30:45 +02:00
|
|
|
for _, url := range urls {
|
2022-09-06 17:07:35 +02:00
|
|
|
Contact.PullServers = append(Contact.PullServers, ServerFromUrl(url))
|
2022-09-06 09:30:45 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-22 14:41:48 +02:00
|
|
|
func (contact *ContactCard) Serialize() ([]byte, error) {
|
|
|
|
out, err := proto.Marshal(contact)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return out, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (contact *ContactCard) Compress() ([]byte, error) {
|
|
|
|
out, err := contact.Serialize()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
var b bytes.Buffer
|
2022-11-29 22:19:54 +01:00
|
|
|
gz, err := gzip.NewWriterLevel(&b, gzip.BestCompression)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-10-22 14:41:48 +02:00
|
|
|
if _, err := gz.Write(out); err != nil {
|
2022-11-29 22:19:54 +01:00
|
|
|
return nil, err
|
2022-10-22 14:41:48 +02:00
|
|
|
}
|
|
|
|
if err := gz.Close(); err != nil {
|
2022-11-29 22:19:54 +01:00
|
|
|
return nil, err
|
2022-10-22 14:41:48 +02:00
|
|
|
}
|
|
|
|
return b.Bytes(), nil
|
|
|
|
}
|
|
|
|
|
2022-11-29 22:19:54 +01:00
|
|
|
func (contact *ContactCard) Split(parts uint8) (packets [][]byte, err error) {
|
|
|
|
data, err := contact.Compress()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return BufferSplit(data, parts)
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewContactCardFromCompressed(compressed []byte) (*ContactCard, error) {
|
|
|
|
cc := &ContactCard{}
|
|
|
|
reader := bytes.NewReader([]byte(compressed))
|
|
|
|
gzreader, err := gzip.NewReader(reader)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-12-19 12:15:10 +01:00
|
|
|
output, err := io.ReadAll(gzreader)
|
2022-11-29 22:19:54 +01:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if err := proto.Unmarshal(output, cc); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return cc, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewContactCardFromSplit(packets [][]byte) (*ContactCard, error) {
|
|
|
|
data, err := BufferMerge(packets)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return NewContactCardFromCompressed(data)
|
|
|
|
}
|
|
|
|
|
2022-11-27 21:21:49 +01:00
|
|
|
func (contact *ContactCard) WriteCompressed(filename string) error {
|
|
|
|
out, err := contact.Compress()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2022-12-19 12:15:10 +01:00
|
|
|
err = os.WriteFile(filename, out, 0600)
|
2022-11-27 21:21:49 +01:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-09-19 14:09:32 +02:00
|
|
|
func (contact *ContactCard) WritePng(filename string) {
|
|
|
|
out, err := proto.Marshal(contact)
|
|
|
|
if err != nil {
|
|
|
|
println(err)
|
|
|
|
}
|
|
|
|
size := int(math.Sqrt(float64(len(out))/3)) + 1
|
2022-09-06 09:30:45 +02:00
|
|
|
println(size)
|
|
|
|
|
|
|
|
// Create a colored i mage of the given width and height.
|
|
|
|
img := image.NewNRGBA(image.Rect(0, 0, size, size))
|
|
|
|
|
|
|
|
for y := 0; y < size; y++ {
|
|
|
|
for x := 0; x < size*3; x = x + 3 {
|
2022-09-19 14:09:32 +02:00
|
|
|
p1 := uint8(out[x+y])
|
|
|
|
p2 := uint8(out[x+y+1])
|
|
|
|
p3 := uint8(out[x+y+2])
|
2022-09-06 09:30:45 +02:00
|
|
|
img.Set(x/3, y, color.NRGBA{
|
|
|
|
R: p1,
|
|
|
|
G: p2,
|
|
|
|
B: p3,
|
|
|
|
A: 255,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
f, err := os.Create(filename)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := png.Encode(f, img); err != nil {
|
|
|
|
f.Close()
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := f.Close(); err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-12-01 22:47:17 +01:00
|
|
|
func (Contact *ContactCard) WriteQr(filename string) error {
|
2022-11-27 21:08:34 +01:00
|
|
|
//jsonContact, _ := json.Marshal(Contact)
|
|
|
|
jsonContact, _ := Contact.Compress()
|
2022-09-06 09:30:45 +02:00
|
|
|
qwriter := qrcode.NewQRCodeWriter()
|
|
|
|
code, err := qwriter.Encode(string(jsonContact), gozxing.BarcodeFormat_QR_CODE, 512, 512, nil)
|
|
|
|
if err != nil {
|
2022-12-01 22:47:17 +01:00
|
|
|
return err
|
2022-09-06 09:30:45 +02:00
|
|
|
}
|
2022-11-27 21:08:34 +01:00
|
|
|
file, _ := os.Create(filename)
|
2022-09-06 09:30:45 +02:00
|
|
|
defer file.Close()
|
|
|
|
|
|
|
|
// *BitMatrix implements the image.Image interface,
|
|
|
|
// so it is able to be passed to png.Encode directly.
|
|
|
|
_ = png.Encode(file, code)
|
2022-12-01 22:47:17 +01:00
|
|
|
return nil
|
2022-09-06 09:30:45 +02:00
|
|
|
}
|
|
|
|
|
2022-12-03 00:05:28 +01:00
|
|
|
func ReadQr(filename string) *ContactCard {
|
2022-09-07 16:29:17 +02:00
|
|
|
var contact ContactCard
|
2022-09-06 09:30:45 +02:00
|
|
|
// open and decode image file
|
2022-12-03 00:05:28 +01:00
|
|
|
file, _ := os.Open(filename)
|
2022-09-06 09:30:45 +02:00
|
|
|
img, _, _ := image.Decode(file)
|
|
|
|
|
|
|
|
// prepare BinaryBitmap
|
|
|
|
bmp, _ := gozxing.NewBinaryBitmapFromImage(img)
|
|
|
|
|
|
|
|
// decode image
|
|
|
|
qrReader := qrcode.NewQRCodeReader()
|
|
|
|
result, _ := qrReader.Decode(bmp, nil)
|
|
|
|
|
|
|
|
fmt.Println(result)
|
2022-12-03 00:05:28 +01:00
|
|
|
return &contact
|
2022-09-06 09:30:45 +02:00
|
|
|
}
|