ts-glitter 21.2.2 → 21.2.4

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.
@@ -1,332 +1,376 @@
1
- import path from "path";
2
- import admin from "firebase-admin";
3
- import {ConfigSetting} from "../config";
4
- import db from "../modules/database";
5
- import {WebSocket} from "../services/web-socket.js";
1
+ import path from 'path';
2
+ import admin from 'firebase-admin';
3
+ import { ConfigSetting } from '../config';
4
+ import db from '../modules/database';
5
+ import { WebSocket } from '../services/web-socket.js';
6
6
  import { CaughtError } from './caught-error.js';
7
7
  import exception from './exception.js';
8
8
  import { AutoSendEmail } from '../api-public/services/auto-send-email.js';
9
9
 
10
10
  export class Firebase {
11
- public app: string = ''
11
+ public app: string = '';
12
12
 
13
- constructor(app: string) {
14
- this.app = app;
15
- }
13
+ constructor(app: string) {
14
+ this.app = app;
15
+ }
16
16
 
17
- public static async initial() {
18
- console.log(`fireBaseInitial:${admin.credential.cert(path.resolve(ConfigSetting.config_path, `../${process.env.firebase}`))}`)
19
- admin.initializeApp({
20
- credential: admin.credential.cert(path.resolve(ConfigSetting.config_path, `../${process.env.firebase}`))
21
- }, 'glitter');
22
- admin.initializeApp({
23
- credential: admin.credential.cert(path.resolve(ConfigSetting.config_path, `../${process.env.firebase}`))
24
- });
25
- }
17
+ public static async initial() {
18
+ console.log(
19
+ `fireBaseInitial:${admin.credential.cert(path.resolve(ConfigSetting.config_path, `../${process.env.firebase}`))}`
20
+ );
21
+ admin.initializeApp(
22
+ {
23
+ credential: admin.credential.cert(path.resolve(ConfigSetting.config_path, `../${process.env.firebase}`)),
24
+ },
25
+ 'glitter'
26
+ );
27
+ admin.initializeApp({
28
+ credential: admin.credential.cert(path.resolve(ConfigSetting.config_path, `../${process.env.firebase}`)),
29
+ });
30
+ }
26
31
 
27
- public static async appRegister(cf: {
28
- appID: string,
29
- appName: string,
30
- type: 'android' | 'ios'
31
- }) {
32
- try {
33
- if (cf.type === 'ios') {
34
- // 註冊 iOS 應用
35
- await admin
36
- .projectManagement().createIosApp(cf.appID, cf.appName)
37
- } else {
38
- // 註冊 Android 應用
39
- await admin
40
- .projectManagement().createAndroidApp(cf.appID, cf.appName)
41
- }
42
- } catch (e) {
32
+ public static async appRegister(cf: { appID: string; appName: string; type: 'android' | 'ios' }) {
33
+ try {
34
+ if (cf.type === 'ios') {
35
+ // 註冊 iOS 應用
36
+ await admin.projectManagement().createIosApp(cf.appID, cf.appName);
37
+ } else {
38
+ // 註冊 Android 應用
39
+ await admin.projectManagement().createAndroidApp(cf.appID, cf.appName);
40
+ }
41
+ } catch (e) {}
42
+ }
43
43
 
44
+ public static async getConfig(cf: { appID: string; type: 'android' | 'ios'; appDomain: string }) {
45
+ try {
46
+ if (cf.type === 'ios') {
47
+ for (const b of await admin.projectManagement().listIosApps()) {
48
+ if ((await b.getMetadata()).bundleId === cf.appID) {
49
+ await b.setDisplayName(cf.appDomain);
50
+ return await b.getConfig();
51
+ }
44
52
  }
45
- }
46
-
47
- public static async getConfig(cf: {
48
- appID: string,
49
- type: 'android' | 'ios',
50
- appDomain: string
51
- }) {
52
- try {
53
- if (cf.type === 'ios') {
54
- for (const b of (await (admin
55
- .projectManagement().listIosApps()))) {
56
- if ((await b.getMetadata()).bundleId === cf.appID) {
57
- await b.setDisplayName(cf.appDomain)
58
- return (await b.getConfig())
59
- }
60
- }
61
- } else {
62
- for (const b of (await (admin
63
- .projectManagement().listAndroidApps()))) {
64
- if ((await b.getMetadata()).packageName === cf.appID) {
65
- await b.setDisplayName(cf.appDomain)
66
- return (await b.getConfig())
67
- }
68
- }
69
- }
70
- } catch (e) {
71
- console.log(e)
72
- return ''
53
+ } else {
54
+ for (const b of await admin.projectManagement().listAndroidApps()) {
55
+ if ((await b.getMetadata()).packageName === cf.appID) {
56
+ await b.setDisplayName(cf.appDomain);
57
+ return await b.getConfig();
58
+ }
73
59
  }
60
+ }
61
+ } catch (e) {
62
+ console.log(e);
63
+ return '';
74
64
  }
65
+ }
75
66
 
76
- public async sendMessage(cf: {
77
- token?: string | string[],
78
- userID?: string,
79
- title: string,
80
- tag: string,
81
- link: string,
82
- body: string,
83
- app?: string,
84
- pass_store?:boolean
85
- }) {
86
- cf.body=cf.body.replace(/<br\s*\/?>/gi, '\n');
87
- if(cf.userID){
88
- WebSocket.noticeChangeMem[cf.userID] && WebSocket.noticeChangeMem[cf.userID].map((d2) => {
89
- d2.callback({
90
- type: 'notice_count_change',
91
- });
92
- })
93
- }
94
- return new Promise(async (resolve, reject) => {
95
- if (cf.userID) {
96
- cf.token = (await db.query(`SELECT deviceToken
97
- FROM \`${cf.app || this.app}\`.t_fcm
98
- where userID = ?;`, [cf.userID])).map((dd: any) => {
99
- return dd.deviceToken
100
- });
101
- const user_cf = (((await db.query(`select \`value\`
102
- from \`${cf.app || this.app}\`.t_user_public_config
103
- where \`key\` ='notify_setting' and user_id=?`, [cf.userID]))[0]) ?? {value: {}}).value;
104
- if (`${user_cf[cf.tag]}` !== 'false') {
105
- if (cf.userID && cf.tag && cf.title && cf.body && cf.link && !cf.pass_store) {
106
- await db.query(`insert into \`${cf.app || this.app}\`.t_notice (user_id, tag, title, content, link)
107
- values (?, ?, ?, ?, ?)`, [
108
- cf.userID,
109
- cf.tag,
110
- cf.title,
111
- cf.body,
112
- cf.link
113
- ])
114
- }
115
- } else {
116
- resolve(true)
117
- return
118
- }
119
-
120
- }
121
- if (typeof cf.token === 'string') {
122
- cf.token = [cf.token]
123
- }
124
- if (Array.isArray(cf.token)) {
125
- for (const token of cf.token) {
126
- try {
127
- admin.apps.find((dd) => {
128
- return dd?.name === 'glitter'
129
- })!.messaging().send({
130
- notification: {
131
- title: cf.title,
132
- body: cf.body.replace(/<br>/g,''),
133
- },
134
- android: {
135
- notification: {
136
- sound: 'default'
137
- },
138
- },
139
- apns: {
140
- payload: {
141
- aps: {
142
- sound: 'default'
143
- },
144
- },
145
- },
146
- data: {
147
- link: `${cf.link || ''}`
148
- },
149
- "token": token!
150
- }).then((response: any) => {
151
- console.log('成功發送推播:', response);
152
- }).catch((error: any) => {
153
- console.error('發送推播時發生錯誤:', error);
154
- })
155
- }catch (e:any) {
156
- CaughtError.warning('fcm',`firebase->74`,`${e}`)
157
- }
158
-
159
- }
160
- }
161
- resolve(true)
162
- })
163
-
67
+ public async sendMessage(cf: {
68
+ token?: string | string[];
69
+ userID?: string;
70
+ title: string;
71
+ tag: string;
72
+ link: string;
73
+ body: string;
74
+ app?: string;
75
+ pass_store?: boolean;
76
+ }) {
77
+ console.log('sendMessage', cf);
78
+ cf.body = cf.body.replace(/<br\s*\/?>/gi, '\n');
79
+ if (cf.userID) {
80
+ WebSocket.noticeChangeMem[cf.userID] &&
81
+ WebSocket.noticeChangeMem[cf.userID].map(d2 => {
82
+ d2.callback({
83
+ type: 'notice_count_change',
84
+ });
85
+ });
164
86
  }
165
-
166
-
167
- async postFCM(data: any): Promise<{ result: boolean; message: string }> {
168
- data.msgid = '';
169
- try {
170
- if (Boolean(data.sendTime)) {
171
- if (isLater(data.sendTime)) {
172
- return { result: false, message: '排定發送的時間需大於現在時間' };
173
- }
174
- const insertData = await db.query(
175
- `INSERT INTO \`${this.app}\`.\`t_triggers\`
176
- SET ?;`,
177
- [
178
- {
179
- tag: 'sendFCM',
180
- content: JSON.stringify(data),
181
- trigger_time: formatDateTime(data.sendTime),
182
- status: 0,
87
+ return new Promise(async (resolve, reject) => {
88
+ if (cf.userID) {
89
+ cf.token = (
90
+ await db.query(
91
+ `SELECT deviceToken
92
+ FROM \`${cf.app || this.app}\`.t_fcm
93
+ where userID = ?;`,
94
+ [cf.userID]
95
+ )
96
+ ).map((dd: any) => {
97
+ return dd.deviceToken;
98
+ });
99
+ console.log(
100
+ `sendMessage:${cf.userID}`,
101
+ `SELECT deviceToken
102
+ FROM \`${cf.app || this.app}\`.t_fcm
103
+ where userID = ${db.escape(cf.userID)};`
104
+ );
105
+ const user_cf = (
106
+ (
107
+ await db.query(
108
+ `select \`value\`
109
+ from \`${cf.app || this.app}\`.t_user_public_config
110
+ where \`key\` = 'notify_setting'
111
+ and user_id = ?`,
112
+ [cf.userID]
113
+ )
114
+ )[0] ?? { value: {} }
115
+ ).value;
116
+ if (`${user_cf[cf.tag]}` !== 'false') {
117
+ if (cf.userID && cf.tag && cf.title && cf.body && cf.link && !cf.pass_store) {
118
+ await db.query(
119
+ `insert into \`${cf.app || this.app}\`.t_notice (user_id, tag, title, content, link)
120
+ values (?, ?, ?, ?, ?)`,
121
+ [cf.userID, cf.tag, cf.title, cf.body, cf.link]
122
+ );
123
+ }
124
+ } else {
125
+ resolve(true);
126
+ return;
127
+ }
128
+ }
129
+ if (typeof cf.token === 'string') {
130
+ cf.token = [cf.token];
131
+ }
132
+ if (Array.isArray(cf.token)) {
133
+ let error_token:string[]=[]
134
+ await Promise.all(
135
+ cf.token.map(token => {
136
+ return new Promise(async (resolve, reject) => {
137
+ try {
138
+ admin.apps
139
+ .find(dd => {
140
+ return dd?.name === 'glitter';
141
+ })!
142
+ .messaging()
143
+ .send({
144
+ notification: {
145
+ title: cf.title,
146
+ body: cf.body.replace(/<br>/g, ''),
147
+ },
148
+ android: {
149
+ notification: {
150
+ sound: 'default',
183
151
  },
184
- ]
185
- );
186
-
187
- this.chunkSendFcm(data, insertData.insertId, formatDateTime(data.sendTime));
188
- } else {
189
- const insertData = await db.query(
190
- `INSERT INTO \`${this.app}\`.\`t_triggers\`
191
- SET ?;`,
192
- [
193
- {
194
- tag: 'sendFCM',
195
- content: JSON.stringify(data),
196
- trigger_time: formatDateTime(),
197
- status: 1,
152
+ },
153
+ apns: {
154
+ payload: {
155
+ aps: {
156
+ sound: 'default',
157
+ },
198
158
  },
199
- ]
200
- );
201
- this.chunkSendFcm(data, insertData.insertId);
202
- }
203
- return { result: true, message: '寄送成功' };
204
- } catch (e) {
205
- throw exception.BadRequestError('BAD_REQUEST', 'postMail Error:' + e, null);
159
+ },
160
+ data: {
161
+ link: `${cf.link || ''}`,
162
+ },
163
+ token: token!,
164
+ })
165
+ .then((response: any) => {
166
+ console.log(`成功發送推播:${token}`, response);
167
+ resolve(true);
168
+ })
169
+ .catch((error: any) => {
170
+ if (error.errorInfo.code === 'messaging/registration-token-not-registered') {
171
+ error_token.push(token)
172
+ }
173
+ resolve(true);
174
+ });
175
+ } catch (e: any) {
176
+ CaughtError.warning('fcm', `firebase->74`, `${e}`);
177
+ resolve(true);
178
+ }
179
+ });
180
+ })
181
+ );
182
+ if(error_token.length>0){
183
+ await db.query(
184
+ `delete
185
+ FROM \`${cf.app || this.app}\`.t_fcm
186
+ where userID = ? and deviceToken in (${error_token.map(d=>db.escape(d)).join(',')});`,
187
+ [cf.userID]
188
+ );
206
189
  }
207
- }
190
+ }
191
+ resolve(true);
192
+ });
193
+ }
208
194
 
209
- async chunkSendFcm(data: any, id: number, date?: string) {
210
- try {
211
- let msgid = '';
212
- for (const b of chunkArray(Array.from(new Set(data.userList.map((dd:any)=>{
213
- return dd.id
214
- }))), 10)) {
215
- let check = b.length;
216
-
217
- await new Promise(resolve => {
218
- for (const d of b) {
219
- this.sendMessage({
220
- userID: d as string,
221
- title: data.title,
222
- body: data.content,
223
- tag:'promote',
224
- link:data.link,
225
- })
226
- // this.sendMessage({ data: data.content, phone: d, date: date }, res => {
227
- // check--;
228
- // console.log(' res -- ', res);
229
- // if (check === 0) {
230
- // db.query(
231
- // `UPDATE \`${this.app}\`.t_triggers
232
- // SET status = ${date ? 0 : 1},
233
- // content = JSON_SET(content, '$.name', '${res.msgid}')
234
- // WHERE id = ?;`,
235
- // [id]
236
- // );
237
- // resolve(true);
238
- // }
239
- // });
240
- }
241
- });
242
- }
243
- // await db.query(`UPDATE \`${this.app}\`.t_triggers SET status = ${date?0:1} , content = JSON_SET(content, '$.name', '變數A') WHERE id = ?;`, [ id]);
244
- // await db.query(`-- UPDATE \`${this.app}\`.t_triggers SET ? WHERE id = ?;`, [{ status: 1 , content : `JSON_SET(content, '$.name', '變數A')`}, id]);
245
- } catch (e) {
246
- throw exception.BadRequestError('BAD_REQUEST', 'chunkSendSns Error:' + e, null);
195
+ async postFCM(data: any): Promise<{ result: boolean; message: string }> {
196
+ data.msgid = '';
197
+ try {
198
+ if (Boolean(data.sendTime)) {
199
+ if (isLater(data.sendTime)) {
200
+ return { result: false, message: '排定發送的時間需大於現在時間' };
247
201
  }
202
+ const insertData = await db.query(
203
+ `INSERT INTO \`${this.app}\`.\`t_triggers\`
204
+ SET ?;`,
205
+ [
206
+ {
207
+ tag: 'sendFCM',
208
+ content: JSON.stringify(data),
209
+ trigger_time: formatDateTime(data.sendTime),
210
+ status: 0,
211
+ },
212
+ ]
213
+ );
214
+
215
+ this.chunkSendFcm(data, insertData.insertId, formatDateTime(data.sendTime));
216
+ } else {
217
+ const insertData = await db.query(
218
+ `INSERT INTO \`${this.app}\`.\`t_triggers\`
219
+ SET ?;`,
220
+ [
221
+ {
222
+ tag: 'sendFCM',
223
+ content: JSON.stringify(data),
224
+ trigger_time: formatDateTime(),
225
+ status: 1,
226
+ },
227
+ ]
228
+ );
229
+ this.chunkSendFcm(data, insertData.insertId);
230
+ }
231
+ return { result: true, message: '寄送成功' };
232
+ } catch (e) {
233
+ throw exception.BadRequestError('BAD_REQUEST', 'postMail Error:' + e, null);
248
234
  }
235
+ }
249
236
 
237
+ async chunkSendFcm(data: any, id: number, date?: string) {
238
+ try {
239
+ let msgid = '';
240
+ for (const b of chunkArray(
241
+ Array.from(
242
+ new Set(
243
+ data.userList.map((dd: any) => {
244
+ return dd.id;
245
+ })
246
+ )
247
+ ),
248
+ 10
249
+ )) {
250
+ let check = b.length;
250
251
 
251
- async getFCM(query: { type: string; page: number; limit: number; search?: string; searchType?: string; mailType?: string; status?: string }) {
252
- try {
253
- const whereList: string[] = ['1 = 1'];
254
- switch (query.searchType) {
255
- case 'email':
256
- // whereList.push(`(JSON_SEARCH(content->'$.email', 'one', '%${query.search ?? ''}%', NULL, '$[*]') IS NOT NULL)`);
257
- break;
258
- case 'name':
259
- whereList.push(`(UPPER(JSON_EXTRACT(content, '$.name')) LIKE UPPER('%${query.search ?? ''}%'))`);
260
- break;
261
- case 'title':
262
- whereList.push(`(UPPER(JSON_EXTRACT(content, '$.title')) LIKE UPPER('%${query.search ?? ''}%'))`);
263
- break;
264
- }
252
+ await new Promise(resolve => {
253
+ for (const d of b) {
254
+ this.sendMessage({
255
+ userID: d as string,
256
+ title: data.title,
257
+ body: data.content,
258
+ tag: 'promote',
259
+ link: data.link,
260
+ });
261
+ // this.sendMessage({ data: data.content, phone: d, date: date }, res => {
262
+ // check--;
263
+ // console.log(' res -- ', res);
264
+ // if (check === 0) {
265
+ // db.query(
266
+ // `UPDATE \`${this.app}\`.t_triggers
267
+ // SET status = ${date ? 0 : 1},
268
+ // content = JSON_SET(content, '$.name', '${res.msgid}')
269
+ // WHERE id = ?;`,
270
+ // [id]
271
+ // );
272
+ // resolve(true);
273
+ // }
274
+ // });
275
+ }
276
+ });
277
+ }
278
+ // await db.query(`UPDATE \`${this.app}\`.t_triggers SET status = ${date?0:1} , content = JSON_SET(content, '$.name', '變數A') WHERE id = ?;`, [ id]);
279
+ // await db.query(`-- UPDATE \`${this.app}\`.t_triggers SET ? WHERE id = ?;`, [{ status: 1 , content : `JSON_SET(content, '$.name', '變數A')`}, id]);
280
+ } catch (e) {
281
+ throw exception.BadRequestError('BAD_REQUEST', 'chunkSendSns Error:' + e, null);
282
+ }
283
+ }
265
284
 
266
- if (query.status) {
267
- whereList.push(`(status in (${query.status}))`);
268
- }
285
+ async getFCM(query: {
286
+ type: string;
287
+ page: number;
288
+ limit: number;
289
+ search?: string;
290
+ searchType?: string;
291
+ mailType?: string;
292
+ status?: string;
293
+ }) {
294
+ try {
295
+ const whereList: string[] = ['1 = 1'];
296
+ switch (query.searchType) {
297
+ case 'email':
298
+ // whereList.push(`(JSON_SEARCH(content->'$.email', 'one', '%${query.search ?? ''}%', NULL, '$[*]') IS NOT NULL)`);
299
+ break;
300
+ case 'name':
301
+ whereList.push(`(UPPER(JSON_EXTRACT(content, '$.name')) LIKE UPPER('%${query.search ?? ''}%'))`);
302
+ break;
303
+ case 'title':
304
+ whereList.push(`(UPPER(JSON_EXTRACT(content, '$.title')) LIKE UPPER('%${query.search ?? ''}%'))`);
305
+ break;
306
+ }
269
307
 
270
- if (query.mailType) {
271
- const maiTypeString = query.mailType.replace(/[^,]+/g, "'$&'");
272
- whereList.push(`(JSON_EXTRACT(content, '$.type') in (${maiTypeString}))`);
273
- }
308
+ if (query.status) {
309
+ whereList.push(`(status in (${query.status}))`);
310
+ }
274
311
 
275
- const whereSQL = `(tag = 'sendFCM') AND ${whereList.join(' AND ')}`;
312
+ if (query.mailType) {
313
+ const maiTypeString = query.mailType.replace(/[^,]+/g, "'$&'");
314
+ whereList.push(`(JSON_EXTRACT(content, '$.type') in (${maiTypeString}))`);
315
+ }
276
316
 
317
+ const whereSQL = `(tag = 'sendFCM') AND ${whereList.join(' AND ')}`;
277
318
 
278
- const emails = await db.query(
279
- `SELECT * FROM \`${this.app}\`.t_triggers
280
- WHERE ${whereSQL}
281
- ORDER BY id DESC
282
- ${query.type === 'download' ? '' : `LIMIT ${query.page * query.limit}, ${query.limit}`};`,
283
- []
284
- );
319
+ const emails = await db.query(
320
+ `SELECT *
321
+ FROM \`${this.app}\`.t_triggers
322
+ WHERE ${whereSQL}
323
+ ORDER BY id DESC
324
+ ${query.type === 'download' ? '' : `LIMIT ${query.page * query.limit}, ${query.limit}`};`,
325
+ []
326
+ );
285
327
 
286
- const total = await db.query(
287
- `SELECT count(id) as c FROM \`${this.app}\`.t_triggers
288
- WHERE ${whereSQL};`,
289
- []
290
- );
328
+ const total = await db.query(
329
+ `SELECT count(id) as c
330
+ FROM \`${this.app}\`.t_triggers
331
+ WHERE ${whereSQL};`,
332
+ []
333
+ );
291
334
 
292
- for (const email of emails) {
293
- email.content.typeName="手動發送"
294
- }
295
- return { data: emails, total: total[0].c };
296
- } catch (e) {
297
- throw exception.BadRequestError('BAD_REQUEST', 'getMail Error:' + e, null);
298
- }
335
+ for (const email of emails) {
336
+ email.content.typeName = '手動發送';
337
+ }
338
+ return { data: emails, total: total[0].c };
339
+ } catch (e) {
340
+ throw exception.BadRequestError('BAD_REQUEST', 'getMail Error:' + e, null);
299
341
  }
342
+ }
300
343
  }
301
344
 
302
345
  function isLater(dateTimeObj: { date: string; time: string }) {
303
- const currentDateTime = new Date();
304
- const { date, time } = dateTimeObj;
305
- const dateTimeString = `${date}T${time}:00`;
306
- const providedDateTime = new Date(dateTimeString);
307
- return currentDateTime > providedDateTime;
346
+ const currentDateTime = new Date();
347
+ const { date, time } = dateTimeObj;
348
+ const dateTimeString = `${date}T${time}:00`;
349
+ const providedDateTime = new Date(dateTimeString);
350
+ return currentDateTime > providedDateTime;
308
351
  }
309
352
 
310
353
  function chunkArray(array: any, groupSize: number) {
311
- const result = [];
312
- for (let i = 0; i < array.length; i += groupSize) {
313
- result.push(array.slice(i, i + groupSize));
314
- }
315
- return result;
354
+ const result = [];
355
+ for (let i = 0; i < array.length; i += groupSize) {
356
+ result.push(array.slice(i, i + groupSize));
357
+ }
358
+ return result;
316
359
  }
360
+
317
361
  function formatDate(date: any) {
318
- const year = date.getFullYear();
319
- const month = String(date.getMonth() + 1).padStart(2, '0');
320
- const day = String(date.getDate()).padStart(2, '0');
321
- const hours = String(date.getHours()).padStart(2, '0');
322
- const minutes = String(date.getMinutes()).padStart(2, '0');
323
- const seconds = String(date.getSeconds()).padStart(2, '0');
362
+ const year = date.getFullYear();
363
+ const month = String(date.getMonth() + 1).padStart(2, '0');
364
+ const day = String(date.getDate()).padStart(2, '0');
365
+ const hours = String(date.getHours()).padStart(2, '0');
366
+ const minutes = String(date.getMinutes()).padStart(2, '0');
367
+ const seconds = String(date.getSeconds()).padStart(2, '0');
324
368
 
325
- return `${year}${month}${day}${hours}${minutes}${seconds}`;
369
+ return `${year}${month}${day}${hours}${minutes}${seconds}`;
326
370
  }
327
371
 
328
372
  function formatDateTime(sendTime?: { date: string; time: string }) {
329
- const dateTimeString = sendTime ? sendTime.date + ' ' + sendTime.time : undefined;
330
- const dateObject = dateTimeString ? new Date(dateTimeString) : new Date();
331
- return formatDate(dateObject);
332
- }
373
+ const dateTimeString = sendTime ? sendTime.date + ' ' + sendTime.time : undefined;
374
+ const dateObject = dateTimeString ? new Date(dateTimeString) : new Date();
375
+ return formatDate(dateObject);
376
+ }