@nlabs/reaktor 0.1.2 → 0.1.3
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/.DS_Store +0 -0
- package/lib/config.d.ts +21 -0
- package/lib/config.js +130 -0
- package/lib/data/conversations.d.ts +6 -0
- package/lib/data/conversations.js +197 -0
- package/lib/data/dynamodb.d.ts +8 -0
- package/lib/data/dynamodb.js +139 -0
- package/lib/data/email.d.ts +7 -0
- package/lib/data/email.js +163 -0
- package/lib/data/files.d.ts +16 -0
- package/lib/data/files.js +406 -0
- package/lib/data/groups.d.ts +13 -0
- package/lib/data/groups.js +354 -0
- package/lib/data/images.d.ts +12 -0
- package/lib/data/images.js +667 -0
- package/{src/data/index.ts → lib/data/index.d.ts} +1 -5
- package/lib/data/index.js +24 -0
- package/lib/data/ios.d.ts +6 -0
- package/lib/data/ios.js +302 -0
- package/lib/data/locations.d.ts +3 -0
- package/lib/data/locations.js +132 -0
- package/lib/data/messages.d.ts +9 -0
- package/lib/data/messages.js +248 -0
- package/lib/data/notifications.d.ts +5 -0
- package/lib/data/notifications.js +42 -0
- package/lib/data/payments.d.ts +11 -0
- package/lib/data/payments.js +748 -0
- package/lib/data/posts.d.ts +22 -0
- package/lib/data/posts.js +578 -0
- package/lib/data/reactions.d.ts +6 -0
- package/lib/data/reactions.js +218 -0
- package/lib/data/s3.d.ts +6 -0
- package/lib/data/s3.js +103 -0
- package/lib/data/search.d.ts +3 -0
- package/lib/data/search.js +98 -0
- package/lib/data/sms.d.ts +3 -0
- package/lib/data/sms.js +59 -0
- package/lib/data/subscription.d.ts +7 -0
- package/lib/data/subscription.js +284 -0
- package/lib/data/tags.d.ts +14 -0
- package/lib/data/tags.js +304 -0
- package/lib/data/users.d.ts +12 -0
- package/lib/data/users.js +310 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.js +8 -0
- package/lib/types/apps.d.ts +43 -0
- package/lib/types/apps.js +2 -0
- package/lib/types/arangodb.d.ts +17 -0
- package/lib/types/arangodb.js +2 -0
- package/lib/types/auth.d.ts +10 -0
- package/lib/types/auth.js +2 -0
- package/lib/types/conversations.d.ts +6 -0
- package/lib/types/conversations.js +2 -0
- package/lib/types/email.d.ts +12 -0
- package/lib/types/email.js +2 -0
- package/lib/types/files.d.ts +26 -0
- package/lib/types/files.js +2 -0
- package/lib/types/google.d.ts +27 -0
- package/lib/types/google.js +2 -0
- package/lib/types/groups.d.ts +21 -0
- package/lib/types/groups.js +2 -0
- package/lib/types/images.d.ts +24 -0
- package/lib/types/images.js +2 -0
- package/{src/types/index.ts → lib/types/index.d.ts} +0 -4
- package/lib/types/index.js +22 -0
- package/lib/types/locations.d.ts +20 -0
- package/lib/types/locations.js +2 -0
- package/lib/types/messages.d.ts +12 -0
- package/lib/types/messages.js +2 -0
- package/lib/types/notifications.d.ts +19 -0
- package/lib/types/notifications.js +2 -0
- package/lib/types/payments.d.ts +114 -0
- package/lib/types/payments.js +2 -0
- package/lib/types/posts.d.ts +28 -0
- package/lib/types/posts.js +2 -0
- package/lib/types/reactions.d.ts +4 -0
- package/lib/types/reactions.js +2 -0
- package/lib/types/tags.d.ts +9 -0
- package/lib/types/tags.js +2 -0
- package/lib/types/users.d.ts +78 -0
- package/lib/types/users.js +2 -0
- package/lib/utils/analytics.d.ts +3 -0
- package/lib/utils/analytics.js +47 -0
- package/lib/utils/arangodb.d.ts +9 -0
- package/lib/utils/arangodb.js +98 -0
- package/lib/utils/auth.d.ts +7 -0
- package/lib/utils/auth.js +80 -0
- package/lib/utils/graphql.d.ts +1 -0
- package/lib/utils/graphql.js +7 -0
- package/{src/utils/index.ts → lib/utils/index.d.ts} +0 -4
- package/lib/utils/index.js +11 -0
- package/lib/utils/objects.d.ts +3 -0
- package/lib/utils/objects.js +34 -0
- package/lib/utils/redis.d.ts +1 -0
- package/lib/utils/redis.js +15 -0
- package/package.json +5 -5
- package/.vscode/extensions.json +0 -15
- package/.vscode/settings.json +0 -82
- package/lex.config.js +0 -4
- package/src/config.ts +0 -127
- package/src/data/conversations.ts +0 -181
- package/src/data/dynamodb.ts +0 -157
- package/src/data/email.ts +0 -163
- package/src/data/files.ts +0 -352
- package/src/data/groups.ts +0 -308
- package/src/data/images.ts +0 -606
- package/src/data/ios.ts +0 -249
- package/src/data/locations.ts +0 -114
- package/src/data/messages.ts +0 -237
- package/src/data/notifications.ts +0 -48
- package/src/data/payments.ts +0 -675
- package/src/data/posts.ts +0 -580
- package/src/data/reactions.ts +0 -186
- package/src/data/s3.ts +0 -117
- package/src/data/search.ts +0 -74
- package/src/data/sms.ts +0 -60
- package/src/data/subscription.ts +0 -228
- package/src/data/tags.ts +0 -230
- package/src/data/users.ts +0 -254
- package/src/index.ts +0 -7
- package/src/types/apps.ts +0 -56
- package/src/types/arangodb.ts +0 -23
- package/src/types/auth.ts +0 -20
- package/src/types/conversations.ts +0 -11
- package/src/types/email.ts +0 -17
- package/src/types/files.ts +0 -31
- package/src/types/google.ts +0 -37
- package/src/types/groups.ts +0 -27
- package/src/types/images.ts +0 -32
- package/src/types/locations.ts +0 -24
- package/src/types/messages.ts +0 -16
- package/src/types/notifications.ts +0 -26
- package/src/types/payments.ts +0 -129
- package/src/types/posts.ts +0 -34
- package/src/types/reactions.ts +0 -8
- package/src/types/tags.ts +0 -13
- package/src/types/users.ts +0 -89
- package/src/utils/analytics.ts +0 -41
- package/src/utils/arangodb.ts +0 -100
- package/src/utils/auth.ts +0 -61
- package/src/utils/graphql.ts +0 -7
- package/src/utils/objects.ts +0 -34
- package/src/utils/redis.ts +0 -17
- package/tsconfig.json +0 -45
package/src/data/email.ts
DELETED
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) 2019-Present, Nitrogen Labs, Inc.
|
|
3
|
-
* Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
|
|
4
|
-
*/
|
|
5
|
-
import aws, {SES} from 'aws-sdk';
|
|
6
|
-
import {GetObjectRequest} from 'aws-sdk/clients/s3';
|
|
7
|
-
import {SendEmailRequest, SendEmailResponse} from 'aws-sdk/clients/ses';
|
|
8
|
-
import fs from 'fs';
|
|
9
|
-
import isEmpty from 'lodash/isEmpty';
|
|
10
|
-
|
|
11
|
-
import {Config} from '../config';
|
|
12
|
-
import {AppType} from '../types/apps';
|
|
13
|
-
import {EmailType} from '../types/email';
|
|
14
|
-
import {s3Get} from './s3';
|
|
15
|
-
|
|
16
|
-
// const eventCategory: string = 'email';
|
|
17
|
-
|
|
18
|
-
export const appTemplate = (app: AppType, message: string = '', vars = {}): string => {
|
|
19
|
-
let updatedMessage: string = '';
|
|
20
|
-
|
|
21
|
-
if(!isEmpty(app)) {
|
|
22
|
-
updatedMessage = message.replace(/\[appName\]/g, app.name)
|
|
23
|
-
.replace(/\[appUrl\]/g, app.url)
|
|
24
|
-
.replace(/\[appEmail\]/g, app.email);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
Object.keys(vars).forEach((key: string) => {
|
|
28
|
-
if(vars[key]) {
|
|
29
|
-
updatedMessage = message.replace(new RegExp(`\\[${key}\\]`, 'g'), vars[key]);
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
return updatedMessage;
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
export const sendEmail = (params: EmailType): Promise<boolean> => {
|
|
37
|
-
const {
|
|
38
|
-
app = {},
|
|
39
|
-
html,
|
|
40
|
-
subject,
|
|
41
|
-
subTitle = '',
|
|
42
|
-
text,
|
|
43
|
-
title = '',
|
|
44
|
-
user = {}
|
|
45
|
-
} = params;
|
|
46
|
-
|
|
47
|
-
const to = [user.email];
|
|
48
|
-
let promise;
|
|
49
|
-
|
|
50
|
-
const formatSubject: string = appTemplate(app, subject);
|
|
51
|
-
const formatSubTitle: string = appTemplate(app, subTitle);
|
|
52
|
-
const formatTitle: string = appTemplate(app, title);
|
|
53
|
-
const formatText: string = appTemplate(app, text);
|
|
54
|
-
const formatHtml: string = appTemplate(app, html);
|
|
55
|
-
const {_key: hasCustomEmail, urlFacebook, urlTwitter} = app;
|
|
56
|
-
|
|
57
|
-
const parseTemplate = (body: string) => {
|
|
58
|
-
const templateBody: string = appTemplate(app, body || '');
|
|
59
|
-
|
|
60
|
-
// Links
|
|
61
|
-
let links: string = '';
|
|
62
|
-
const spacer = '<td width="5"><img width="1" height="1" border="0" title="" alt="" ' +
|
|
63
|
-
'src="https://box.reaktor.io/images/email/spacer.gif"/></td>';
|
|
64
|
-
|
|
65
|
-
if(urlFacebook) {
|
|
66
|
-
links = `<td width="30"><a href="${urlFacebook}"><img width="30" height="30" border="0" ` +
|
|
67
|
-
'title="Facebook" alt="Facebook" src="https://box.reaktor.io/images/email/icon-facebook.png"/></a></td>';
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if(urlTwitter) {
|
|
71
|
-
if(urlFacebook) {
|
|
72
|
-
links += spacer;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
links += `<td width="30"><a href="${urlTwitter}"><img width="30" height="30" border="0" ` +
|
|
76
|
-
'title="Twitter" alt="Twitter" src="https://box.reaktor.io/images/email/icon-twitter.png"/></a></td>';
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
if(!links.length) {
|
|
80
|
-
links += spacer;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return templateBody.replace(/\[title\]/g, formatTitle)
|
|
84
|
-
.replace(/\[subTitle\]/g, formatSubTitle)
|
|
85
|
-
.replace(/\[subject\]/g, formatSubject)
|
|
86
|
-
.replace(/\[message\]/g, formatHtml)
|
|
87
|
-
.replace(/\[links\]/g, links);
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
if(hasCustomEmail) {
|
|
91
|
-
const s3Params: GetObjectRequest = {Bucket: null, Key: `apps/templates/email.html`};
|
|
92
|
-
promise = s3Get(s3Params).then((results) => parseTemplate(results.Body.toString()));
|
|
93
|
-
} else {
|
|
94
|
-
promise = new Promise((resolve, reject) => {
|
|
95
|
-
fs.readFile('./templates/email/layout.html', 'utf8', (err, data) => {
|
|
96
|
-
if(err) {
|
|
97
|
-
return reject(err);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
return resolve(parseTemplate(data));
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
return promise.then((parsedHtml: string) => {
|
|
106
|
-
const emailParams: SendEmailRequest = {
|
|
107
|
-
Destination: {ToAddresses: to},
|
|
108
|
-
Message: {
|
|
109
|
-
Body: {
|
|
110
|
-
Html: {Data: parsedHtml},
|
|
111
|
-
Text: {Data: formatText}
|
|
112
|
-
},
|
|
113
|
-
Subject: {Data: formatSubject}
|
|
114
|
-
},
|
|
115
|
-
Source: `"${app.supportName}" <noreply@${Config.get('app.url')}>`
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
return sesSend(emailParams);
|
|
119
|
-
});
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
export const sendTemplate = (templateName: string, emailParams: EmailType): Promise<boolean> => {
|
|
123
|
-
const {app, user, subject, subTitle, title, vars}: EmailType = emailParams;
|
|
124
|
-
|
|
125
|
-
try {
|
|
126
|
-
const html: string = fs.readFileSync(`./templates/email/${templateName}.html`, 'utf8');
|
|
127
|
-
const templateHtml: string = appTemplate(app, html, vars);
|
|
128
|
-
const text: string = fs.readFileSync(`./templates/sms/${templateName}.txt`, 'utf8');
|
|
129
|
-
const templateText: string = appTemplate(app, text, vars);
|
|
130
|
-
|
|
131
|
-
const params = {
|
|
132
|
-
app,
|
|
133
|
-
html: templateHtml,
|
|
134
|
-
subTitle,
|
|
135
|
-
subject,
|
|
136
|
-
text: templateText,
|
|
137
|
-
title,
|
|
138
|
-
user
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
return sendEmail(params)
|
|
142
|
-
.then(() => true)
|
|
143
|
-
.catch(() => false);
|
|
144
|
-
} catch(error) {
|
|
145
|
-
return Promise.reject(error);
|
|
146
|
-
}
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
// AWS::SES
|
|
150
|
-
export const sesSend = (params: SendEmailRequest): Promise<SendEmailResponse> => {
|
|
151
|
-
return new Promise((resolve, reject) => {
|
|
152
|
-
aws.config.update(Config.get('aws'));
|
|
153
|
-
const ses: SES = new SES();
|
|
154
|
-
|
|
155
|
-
ses.sendEmail(params, (error: Error, response: SendEmailResponse) => {
|
|
156
|
-
if(error) {
|
|
157
|
-
return reject(error);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
return resolve(response);
|
|
161
|
-
});
|
|
162
|
-
});
|
|
163
|
-
};
|
package/src/data/files.ts
DELETED
|
@@ -1,352 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) 2019-Present, Nitrogen Labs, Inc.
|
|
3
|
-
* Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
|
|
4
|
-
*/
|
|
5
|
-
import {get as httpGet} from '@nlabs/rip-hunter';
|
|
6
|
-
import {createHash, parseId, parseString} from '@nlabs/utils';
|
|
7
|
-
import {aql, Database} from 'arangojs';
|
|
8
|
-
import {AqlQuery} from 'arangojs/lib/cjs/aql-query';
|
|
9
|
-
import {ArrayCursor} from 'arangojs/lib/cjs/cursor';
|
|
10
|
-
import {google} from 'googleapis';
|
|
11
|
-
import {UserError} from 'graphql-errors';
|
|
12
|
-
import * as request from 'request-promise';
|
|
13
|
-
import {ApiContext} from 'types/auth';
|
|
14
|
-
|
|
15
|
-
import {Config} from '../config';
|
|
16
|
-
import {FileType} from '../types/files';
|
|
17
|
-
import {useDb} from '../utils';
|
|
18
|
-
import {resizeSaveImage} from './images';
|
|
19
|
-
import {createPostEdge} from './posts';
|
|
20
|
-
|
|
21
|
-
const youtube = google.youtube({auth: Config.get('google.key'), version: 'v3'});
|
|
22
|
-
request.defaults({encoding: null});
|
|
23
|
-
|
|
24
|
-
// const eventCategory: string = 'files';
|
|
25
|
-
|
|
26
|
-
// Upload file
|
|
27
|
-
export const addFile = (context: ApiContext, item: FileType = {}): Promise<FileType> => {
|
|
28
|
-
const {database, userId: sessionId, userType} = context;
|
|
29
|
-
const {
|
|
30
|
-
description = '',
|
|
31
|
-
fileType = '',
|
|
32
|
-
id,
|
|
33
|
-
name = '',
|
|
34
|
-
url = ''
|
|
35
|
-
} = item;
|
|
36
|
-
|
|
37
|
-
// Id
|
|
38
|
-
const fileId: string = id ? parseId(id) : createHash(`file-${sessionId}`);
|
|
39
|
-
|
|
40
|
-
// Name
|
|
41
|
-
const isUrl: boolean = url !== '';
|
|
42
|
-
|
|
43
|
-
// If no name, get it from url path
|
|
44
|
-
let formatName: string = parseString(name, 160);
|
|
45
|
-
let formatType: string = parseString(fileType, 16);
|
|
46
|
-
|
|
47
|
-
if(formatName === '' && isUrl) {
|
|
48
|
-
formatName = url.substring(url.lastIndexOf('/') + 1);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if(formatType === '') {
|
|
52
|
-
const nameArr: string[] = formatName.split('.');
|
|
53
|
-
const ext: string = nameArr[nameArr.length - 1];
|
|
54
|
-
|
|
55
|
-
switch(ext) {
|
|
56
|
-
case 'jpeg':
|
|
57
|
-
case 'jpg':
|
|
58
|
-
formatType = 'image/jpeg';
|
|
59
|
-
break;
|
|
60
|
-
case 'png':
|
|
61
|
-
formatType = 'image/png';
|
|
62
|
-
break;
|
|
63
|
-
case 'zip':
|
|
64
|
-
formatType = 'application/zip';
|
|
65
|
-
break;
|
|
66
|
-
default:
|
|
67
|
-
break;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
let isImage: boolean;
|
|
72
|
-
|
|
73
|
-
switch(formatType) {
|
|
74
|
-
case 'image/jpeg':
|
|
75
|
-
case 'image/png':
|
|
76
|
-
isImage = true;
|
|
77
|
-
break;
|
|
78
|
-
default:
|
|
79
|
-
isImage = false;
|
|
80
|
-
break;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Description
|
|
84
|
-
const formatDesc: string = parseString(description, 500);
|
|
85
|
-
|
|
86
|
-
// Only allow file uploads to premium users
|
|
87
|
-
if(!isImage && userType !== 2) {
|
|
88
|
-
throw new UserError('account_restriction');
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const saveToDb = (insert: FileType) => {
|
|
92
|
-
const aqlQry: AqlQuery = aql`INSERT ${insert} IN files RETURN NEW`;
|
|
93
|
-
|
|
94
|
-
return useDb(database).query(aqlQry)
|
|
95
|
-
.then((cursor: ArrayCursor) => cursor.next())
|
|
96
|
-
.then((file = {}) => file)
|
|
97
|
-
.catch((error: Error) => {
|
|
98
|
-
throw error;
|
|
99
|
-
});
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
const uploadFile = (buf: Buffer, uploadType: string) => {
|
|
103
|
-
const now: number = Date.now();
|
|
104
|
-
|
|
105
|
-
// If image, resize and create a thumbnail
|
|
106
|
-
if(isImage) {
|
|
107
|
-
return resizeSaveImage(sessionId, fileId, buf, uploadType)
|
|
108
|
-
.then((resizedImage: FileType) => {
|
|
109
|
-
const insert: FileType = {
|
|
110
|
-
...resizedImage,
|
|
111
|
-
_key: fileId,
|
|
112
|
-
added: now,
|
|
113
|
-
description: formatDesc,
|
|
114
|
-
fileType: formatType,
|
|
115
|
-
modified: now,
|
|
116
|
-
name: formatName,
|
|
117
|
-
userId: sessionId
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
return saveToDb(insert);
|
|
121
|
-
})
|
|
122
|
-
.catch((error: Error) => {
|
|
123
|
-
throw error;
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
const insert: FileType = {
|
|
127
|
-
_key: fileId,
|
|
128
|
-
added: now,
|
|
129
|
-
description: formatDesc,
|
|
130
|
-
fileType: formatType,
|
|
131
|
-
modified: now,
|
|
132
|
-
name: formatName,
|
|
133
|
-
userId: sessionId
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
return saveToDb(insert);
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
// If file is a url path, download the file and save
|
|
140
|
-
if(isUrl) {
|
|
141
|
-
return request.get({encoding: null, uri: url})
|
|
142
|
-
.then((body) => uploadFile(new Buffer(body, 'binary'), formatType))
|
|
143
|
-
.catch(() => {
|
|
144
|
-
throw new UserError('file_request');
|
|
145
|
-
});
|
|
146
|
-
} else if(item.base64 !== '') {
|
|
147
|
-
const buffer: Buffer = new Buffer(item.base64);
|
|
148
|
-
return uploadFile(buffer, formatType);
|
|
149
|
-
}
|
|
150
|
-
throw new Error('file_required');
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
// Giphy
|
|
154
|
-
export const getGiphyTrends = (context: ApiContext, limit: number = 30): Promise<any[]> => {
|
|
155
|
-
const gifUrl: string = `http://api.giphy.com/v1/gifs/trending?api_key=${Config.get('giphy.key')}&limit=${limit}`;
|
|
156
|
-
|
|
157
|
-
return httpGet(gifUrl)
|
|
158
|
-
.then((res: Response) => res.json())
|
|
159
|
-
.then((json) => json.data.map((gifImage = {id: null, images: null}) => {
|
|
160
|
-
const {
|
|
161
|
-
id,
|
|
162
|
-
images: {
|
|
163
|
-
original: {url = ''} = {},
|
|
164
|
-
fixed_height_small: {url: thumb = ''} = {}
|
|
165
|
-
} = {}
|
|
166
|
-
} = gifImage;
|
|
167
|
-
|
|
168
|
-
return {
|
|
169
|
-
id,
|
|
170
|
-
thumb,
|
|
171
|
-
type: 'giphy',
|
|
172
|
-
url
|
|
173
|
-
};
|
|
174
|
-
}));
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
export const getGiphySearch = (context: ApiContext, query: string, limit: number = 30): Promise<any[]> => {
|
|
178
|
-
const formatQuery: string = encodeURI(query);
|
|
179
|
-
const gifUrl: string = `http://api.giphy.com/v1/gifs/search?q=${formatQuery}&api_key=${Config.get('giphy.key')}&limit=${limit}`;
|
|
180
|
-
|
|
181
|
-
return fetch(gifUrl)
|
|
182
|
-
.then((res: Response) => res.json())
|
|
183
|
-
.then((json) => json.data.map((gifImage = {id: null, images: null}) => {
|
|
184
|
-
const {
|
|
185
|
-
id,
|
|
186
|
-
images: {
|
|
187
|
-
original: {url = ''} = {},
|
|
188
|
-
fixed_height_small: {url: thumb = ''} = {}
|
|
189
|
-
} = {}
|
|
190
|
-
} = gifImage;
|
|
191
|
-
|
|
192
|
-
return {
|
|
193
|
-
id,
|
|
194
|
-
thumb,
|
|
195
|
-
type: 'giphy',
|
|
196
|
-
url
|
|
197
|
-
};
|
|
198
|
-
}));
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
export const getYouTubeTrends = (context: ApiContext, limit: number = 30): Promise<any[]> => {
|
|
202
|
-
return new Promise((resolve, reject) => {
|
|
203
|
-
youtube.videos.list({
|
|
204
|
-
chart: 'mostPopular',
|
|
205
|
-
maxResults: limit,
|
|
206
|
-
part: 'snippet',
|
|
207
|
-
regionCode: 'US'
|
|
208
|
-
}, (error: Error, data: any) => {
|
|
209
|
-
if(error) {
|
|
210
|
-
console.error(error);
|
|
211
|
-
reject(new Error(error[0].message));
|
|
212
|
-
} else if(data) {
|
|
213
|
-
const list = data.items.map((item) => ({
|
|
214
|
-
id: item.id,
|
|
215
|
-
thumb: item.snippet.thumbnails.high.url,
|
|
216
|
-
type: 'youtube',
|
|
217
|
-
url: `http://www.youtube.com/embed/${item.id}`
|
|
218
|
-
}));
|
|
219
|
-
|
|
220
|
-
resolve(list);
|
|
221
|
-
}
|
|
222
|
-
});
|
|
223
|
-
});
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
export const getYouTubeSearch = (context: ApiContext, query: string, limit: number = 30): Promise<any[]> => {
|
|
227
|
-
return new Promise((resolve, reject) => {
|
|
228
|
-
youtube.search.list({
|
|
229
|
-
maxResults: limit,
|
|
230
|
-
part: 'snippet',
|
|
231
|
-
q: query,
|
|
232
|
-
regionCode: 'US'
|
|
233
|
-
}, (error: Error, data: any) => {
|
|
234
|
-
if(error) {
|
|
235
|
-
console.error(error);
|
|
236
|
-
reject(new Error(error[0].message));
|
|
237
|
-
} else if(data) {
|
|
238
|
-
const {items} = data;
|
|
239
|
-
const list = items.map((item) => ({
|
|
240
|
-
id: item.id,
|
|
241
|
-
thumb: item.snippet.thumbnails.high.url,
|
|
242
|
-
type: 'youtube',
|
|
243
|
-
url: `http://www.youtube.com/embed/${item.id}`
|
|
244
|
-
}));
|
|
245
|
-
|
|
246
|
-
resolve(list);
|
|
247
|
-
}
|
|
248
|
-
});
|
|
249
|
-
});
|
|
250
|
-
};
|
|
251
|
-
|
|
252
|
-
// Files
|
|
253
|
-
export const getPathUserFiles = (userId: string, filename: string): string => {
|
|
254
|
-
return `users/${userId}/files/${filename}`;
|
|
255
|
-
};
|
|
256
|
-
|
|
257
|
-
export const getUrlUserFiles = (userId: string, filename: string, dir: string = 'files', type: string = 'profile'): string => {
|
|
258
|
-
if(filename) {
|
|
259
|
-
return `https://box.${Config.get('app.url')}/users/${userId}/${dir}/${filename}`;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
if(type === 'profile') {
|
|
263
|
-
return `https://box.${Config.get('app.url')}/defaults/user_bk.jpg`;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
return `https://box.${Config.get('app.url')}/defaults/user_wh.jpg`;
|
|
267
|
-
};
|
|
268
|
-
|
|
269
|
-
export const linkFiles = (db: Database, files: FileType[], postId: string): Promise<any> => {
|
|
270
|
-
return Promise.all(
|
|
271
|
-
files.map((file: FileType) => createFile(db, file)
|
|
272
|
-
.then((file: FileType) => createPostEdge(db, file, postId)))
|
|
273
|
-
);
|
|
274
|
-
};
|
|
275
|
-
|
|
276
|
-
export const updateFiles = (db: Database, postId: string, files: FileType[]): Promise<any> => {
|
|
277
|
-
const edgeCollection = db.edgeCollection('isPosted');
|
|
278
|
-
|
|
279
|
-
return edgeCollection.inEdges(postId)
|
|
280
|
-
.then((edges) => {
|
|
281
|
-
if(edges.length) {
|
|
282
|
-
// Remove linked edges
|
|
283
|
-
return Promise.all(
|
|
284
|
-
edges.map((edge) => {
|
|
285
|
-
const {_key: edgeKey} = edge;
|
|
286
|
-
const aqlQry: AqlQuery = aql`REMOVE {_key:${edgeKey}} IN isPosted`;
|
|
287
|
-
|
|
288
|
-
return db.query(aqlQry).catch((error: Error) => {
|
|
289
|
-
throw error;
|
|
290
|
-
});
|
|
291
|
-
}))
|
|
292
|
-
.then(() => {
|
|
293
|
-
if(files.length) {
|
|
294
|
-
// Link files
|
|
295
|
-
return linkFiles(db, files, postId).then(() => files);
|
|
296
|
-
}
|
|
297
|
-
return files;
|
|
298
|
-
});
|
|
299
|
-
} else if(files.length) {
|
|
300
|
-
// Link files
|
|
301
|
-
return linkFiles(db, files, postId).then(() => files);
|
|
302
|
-
}
|
|
303
|
-
return files;
|
|
304
|
-
})
|
|
305
|
-
.catch((error: Error) => {
|
|
306
|
-
throw error;
|
|
307
|
-
});
|
|
308
|
-
};
|
|
309
|
-
|
|
310
|
-
export const createFile = (db: Database, file: FileType): Promise<FileType> => {
|
|
311
|
-
const insert: any = {
|
|
312
|
-
_key: file.id,
|
|
313
|
-
added: Date.now()
|
|
314
|
-
};
|
|
315
|
-
|
|
316
|
-
const aqlQry: AqlQuery = aql`UPSERT {_key: ${file.id}}
|
|
317
|
-
INSERT ${insert}
|
|
318
|
-
UPDATE {}
|
|
319
|
-
IN files RETURN NEW`;
|
|
320
|
-
|
|
321
|
-
return db.query(aqlQry)
|
|
322
|
-
.then((cursor: ArrayCursor) => cursor.next())
|
|
323
|
-
.then((updatedFile: FileType = {}) => updatedFile)
|
|
324
|
-
.catch((error: Error) => {
|
|
325
|
-
throw error;
|
|
326
|
-
});
|
|
327
|
-
};
|
|
328
|
-
|
|
329
|
-
export const encodeBase64 = (buffer: Buffer): string => {
|
|
330
|
-
return new Buffer(buffer).toString('base64');
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
export const decodeBase64 = (dataString: string): object => {
|
|
334
|
-
// const getData = (str: string) => str.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/) || [];
|
|
335
|
-
const getData = (str: string) => str.match(/^data:([A-Za-z-+/]+);base64,(.+)$/) || [];
|
|
336
|
-
let matches = getData(dataString);
|
|
337
|
-
|
|
338
|
-
if(matches.length !== 3) {
|
|
339
|
-
// If invalid make sure we don't need to decode
|
|
340
|
-
matches = getData(decodeURIComponent(dataString));
|
|
341
|
-
|
|
342
|
-
// Check it again.
|
|
343
|
-
if(matches.length !== 3) {
|
|
344
|
-
throw Error('Invalid input string');
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
return {
|
|
349
|
-
data: new Buffer(matches[2], 'base64'),
|
|
350
|
-
type: matches[1]
|
|
351
|
-
};
|
|
352
|
-
};
|