@chat21/chat21-ionic 3.4.18 → 3.4.19-rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -8,6 +8,10 @@
8
8
  ### **Copyrigth**:
9
9
  *Tiledesk SRL*
10
10
 
11
+ # 3.4.19-rc1
12
+ - added: ability to check for if emoji is allowd to be sent in message textarea
13
+ - added: ability to check for if url domain is allowd to be sent in message textarea
14
+
11
15
  # 3.4.18 in PROD
12
16
 
13
17
  # 3.4.17 in PROD
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@chat21/chat21-ionic",
3
3
  "author": "Tiledesk SRL",
4
- "version": "3.4.18",
4
+ "version": "3.4.19-rc1",
5
5
  "license": "MIT License",
6
6
  "homepage": "https://tiledesk.com/",
7
7
  "repository": {
@@ -1242,9 +1242,9 @@ export class AppComponent implements OnInit {
1242
1242
  }
1243
1243
 
1244
1244
  goToDashboardLogin(){
1245
- let DASHBOARD_URL = this.appConfigProvider.getConfig().dashboardUrl + '#/login'
1246
- const myWindow = window.open(DASHBOARD_URL, '_self');
1247
- myWindow.focus();
1245
+ // let DASHBOARD_URL = this.appConfigProvider.getConfig().dashboardUrl + '#/login'
1246
+ // const myWindow = window.open(DASHBOARD_URL, '_self');
1247
+ // myWindow.focus();
1248
1248
  }
1249
1249
 
1250
1250
 
@@ -22,10 +22,23 @@
22
22
  {{translationMap?.get('WHATSAPP.LABEL_TEMPLATES')}}
23
23
  </ion-button>
24
24
  </div>
25
-
25
+ </div>
26
+
27
+ <div class="footerContainerAlert">
26
28
  <div *ngIf="offlineMsgEmail && section==='chat' && channel !== CHANNEL_TYPE.WHATSAPP && messageString && (leadInfo?.presence['status']==='offline' && leadInfo?.hasEmail)" class="section-option offline-lead-tip" >
27
29
  {{translationMap.get('EMAIL.EMAIL_OFFLINE_TIP')}}
28
30
  </div>
31
+
32
+ <!-- ALERT EMOJI & URLS -->
33
+ <div id="textAlert" *ngIf="showAlertEmoji" class="section-option offline-lead-tip">
34
+ <ion-icon name="information-circle-outline"></ion-icon>
35
+ {{translationMap.get('EMOJI_NOT_ELLOWED')}}
36
+ </div>
37
+
38
+ <div id="textAlert" *ngIf="showAlertUrl" class="section-option offline-lead-tip">
39
+ <ion-icon name="information-circle-outline"></ion-icon>
40
+ {{translationMap.get('DOMAIN_NOT_ALLOWED')}}
41
+ </div>
29
42
  </div>
30
43
 
31
44
  </div>
@@ -113,6 +126,7 @@
113
126
 
114
127
  <div class="text-message" [ngClass]="{'text-message-no-cr': areVisibleCAR === false || supportMode === false}">
115
128
  <ion-textarea id="ion-textarea" #messageTextArea #message_text_area #textArea rows="1"
129
+ [class.hasError]="showAlertEmoji || showAlertUrl"
116
130
  [placeholder]="translationMap?.get('LABEL_ENTER_MSG_SHORT')"
117
131
  autosize="false"
118
132
  auto-grow="true"
@@ -58,6 +58,7 @@
58
58
  display: block;
59
59
  text-align: right;
60
60
  }
61
+
61
62
  }
62
63
 
63
64
  #message-email{
@@ -170,6 +171,10 @@
170
171
  --padding-start: 10px;
171
172
  line-height: 1.34;
172
173
  font-size: 15px;
174
+
175
+ &.hasError{
176
+ box-shadow: 0 0 0 1px var(--base-red) inset;
177
+ }
173
178
  }
174
179
  }
175
180
  .text-message-no-cr {
@@ -295,6 +300,23 @@ emoji-mart::ng-deep{
295
300
  color: var(--emoji-mart-color);
296
301
  }
297
302
  }
