#!/usr/bin/env python3 """ Generatore di QR Code Universale Supporta WiFi, URL, testo, email, SMS, contatti vCard, eventi calendario e altro """ import qrcode from PIL import Image import argparse import sys import os import re from datetime import datetime from urllib.parse import quote class UniversalQRGenerator: def __init__(self): self.qr_types = { 'wifi': 'Connessione WiFi', 'url': 'URL/Link web', 'text': 'Testo semplice', 'email': 'Email', 'sms': 'SMS', 'phone': 'Numero telefono', 'vcard': 'Biglietto da visita (vCard)', 'event': 'Evento calendario', 'geo': 'Posizione geografica', 'whatsapp': 'Messaggio WhatsApp', 'raw': 'Contenuto personalizzato' } # === GENERATORI DI CONTENUTO === def generate_wifi_qr(self, ssid, password=None, security='WPA', hidden=False): """Genera QR code per WiFi""" if security not in ['WPA', 'WEP', 'nopass']: raise ValueError("Sicurezza deve essere: WPA, WEP o nopass") ssid_escaped = self._escape_wifi_chars(ssid) password_escaped = self._escape_wifi_chars(password) if password else "" wifi_string = f"WIFI:T:{security};" wifi_string += f"S:{ssid_escaped};" if password and security != 'nopass': wifi_string += f"P:{password_escaped};" if hidden: wifi_string += "H:true;" wifi_string += ";" return wifi_string def generate_url_qr(self, url): """Genera QR code per URL""" if not url.startswith(('http://', 'https://')): url = 'https://' + url return url def generate_email_qr(self, email, subject=None, body=None): """Genera QR code per email""" if not self._is_valid_email(email): raise ValueError("Email non valida") mailto_string = f"mailto:{email}" params = [] if subject: params.append(f"subject={quote(subject)}") if body: params.append(f"body={quote(body)}") if params: mailto_string += "?" + "&".join(params) return mailto_string def generate_sms_qr(self, number, message=None): """Genera QR code per SMS""" sms_string = f"sms:{number}" if message: sms_string += f"?body={quote(message)}" return sms_string def generate_phone_qr(self, number): """Genera QR code per chiamata telefonica""" return f"tel:{number}" def generate_vcard_qr(self, first_name, last_name, phone=None, email=None, organization=None, url=None): """Genera QR code per biglietto da visita (vCard)""" vcard = "BEGIN:VCARD\nVERSION:3.0\n" vcard += f"FN:{first_name} {last_name}\n" vcard += f"N:{last_name};{first_name};;;\n" if phone: vcard += f"TEL:{phone}\n" if email: vcard += f"EMAIL:{email}\n" if organization: vcard += f"ORG:{organization}\n" if url: vcard += f"URL:{url}\n" vcard += "END:VCARD" return vcard def generate_event_qr(self, title, start_date, end_date=None, location=None, description=None): """Genera QR code per evento calendario""" # Formato: YYYYMMDDTHHMMSS start_formatted = start_date.strftime("%Y%m%dT%H%M%S") end_formatted = end_date.strftime("%Y%m%dT%H%M%S") if end_date else start_formatted vevent = "BEGIN:VEVENT\n" vevent += f"SUMMARY:{title}\n" vevent += f"DTSTART:{start_formatted}\n" vevent += f"DTEND:{end_formatted}\n" if location: vevent += f"LOCATION:{location}\n" if description: vevent += f"DESCRIPTION:{description}\n" vevent += "END:VEVENT" return vevent def generate_geo_qr(self, latitude, longitude, altitude=None): """Genera QR code per posizione geografica""" if altitude: return f"geo:{latitude},{longitude},{altitude}" else: return f"geo:{latitude},{longitude}" def generate_whatsapp_qr(self, number, message=None): """Genera QR code per messaggio WhatsApp""" # Rimuovi caratteri non numerici dal numero clean_number = re.sub(r'[^\d+]', '', number) wa_string = f"https://wa.me/{clean_number}" if message: wa_string += f"?text={quote(message)}" return wa_string def generate_text_qr(self, text): """Genera QR code per testo semplice""" return text def generate_raw_qr(self, content): """Genera QR code per contenuto personalizzato""" return content # === UTILITΓ€ === def _escape_wifi_chars(self, text): """Escape caratteri speciali per WiFi""" if not text: return "" special_chars = ['\\', ';', ',', '"', ':'] escaped_text = text for char in special_chars: escaped_text = escaped_text.replace(char, f'\\{char}') return escaped_text def _is_valid_email(self, email): """Validazione email semplice""" pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$' return re.match(pattern, email) is not None # === GENERATORE QR CODE === def create_qr_code(self, content, filename='qrcode.png', error_correction=qrcode.constants.ERROR_CORRECT_M, border=4, box_size=10, fill_color="black", back_color="white"): """Genera il QR code dal contenuto""" try: qr = qrcode.QRCode( version=1, error_correction=error_correction, box_size=box_size, border=border, ) qr.add_data(content) qr.make(fit=True) img = qr.make_image(fill_color=fill_color, back_color=back_color) img.save(filename) return img, content except Exception as e: print(f"❌ Errore nella generazione del QR code: {e}") return None, None # === INTERFACCIA PRINCIPALE === def generate_qr(self, qr_type, filename='qrcode.png', show_details=True, **kwargs): """Metodo principale per generare QR code di qualsiasi tipo""" try: # Genera il contenuto in base al tipo if qr_type == 'wifi': content = self.generate_wifi_qr(**kwargs) elif qr_type == 'url': content = self.generate_url_qr(**kwargs) elif qr_type == 'email': content = self.generate_email_qr(**kwargs) elif qr_type == 'sms': content = self.generate_sms_qr(**kwargs) elif qr_type == 'phone': content = self.generate_phone_qr(**kwargs) elif qr_type == 'vcard': content = self.generate_vcard_qr(**kwargs) elif qr_type == 'event': content = self.generate_event_qr(**kwargs) elif qr_type == 'geo': content = self.generate_geo_qr(**kwargs) elif qr_type == 'whatsapp': content = self.generate_whatsapp_qr(**kwargs) elif qr_type == 'text': content = self.generate_text_qr(**kwargs) elif qr_type == 'raw': content = self.generate_raw_qr(**kwargs) else: raise ValueError(f"Tipo QR non supportato: {qr_type}") # Genera il QR code img, final_content = self.create_qr_code(content, filename) if img and show_details: print("βœ… QR Code generato con successo!") print(f"πŸ“ File salvato: {filename}") print(f"🏷️ Tipo: {self.qr_types.get(qr_type, qr_type)}") print(f"πŸ“„ Contenuto: {final_content[:100]}{'...' if len(final_content) > 100 else ''}") return img except Exception as e: print(f"❌ Errore: {e}") return None def main(): """Interfaccia da riga di comando""" parser = argparse.ArgumentParser( description='Generatore QR Code Universale', formatter_class=argparse.RawDescriptionHelpFormatter, epilog=""" Tipi di QR Code supportati: wifi - Connessione WiFi url - URL/Link web text - Testo semplice email - Email sms - SMS phone - Numero telefono vcard - Biglietto da visita event - Evento calendario geo - Posizione geografica whatsapp - Messaggio WhatsApp raw - Contenuto personalizzato Esempi di utilizzo: python qr_generator.py wifi -s "MiaRete" -p "password123" python qr_generator.py url --url "https://google.com" python qr_generator.py email --email "test@example.com" --subject "Ciao" python qr_generator.py sms --number "+39123456789" --message "Ciao!" python qr_generator.py vcard --first-name "Mario" --last-name "Rossi" --phone "+39123456789" python qr_generator.py geo --latitude 45.4642 --longitude 9.1900 """ ) parser.add_argument('type', choices=list(UniversalQRGenerator().qr_types.keys()), help='Tipo di QR code da generare') parser.add_argument('-o', '--output', default='qrcode.png', help='Nome del file di output') parser.add_argument('-q', '--quiet', action='store_true', help='Non mostrare i dettagli') # Argomenti per WiFi wifi_group = parser.add_argument_group('WiFi') wifi_group.add_argument('-s', '--ssid', help='Nome rete WiFi') wifi_group.add_argument('-p', '--password', help='Password WiFi') wifi_group.add_argument('--security', choices=['WPA', 'WEP', 'nopass'], default='WPA', help='Tipo sicurezza WiFi') wifi_group.add_argument('--hidden', action='store_true', help='Rete nascosta') # Argomenti per URL url_group = parser.add_argument_group('URL') url_group.add_argument('--url', help='URL del sito web') # Argomenti per email email_group = parser.add_argument_group('Email') email_group.add_argument('--email', help='Indirizzo email') email_group.add_argument('--subject', help='Oggetto email') email_group.add_argument('--body', help='Corpo email') # Argomenti per SMS/Phone comm_group = parser.add_argument_group('SMS/Telefono') comm_group.add_argument('--number', help='Numero di telefono') comm_group.add_argument('--message', help='Messaggio SMS/WhatsApp') # Argomenti per vCard vcard_group = parser.add_argument_group('vCard') vcard_group.add_argument('--first-name', help='Nome') vcard_group.add_argument('--last-name', help='Cognome') vcard_group.add_argument('--organization', help='Organizzazione') # Argomenti per geolocalizzazione geo_group = parser.add_argument_group('Geolocalizzazione') geo_group.add_argument('--latitude', type=float, help='Latitudine') geo_group.add_argument('--longitude', type=float, help='Longitudine') geo_group.add_argument('--altitude', type=float, help='Altitudine') # Argomenti per testo/raw text_group = parser.add_argument_group('Testo/Raw') text_group.add_argument('--text', help='Testo da codificare') text_group.add_argument('--content', help='Contenuto raw personalizzato') args = parser.parse_args() # Preparazione parametri per il generatore generator = UniversalQRGenerator() kwargs = {} if args.type == 'wifi': if not args.ssid: print("❌ SSID obbligatorio per WiFi") sys.exit(1) kwargs = { 'ssid': args.ssid, 'password': args.password, 'security': args.security, 'hidden': args.hidden } elif args.type == 'url': if not args.url: print("❌ URL obbligatorio") sys.exit(1) kwargs = {'url': args.url} elif args.type == 'email': if not args.email: print("❌ Email obbligatoria") sys.exit(1) kwargs = { 'email': args.email, 'subject': args.subject, 'body': args.body } elif args.type in ['sms', 'phone']: if not args.number: print("❌ Numero obbligatorio") sys.exit(1) kwargs = {'number': args.number} if args.type == 'sms' and args.message: kwargs['message'] = args.message elif args.type == 'vcard': if not (args.first_name and args.last_name): print("❌ Nome e cognome obbligatori per vCard") sys.exit(1) kwargs = { 'first_name': args.first_name, 'last_name': args.last_name, 'phone': args.number, 'email': args.email, 'organization': args.organization } elif args.type == 'geo': if args.latitude is None or args.longitude is None: print("❌ Latitudine e longitudine obbligatorie") sys.exit(1) kwargs = { 'latitude': args.latitude, 'longitude': args.longitude, 'altitude': args.altitude } elif args.type == 'whatsapp': if not args.number: print("❌ Numero obbligatorio per WhatsApp") sys.exit(1) kwargs = { 'number': args.number, 'message': args.message } elif args.type == 'text': if not args.text: print("❌ Testo obbligatorio") sys.exit(1) kwargs = {'text': args.text} elif args.type == 'raw': if not args.content: print("❌ Contenuto obbligatorio") sys.exit(1) kwargs = {'content': args.content} # Genera il QR code result = generator.generate_qr( args.type, filename=args.output, show_details=not args.quiet, **kwargs ) sys.exit(0 if result else 1) def interactive_mode(): """ModalitΓ  interattiva""" generator = UniversalQRGenerator() print("πŸ”§ Generatore QR Code Universale - ModalitΓ  Interattiva") print("=" * 60) # Selezione tipo print("\nπŸ“‹ Tipi di QR Code disponibili:") types_list = list(generator.qr_types.items()) for i, (key, desc) in enumerate(types_list, 1): print(f" {i:2d}. {desc}") try: choice = int(input(f"\nScegli (1-{len(types_list)}): ")) qr_type = types_list[choice - 1][0] except (ValueError, IndexError): print("❌ Scelta non valida") return print(f"\n🎯 Tipo selezionato: {generator.qr_types[qr_type]}") # Input specifici per tipo kwargs = {} if qr_type == 'wifi': kwargs['ssid'] = input("πŸ“Ά SSID (nome rete): ") kwargs['security'] = input("πŸ”’ Sicurezza (WPA/WEP/nopass) [WPA]: ") or 'WPA' if kwargs['security'] != 'nopass': kwargs['password'] = input("πŸ”‘ Password: ") kwargs['hidden'] = input("πŸ‘οΈ Rete nascosta? (s/N): ").lower().startswith('s') elif qr_type == 'url': kwargs['url'] = input("🌐 URL: ") elif qr_type == 'email': kwargs['email'] = input("πŸ“§ Email: ") kwargs['subject'] = input("πŸ“ Oggetto (opzionale): ") or None kwargs['body'] = input("πŸ’¬ Messaggio (opzionale): ") or None elif qr_type == 'text': kwargs['text'] = input("πŸ“„ Testo: ") # Altri tipi... # Nome file filename = input("πŸ“ Nome file [qrcode.png]: ") or "qrcode.png" # Genera print("\n⏳ Generazione in corso...") generator.generate_qr(qr_type, filename=filename, **kwargs) if __name__ == "__main__": if len(sys.argv) == 1: interactive_mode() else: main()