mirror of
				https://github.com/lingble/chatwoot.git
				synced 2025-10-31 19:17:48 +00:00 
			
		
		
		
	 99997a701a
			
		
	
	99997a701a
	
	
	
		
			
			Implements comprehensive Twilio WhatsApp content template support (Phase
1) enabling text, media, and quick reply templates with proper parameter
conversion, sync capabilities, and feature flag protection.
###  Features Implemented
  **Template Types Supported**
  - Basic Text Templates: Simple text with variables ({{1}}, {{2}})
  - Media Templates: Image/Video/Document templates with text variables
  - Quick Reply Templates: Interactive button templates
- Phase 2 (Future): List Picker, Call-to-Action, Catalog, Carousel,
Authentication templates
  **Template Synchronization**
- API Endpoint: POST
/api/v1/accounts/{account_id}/inboxes/{inbox_id}/sync_templates
  - Background Job: Channels::Twilio::TemplatesSyncJob
  - Storage: JSONB format in channel_twilio_sms.content_templates
  - Auto-categorization: UTILITY, MARKETING, AUTHENTICATION categories
 ###  Template Examples Tested
  #### Text template
```
  { "name": "greet", "language": "en" }
```
  #### Template with variables
```
  { "name": "order_status", "parameters": [{"type": "body", "parameters": [{"text": "John"}]}] }
```
  #### Media template with image
```
  { "name": "product_showcase", "parameters": [
    {"type": "header", "parameters": [{"image": {"link": "image.jpg"}}]},
    {"type": "body", "parameters": [{"text": "iPhone"}, {"text": "$999"}]}
  ]}
```
#### Preview
<img width="1362" height="1058" alt="CleanShot 2025-08-26 at 10 01
51@2x"
src="https://github.com/user-attachments/assets/cb280cea-08c3-44ca-8025-58a96cb3a451"
/>
<img width="1308" height="1246" alt="CleanShot 2025-08-26 at 10 02
02@2x"
src="https://github.com/user-attachments/assets/9ea8537a-61e9-40f5-844f-eaad337e1ddd"
/>
#### User guide
https://www.chatwoot.com/hc/user-guide/articles/1756195741-twilio-content-templates
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
		
	
		
			
				
	
	
		
			171 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			171 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| export const MESSAGE_STATUS = {
 | |
|   FAILED: 'failed',
 | |
|   SENT: 'sent',
 | |
|   DELIVERED: 'delivered',
 | |
|   READ: 'read',
 | |
|   PROGRESS: 'progress',
 | |
| };
 | |
| 
 | |
| export const MESSAGE_TYPE = {
 | |
|   INCOMING: 0,
 | |
|   OUTGOING: 1,
 | |
|   ACTIVITY: 2,
 | |
|   TEMPLATE: 3,
 | |
| };
 | |
| 
 | |
| export const CONVERSATION_STATUS = {
 | |
|   OPEN: 'open',
 | |
|   RESOLVED: 'resolved',
 | |
|   PENDING: 'pending',
 | |
|   SNOOZED: 'snoozed',
 | |
| };
 | |
| 
 | |
| export const CONVERSATION_PRIORITY = {
 | |
|   URGENT: 'urgent',
 | |
|   HIGH: 'high',
 | |
|   LOW: 'low',
 | |
|   MEDIUM: 'medium',
 | |
| };
 | |
| 
 | |
| export const CONVERSATION_PRIORITY_ORDER = {
 | |
|   urgent: 4,
 | |
|   high: 3,
 | |
|   medium: 2,
 | |
|   low: 1,
 | |
| };
 | |
| 
 | |
| // Size in mega bytes
 | |
| export const MAXIMUM_FILE_UPLOAD_SIZE = 40;
 | |
| 
 | |
| export const ALLOWED_FILE_TYPES =
 | |
|   'image/*,' +
 | |
|   'audio/*,' +
 | |
|   'video/*,' +
 | |
|   '.3gpp,' +
 | |
|   'text/csv, text/plain, application/json, application/pdf, text/rtf,' +
 | |
|   'application/xml, text/xml,' +
 | |
|   'application/zip, application/x-7z-compressed application/vnd.rar application/x-tar,' +
 | |
|   'application/msword, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/vnd.oasis.opendocument.text,' +
 | |
|   'application/vnd.openxmlformats-officedocument.presentationml.presentation, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,' +
 | |