303
+
304
+
305
+ .footerContainerAlert{
306
+ #textAlert{
307
+ display: flex;
308
+ align-items: center;
309
+ justify-content: center;
310
+ color: var(--base-red);
311
+ font-size: 11px;
312
+ }
313
+
314
+ ion-icon{
315
+ font-size: initial;
316
+ margin-right: 4px;
317
+ margin-left: 4px;
318
+ }
319
+ }
298
320
  // input[placeholder] { text-overflow: ellipsis; }
299
321
  // ::-moz-placeholder { text-overflow: ellipsis; } /* firefox 19+ */
300
322
  // input:-moz-placeholder { text-overflow: ellipsis; }
@@ -20,10 +20,12 @@ import { UploadModel } from 'src/chat21-core/models/upload';
20
20
  import { LoggerService } from 'src/chat21-core/providers/abstract/logger.service';
21
21
  import { LoggerInstance } from 'src/chat21-core/providers/logger/loggerInstance';
22
22
  import { EventsService } from 'src/app/services/events-service';
23
- import { isOnMobileDevice } from 'src/chat21-core/utils/utils';
23
+ import { isAllowedUrlInText, isEmoji, isOnMobileDevice } from 'src/chat21-core/utils/utils';
24
24
  import { checkAcceptedFile } from 'src/chat21-core/utils/utils';
25
25
  import { CopilotService } from 'src/app/services/copilot/copilot.service';
26
26
  import { BRAND_BASE_INFO } from 'src/app/utils/utils-resources';
27
+ import { ProjectService } from 'src/app/services/projects/project.service';
28
+ import { Project } from 'src/chat21-core/models/projects';
27
29
 
28
30
 
