Skip to content

feat: 1.2.0 add QR code file output #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 52 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,27 +70,32 @@ passgen -b # 24 words in English
passgen -b -12 # 12 words in English
```

#### 🌐 Supported Languages
### 🔍 Help Command
```bash
# Full phrases (24 words)
passgen -b -en # 🇬🇧 English (default)
passgen -b -ru # 🇷🇺 Russian (Русский)
passgen -b -jp # 🇯🇵 Japanese (日本語)
passgen -b -cn # 🇨🇳 Chinese (简体中文)
passgen -b -fr # 🇫🇷 French (Français)
passgen -b -it # 🇮🇹 Italian (Italiano)
passgen -b -ko # 🇰🇷 Korean (한국어)
passgen -b -es # 🇪🇸 Spanish (Español)

# Short phrases (12 words)
passgen -b -12 -en # 🇬🇧 English
passgen -b -12 -ru # 🇷🇺 Русский
passgen -b -12 -jp # 🇯🇵 日本語
passgen -b -12 -cn # 🇨🇳 简体中文
passgen -b -12 -fr # 🇫🇷 Français
passgen -b -12 -it # 🇮🇹 Italiano
passgen -b -12 -ko # 🇰🇷 한국어
passgen -b -12 -es # 🇪🇸 Español
# Show all available options
passgen -help
passgen -h

# Output includes:
-12
Generate 12-word mnemonic (default is 24)
-b, -bip39
Generate BIP39 mnemonic
-l, -length int
Password length (default 24-28)
-o string
Output file for QR code (PNG format)
-s int
QR code size in pixels (default: 256)
# Language options:
-en Use English wordlist (default) # 🇬🇧
-ru Use Russian wordlist # 🇷🇺
-jp Use Japanese wordlist # 🇯🇵
-cn Use Chinese wordlist # 🇨🇳
-fr Use French wordlist # 🇫🇷
-it Use Italian wordlist # 🇮🇹
-ko Use Korean wordlist # 🇰🇷
-es Use Spanish wordlist # 🇪🇸
```

### 📤 Output Features
Expand All @@ -99,6 +104,33 @@ Every generated password or mnemonic is automatically:
- 📋 Copied to clipboard
- 📱 Converted to QR code

### QR Code Options
```bash
# Display QR in terminal (default)
passgen -b

# Save QR as PNG file (default size: 256x256)
passgen -b -o mnemonic.png

# Save QR with custom size (in pixels)
passgen -b -o mnemonic.png -s 512 # 512x512
passgen -b -o mnemonic.png -s 1024 # 1024x1024

# Save QR with custom path
passgen -b -o ~/Documents/mnemonic.png
passgen -b -o ../backup/phrase.png

# Examples with different options combined
passgen -b -12 -ru -o russian-12words.png -s 512 # Russian 12-word phrase, 512x512 QR
passgen -b -jp -o ~/backup/japanese.png -s 1024 # Japanese 24-word phrase, 1024x1024 QR
passgen -l 32 -o password.png # 32-char password QR
```

All outputs (password/mnemonic) are still:
- 📝 Displayed in terminal
- 📋 Copied to clipboard
- 💾 Saved as QR code (if -o flag is used)

## 🏗️ Project Structure
```
passGen/
Expand Down
22 changes: 17 additions & 5 deletions cmd/passgen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@ func main() {
var useBip39 bool
var useShort bool
var lang string
var outputFile string
var qrSize int

flag.IntVar(&length, "length", 0, "Password length (default 24-28)")
flag.IntVar(&length, "l", 0, "Password length (shorthand)")
flag.BoolVar(&useBip39, "bip39", false, "Generate BIP39 mnemonic")
flag.BoolVar(&useBip39, "b", false, "Generate BIP39 mnemonic (shorthand)")
flag.BoolVar(&useShort, "12", false, "Generate 12-word mnemonic (default is 24)")
flag.StringVar(&outputFile, "o", "", "Output file for QR code (PNG format)")
flag.IntVar(&qrSize, "s", 256, "QR code size in pixels (default: 256)")

// Флаги для языков
var langRu, langEn, langJp, langFr, langIt, langKo, langCn, langEs bool
Expand Down Expand Up @@ -95,11 +99,19 @@ func main() {
fmt.Println("Copied to clipboard")
}

qrCode, err := qr.Generate(result)
if err != nil {
log.Printf("Failed to create QR code: %v", err)
if outputFile != "" {
if err := qr.GenerateToFile(result, outputFile, qrSize); err != nil {
log.Printf("Failed to save QR code to file: %v", err)
} else {
fmt.Printf("QR code saved to: %s\n", outputFile)
}
} else {
fmt.Println("\nQR code:")
fmt.Println(qrCode)
qrCode, err := qr.Generate(result)
if err != nil {
log.Printf("Failed to create QR code: %v", err)
} else {
fmt.Println("\nQR code:")
fmt.Println(qrCode)
}
}
}
Binary file modified demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
92 changes: 13 additions & 79 deletions internal/qr/qr.go
Original file line number Diff line number Diff line change
@@ -1,94 +1,28 @@
package qr

import (
"bytes"
"fmt"

"github.com/skip2/go-qrcode"
)

// Generate creates QR code from string and returns it as terminal-friendly string
// Generate creates QR code as ASCII art
func Generate(text string) (string, error) {
qr, err := qrcode.New(text, qrcode.Low)
qr, err := qrcode.New(text, qrcode.Medium)
if err != nil {
return "", err
return "", fmt.Errorf("failed to generate QR code: %v", err)
}

var buf bytes.Buffer
grid := qr.Bitmap()

// Находим границы непустой области QR-кода
minX, maxX, minY, maxY := findBounds(grid)

// Вычисляем ширину содержимого (каждый пиксель = 2 символа)
width := (maxX - minX) * 2

// Верхняя граница с правильной шириной
buf.WriteString("┌")
for i := 0; i < width; i++ {
buf.WriteString("─")
}
buf.WriteString("┐\n")

// QR код
for y := minY; y < maxY; y++ {
buf.WriteString("│")
for x := minX; x < maxX; x++ {
if grid[y][x] {
buf.WriteString("██")
} else {
buf.WriteString(" ")
}
}
buf.WriteString("│\n")
}

// Нижняя граница с правильной шириной
buf.WriteString("└")
for i := 0; i < width; i++ {
buf.WriteString("─")
}
buf.WriteString("┘\n")

return buf.String(), nil
return qr.ToSmallString(false), nil
}

// findBounds находит реальные границы QR-кода без пустых областей
func findBounds(grid [][]bool) (minX, maxX, minY, maxY int) {
minX, minY = len(grid), len(grid)
maxX, maxY = 0, 0

for y := 0; y < len(grid); y++ {
for x := 0; x < len(grid[y]); x++ {
if grid[y][x] {
if x < minX {
minX = x
}
if x > maxX {
maxX = x
}
if y < minY {
minY = y
}
if y > maxY {
maxY = y
}
}
}
}

// Добавляем небольшой отступ в 1 символ
if minX > 0 {
minX--
// GenerateToFile creates QR code and saves it as PNG file
func GenerateToFile(text string, filename string, size int) error {
if size == 0 {
size = 256 // default size
}
if maxX < len(grid)-1 {
maxX++
}
if minY > 0 {
minY--
}
if maxY < len(grid)-1 {
maxY++
err := qrcode.WriteFile(text, qrcode.Medium, size, filename)
if err != nil {
return fmt.Errorf("failed to save QR code to file: %v", err)
}

return minX, maxX + 1, minY, maxY + 1
return nil
}