|   'application/vnd.openxmlformats-officedocument.wordprocessingml.document,';
 | |
| 
 | |
| export const CSAT_RATINGS = [
 | |
|   {
 | |
|     key: 'disappointed',
 | |
|     translationKey: 'CSAT.RATINGS.POOR',
 | |
|     emoji: '😞',
 | |
|     value: 1,
 | |
|     color: '#FDAD2A',
 | |
|   },
 | |
|   {
 | |
|     key: 'expressionless',
 | |
|     translationKey: 'CSAT.RATINGS.FAIR',
 | |
|     emoji: '😑',
 | |
|     value: 2,
 | |
|     color: '#FFC532',
 | |
|   },
 | |
|   {
 | |
|     key: 'neutral',
 | |
|     translationKey: 'CSAT.RATINGS.AVERAGE',
 | |
|     emoji: '😐',
 | |
|     value: 3,
 | |
|     color: '#FCEC56',
 | |
|   },
 | |
|   {
 | |
|     key: 'grinning',
 | |
|     translationKey: 'CSAT.RATINGS.GOOD',
 | |
|     emoji: '😀',
 | |
|     value: 4,
 | |
|     color: '#6FD86F',
 | |
|   },
 | |
|   {
 | |
|     key: 'smiling',
 | |
|     emoji: '😍',
 | |
|     translationKey: 'CSAT.RATINGS.EXCELLENT',
 | |
|     value: 5,
 | |
|     color: '#44CE4B',
 | |
|   },
 | |
| ];
 | |
| 
 | |
| export const CSAT_DISPLAY_TYPES = {
 | |
|   EMOJI: 'emoji',
 | |
|   STAR: 'star',
 | |
| };
 | |
| 
 | |
| export const AUDIO_FORMATS = {
 | |
|   WEBM: 'audio/webm',
 | |
|   OGG: 'audio/ogg',
 | |
|   MP3: 'audio/mp3',
 | |
|   WAV: 'audio/wav',
 | |
| };
 | |
| 
 | |
| export const MESSAGE_VARIABLES = [
 | |
|   {
 | |
|     label: 'Conversation Id',
 | |
|     key: 'conversation.id',
 | |
|   },
 | |
|   {
 | |
|     label: 'Contact Id',
 | |
|     key: 'contact.id',
 | |
|   },
 | |
|   {
 | |
|     label: 'Contact name',
 | |
|     key: 'contact.name',
 | |
|   },
 | |
|   {
 | |
|     label: 'Contact first name',
 | |
|     key: 'contact.first_name',
 | |
|   },
 | |
|   {
 | |
|     label: 'Contact last name',
 | |
|     key: 'contact.last_name',
 | |
|   },
 | |
|   {
 | |
|     label: 'Contact email',
 | |
|     key: 'contact.email',
 | |
|   },
 | |
|   {
 | |
|     label: 'Contact phone',
 | |
|     key: 'contact.phone',
 | |
|   },
 | |
|   {
 | |
|     label: 'Agent name',
 | |
|     key: 'agent.name',
 | |
|   },
 | |
|   {
 | |
|     label: 'Agent first name',
 | |
|     key: 'agent.first_name',
 | |
|   },
 | |
|   {
 | |
|     label: 'Agent last name',
 | |
|     key: 'agent.last_name',
 | |
|   },
 | |
|   {
 | |
|     label: 'Agent email',
 | |
|     key: 'agent.email',
 | |
|   },
 | |
|   {
 | |
|     key: 'inbox.name',
 | |
|     label: 'Inbox name',
 | |
|   },
 | |
|   {
 | |
|     label: 'Inbox id',
 | |
|     key: 'inbox.id',
 | |
|   },
 | |
| ];
 | |
| 
 | |
| export const ATTACHMENT_ICONS = {
 | |
|   image: 'image',
 | |
|   audio: 'headphones-sound-wave',
 | |
|   video: 'video',
 | |
|   file: 'document',
 | |
|   location: 'location',
 | |
|   fallback: 'link',
 | |
| };
 | |
| 
 | |
| export const TWILIO_CONTENT_TEMPLATE_TYPES = {
 | |
|   TEXT: 'text',
 | |
|   MEDIA: 'media',
 | |
|   QUICK_REPLY: 'quick_reply',
 | |
| };
 |