29
31
  @Component({
@@ -70,6 +72,7 @@ export class MessageTextAreaComponent implements OnInit, AfterViewInit, OnChange
70
72
  @Output() onPresentModalScrollToBottom = new EventEmitter<boolean>();
71
73
  @Output() onOpenFooterSection = new EventEmitter<string>();
72
74
 
75
+ public project: Project;
73
76
  public conversationEnabled = false;
74
77
  public messageString: string;
75
78
  public HAS_PASTED: boolean = false;
@@ -111,6 +114,9 @@ export class MessageTextAreaComponent implements OnInit, AfterViewInit, OnChange
111
114
 
112
115
  BRAND_BASE_INFO = BRAND_BASE_INFO
113
116
 
117
+ showAlertEmoji: boolean = false
118
+ showAlertUrl: boolean = false;
119
+
114
120
  /**
115
121
  * Constructor
116
122
  * @param chooser
@@ -123,7 +129,8 @@ export class MessageTextAreaComponent implements OnInit, AfterViewInit, OnChange
123
129
  public modalController: ModalController,
124
130
  public uploadService: UploadService,
125
131
  public toastController: ToastController,
126
- public eventsService: EventsService
132
+ public eventsService: EventsService,
133
+ public projectService: ProjectService
127
134
  ) { }
128
135
 
129
136
  // ---------------------------------------------------------
@@ -153,6 +160,8 @@ export class MessageTextAreaComponent implements OnInit, AfterViewInit, OnChange
153
160
  this.logger.log('[CONVS-DETAIL] - returnChangeTextArea ngOnChanges in [MSG-TEXT-AREA] this.tagsCannedFilter.length ', this.tagsCannedFilter.length)
154
161
  this.logger.log('[CONVS-DETAIL] - returnChangeTextArea ngOnChanges in [MSG-TEXT-AREA] channel', this.channel, this.whatsappTemplatesSection, this.emailSection )
155
162
 
163
+ this.project = this.projectService.getProject();
164
+ this.logger.log('[CONVS-DETAIL] - returnChangeTextArea ngOnChanges in [MSG-TEXT-AREA] project', this.project)
156
165
  // use case drop
157
166
  if (this.dropEvent) {
158
167
  this.presentModal(this.dropEvent)
@@ -495,6 +504,11 @@ export class MessageTextAreaComponent implements OnInit, AfterViewInit, OnChange
495
504
  this.conversationEnabled = false;
496
505
  }
497
506
 
507
+ let check = this.checkForEmojii(e.detail.value)
508
+ if(!check){
509
+ return;
510
+ }
511
+
498
512
  this.eventChangeTextArea.emit({ msg: message, offsetHeight: height });
499
513
  }
500
514
 
@@ -611,6 +625,12 @@ export class MessageTextAreaComponent implements OnInit, AfterViewInit, OnChange
611
625
  // text.replace(/\s/g, "")
612
626
  this.messageString = '';
613
627
  // text = text.replace(/(\r\n|\n|\r)/gm, '');
628
+
629
+ let checkUrlDomain = this.checkForUrlDomain(text)
630
+ if(!checkUrlDomain){
631
+ return
632
+ }
633
+
614
634
  if (text && text.trim() !== '') {
615
635
  this.eventSendMessage.emit({ msg: text, type: TYPE_MSG_TEXT, metadata: null, attributes: null });
616
636
  }
@@ -673,6 +693,38 @@ export class MessageTextAreaComponent implements OnInit, AfterViewInit, OnChange
673
693
  }
674
694
 
675
695
 
696
+ //check if the text contains emojii
697
+ checkForEmojii(text){
698
+ //remove emojii only if "emojii" exist and is set to false
699
+ if(this.project && this.project.settings?.allow_send_emoji === false){
700
+ this.showAlertEmoji = isEmoji(text);
701
+ if(this.showAlertEmoji){
702
+ return false
703
+ }
704
+ this.showAlertEmoji = false;
705
+ return true
706
+ }
707
+ this.showAlertEmoji = false;
708
+ return true
709
+ }
710
+
711
+ //check if the text contains url domain allowed in list
712
+ checkForUrlDomain(text){
713
+ if(this.project && this.project.settings?.allowed_urls === true){
714
+ this.showAlertUrl = !isAllowedUrlInText(text, this.project.settings?.allowed_urls_list);
715
+ if(this.showAlertUrl){
716
+ return false
717
+ }
718
+ this.showAlertUrl = false
719
+ return true
720
+ }
721
+ this.showAlertUrl = false
722
+ return true
723
+
724
+
725
+ }
726
+
727
+
676
728
 
677
729
  // --------------------------------
678
730
  // on mobile !
@@ -683,8 +683,11 @@ export class ConversationDetailPage implements OnInit, OnDestroy, AfterViewInit
683
683
  "WHATSAPP.ERROR_WHATSAPP_GENERIC_ERROR",
684
684
 
685
685
  "COPILOT.ASK_AI",
686
- "COPILOT.NO_SUGGESTIONS_PRESENT"
686
+ "COPILOT.NO_SUGGESTIONS_PRESENT",
687
687
 
688
+ "EMOJI_NOT_ELLOWED",
689
+ "DOMAIN_NOT_ALLOWED",
690
+
688
691
  ]
689
692
 
690
693
  const keysHeader = [
@@ -15,9 +15,12 @@ export class ProjectService {
15
15
 
16
16
  private SERVER_BASE_URL: string;
17
17
  private tiledeskToken: string;
18
+ private _project: Project;
18
19
 
19
20
  private logger: LoggerService = LoggerInstance.getInstance();
20
21
 
22
+
23
+
21
24
  constructor(
22
25
  public http: HttpClient,
23
26
  public appStorageService: AppStorageService
@@ -61,8 +64,26 @@ export class ProjectService {
61
64
  };
62
65
  return this.http.get(url, httpOptions).pipe(map((project: Project) => {
63
66
  this.logger.log('[TILEDESK-SERVICE] GET PROJECT BY ID URL - RES ', project);
67
+ this._project = project;
64
68
  return project
65
69
  }))
66
70
  }
67
71
 
72
+ /**
73
+ * Get the current project
74
+ * @returns The current project
75
+ */
76
+ public getProject(): Project {
77
+ return this._project;
78
+ }
79
+
80
+ /**
81
+ * Set the current project
82
+ * @param project The project to set
83
+ */
84
+ public setProject(project: Project): void {
85
+ this._project = project;
86
+ this.logger.log('[PROJECTS-SERVICE] setProject - Project set: ', this._project);
87
+ }
88
+
68
89
  }
@@ -304,5 +304,7 @@
304
304
  "SEND_EMAIL_ERROR":"⚠️ تنبيه ⚠️ حدث خطأ أثناء إرسال البريد الإلكتروني. يرجى المحاولة مرة أخرى",
305
305
  "SUBJECT_OFFLINE_MESSAGE":"رسالة Tiledesk غير متصل 💬",
306
306
  "SEND_EMAIL_SUCCESS_OFFLINE_MESSAGE":"تم إرسال الرسالة أيضًا عبر البريد الإلكتروني 📩"
307
- }
307
+ },
308
+ "EMOJI_NOT_ELLOWED": "الرموز التعبيرية غير مسموح بها",
309
+ "DOMAIN_NOT_ALLOWED": "يحتوي الرابط على نطاق غير مسموح"
308
310
  }
@@ -304,5 +304,7 @@
304
304
  "SEND_EMAIL_ERROR":"⚠️ DİQQƏT ⚠️ E-poçt göndərilərkən xəta baş verdi. Yenidən cəhd edin",
305
305
  "SUBJECT_OFFLINE_MESSAGE":"Tiledesk Offline mesajı 💬",
306
306
  "SEND_EMAIL_SUCCESS_OFFLINE_MESSAGE":"Mesaj e-poçt vasitəsilə də göndərilib 📩"
307
- }
307
+ },
308
+ "EMOJI_NOT_ELLOWED": "Emoji icazə verilmir",
309
+ "DOMAIN_NOT_ALLOWED": "URL icazə verilməyən domeni ehtiva edir"
308
310
  }
@@ -304,5 +304,7 @@
304
304
  "SEND_EMAIL_ERROR":"⚠️ ACHTUNG ⚠️ Beim Senden der E-Mail ist ein Fehler aufgetreten. Bitte versuchen Sie es erneut",
305
305
  "SUBJECT_OFFLINE_MESSAGE":"Tiledesk Offline-Nachricht 💬",
306
306
  "SEND_EMAIL_SUCCESS_OFFLINE_MESSAGE":"Nachricht auch per E-Mail gesendet 📩"
307
- }
307
+ },
308
+ "EMOJI_NOT_ELLOWED": "Emoji nicht erlaubt",
309
+ "DOMAIN_NOT_ALLOWED": "Die URL enthält eine nicht erlaubte Domain"
308
310
  }
@@ -312,5 +312,7 @@
312
312
  "NO_SUGGESTIONS_PRESENT":"No suggestions found",
313
313
  "INSERT_PROMPT_HERE":"Inster a prompt here",
314
314
  "HOW_CAN_I_HELP_YOU":"How can i help you?"
315
- }
315
+ },
316
+ "EMOJI_NOT_ELLOWED":"Emoji not allowed",
317
+ "DOMAIN_NOT_ALLOWED":"URL contains a non-allowed domain"
316
318
  }
@@ -304,5 +304,7 @@
304
304
  "SEND_EMAIL_ERROR":"⚠️ ATENCIÓN ⚠️ Ocurrió un error al enviar el correo. Vuelve a intentarlo",
305
305
  "SUBJECT_OFFLINE_MESSAGE":"Mensaje sin conexión de Tiledesk 💬",
306
306
  "SEND_EMAIL_SUCCESS_OFFLINE_MESSAGE":"Mensaje también enviado por correo electrónico 📩"
307
- }
307
+ },
308
+ "EMOJI_NOT_ELLOWED": "Emoji no permitido",
309
+ "DOMAIN_NOT_ALLOWED": "La URL contiene un dominio no permitido"
308
310
  }
@@ -294,7 +294,7 @@
294
294
  },
295
295
  "EMAIL":{
296
296
  "LABEL_TOOLTIP":"Répondre avec un e-mail",
297
- "EMAIL_OFFLINE_TIP":"Attention : l'utilisateur est hors ligne ! Le message sera envoyé par email",
297
+ "EMAIL_OFFLINE_TIP":"Attention : l'utilisateur est hors ligne ! Le message sera envoyé par email",
298
298
  "EMAIL_PLACEHOLDER":"Brouillon disponible ici - cliquez pour modifier",
299
299
  "EMAIL_NOT_FOUND_PLACEHOLDER":"Cet utilisateur n'a pas fourni d'adresse e-mail. Mettre à jour l'adresse du visiteur pour envoyer un e-mail",
300
300
  "SUBJECT":"Matière",
@@ -304,5 +304,7 @@
304
304
  "SEND_EMAIL_ERROR":"⚠️ ATTENTION ⚠️ Une erreur s'est produite lors de l'envoi de l'e-mail. Veuillez réessayer",
305
305
  "SUBJECT_OFFLINE_MESSAGE":"Message hors ligne de Tiledesk 💬",
306
306
  "SEND_EMAIL_SUCCESS_OFFLINE_MESSAGE":"Message également envoyé par mail 📩"
307
- }
307
+ },
308
+ "EMOJI_NOT_ELLOWED": "Emoji non autorisé",
309
+ "DOMAIN_NOT_ALLOWED": "L'URL contient un domaine non autorisé"
308
310
  }
