generated from VLADIMIR/template
add pdf
This commit is contained in:
parent
b17599eb39
commit
be8e7fa482
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@ -5,8 +5,11 @@
|
||||
"Точка",
|
||||
"точки",
|
||||
"AUTOINCREMENT",
|
||||
"gopdf",
|
||||
"gwmux",
|
||||
"localtime",
|
||||
"palces"
|
||||
"palces",
|
||||
"qrcode",
|
||||
"signintech"
|
||||
]
|
||||
}
|
7
go.mod
7
go.mod
@ -9,6 +9,11 @@ require (
|
||||
google.golang.org/grpc v1.64.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/phpdave11/gofpdi v1.0.14-0.20211212211723-1f10f9844311 // indirect
|
||||
github.com/pkg/errors v0.8.1 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
@ -20,6 +25,8 @@ require (
|
||||
|
||||
require (
|
||||
github.com/mattn/go-sqlite3 v1.14.28
|
||||
github.com/signintech/gopdf v0.32.0
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
||||
golang.org/x/net v0.23.0 // indirect
|
||||
golang.org/x/sys v0.26.0 // indirect
|
||||
golang.org/x/text v0.15.0 // indirect
|
||||
|
@ -1,7 +1,49 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
type Team struct {
|
||||
ID int64
|
||||
Name string
|
||||
Password string
|
||||
}
|
||||
|
||||
func (t *Team) GetTeamUrl() (string, error) {
|
||||
ips, err := getLocalIPs()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
ip := ips[0]
|
||||
u := fmt.Sprintf("http://%s:8100?name=%s&password=%s", ip, url.PathEscape(t.Name), t.Password)
|
||||
return u, nil
|
||||
}
|
||||
|
||||
func getLocalIPs() ([]string, error) {
|
||||
var ips []string
|
||||
addrs, err := net.InterfaceAddrs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, addr := range addrs {
|
||||
ipNet, ok := addr.(*net.IPNet)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
ip := ipNet.IP
|
||||
if ip.IsLoopback() || ip.IsLinkLocalMulticast() || ip.IsLinkLocalUnicast() {
|
||||
continue
|
||||
}
|
||||
|
||||
if ipv4 := ip.To4(); ipv4 != nil {
|
||||
ips = append(ips, ipv4.String())
|
||||
}
|
||||
}
|
||||
|
||||
return ips, nil
|
||||
}
|
||||
|
112
internal/services/pdf_service/service.go
Normal file
112
internal/services/pdf_service/service.go
Normal file
@ -0,0 +1,112 @@
|
||||
package pdf_service
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"evening_detective/internal/models"
|
||||
"strings"
|
||||
|
||||
"github.com/signintech/gopdf"
|
||||
"github.com/skip2/go-qrcode"
|
||||
)
|
||||
|
||||
func CreateTeamsPdf(teams []*models.Team) ([]byte, error) {
|
||||
pdf := &gopdf.GoPdf{}
|
||||
pdf.Start(gopdf.Config{PageSize: *gopdf.PageSizeA4}) // W: 595, H: 842
|
||||
if err := pdf.AddTTFFont("main", "JetBrainsMono-Medium.ttf"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := pdf.SetFont("main", "", 10); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
padding := 17.
|
||||
xDelta := 187.
|
||||
yDelta := 202.
|
||||
for i, team := range teams {
|
||||
if i%12 == 0 {
|
||||
pdf.AddPage()
|
||||
pdf.SetPage(1 + i/12)
|
||||
}
|
||||
y := (padding + 15) + yDelta*float64(i%12/3)
|
||||
x := padding + xDelta*float64(i%3)
|
||||
|
||||
url, err := team.GetTeamUrl()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := printQR(pdf, url, x+21, y); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := printTextCenter(pdf, team.Name, xDelta-6, x+3, y+150); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
buffer := &bytes.Buffer{}
|
||||
_, err := pdf.WriteTo(buffer)
|
||||
return buffer.Bytes(), err
|
||||
}
|
||||
|
||||
func printQR(pdf *gopdf.GoPdf, url string, x, y float64) error {
|
||||
png, err := qrcode.Encode(url, qrcode.Medium, 256)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
imgHolder, err := gopdf.ImageHolderByBytes(png)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = pdf.ImageByHolder(imgHolder, x, y, &gopdf.Rect{W: 145, H: 145})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func printTextCenter(pdf *gopdf.GoPdf, text string, pageWidth, x, y float64) error {
|
||||
lines := splitTextByWords(pdf, text, pageWidth)
|
||||
for i, line := range lines {
|
||||
lineWidth, err := pdf.MeasureTextWidth(line)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
xLine := x + (pageWidth-lineWidth)/2
|
||||
yLine := y + 15*float64(i)
|
||||
pdf.SetXY(xLine, yLine)
|
||||
|
||||
pdf.Cell(nil, line)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func splitTextByWords(pdf *gopdf.GoPdf, text string, maxWidth float64) []string {
|
||||
words := strings.Fields(text)
|
||||
var lines []string
|
||||
var currentLine string
|
||||
|
||||
for _, word := range words {
|
||||
testLine := currentLine
|
||||
if testLine != "" {
|
||||
testLine += " " + word
|
||||
} else {
|
||||
testLine = word
|
||||
}
|
||||
|
||||
width, _ := pdf.MeasureTextWidth(testLine)
|
||||
|
||||
if width <= maxWidth {
|
||||
currentLine = testLine
|
||||
} else {
|
||||
if currentLine != "" {
|
||||
lines = append(lines, currentLine)
|
||||
}
|
||||
currentLine = word
|
||||
}
|
||||
}
|
||||
|
||||
if currentLine != "" {
|
||||
lines = append(lines, currentLine)
|
||||
}
|
||||
|
||||
return lines
|
||||
}
|
@ -9,8 +9,6 @@ import (
|
||||
"evening_detective/internal/services/story_service"
|
||||
"evening_detective/proto"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/metadata"
|
||||
@ -153,7 +151,7 @@ func (s *Services) GetTeams(ctx context.Context, _ *proto.GetTeamsReq) (*proto.G
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newTeam.Url, err = getTeamUrl(team)
|
||||
newTeam.Url, err = team.GetTeamUrl()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -220,39 +218,3 @@ func addLog(team *models.Team, action string, v any) {
|
||||
fmt.Printf("Team %s: %s %s\n", team.Name, action, string(vJson))
|
||||
}
|
||||
}
|
||||
|
||||
func getTeamUrl(team *models.Team) (string, error) {
|
||||
ips, err := getLocalIPs()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
ip := ips[0]
|
||||
u := fmt.Sprintf("http://%s:8100?name=%s&password=%s", ip, url.PathEscape(team.Name), team.Password)
|
||||
return u, nil
|
||||
}
|
||||
|
||||
func getLocalIPs() ([]string, error) {
|
||||
var ips []string
|
||||
addrs, err := net.InterfaceAddrs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, addr := range addrs {
|
||||
ipNet, ok := addr.(*net.IPNet)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
ip := ipNet.IP
|
||||
if ip.IsLoopback() || ip.IsLinkLocalMulticast() || ip.IsLinkLocalUnicast() {
|
||||
continue
|
||||
}
|
||||
|
||||
if ipv4 := ip.To4(); ipv4 != nil {
|
||||
ips = append(ips, ipv4.String())
|
||||
}
|
||||
}
|
||||
|
||||
return ips, nil
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user