@itleanchatbot/shared-models-js-postgres 3.1.7 → 3.1.8
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@itleanchatbot/shared-models-js-postgres",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.8",
|
|
4
4
|
"description": "Shared Models JS Postgres",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"license": "ISC",
|
|
@@ -40,10 +40,10 @@
|
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"crypto-js": "^4.0.0",
|
|
42
42
|
"dotenv": "^16.0.0",
|
|
43
|
-
"moment": "^2.29.
|
|
43
|
+
"moment": "^2.29.3",
|
|
44
44
|
"pg": "^8.5.1",
|
|
45
45
|
"pg-hstore": "^2.3.3",
|
|
46
|
-
"sequelize": "^6.
|
|
46
|
+
"sequelize": "^6.3.5",
|
|
47
47
|
"sequelize-cli": "^6.4.1",
|
|
48
48
|
"uuid-apikey": "^1.5.3"
|
|
49
49
|
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
async up(queryInterface) {
|
|
5
|
+
await queryInterface.sequelize.query(`
|
|
6
|
+
CREATE INDEX IF NOT EXISTS idx_botiterables_ent_createdat
|
|
7
|
+
ON "BotIterables"("EnterpriseId", "createdAt");
|
|
8
|
+
`)
|
|
9
|
+
|
|
10
|
+
await queryInterface.sequelize.query(`
|
|
11
|
+
CREATE INDEX IF NOT EXISTS idx_botiterables_session
|
|
12
|
+
ON "BotIterables"("SessionId");
|
|
13
|
+
`)
|
|
14
|
+
|
|
15
|
+
await queryInterface.sequelize.query(`
|
|
16
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_id_channel
|
|
17
|
+
ON "Sessions"(id, "ChannelId");
|
|
18
|
+
`)
|
|
19
|
+
|
|
20
|
+
await queryInterface.sequelize.query(`
|
|
21
|
+
CREATE INDEX IF NOT EXISTS idx_channels_id
|
|
22
|
+
ON "Channels"(id);
|
|
23
|
+
`)
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
async down(queryInterface) {
|
|
27
|
+
await queryInterface.sequelize.query(`
|
|
28
|
+
DROP INDEX IF EXISTS idx_botiterables_ent_createdat;
|
|
29
|
+
`)
|
|
30
|
+
await queryInterface.sequelize.query(`
|
|
31
|
+
DROP INDEX IF EXISTS idx_botiterables_session;
|
|
32
|
+
`)
|
|
33
|
+
await queryInterface.sequelize.query(`
|
|
34
|
+
DROP INDEX IF EXISTS idx_sessions_id_channel;
|
|
35
|
+
`)
|
|
36
|
+
await queryInterface.sequelize.query(`
|
|
37
|
+
DROP INDEX IF EXISTS idx_channels_id;
|
|
38
|
+
`)
|
|
39
|
+
},
|
|
40
|
+
}
|
|
@@ -1,236 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
module.exports = {
|
|
4
|
-
async up(queryInterface) {
|
|
5
|
-
await queryInterface.sequelize.query(`
|
|
6
|
-
DROP VIEW IF EXISTS channel_message_type_daily;
|
|
7
|
-
|
|
8
|
-
CREATE VIEW channel_message_type_daily AS
|
|
9
|
-
WITH base AS (
|
|
10
|
-
SELECT
|
|
11
|
-
((bi."createdAt" AT TIME ZONE 'UTC') AT TIME ZONE 'America/Sao_Paulo')::date AS day,
|
|
12
|
-
bi."EnterpriseId" AS "EnterpriseId",
|
|
13
|
-
s."ChannelId" AS "SessionChannelId",
|
|
14
|
-
|
|
15
|
-
LOWER(
|
|
16
|
-
COALESCE(
|
|
17
|
-
NULLIF(bi.context::jsonb ->> 'channelType', ''),
|
|
18
|
-
NULLIF(bi.context::jsonb #>> '{inbound_message,channel}', ''),
|
|
19
|
-
NULLIF(bi.context::jsonb #>> '{inboundMessage,channel}', ''),
|
|
20
|
-
CASE
|
|
21
|
-
WHEN (bi.payload::jsonb #>> '{channelId}') = 'msteams'
|
|
22
|
-
OR (bi.context::jsonb #>> '{parsedMessage,channel,id}') = 'msteams'
|
|
23
|
-
THEN 'microsoft_teams' ELSE NULL END,
|
|
24
|
-
CASE
|
|
25
|
-
WHEN (bi.context::jsonb ->> 'channel') ILIKE 'whats%'
|
|
26
|
-
OR (bi.context::jsonb ->> 'channelType') ILIKE 'whats%'
|
|
27
|
-
THEN 'whatsapp_gupshup' ELSE NULL END
|
|
28
|
-
)
|
|
29
|
-
) AS inferred_channel_type_raw,
|
|
30
|
-
|
|
31
|
-
COALESCE(
|
|
32
|
-
bi.context::jsonb #>> '{inbound_id}',
|
|
33
|
-
bi.payload::jsonb #>> '{inboundId}',
|
|
34
|
-
bi.context::jsonb #>> '{inbound_message,payload,id}',
|
|
35
|
-
bi.context::jsonb #>> '{inboundMessage,payload,id}',
|
|
36
|
-
bi.context::jsonb #>> '{inbound_message,id}',
|
|
37
|
-
bi.context::jsonb #>> '{inboundMessage,id}',
|
|
38
|
-
bi.payload::jsonb #>> '{transcription,jobId}',
|
|
39
|
-
bi.id::text
|
|
40
|
-
) AS inbound_id,
|
|
41
|
-
|
|
42
|
-
NULLIF(
|
|
43
|
-
COALESCE(
|
|
44
|
-
bi.payload::jsonb #>> '{transcription,jobId}',
|
|
45
|
-
bi.payload::jsonb ->> 'jobId',
|
|
46
|
-
bi.context::jsonb #>> '{inbound_message,payload,transcription,jobId}',
|
|
47
|
-
bi.context::jsonb #>> '{inboundMessage,payload,transcription,jobId}'
|
|
48
|
-
),
|
|
49
|
-
''
|
|
50
|
-
) AS audio_job_id,
|
|
51
|
-
|
|
52
|
-
/*
|
|
53
|
-
Flags explícitas de áudio (sem regex):
|
|
54
|
-
- contentType/mimetype começando com audio/
|
|
55
|
-
- type = 'audio'
|
|
56
|
-
- fallback por extensão usando ILIKE ANY
|
|
57
|
-
*/
|
|
58
|
-
(
|
|
59
|
-
COALESCE(bi.payload::jsonb ->> 'mimetype', '') ILIKE 'audio/%'
|
|
60
|
-
OR COALESCE(bi.payload::jsonb ->> 'contentType', '') ILIKE 'audio/%'
|
|
61
|
-
OR COALESCE(bi.payload::jsonb #>> '{file,contentType}', '') ILIKE 'audio/%'
|
|
62
|
-
OR COALESCE(bi.context::jsonb #>> '{inbound_message,payload,payload,contentType}', '') ILIKE 'audio/%'
|
|
63
|
-
OR COALESCE(bi.context::jsonb #>> '{inboundMessage,payload,payload,contentType}', '') ILIKE 'audio/%'
|
|
64
|
-
OR COALESCE(bi.context::jsonb #>> '{inbound_message,payload,file,contentType}', '') ILIKE 'audio/%'
|
|
65
|
-
OR COALESCE(bi.context::jsonb #>> '{inboundMessage,payload,file,contentType}', '') ILIKE 'audio/%'
|
|
66
|
-
OR COALESCE(bi.context::jsonb #>> '{inbound_message,payload,payload,type}', '') = 'audio'
|
|
67
|
-
OR COALESCE(bi.context::jsonb #>> '{inboundMessage,payload,payload,type}', '') = 'audio'
|
|
68
|
-
OR LOWER(COALESCE(bi.payload::jsonb #>> '{file,name}', '')) ILIKE ANY (ARRAY['%.ogg','%.oga','%.mp3','%.m4a','%.wav','%.opus','%.ogg%','%.oga%','%.mp3%','%.m4a%','%.wav%','%.opus%'])
|
|
69
|
-
OR LOWER(COALESCE(bi.context::jsonb #>> '{inbound_message,payload,file,name}', '')) ILIKE ANY (ARRAY['%.ogg','%.oga','%.mp3','%.m4a','%.wav','%.opus','%.ogg%','%.oga%','%.mp3%','%.m4a%','%.wav%','%.opus%'])
|
|
70
|
-
OR LOWER(COALESCE(bi.context::jsonb #>> '{inboundMessage,payload,file,name}', '')) ILIKE ANY (ARRAY['%.ogg','%.oga','%.mp3','%.m4a','%.wav','%.opus','%.ogg%','%.oga%','%.mp3%','%.m4a%','%.wav%','%.opus%'])
|
|
71
|
-
OR LOWER(COALESCE(bi.payload::jsonb #>> '{file,url}', '')) ILIKE ANY (ARRAY['%.ogg%','%.oga%','%.mp3%','%.m4a%','%.wav%','%.opus%'])
|
|
72
|
-
OR LOWER(COALESCE(bi.context::jsonb #>> '{inbound_message,payload,file,url}', '')) ILIKE ANY (ARRAY['%.ogg%','%.oga%','%.mp3%','%.m4a%','%.wav%','%.opus%'])
|
|
73
|
-
OR LOWER(COALESCE(bi.context::jsonb #>> '{inboundMessage,payload,file,url}', '')) ILIKE ANY (ARRAY['%.ogg%','%.oga%','%.mp3%','%.m4a%','%.wav%','%.opus%'])
|
|
74
|
-
) AS has_explicit_audio,
|
|
75
|
-
|
|
76
|
-
(
|
|
77
|
-
COALESCE(
|
|
78
|
-
bi.payload::jsonb #>> '{transcription,jobId}',
|
|
79
|
-
bi.payload::jsonb ->> 'jobId',
|
|
80
|
-
bi.context::jsonb #>> '{inbound_message,payload,transcription,jobId}',
|
|
81
|
-
bi.context::jsonb #>> '{inboundMessage,payload,transcription,jobId}'
|
|
82
|
-
) IS NOT NULL
|
|
83
|
-
AND COALESCE(
|
|
84
|
-
NULLIF(bi.payload::jsonb #>> '{transcription,jobId}', ''),
|
|
85
|
-
NULLIF(bi.payload::jsonb ->> 'jobId', ''),
|
|
86
|
-
NULLIF(bi.context::jsonb #>> '{inbound_message,payload,transcription,jobId}', ''),
|
|
87
|
-
NULLIF(bi.context::jsonb #>> '{inboundMessage,payload,transcription,jobId}', '')
|
|
88
|
-
) IS NOT NULL
|
|
89
|
-
) AS has_stt_job
|
|
90
|
-
|
|
91
|
-
FROM "BotIterables" bi
|
|
92
|
-
LEFT JOIN "Sessions" s ON s.id = bi."SessionId"
|
|
93
|
-
WHERE bi.action = 'client'
|
|
94
|
-
AND (
|
|
95
|
-
(bi.context::jsonb ? 'inbound_message') OR
|
|
96
|
-
(bi.context::jsonb ? 'inboundMessage') OR
|
|
97
|
-
(bi.context::jsonb ? 'inbound_id') OR
|
|
98
|
-
(bi.payload::jsonb ? 'inboundId')
|
|
99
|
-
)
|
|
100
|
-
),
|
|
101
|
-
|
|
102
|
-
norm AS (
|
|
103
|
-
SELECT
|
|
104
|
-
b.*,
|
|
105
|
-
CASE
|
|
106
|
-
WHEN inferred_channel_type_raw IN ('microsoft_teams','msteams','teams') THEN 'microsoft_teams'
|
|
107
|
-
WHEN inferred_channel_type_raw IN ('webchat','webchat-transcript') THEN 'webchat'
|
|
108
|
-
WHEN inferred_channel_type_raw LIKE 'whatsapp%' THEN 'whatsapp_gupshup'
|
|
109
|
-
ELSE NULL
|
|
110
|
-
END AS "channelFamily"
|
|
111
|
-
FROM base b
|
|
112
|
-
),
|
|
113
|
-
|
|
114
|
-
typed AS (
|
|
115
|
-
SELECT
|
|
116
|
-
n.*,
|
|
117
|
-
CASE
|
|
118
|
-
WHEN n."channelFamily" = 'microsoft_teams' THEN FALSE
|
|
119
|
-
ELSE (n.has_explicit_audio OR (n.has_stt_job AND n."channelFamily" IN ('webchat','whatsapp_gupshup')))
|
|
120
|
-
END AS has_audio_flag
|
|
121
|
-
FROM norm n
|
|
122
|
-
),
|
|
123
|
-
|
|
124
|
-
consolidated AS (
|
|
125
|
-
SELECT
|
|
126
|
-
t.day,
|
|
127
|
-
t."EnterpriseId",
|
|
128
|
-
t."SessionChannelId",
|
|
129
|
-
t."channelFamily",
|
|
130
|
-
FIRST_VALUE(t.inferred_channel_type_raw) OVER w AS rawChannelTypeAny,
|
|
131
|
-
BOOL_OR(t.has_audio_flag) OVER w AS any_audio_flag,
|
|
132
|
-
FIRST_VALUE(t.audio_job_id) OVER w AS audio_job_id_any,
|
|
133
|
-
t.inbound_id
|
|
134
|
-
FROM typed t
|
|
135
|
-
WINDOW w AS (PARTITION BY t.inbound_id, t."SessionChannelId")
|
|
136
|
-
),
|
|
137
|
-
|
|
138
|
-
msgs_final AS (
|
|
139
|
-
SELECT
|
|
140
|
-
c.day,
|
|
141
|
-
c."EnterpriseId",
|
|
142
|
-
c."SessionChannelId",
|
|
143
|
-
c."channelFamily",
|
|
144
|
-
c.rawChannelTypeAny AS "rawChannelName_from_infer",
|
|
145
|
-
c.inbound_id,
|
|
146
|
-
CASE WHEN c.any_audio_flag THEN 'audio' ELSE 'text' END AS "messageType"
|
|
147
|
-
FROM consolidated c
|
|
148
|
-
)
|
|
149
|
-
|
|
150
|
-
SELECT
|
|
151
|
-
m.day,
|
|
152
|
-
m."EnterpriseId",
|
|
153
|
-
COALESCE(ch2.id, m."SessionChannelId") AS "ChannelId",
|
|
154
|
-
CASE m."channelFamily"
|
|
155
|
-
WHEN 'microsoft_teams' THEN 'Microsoft Teams'
|
|
156
|
-
WHEN 'webchat' THEN 'WebChat'
|
|
157
|
-
WHEN 'whatsapp_gupshup' THEN 'WhatsApp'
|
|
158
|
-
ELSE COALESCE(m."rawChannelName_from_infer", ch.name)
|
|
159
|
-
END AS "channelName",
|
|
160
|
-
COALESCE(m."rawChannelName_from_infer", ch.name) AS "rawChannelName",
|
|
161
|
-
m."channelFamily",
|
|
162
|
-
m."messageType",
|
|
163
|
-
COUNT(DISTINCT m.inbound_id) AS total
|
|
164
|
-
FROM msgs_final m
|
|
165
|
-
LEFT JOIN "Channels" ch ON ch.id = m."SessionChannelId"
|
|
166
|
-
LEFT JOIN "Channels" ch2 ON ch2."EnterpriseId" = m."EnterpriseId"
|
|
167
|
-
AND (
|
|
168
|
-
(m."channelFamily" = 'microsoft_teams' AND ch2.name ILIKE '%teams%')
|
|
169
|
-
OR (m."channelFamily" = 'webchat' AND ch2.name ILIKE '%webchat%')
|
|
170
|
-
OR (m."channelFamily" = 'whatsapp_gupshup' AND (ch2.name ILIKE '%whatsapp%' OR ch2.name ILIKE '%gupshup%' OR ch2.name ILIKE '%whats%'))
|
|
171
|
-
)
|
|
172
|
-
GROUP BY
|
|
173
|
-
m.day,
|
|
174
|
-
m."EnterpriseId",
|
|
175
|
-
COALESCE(ch2.id, m."SessionChannelId"),
|
|
176
|
-
CASE m."channelFamily"
|
|
177
|
-
WHEN 'microsoft_teams' THEN 'Microsoft Teams'
|
|
178
|
-
WHEN 'webchat' THEN 'WebChat'
|
|
179
|
-
WHEN 'whatsapp_gupshup' THEN 'WhatsApp'
|
|
180
|
-
ELSE COALESCE(m."rawChannelName_from_infer", ch.name)
|
|
181
|
-
END,
|
|
182
|
-
COALESCE(m."rawChannelName_from_infer", ch.name),
|
|
183
|
-
m."channelFamily",
|
|
184
|
-
m."messageType";
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
`);
|
|
189
|
-
},
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
async down(queryInterface) {
|
|
193
|
-
await queryInterface.sequelize.query(`
|
|
194
|
-
DROP VIEW IF EXISTS channel_message_type_daily;
|
|
195
|
-
|
|
196
|
-
CREATE VIEW channel_message_type_daily AS
|
|
197
|
-
WITH base AS (
|
|
198
|
-
SELECT
|
|
199
|
-
((bi."createdAt" AT TIME ZONE 'UTC') AT TIME ZONE 'America/Sao_Paulo')::date AS day,
|
|
200
|
-
bi."EnterpriseId" AS "EnterpriseId",
|
|
201
|
-
s."ChannelId" AS "ChannelId",
|
|
202
|
-
ch.name AS "channelName",
|
|
203
|
-
COALESCE(
|
|
204
|
-
bi.context::jsonb #>> '{inbound_id}',
|
|
205
|
-
bi.payload::jsonb #>> '{inboundId}',
|
|
206
|
-
bi.context::jsonb #>> '{inbound_message,payload,id}',
|
|
207
|
-
bi.context::jsonb #>> '{inboundMessage,payload,id}',
|
|
208
|
-
bi.context::jsonb #>> '{inbound_message,id}',
|
|
209
|
-
bi.context::jsonb #>> '{inboundMessage,id}',
|
|
210
|
-
bi.payload::jsonb #>> '{transcription,jobId}',
|
|
211
|
-
bi.id::text
|
|
212
|
-
) AS inbound_id,
|
|
213
|
-
CASE WHEN
|
|
214
|
-
(bi.context::jsonb #>> '{inbound_message,payload,payload,type}') = 'audio' OR
|
|
215
|
-
(bi.context::jsonb #>> '{inboundMessage,payload,payload,type}') = 'audio' OR
|
|
216
|
-
(bi.context::jsonb #>> '{inbound_message,payload,payload,contentType}') ILIKE 'audio/%' OR
|
|
217
|
-
(bi.context::jsonb #>> '{inboundMessage,payload,payload,contentType}') ILIKE 'audio/%' OR
|
|
218
|
-
((bi.payload::jsonb ->> 'mimetype') ILIKE 'audio/%')
|
|
219
|
-
THEN 'audio' ELSE 'text' END AS "messageType"
|
|
220
|
-
FROM "BotIterables" bi
|
|
221
|
-
LEFT JOIN "Sessions" s ON s.id = bi."SessionId"
|
|
222
|
-
LEFT JOIN "Channels" ch ON ch.id = s."ChannelId"
|
|
223
|
-
WHERE bi.action = 'client'
|
|
224
|
-
AND (
|
|
225
|
-
(bi.context::jsonb ? 'inbound_message') OR
|
|
226
|
-
(bi.context::jsonb ? 'inboundMessage')
|
|
227
|
-
)
|
|
228
|
-
)
|
|
229
|
-
SELECT
|
|
230
|
-
day, "EnterpriseId", "ChannelId", "channelName", "messageType",
|
|
231
|
-
COUNT(DISTINCT inbound_id) AS total
|
|
232
|
-
FROM base
|
|
233
|
-
GROUP BY day, "EnterpriseId", "ChannelId", "channelName", "messageType";
|
|
234
|
-
`);
|
|
235
|
-
}
|
|
236
|
-
};
|