@@ -312,5 +312,7 @@
312
312
  "NO_SUGGESTIONS_PRESENT":"Nessun suggerimento trovato",
313
313
  "INSERT_PROMPT_HERE":"Inserisci un prompt qui",
314
314
  "HOW_CAN_I_HELP_YOU":"Come posso aiutarti?"
315
- }
315
+ },
316
+ "EMOJI_NOT_ELLOWED": "Emoji non consentite",
317
+ "DOMAIN_NOT_ALLOWED": "L'URL contiene un dominio non consentito"
316
318
  }
@@ -304,5 +304,7 @@
304
304
  "SEND_EMAIL_ERROR":"⚠️ НАЗАР АУДАРЫҢЫЗ ⚠️ Электрондық поштаны жіберу кезінде қате орын алды. Қайталап көріңіз",
305
305
  "SUBJECT_OFFLINE_MESSAGE":"Tiledesk офлайн хабарламасы 💬",
306
306
  "SEND_EMAIL_SUCCESS_OFFLINE_MESSAGE":"Хабарлама электрондық пошта арқылы да жіберілді 📩"
307
- }
307
+ },
308
+ "EMOJI_NOT_ELLOWED": "Эмодзи рұқсат етілмеген",
309
+ "DOMAIN_NOT_ALLOWED": "URL рұқсат етілмеген доменді қамтиды"
308
310
  }
@@ -304,5 +304,7 @@
304
304
  "SEND_EMAIL_ERROR":"⚠️ ATENÇÃO ⚠️ Ocorreu um erro ao enviar o e-mail. Tente novamente",
305
305
  "SUBJECT_OFFLINE_MESSAGE":"Mensagem off-line do Tiledesk 💬",
306
306
  "SEND_EMAIL_SUCCESS_OFFLINE_MESSAGE":"Mensagem também enviada por e-mail 📩"
307
- }
307
+ },
308
+ "EMOJI_NOT_ELLOWED": "Emoji não permitido",
309
+ "DOMAIN_NOT_ALLOWED": "O URL contém um domínio não permitido"
308
310
  }
@@ -304,5 +304,7 @@
304
304
  "SEND_EMAIL_ERROR":"⚠️ ВНИМАНИЕ ⚠️ При отправке письма произошла ошибка. Пожалуйста, повторите попытку",
305
305
  "SUBJECT_OFFLINE_MESSAGE":"Сообщение Tiledesk Offline 💬",
306
306
  "SEND_EMAIL_SUCCESS_OFFLINE_MESSAGE":"Сообщение также отправлено по электронной почте 📩"
307
- }
307
+ },
308
+ "EMOJI_NOT_ELLOWED": "Эмодзи не разрешены",
309
+ "DOMAIN_NOT_ALLOWED": "URL содержит недопустимый домен"
308
310
  }
@@ -304,5 +304,7 @@
304
304
  "SEND_EMAIL_ERROR":"⚠ ПАЖЊА ⚠ Дошло је до грешке при слању е-поште. Молимо покушајте поново",
305
305
  "SUBJECT_OFFLINE_MESSAGE":"Тиледеск Офлајн порука 💬",
306
306
  "SEND_EMAIL_SUCCESS_OFFLINE_MESSAGE":"Порука је такође послата е-поштом 📩"
307
- }
307
+ },
308
+ "EMOJI_NOT_ELLOWED": "Emodžiji nisu dozvoljeni",
309
+ "DOMAIN_NOT_ALLOWED": "URL sadrži nedozvoljenu domenu"
308
310
  }
@@ -304,5 +304,7 @@
304
304
  "SEND_EMAIL_ERROR":"⚠️ OBS ⚠️ Ett fel uppstod när e-post skickades. Försök igen",
305
305
  "SUBJECT_OFFLINE_MESSAGE":"Tiledesk Offline meddelande 💬",
306
306
  "SEND_EMAIL_SUCCESS_OFFLINE_MESSAGE":"Meddelande skickas även via mail 📩"
307
- }
307
+ },
308
+ "EMOJI_NOT_ELLOWED": "Emoji är inte tillåtna",
309
+ "DOMAIN_NOT_ALLOWED": "URL:en innehåller en otillåten domän"
308
310
  }
@@ -304,5 +304,7 @@
304
304
  "SEND_EMAIL_ERROR":"⚠️ DİKKAT ⚠️ E-posta gönderirken hata oluştu. Lütfen tekrar deneyin",
305
305
  "SUBJECT_OFFLINE_MESSAGE":"Tiledesk Çevrimdışı mesaj 💬",
306
306
  "SEND_EMAIL_SUCCESS_OFFLINE_MESSAGE":"Mesaj ayrıca e-posta ile gönderilir 📩"
307
- }
307
+ },
308
+ "EMOJI_NOT_ELLOWED": "Emoji'ye izin verilmiyor",
309
+ "DOMAIN_NOT_ALLOWED": "URL izin verilmeyen bir alan adı içeriyor"
308
310
  }
@@ -304,5 +304,7 @@
304
304
  "SEND_EMAIL_ERROR":"⚠️ УВАГА ⚠️ Під час надсилання електронної пошти сталася помилка. Будь ласка, повторіть спробу",
305
305
  "SUBJECT_OFFLINE_MESSAGE":"Повідомлення Tiledesk Offline 💬",
306
306
  "SEND_EMAIL_SUCCESS_OFFLINE_MESSAGE":"Повідомлення також надіслано електронною поштою 📩"
307
- }
307
+ },
308
+ "EMOJI_NOT_ELLOWED": "Емодзі не дозволені",
309
+ "DOMAIN_NOT_ALLOWED": "URL містить недозволений домен"
308
310
  }
@@ -1,4 +1,3 @@
1
-
2
1
  {
3
2
  "LABEL_TU": "siz: ",
4
3
  "LABEL_MSG_PUSH_START_CHAT": "Hali suhbat yo'q",
@@ -305,5 +304,7 @@
305
304
  "SEND_EMAIL_ERROR":"⚠️ DIQQAT ⚠️ Elektron pochta xabarini yuborishda xatolik yuz berdi. Qaytadan urining",
306
305
  "SUBJECT_OFFLINE_MESSAGE":"Tiledesk oflayn xabar 💬",
307
306
  "SEND_EMAIL_SUCCESS_OFFLINE_MESSAGE":"Xabar elektron pochta orqali ham yuborildi 📩"
308
- }
307
+ },
308
+ "EMOJI_NOT_ELLOWED": "Emoji'ga ruxsat berilmagan",
309
+ "DOMAIN_NOT_ALLOWED": "URL ruxsat etilmagan domenni o'z ichiga oladi"
309
310
  }
@@ -921,3 +921,95 @@ export function getProjectIdSelectedConversation(conversationWith: string): stri
921
921
  }
922
922
  return projectId
923
923
  }
