diff --git a/make_guest_form.py b/make_guest_form.py index c4354b3..286e3ae 100644 --- a/make_guest_form.py +++ b/make_guest_form.py @@ -30,6 +30,9 @@ def pregunta(q): EMAIL = ''' + ''' bloques = [] for s in secciones: diff --git a/public/invitados.html b/public/invitados.html index 498eff8..ef8d4b4 100644 --- a/public/invitados.html +++ b/public/invitados.html @@ -42,6 +42,9 @@ +
diff --git a/public/invitados.js b/public/invitados.js index a2c9914..f84cf24 100644 --- a/public/invitados.js +++ b/public/invitados.js @@ -24,6 +24,8 @@ var el = els[j], bad = el.type === 'checkbox' ? !el.checked : !el.value.trim(); if (bad) { el.focus(); say(el.type === 'checkbox' ? 'Marca las dos casillas finales para poder enviar la ficha.' : 'Faltan respuestas obligatorias (las marcadas con *).', false); return false; } } + var t = s.querySelector('input[type=tel]'); + if (t && !/^\+?[\d ().-]{7,20}$/.test(t.value.trim())) { t.focus(); say('El teléfono no parece válido.', false); return false; } var m = s.querySelector('input[type=email]'); if (m && !okMail(m.value.trim())) { m.focus(); say('El correo no parece válido.', false); return false; } return true; @@ -47,7 +49,7 @@ var d = new Date(j.cita * 1000), o = { timeZone: 'Europe/Madrid' }; var dia = d.toLocaleDateString('es-ES', Object.assign({ weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' }, o)).replace(',', ''); var hora = d.toLocaleTimeString('es-ES', Object.assign({ hour: '2-digit', minute: '2-digit' }, o)); - cita.textContent = '📅 Recuerda que grabamos el ' + dia + ' a las ' + hora + ', y te enviaremos por correo la dirección del estudio.'; + cita.textContent = '📅 Recuerda que grabamos el ' + dia + ' a las ' + hora + ', y te enviaremos por correo electrónico la dirección del estudio.'; hola.hidden = false; cita.hidden = false; intro.hidden = false; f.hidden = false; try { var s = JSON.parse(store('get') || '{}'); Object.keys(s).forEach(function (nm) { if (f.elements[nm] && f.elements[nm].type !== 'checkbox') f.elements[nm].value = s[nm]; }); } catch (e) {} show(0); @@ -73,7 +75,7 @@ Array.prototype.forEach.call(f.elements, function (el) { if (/^q\d+$/.test(el.name)) resp[el.name] = el.value.trim(); }); busy = true; say('Enviando…', true); fetch('/api/invitados', { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ n: n, f: fe, email: f.email.value.trim(), resp: resp, consent: true, web: f.web.value || '', t: Date.now() - t0 }) }) + body: JSON.stringify({ n: n, f: fe, email: f.email.value.trim(), tel: f.tel.value.trim(), resp: resp, consent: true, web: f.web.value || '', t: Date.now() - t0 }) }) .then(function (r) { return r.json().catch(function () { return {}; }).then(function (j) { return { ok: r.ok && j.ok, j: j }; }); }) .then(function (x) { if (x.ok) { store('del'); f.reset(); steps.forEach(function (s) { s.hidden = true; }); paso.hidden = true; f.querySelector('.note:last-of-type').hidden = true; say(f.getAttribute('data-ok'), true); } diff --git a/public/privacidad.html b/public/privacidad.html index 983fbf9..d11cc17 100644 --- a/public/privacidad.html +++ b/public/privacidad.html @@ -32,7 +32,7 @@

Si nos escribes desde la página de contacto o de patrocinadores, recogemos los datos que tú mismo introduces: nombre, correo electrónico, mensaje y motivo o tipo de colaboración y, en el formulario de patrocinio, también el nombre de la empresa y su web si la indicas. Los usamos únicamente para responderte. La base legal es tu consentimiento, que das al marcar la casilla del formulario.

La web no guarda los mensajes: el formulario los reenvía por correo electrónico, a través de nuestro propio servidor de correo, a la cuenta del programa. Los conservamos solo el tiempo necesario para atender tu consulta y no los cedemos a terceros ni los usamos para otra cosa. Los formularios incluyen medidas antispam que no identifican a nadie. Puedes pedirnos que borremos tus datos escribiendo al correo de contacto.

-

Ficha del invitado. Si participas como invitado y rellenas la ficha (a la que se accede solo mediante un enlace personal), recogemos las respuestas que escribes, que pueden incluir datos sobre tu actividad profesional, tu trayectoria y, si tú decides contarlo, aspectos personales. Las usamos únicamente para preparar la entrevista y el episodio, y se envían por correo electrónico al equipo del programa; la web no las guarda. No las cedemos a terceros. La base legal es tu consentimiento, que das al aceptar las condiciones de participación y esta política, y puedes pedirnos que las borremos en cualquier momento.

+

Ficha del invitado. Si participas como invitado y rellenas la ficha (a la que se accede solo mediante un enlace personal), recogemos tu correo electrónico (para enviarte el recordatorio de la cita y la dirección del estudio), tu teléfono móvil (solo para contactarte el día de la grabación si surge algún imprevisto) y las respuestas que escribes, que pueden incluir datos sobre tu actividad profesional, tu trayectoria y, si tú decides contarlo, aspectos personales. Las usamos únicamente para preparar la entrevista y el episodio, y se envían por correo electrónico al equipo del programa; la web no las guarda. No las cedemos a terceros. La base legal es tu consentimiento, que das al aceptar las condiciones de participación y esta política, y puedes pedirnos que las borremos en cualquier momento.

4. Nuestra aplicación de publicación

Usamos una aplicación de gestión de redes sociales de código abierto (Postiz), instalada en un servidor propio, para programar y publicar el contenido del programa. La aplicación está pensada para uso interno: solo la utiliza el propietario de las cuentas y no está abierta al público.

diff --git a/server.py b/server.py index f3e69a8..b1ad75e 100644 --- a/server.py +++ b/server.py @@ -186,6 +186,9 @@ class H(BaseHTTPRequestHandler): email = clean(d.get('email'), 200) if not email or not EMAIL_RE.match(email): return self.reply(400, {'ok': False, 'error': 'El correo no parece válido.'}) + tel = ' '.join(str(d.get('tel') or '').split()) + if not re.match(r'^\+?[\d ().-]{7,20}$', tel): + return self.reply(400, {'ok': False, 'error': 'El teléfono no parece válido.'}) lineas, seccion = [], None for q in GUEST_Q: ans = str(resp.get(q['id']) or '').replace('\r', '').strip()[:3000] @@ -196,7 +199,7 @@ class H(BaseHTTPRequestHandler): lineas += ['', f'== {seccion} =='] lineas += ['', f"• {q['t']}", ' ' + (ans.replace('\n', '\n ') if ans else '(sin respuesta)')] cabecera = [f'Ficha del invitado: {nombre}', 'Recibida: ' + time.strftime('%d/%m/%Y %H:%M', time.localtime()), - f'Cita: {cita_txt(ts)}', f'Correo del invitado: {email}', + f'Cita: {cita_txt(ts)}', f'Correo del invitado: {email}', f'Teléfono móvil: {tel}', 'Aceptó las condiciones de participación y la política de privacidad: sí'] try: send(f'[Invitado] {clean(nombre, 80)} · ficha del podcast', email, '\n'.join(cabecera + lineas) + '\n') @@ -211,7 +214,7 @@ class H(BaseHTTPRequestHandler): try: send('Tu cita en Anda Que No Sabes Ná', None, f'Hola, {nombre}:\n\nGracias por rellenar tu ficha. Recuerda que grabamos el ' - f'{cita_txt(ts)}, y te enviaremos por correo la dirección del estudio.\n\n' + f'{cita_txt(ts)}, y te enviaremos por correo electrónico la dirección del estudio.\n\n' 'Si no puedes venir o necesitas cambiar algo, responde a este correo.\n\n' 'Un abrazo,\nÁlex y Juan\nAnda Que No Sabes Ná\nhttps://andaquenosabesna.com\n', to=email) except Exception as exc: