1let restarted = false; 2let __iuadLastLeadKey = null; 3 4function iuadGetCrmEndpoint() { 5 if (window.iuadChat && typeof window.iuadChat.endpoint === 'string' && window.iuadChat.endpoint) { 6 return window.iuadChat.endpoint 7 } 8 return null 9} 10 11function iuadGetLangFallback() { 12 const htmlLang = (document && document.documentElement && document.documentElement.lang) ? document.documentElement.lang : '' 13 return (typeof htmlLang === 'string' && htmlLang.toLowerCase().startsWith('en')) ? 'en' : 'it' 14} 15 16function iuadNormalizeLang(lang) { 17 if (!lang || typeof lang !== 'string') return null 18 const s = lang.trim().toLowerCase() 19 if (!s) return null 20 const base = s.split(/[_-]/)[0] 21 if (base === 'en' || base === 'it') return base 22 return null 23} 24 25function iuadGetCookie(name) { 26 try { 27 const cookieStr = (typeof document !== 'undefined' && typeof document.cookie === 'string') ? document.cookie : '' 28 if (!cookieStr) return null 29 const parts = cookieStr.split(';') 30 for (let i = 0; i < parts.length; i++) { 31 const p = parts[i].trim() 32 if (!p) continue 33 if (p.startsWith(name + '=')) { 34 return decodeURIComponent(p.substring(name.length + 1)) 35 } 36 } 37 } catch (e) {} 38 return null 39} 40 41function iuadGetWpmlCurrentLang() { 42 // 1) Alcune installazioni espongono un oggetto globale WPML 43 const fromWpmlGlobal = 44 iuadNormalizeLang(window?.wpml?.current_language) || 45 iuadNormalizeLang(window?.wpml?.language) || 46 iuadNormalizeLang(window?.WPML?.current_language) || 47 iuadNormalizeLang(window?.WPML?.language) 48 if (fromWpmlGlobal) return fromWpmlGlobal 49 50 // 2) Cookie WPML (tipicamente: wp-wpml_current_language) 51 const fromCookie = 52 iuadNormalizeLang(iuadGetCookie('wp-wpml_current_language')) || 53 iuadNormalizeLang(iuadGetCookie('wpml_current_language')) 54 if (fromCookie) return fromCookie 55 56 // 3) Classi sul body (es. lang-it / lang-en) 57 try { 58 const cls = (document && document.body && document.body.classList) ? Array.from(document.body.classList) : [] 59 for (let i = 0; i < cls.length; i++) { 60 const m = /^lang-([a-z]{2})(?:[_-][a-z]{2})?$/.exec(String(cls[i]).toLowerCase()) 61 if (m && m[1]) { 62 const normalized = iuadNormalizeLang(m[1]) 63 if (normalized) return normalized 64 } 65 } 66 } catch (e) {} 67 68 return null 69} 70 71function iuadGetCurrentLang() { 72 return ( 73 iuadNormalizeLang(window?.iuadChat?.lang) || 74 iuadGetWpmlCurrentLang() || 75 iuadNormalizeLang(document?.documentElement?.lang) || 76 iuadGetLangFallback() 77 ) 78} 79 80function iuadNormalizeCorsiToLabels(corsi) { 81 if (typeof corsi === 'string') { 82 const t = corsi.trim() 83 return t ? [t] : [] 84 } 85 if (Array.isArray(corsi)) { 86 return corsi.map((item) => String(item == null ? '' : item).trim()).filter(Boolean) 87 } 88 if (corsi != null) { 89 return [String(corsi).trim()].filter(Boolean) 90 } 91 return [] 92} 93 94// Helper per mappare il testo del corso nello slug atteso dal CRM (stessa logica di chat.js) 95function iuadMapCourseLabelToSlug(courseLabel) { 96 const label = String(courseLabel == null ? '' : courseLabel).trim() 97 if (!label) { 98 return ''; 99 } 100 101 switch (label) { 102 case 'Regia per il Cinema e la Pubblicità ': 103 return 'regia per il cinema e la pubblicità '; 104 case 'Design e Architettura degli Interni': 105 return 'design e architettura degli interni'; 106 case 'Game Design': 107 return 'game design'; 108 case 'Design della Comunicazione': 109 return 'design della comunicazione'; 110 case 'Design della Moda': 111 return 'design della moda'; 112 case 'Design della moda indirizzo Business & Management': 113 return 'corso triennale di i livello in design della moda indirizzo fashion business & management'; 114 case 'Art direction & Copywriting': 115 return 'art direction & copywriting'; 116 case 'Design dell\'Accessorio': 117 return 'design accessorio'; 118 case 'Disegno Tecnico per la Moda 2D - 3D': 119 return 'master in disegno tecnico per la moda'; 120 case 'Borse e Pelletteria': 121 return 'master in borse e pelletteria'; 122 case 'Design di Calzature': 123 return 'design di calzature'; 124 case 'Interior designer 2D/3D': 125 return 'arredatore d\'interni e operatore cad 2d e 3d'; 126 case 'Visual Merchandiser': 127 return 'visual merchandiser'; 128 case '3D Virtual Fashion': 129 return 'virtual fashion 3d'; 130 case 'Modellista Industriale Tessile Abbigliamento T.U.': 131 return 'modellista industriale tessile abbigliamento t.u.'; 132 case 'Modellista Tecnico CAD': 133 return 'modellista operatore cad'; 134 case 'Modellista Borse': 135 return 'modellista borse'; 136 case 'Modellista Borse CAD': 137 return 'modellista borse cad'; 138 case 'Fashion Illustrator':
139 return 'fashion illustrator'; 140 case 'Fashion Designer Tecnico CAD': 141 return 'fashion designer operatore cad'; 142 case 'Modellista Calzature': 143 return 'modellista per calzature'; 144 case 'Modellista Calzature CAD': 145 return 'modellista calzature cad'; 146 case 'Content Creator, Storytelling e Produzione Digitale': 147 return 'content creation storytelling e produzione digitale'; 148 149 // ENGLISH 150 case 'Cinema and Advertising Direction': 151 return 'regia per il cinema e la pubblicità '; 152 case 'Design and Interior Architecture': 153 return 'design e architettura degli interni'; 154 case 'Game Design': 155 return 'game design'; 156 case 'Communication Design': 157 return 'design della comunicazione'; 158 case 'Fashion Design': 159 return 'design della moda'; 160 case 'Fashion Design Business & Management': 161 return 'corso triennale di i livello in design della moda indirizzo fashion business & management'; 162 case 'Fashion Illustrator': 163 return 'fashion illustrator'; 164 case 'Art Direction & Copywriting': 165 return 'art direction & copywriting'; 166 case 'Accessory Design': 167 return 'design accessorio'; 168 case 'Technical Drawing for fashion 2D-3D': 169 return 'master in disegno tecnico per la moda'; 170 case 'Handbags and Leather Goods Design': 171 return 'master in borse e pelletteria'; 172 case 'Footwear Design': 173 return 'design di calzature'; 174 case '2D/3D Interior Designer': 175 return 'arredatore d\'interni e operatore cad 2d e 3d'; 176 case 'Visual Merchandiser': 177 return 'visual merchandiser'; 178 case '3D Virtual Fashion': 179 return 'virtual fashion 3d'; 180 case 'Industrial Patternmaker for Textiles and Clothing (T.U.)': 181 return 'modellista industriale tessile abbigliamento t.u.'; 182 case 'Industrial Patternmaker': 183 return 'modellista industriale tessile abbigliamento t.u.'; 184 case 'Industrial Patternmaker CAD Operator': 185 return 'modellista operatore cad'; 186 case 'Bag Patternmaker': 187 return 'modellista borse'; 188 case 'Bag Patternmaker CAD Operator': 189 return 'modellista borse cad'; 190 case 'Fashion Designer CAD Operator': 191 return 'fashion designer operatore cad'; 192 case 'Footwear Patternmaker': 193 return 'modellista per calzature'; 194 case 'Footwear Patternmaker CAD': 195 return 'modellista calzature cad'; 196 case 'Content Creator, Storytelling and Digital Production': 197 return 'content creation storytelling e produzione digitale'; 198 default: 199 console.warn('[IUAD Botpress] Valore corso non riconosciuto:', label); 200 return 'design della moda'; 201 } 202} 203 204let userUpdated = false 205const translations = { 206 it: { 207 botName: 'IUAD', 208 botDescription: 'Benvenuto! Se sei già uno studente IUAD, puoi contattare direttamente la Segreteria di pertinenza. Se invece vuoi informazioni per una nuova iscrizione siamo qui per aiutarti!', 209 composerPlaceholder: 'Scrivi qui...', 210 restartConversation: 'Riavvia la conversazione', 211 newConversation: 'Nuova conversazione', 212 modalTitle: 'Crea una nuova conversazione', 213 modalConfirm: 'Nuova conversazione', 214 modalCancel: 'Annulla', 215 modalDescription: 'Questo cancellerà la conversazione corrente e ne avvierà una nuova.', 216 }, 217 en: { 218 botName: 'IUAD', 219 botDescription: 'Welcome! If you are already an IUAD student, you can contact your office directly. If you need information for a new enrollment, we are here to help!', 220 composerPlaceholder: 'Write here...', 221 restartConversation: 'Restart the conversation', 222 newConversation: 'New conversation', 223 modalTitle: 'Create New Conversation', 224 modalConfirm: 'New Conversation', 225 modalCancel: 'Cancel', 226 modalDescription: 'This will clear the current conversation and start a new one.' 227 } 228} 229 230window.botpress.on('webchat:initialized', async () => { 231 const currentLang = (iuadGetCurrentLang() || 'it').toLowerCase() 232 const t = translations[currentLang] || translations.it 233 234 console.log('currentLang:', currentLang) 235 236 window.botpress.config({ 237 configuration: { 238 botName: t.botName, 239 botDescription: t.botDescription, 240 composerPlaceholder: t.composerPlaceholder, 241 color: '#000000', 242 footer: '', 243 additionalStylesheet: ` 244 .bpFabWrapper { 245 z-index: 1000 !important; 246 } 247 @media (max-width: 768px) { 248 .bpFabWrapper { 249 bottom: 100px !important; 250 right: 10px !important; 251 z-index: 1000 !important; 252 } 253 .bpFab{ 254 box-shadow: none !important; 255 } 256 /* Container chat */ 257 .bpChat, 258 .bpContainer, 259 .bpFab, 260 .bpMessageList { 261 border-radius: 0px !important; 262 } 263 } 264 /* Modal title */ 265 .bpModalTitle { 266 visibility: hidden; 267 position: relative; 268 } 269 270 .bpModalTitle::after { 271 visibility: visible; 272 position: absolute; 273 inset: 0; 274 content: "${t.modalTitle}"; 275 text-align: center; 276 } 277 278 /* Modal description */ 279 .bpModalDescription { 280 visibility: hidden; 281 position: relative; 282 } 283 284 .bpModalDescription::after { 285 visibility: visible; 286 position: absolute; 287 inset: 0; 288 content: "${t.modalDescription}"; 289 white-space: pre-wrap; 290 } 291 292 /* Confirm button */ 293 .bpModalButtonConfirm { 294 position: relative; 295 color: transparent !important; 296 } 297 298 .bpModalButtonConfirm::after { 299 content: "${t.modalConfirm}"; 300 position: absolute; 301 top: 50%; 302 left: 50%; 303 transform: translate(-50%, -50%); 304 color: white; 305 white-space: nowrap; 306 } 307 308 /* Cancel button */ 309 .bpModalButtonCancel { 310 visibility: hidden; 311 position: relative; 312 } 313 314 .bpModalButtonCancel::after { 315 visibility: visible; 316 position: absolute; 317 top: 50%; 318 left: 50%; 319 transform: translate(-50%, -50%); 320 content: "${t.modalCancel}"; 321 white-space: nowrap; 322 } 323 `, 324 translations: { 325 restartConversation: t.restartConversation, 326 newConversation: t.newConversation 327 } 328 } 329 }) 330 331 await window.botpress.updateUser({ 332 data: { 333 language: currentLang 334 } 335 }) 336 337 userUpdated = true 338 console.log('Botpress user language updated:', currentLang) 339}
339) 340 341 342 343window.botpress.on('customEvent', async (event) => { 344 let payload = event 345 346 if (typeof event === 'string') { 347 try { 348 payload = JSON.parse(event) 349 } catch {} 350 } 351 352 try { 353 //console.log('[IUAD Botpress] customEvent ricevuto, type:', payload?.type, 'data keys:', payload?.data ? Object.keys(payload.data) : null) 354 } catch (e) {} 355 356 if (payload?.type === 'debug') { 357 console.log('DATI DAL BOT:', payload.data) 358 359 // Se il bot manda i dati finali solo come "debug", inviamo comunque la lead. 360 try { 361 const d = payload?.data || {} 362 const email = (d.email || '').trim() 363 const nome = (d.nome || '').trim() 364 const cognome = (d.cognome || '').trim() 365 const telefono = (d.telefono || d.phone || '').trim() 366 const sede = (d.sede || '').trim() 367 const corsi = d.corsi 368 369 if (!email) { 370 console.warn('[IUAD Botpress] debug: email mancante, skip invio lead') 371 return 372 } 373 374 const leadKey = email + '|' + nome + '|' + cognome + '|' + telefono + '|' + JSON.stringify(corsi || null) + '|' + sede 375 if (__iuadLastLeadKey === leadKey) { 376 console.log('[IUAD Botpress] debug: lead già inviata (dedupe), skip') 377 return 378 } 379 380 const rawCourseItems = iuadNormalizeCorsiToLabels(corsi) 381 382 const courses_array = [] 383 rawCourseItems.forEach((courseLabel) => { 384 const slug = iuadMapCourseLabelToSlug(courseLabel) 385 if (slug && courses_array.indexOf(slug) === -1) { 386 courses_array.push(slug) 387 } 388 }) 389 390 const currentLang = iuadGetCurrentLang() 391 const location_value = sede || (typeof window.iuadChatLocation !== 'undefined' ? window.iuadChatLocation : '') 392 const how_to_know_value = 7 // "Altro" 393 394 const userData = { 395 first_name: nome, 396 last_name: cognome, 397 email: email, 398 phone_number: telefono, 399 course: courses_array, 400 lang: currentLang, 401 origin: ['chatbot'], 402 how_you_knows: how_to_know_value, 403 location: location_value, 404 request_description: 'Richiesta da Chatbot' 405 } 406 407 //console.log('[IUAD Botpress] debug: userData pronto:', userData) 408 409 const endpoint = iuadGetCrmEndpoint() 410 if (!endpoint) { 411 console.error('[IUAD Botpress] debug: Endpoint CRM non configurato (window.iuadChat.endpoint mancante).', window.iuadChat) 412 return 413 } 414 415 __iuadLastLeadKey = leadKey 416 //console.log('[IUAD Botpress] debug: Invio dati al proxy CRM', endpoint, userData) 417 fetch(endpoint, { 418 method: 'POST', 419 headers: { 'Content-Type': 'application/json' }, 420 body: JSON.stringify(userData) 421 }) 422 .then(response => { 423 console.log('[IUAD Botpress] debug: Response status (proxy):', response.status) 424 return response.json() 425 }) 426 .then(responseData => { 427 console.log('[IUAD Botpress] debug: Response data (proxy):', responseData) 428 }) 429 .catch(error => { 430 console.error('[IUAD Botpress] debug: Errore nella chiamata API:', error) 431 }) 432 } catch (err) { 433 console.error('[IUAD Botpress] debug: Errore costruzione/invio payload CRM:', err) 434 } 435 } 436 //Aggiorna profilo con domanda di ricontatto 437 if (payload?.type === 'update_lead_with_question') { 438 //console.log('DATI DAL BOT:', payload.data) 439 440 // Se il bot manda i dati finali solo come "debug", inviamo comunque la lead. 441 try { 442 const d = payload?.data || {} 443 const email = (d.email || '').trim() 444 const nome = (d.nome || '').trim() 445 const cognome = (d.cognome || '').trim() 446 const telefono = (d.telefono || d.phone || '').trim() 447 const sede = (d.sede || '').trim() 448 const corsi = d.corsi 449 450 const lastQuestion = d.domanda_selezionata[d.domanda_selezionata.length - 1] 451 452 const question = lastQuestion.token ? lastQuestion.token : lastQuestion.text 453 454 if (!email) { 455 console.warn('[IUAD Botpress] debug: email mancante, skip invio lead') 456 return 457 } 458 459 const rawCourseItems = iuadNormalizeCorsiToLabels(corsi) 460 461 const courses_array = []
462 rawCourseItems.forEach((courseLabel) => { 463 const slug = iuadMapCourseLabelToSlug(courseLabel) 464 if (slug && courses_array.indexOf(slug) === -1) { 465 courses_array.push(slug) 466 } 467 }) 468 469 const currentLang = iuadGetCurrentLang() 470 const location_value = sede || (typeof window.iuadChatLocation !== 'undefined' ? window.iuadChatLocation : '') 471 const how_to_know_value = 7 // "Altro" 472 473 const userData = { 474 first_name: nome, 475 last_name: cognome, 476 email: email, 477 phone_number: telefono, 478 course: courses_array, 479 lang: currentLang, 480 origin: ['chatbot'], 481 how_you_knows: how_to_know_value, 482 location: location_value, 483 request_description: question 484 } 485 486 //console.log('[IUAD Botpress] debug: userData pronto:', userData) 487 488 const endpoint = iuadGetCrmEndpoint() 489 if (!endpoint) { 490 console.error('[IUAD Botpress] debug: Endpoint CRM non configurato (window.iuadChat.endpoint mancante).', window.iuadChat) 491 return 492 } 493 494 //console.log('[IUAD Botpress] debug: Invio dati al proxy CRM', endpoint, userData) 495 fetch(endpoint, { 496 method: 'POST', 497 headers: { 'Content-Type': 'application/json' }, 498 body: JSON.stringify(userData) 499 }) 500 .then(response => { 501 console.log('[IUAD Botpress] debug: Response status (proxy):', response.status) 502 return response.json() 503 }) 504 .then(responseData => { 505 console.log('[IUAD Botpress] debug: Response data (proxy):', responseData) 506 }) 507 .catch(error => { 508 console.error('[IUAD Botpress] debug: Errore nella chiamata API:', error) 509 }) 510 } catch (err) { 511 console.error('[IUAD Botpress] debug: Errore costruzione/invio payload CRM:', err) 512 } 513 } 514 515 if (typeof event === 'string') { 516 try { 517 payload = JSON.parse(event) 518 } catch (e) {} 519 } 520 521 if (payload?.type === 'set-user-profile') { 522 console.log('[IUAD Botpress] set-user-profile ricevuto:', payload?.data) 523 const email = (payload?.data?.email || '').trim() 524 const nome = (payload?.data?.nome || '').trim() 525 const cognome = (payload?.data?.cognome || '').trim() 526 const telefono = (payload?.data?.telefono || payload?.data?.phone || '').trim() 527 const fullName = (payload?.data?.name || '').trim() 528 const sede = (payload?.data?.sede || '').trim() 529 const corsi = payload?.data?.corsi 530 531 if (!email) { 532 console.warn('Profilo utente non aggiornato: email mancante') 533 return 534 } 535 536 try { 537 await window.botpress.updateUser({ 538 name: fullName || undefined, 539 userKey: email, 540 data: { 541 email, 542 firstName: nome, 543 lastName: cognome, 544 phone: telefono 545 } 546 }) 547 548 console.log('Profilo Webchat aggiornato via email:', { 549 name: fullName, 550 userKey: email, 551 email, 552 phone: telefono 553 }) 554 } catch (err) { 555 console.error('Errore aggiornamento profilo Webchat:', err) 556 } 557 } 558}) 559 560window.botpress.on('customEvent', (event) => { 561 console.log('EVENT RAW:', event) 562})
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.