924
+
925
+
926
+ export function isEmoji(str: string) {
927
+ // tslint:disable-next-line:max-line-length
928
+ const ranges = ['(?:[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff]|[\u0023-\u0039]\ufe0f?\u20e3|\u3299|\u3297|\u303d|\u3030|\u24c2|\ud83c[\udd70-\udd71]|\ud83c[\udd7e-\udd7f]|\ud83c\udd8e|\ud83c[\udd91-\udd9a]|\ud83c[\udde6-\uddff]|[\ud83c[\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|[\ud83c[\ude32-\ude3a]|[\ud83c[\ude50-\ude51]|\u203c|\u2049|[\u25aa-\u25ab]|\u25b6|\u25c0|[\u25fb-\u25fe]|\u00a9|\u00ae|\u2122|\u2139|\ud83c\udc04|[\u2600-\u26FF]|\u2b05|\u2b06|\u2b07|\u2b1b|\u2b1c|\u2b50|\u2b55|\u231a|\u231b|\u2328|\u23cf|[\u23e9-\u23f3]|[\u23f8-\u23fa]|\ud83c\udccf|\u2934|\u2935|[\u2190-\u21ff])'];
929
+ if (str.match(ranges.join('|'))) {
930
+ return true;
931
+ } else {
932
+ return false;
933
+ }
934
+ }
935
+
936
+ // export function isAllowedUrlInText(text: string, allowedUrls: string[]): boolean {
937
+ // // Regex per trovare URL o domini nudi nel testo
938
+ // const urlRegex = /https?:\/\/[^\s]+|www\.[^\s]+|(?:\b[\w-]+\.)+[a-z]{2,}(\/[^\s]*)?/gi;
939
+ // const foundUrls = text.match(urlRegex);
940
+
941
+ // if (!foundUrls) {
942
+ // return true; // Nessun URL => testo ammesso
943
+ // }
944
+
945
+ // // Normalizza dominio: rimuove schema, www., slash finali
946
+ // const normalize = (url: string) =>
947
+ // url
948
+ // .replace(/^https?:\/\//i, '')
949
+ // .replace(/^www\./i, '')
950
+ // .replace(/\/$/, '')
951
+ // .toLowerCase();
952
+
953
+ // // Normalizza tutti gli allowed pattern per confronto
954
+ // const normalizedAllowedPatterns = allowedUrls.map(pattern =>
955
+ // pattern
956
+ // .replace(/^https?:\/\//i, '')
957
+ // .replace(/^www\./i, '')
958
+ // .replace(/\/$/, '')
959
+ // .toLowerCase()
960
+ // .replace(/\./g, '\\.')
961
+ // .replace(/\//g, '\\/')
962
+ // .replace(/\*/g, '.*')
963
+ // );
964
+
965
+ // return foundUrls.every(rawUrl => {
966
+ // const url = normalize(rawUrl);
967
+ // return normalizedAllowedPatterns.some(pattern => {
968
+ // const regex = new RegExp(`^${pattern}$`, 'i');
969
+ // return regex.test(url);
970
+ // });
971
+ // });
972
+ // }
973
+
974
+ export function isAllowedUrlInText(text: string, allowedUrls: string[]) {
975
+ const urlsInMessage = extractUrls(text);
976
+ console.log('urlsInMessage ++++ :', urlsInMessage);
977
+
978
+ const allowedPatterns = allowedUrls.map((url) => {
979
+ try {
980
+ // Prova a estrarre il dominio da una URL completa
981
+ const hostname = new URL(url).hostname.toLowerCase();
982
+ return hostname;
983
+ } catch {
984
+ // Lascia il dominio nudo (es: "*.tiledesk.com" o "tiledesk.com")
985
+ return url.toLowerCase();
986
+ }
987
+ });
988
+
989
+ const matchesAllowed = (domain: string) => {
990
+ return allowedPatterns.some((pattern) => {
991
+ if (pattern.startsWith('*.')) {
992
+ const base = pattern.replace(/^\*\./, '');
993
+ return domain === base || domain.endsWith('.' + base);
994
+ } else {
995
+ return domain === pattern;
996
+ }
997
+ });
998
+ };
999
+
1000
+ const nonWhitelistedDomains = urlsInMessage.filter((url) => {
1001
+ try {
1002
+ const domain = new URL(url).hostname.toLowerCase();
1003
+ return !matchesAllowed(domain);
1004
+ } catch (e) {
1005
+ return true; // Considera URL non valido come non ammesso
1006
+ }
1007
+ });
1008
+
1009
+ return nonWhitelistedDomains.length === 0;
1010
+ }
1011
+
1012
+ function extractUrls(text: string): string[] {
1013
+ const urlRegex = /https?:\/\/[^\s]+/g;
1014
+ return text.match(urlRegex) || [];
1015
+ }
@@ -11,6 +11,7 @@ body {
11
11
  --basic-gray: #666666;
12
12
  --dark-gray: #363636;
13
13
  --light-blue: #C9E4F6;
14
+ --base-red: #aa0404;
14
15
 
15
16
  --header-height: 60px;
16
17
  --padding-conversation-detail: 10px;