qr-code-master / app.py
duqing2026's picture
Feat: Auto-detect local WiFi SSID and add password toggle
2975274
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)