File size: 5,230 Bytes
0763242
 
 
2975274
 
 
0763242
 
 
 
 
 
 
 
2975274
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0763242
 
 
 
 
 
2975274
 
0763242
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import os
import io
import base64
import subprocess
import re
import platform
from flask import Flask, render_template, request, jsonify, send_file
import segno
from segno import helpers
from PIL import Image

app = Flask(__name__)
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024  # 16MB max upload

def get_current_wifi_ssid():
    """
    Attempt to get the current connected WiFi SSID.
    Works primarily on macOS for local development.
    Returns None if detection fails or running in cloud.
    """
    try:
        system = platform.system()
        if system == 'Darwin':  # macOS
            process = subprocess.Popen(
                ['/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport', '-I'],
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE
            )
            out, err = process.communicate()
            if process.returncode == 0:
                output = out.decode('utf-8')
                match = re.search(r' SSID: (.+)', output)
                if match:
                    return match.group(1).strip()
        elif system == 'Linux':
            # Basic attempt for Linux (might work if nmcli is installed and has permissions)
            # Unlikely to work in Docker/HF Spaces without host networking
            pass
    except Exception as e:
        print(f"WiFi detection failed: {e}")
    return None

def hex_to_rgb(hex_color):
    hex_color = hex_color.lstrip('#')
    return tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))

@app.route('/')
def index():
    default_ssid = get_current_wifi_ssid() or ''
    return render_template('index.html', default_ssid=default_ssid)

@app.route('/api/generate', methods=['POST'])
def generate_qr():
    try:
        data = request.form
        qr_type = data.get('type', 'text')
        content = data.get('content', '')
        fg_color = data.get('fg_color', '#000000')
        bg_color = data.get('bg_color', '#ffffff')
        scale = int(data.get('scale', 10))
        border = int(data.get('border', 4))
        
        # Handle colors (Segno expects hex or RGB tuple, but let's be safe)
        # Segno handles hex strings well.
        
        qr = None
        
        # 1. Generate QR Object
        if qr_type == 'wifi':
            ssid = data.get('wifi_ssid')
            password = data.get('wifi_password')
            security = data.get('wifi_security', 'WPA')
            hidden = data.get('wifi_hidden') == 'true'
            qr = helpers.make_wifi(ssid=ssid, password=password, security=security, hidden=hidden)
        elif qr_type == 'vcard':
            name = data.get('vcard_name')
            displayname = data.get('vcard_displayname')
            email = data.get('vcard_email')
            phone = data.get('vcard_phone')
            url = data.get('vcard_url')
            # Segno make_vcard is powerful
            qr = helpers.make_vcard(name=name, displayname=displayname, email=email, phone=phone, url=url)
        else:
            # Default text/url
            if not content:
                return jsonify({'error': '内容不能为空'}), 400
            qr = segno.make(content, error='h') # High error correction for logos

        # 2. Convert to PIL Image
        out = io.BytesIO()
        qr.save(out, kind='png', scale=scale, border=border, dark=fg_color, light=bg_color)
        out.seek(0)
        img = Image.open(out).convert("RGBA")
        
        # 3. Handle Logo
        logo_file = request.files.get('logo')
        if logo_file:
            logo = Image.open(logo_file).convert("RGBA")
            
            # Calculate logo size (e.g., 20% of QR width)
            qr_width, qr_height = img.size
            logo_max_size = int(qr_width * 0.25) # 25% coverage max
            
            # Resize logo maintaining aspect ratio
            logo.thumbnail((logo_max_size, logo_max_size), Image.Resampling.LANCZOS)
            
            # Position centered
            logo_pos = ((qr_width - logo.size[0]) // 2, (qr_height - logo.size[1]) // 2)
            
            # Paste logo (with transparency support)
            # Create a white background for logo if needed or just paste
            # Usually better to have a small white border around logo for readability
            # Let's create a white backing for the logo
            logo_bg_size = (logo.size[0] + 4, logo.size[1] + 4) # 4px padding
            logo_bg = Image.new('RGBA', logo_bg_size, bg_color)
            logo_bg_pos = (logo_pos[0] - 2, logo_pos[1] - 2)
            
            img.paste(logo_bg, logo_bg_pos, logo_bg) # Paste white square
            img.paste(logo, logo_pos, logo) # Paste logo
            
        # 4. Return as Base64
        final_out = io.BytesIO()
        img.save(final_out, format='PNG')
        final_out.seek(0)
        b64_data = base64.b64encode(final_out.getvalue()).decode()
        
        return jsonify({
            'image': f'data:image/png;base64,{b64_data}',
            'filename': 'qrcode.png'
        })

    except Exception as e:
        print(f"Error: {e}")
        return jsonify({'error': str(e)}), 500

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=7860, debug=True)