@nlabs/reaktor 0.1.0 → 0.1.2
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 +13 -13
- package/src/config.ts +8 -2
- package/src/data/conversations.ts +2 -4
- package/src/data/email.ts +3 -4
- package/src/data/files.ts +2 -2
- package/src/data/images.ts +5 -5
- package/src/data/posts.ts +239 -167
- package/src/data/users.ts +0 -2
- package/src/types/apps.ts +0 -1
- package/src/types/auth.ts +1 -0
- package/src/types/files.ts +0 -2
- package/src/types/groups.ts +0 -1
- package/src/types/images.ts +0 -1
- package/src/types/locations.ts +0 -1
- package/src/types/payments.ts +0 -5
- package/src/types/posts.ts +13 -4
- package/src/types/tags.ts +0 -1
- package/src/utils/auth.ts +35 -2
- package/src/utils/graphql.ts +7 -0
- package/src/utils/index.ts +1 -0
- package/lib/config.d.ts +0 -21
- package/lib/config.js +0 -127
- package/lib/data/conversations.d.ts +0 -6
- package/lib/data/conversations.js +0 -201
- package/lib/data/dynamodb.d.ts +0 -8
- package/lib/data/dynamodb.js +0 -139
- package/lib/data/email.d.ts +0 -7
- package/lib/data/email.js +0 -164
- package/lib/data/files.d.ts +0 -16
- package/lib/data/files.js +0 -407
- package/lib/data/groups.d.ts +0 -13
- package/lib/data/groups.js +0 -354
- package/lib/data/images.d.ts +0 -12
- package/lib/data/images.js +0 -668
- package/lib/data/index.d.ts +0 -19
- package/lib/data/index.js +0 -24
- package/lib/data/ios.d.ts +0 -6
- package/lib/data/ios.js +0 -302
- package/lib/data/locations.d.ts +0 -3
- package/lib/data/locations.js +0 -132
- package/lib/data/messages.d.ts +0 -9
- package/lib/data/messages.js +0 -248
- package/lib/data/notifications.d.ts +0 -5
- package/lib/data/notifications.js +0 -42
- package/lib/data/payments.d.ts +0 -11
- package/lib/data/payments.js +0 -748
- package/lib/data/posts.d.ts +0 -14
- package/lib/data/posts.js +0 -458
- package/lib/data/reactions.d.ts +0 -6
- package/lib/data/reactions.js +0 -218
- package/lib/data/s3.d.ts +0 -6
- package/lib/data/s3.js +0 -103
- package/lib/data/search.d.ts +0 -3
- package/lib/data/search.js +0 -98
- package/lib/data/sms.d.ts +0 -3
- package/lib/data/sms.js +0 -59
- package/lib/data/subscription.d.ts +0 -7
- package/lib/data/subscription.js +0 -284
- package/lib/data/tags.d.ts +0 -14
- package/lib/data/tags.js +0 -304
- package/lib/data/users.d.ts +0 -12
- package/lib/data/users.js +0 -312
- package/lib/index.d.ts +0 -3
- package/lib/index.js +0 -8
- package/lib/types/apps.d.ts +0 -44
- package/lib/types/apps.js +0 -2
- package/lib/types/arangodb.d.ts +0 -17
- package/lib/types/arangodb.js +0 -2
- package/lib/types/auth.d.ts +0 -9
- package/lib/types/auth.js +0 -2
- package/lib/types/conversations.d.ts +0 -6
- package/lib/types/conversations.js +0 -2
- package/lib/types/email.d.ts +0 -12
- package/lib/types/email.js +0 -2
- package/lib/types/files.d.ts +0 -28
- package/lib/types/files.js +0 -2
- package/lib/types/google.d.ts +0 -27
- package/lib/types/google.js +0 -2
- package/lib/types/groups.d.ts +0 -22
- package/lib/types/groups.js +0 -2
- package/lib/types/images.d.ts +0 -25
- package/lib/types/images.js +0 -2
- package/lib/types/index.d.ts +0 -17
- package/lib/types/index.js +0 -22
- package/lib/types/locations.d.ts +0 -21
- package/lib/types/locations.js +0 -2
- package/lib/types/messages.d.ts +0 -12
- package/lib/types/messages.js +0 -2
- package/lib/types/notifications.d.ts +0 -19
- package/lib/types/notifications.js +0 -2
- package/lib/types/payments.d.ts +0 -119
- package/lib/types/payments.js +0 -2
- package/lib/types/posts.d.ts +0 -20
- package/lib/types/posts.js +0 -2
- package/lib/types/reactions.d.ts +0 -4
- package/lib/types/reactions.js +0 -2
- package/lib/types/tags.d.ts +0 -10
- package/lib/types/tags.js +0 -2
- package/lib/types/users.d.ts +0 -78
- package/lib/types/users.js +0 -2
- package/lib/utils/analytics.d.ts +0 -3
- package/lib/utils/analytics.js +0 -47
- package/lib/utils/arangodb.d.ts +0 -9
- package/lib/utils/arangodb.js +0 -98
- package/lib/utils/auth.d.ts +0 -2
- package/lib/utils/auth.js +0 -43
- package/lib/utils/index.d.ts +0 -5
- package/lib/utils/index.js +0 -10
- package/lib/utils/objects.d.ts +0 -3
- package/lib/utils/objects.js +0 -34
- package/lib/utils/redis.d.ts +0 -1
- package/lib/utils/redis.js +0 -15
package/src/data/posts.ts
CHANGED
|
@@ -2,36 +2,86 @@
|
|
|
2
2
|
* Copyright (c) 2019-Present, Nitrogen Labs, Inc.
|
|
3
3
|
* Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
|
|
4
4
|
*/
|
|
5
|
-
import {createHash, parseChar, parseId, parseString, parseVarChar} from '@nlabs/utils';
|
|
5
|
+
import {createHash, parseChar, parseId, parseNum, parseString, parseVarChar} from '@nlabs/utils';
|
|
6
6
|
import {aql, Database} from 'arangojs';
|
|
7
7
|
import {AqlQuery} from 'arangojs/lib/cjs/aql-query';
|
|
8
8
|
import {ArrayCursor} from 'arangojs/lib/cjs/cursor';
|
|
9
9
|
import flatten from 'lodash/flatten';
|
|
10
10
|
import uniqBy from 'lodash/uniqBy';
|
|
11
11
|
|
|
12
|
-
import {ApiContext,
|
|
12
|
+
import {ApiContext, FileType, GroupType, PostOptions, PostType, TagType} from '../types';
|
|
13
13
|
import {getLimit, useDb} from '../utils';
|
|
14
14
|
import {updateFiles} from './files';
|
|
15
15
|
import {extractTags} from './tags';
|
|
16
16
|
|
|
17
17
|
// const eventCategory: string = 'posts';
|
|
18
|
+
const MAX_CONTENT_LENGTH: number = 100000;
|
|
18
19
|
|
|
19
|
-
export const
|
|
20
|
+
export const parsePostOptions = (options: PostOptions = {}) => {
|
|
21
|
+
const {
|
|
22
|
+
from = 0,
|
|
23
|
+
latitude,
|
|
24
|
+
longitude,
|
|
25
|
+
to = 30,
|
|
26
|
+
type = 'default'
|
|
27
|
+
} = options;
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
latitude: parseNum(latitude, 32),
|
|
32
|
+
longitude: parseNum(longitude, 32),
|
|
33
|
+
limit: getLimit(from, to),
|
|
34
|
+
type: parseChar(type, 32)
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const getPostOptional = (fields: string[]) =>
|
|
39
|
+
fields.reduce((selects: any, field: string) => {
|
|
40
|
+
switch(field) {
|
|
41
|
+
case 'reactions': {
|
|
42
|
+
selects.queries.push(`LET reactions = (
|
|
43
|
+
FOR post, r IN INBOUND p._id reactions
|
|
44
|
+
COLLECT reactionName = r.value INTO reactionItems
|
|
45
|
+
RETURN {name: reactionName, count: LENGTH(reactionItems[*].r.value)}
|
|
46
|
+
)`);
|
|
47
|
+
selects.objects.push('reactions:reactions');
|
|
48
|
+
return selects;
|
|
49
|
+
}
|
|
50
|
+
case 'tags': {
|
|
51
|
+
selects.queries.push(`LET tags = (
|
|
52
|
+
FOR t, pl IN INBOUND p._id isTagged
|
|
53
|
+
RETURN t
|
|
54
|
+
)`);
|
|
55
|
+
selects.objects.push('tags:tags');
|
|
56
|
+
return selects;
|
|
57
|
+
}
|
|
58
|
+
case 'user': {
|
|
59
|
+
selects.queries.push(`LET user = FIRST(
|
|
60
|
+
FOR u IN users
|
|
61
|
+
FILTER p.userId == u._key
|
|
62
|
+
LIMIT 1
|
|
63
|
+
RETURN u
|
|
64
|
+
)`);
|
|
65
|
+
selects.objects.push('user:user');
|
|
66
|
+
return selects;
|
|
67
|
+
}
|
|
68
|
+
default: {
|
|
69
|
+
return selects;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}, {objects: [], queries: []});
|
|
73
|
+
|
|
74
|
+
export const getPostList = (context: ApiContext, options?: PostOptions): Promise<PostType[]> => {
|
|
20
75
|
// const action: string = 'getListByApp';
|
|
21
|
-
const {database} = context;
|
|
22
|
-
const limit
|
|
76
|
+
const {database, fields} = context;
|
|
77
|
+
const {limit, type} = parsePostOptions(options);
|
|
78
|
+
const {objects: selectObjects, queries: selectQueries} = getPostOptional(fields);
|
|
23
79
|
const aqlQry: string = `FOR p IN posts
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
)
|
|
30
|
-
FOR u IN users
|
|
31
|
-
FILTER p.userId == u._key
|
|
32
|
-
${limit.aql}
|
|
33
|
-
SORT p.added
|
|
34
|
-
RETURN DISTINCT MERGE(p, {user:u, reactions:reactions})`;
|
|
80
|
+
FILTER p.type == "${type}" && p.privacy == "public" && p.parent == null
|
|
81
|
+
${selectQueries.join('\n')}
|
|
82
|
+
${limit.aql}
|
|
83
|
+
SORT p.added
|
|
84
|
+
RETURN DISTINCT MERGE(p, {${selectObjects.join(', ')}})`;
|
|
35
85
|
|
|
36
86
|
return useDb(database).query(aqlQry)
|
|
37
87
|
.then((cursor: ArrayCursor) => cursor.all())
|
|
@@ -40,9 +90,10 @@ export const getPostList = (context: ApiContext, from: number, to: number): Prom
|
|
|
40
90
|
});
|
|
41
91
|
};
|
|
42
92
|
|
|
43
|
-
export const getPostListByGroup = (context: ApiContext, groupId: string,
|
|
93
|
+
export const getPostListByGroup = (context: ApiContext, groupId: string, options?: PostOptions): Promise<PostType[]> => {
|
|
44
94
|
// const action: string = 'getListByGroup';
|
|
45
|
-
const {database, userId: sessionId} = context;
|
|
95
|
+
const {database, fields, userId: sessionId} = context;
|
|
96
|
+
const {objects: selectObjects, queries: selectQueries} = getPostOptional(fields);
|
|
46
97
|
|
|
47
98
|
// Group id
|
|
48
99
|
const formatGroupId: string = parseId(groupId);
|
|
@@ -55,19 +106,13 @@ export const getPostListByGroup = (context: ApiContext, groupId: string, from: n
|
|
|
55
106
|
.then((cursor: ArrayCursor) => cursor.all())
|
|
56
107
|
.then((groups: GroupType[] = []) => {
|
|
57
108
|
if(groups.length) {
|
|
58
|
-
const limit
|
|
109
|
+
const {limit, type} = parsePostOptions(options);
|
|
59
110
|
const postAqlQry: string = `FOR p IN posts
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
)
|
|
66
|
-
FOR u IN users
|
|
67
|
-
FILTER p.userId == u._key
|
|
68
|
-
${limit.aql}
|
|
69
|
-
SORT p.added
|
|
70
|
-
RETURN DISTINCT MERGE(p, {user:u, reactions:reactions})`;
|
|
111
|
+
FILTER p.type == "${type}" && p.groupId == "${formatGroupId}" && p.parent == null
|
|
112
|
+
${selectQueries.join('\n')}
|
|
113
|
+
${limit.aql}
|
|
114
|
+
SORT p.added
|
|
115
|
+
RETURN DISTINCT MERGE(p, {${selectObjects.join(', ')}})`;
|
|
71
116
|
|
|
72
117
|
return db.query(postAqlQry)
|
|
73
118
|
.then((cursor: ArrayCursor) => cursor.all())
|
|
@@ -83,22 +128,17 @@ export const getPostListByGroup = (context: ApiContext, groupId: string, from: n
|
|
|
83
128
|
});
|
|
84
129
|
};
|
|
85
130
|
|
|
86
|
-
export const getPostListByLatest = (context: ApiContext,
|
|
131
|
+
export const getPostListByLatest = (context: ApiContext, options?: PostOptions): Promise<PostType[]> => {
|
|
87
132
|
// const action: string = 'getListByLatest';
|
|
88
|
-
const {database} = context;
|
|
89
|
-
const limit
|
|
133
|
+
const {database, fields} = context;
|
|
134
|
+
const {limit, type} = parsePostOptions(options);
|
|
135
|
+
const {objects: selectObjects, queries: selectQueries} = getPostOptional(fields);
|
|
90
136
|
const aqlQry: string = `FOR p IN posts
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
)
|
|
97
|
-
FOR u IN users
|
|
98
|
-
FILTER p.userId == u._key
|
|
99
|
-
${limit.aql}
|
|
100
|
-
SORT p.added
|
|
101
|
-
RETURN DISTINCT MERGE(p, {user:u, reactions:reactions})`;
|
|
137
|
+
FILTER p.type == "${type}" && p.privacy == "public" && p.parent == null
|
|
138
|
+
${selectQueries.join('\n')}
|
|
139
|
+
${limit.aql}
|
|
140
|
+
SORT p.added
|
|
141
|
+
RETURN DISTINCT MERGE(p, {${selectObjects.join(', ')}})`;
|
|
102
142
|
|
|
103
143
|
return useDb(database).query(aqlQry)
|
|
104
144
|
.then((cursor: ArrayCursor) => cursor.all())
|
|
@@ -107,31 +147,47 @@ export const getPostListByLatest = (context: ApiContext, from: number, to: numbe
|
|
|
107
147
|
});
|
|
108
148
|
};
|
|
109
149
|
|
|
110
|
-
export const getPostListByTags = (
|
|
150
|
+
export const getPostListByTags = (
|
|
151
|
+
context: ApiContext,
|
|
152
|
+
tagNames: string[],
|
|
153
|
+
options?: PostOptions
|
|
154
|
+
): Promise<PostType[]> => {
|
|
111
155
|
// const action: string = 'getListByTags';
|
|
112
|
-
const {database} = context;
|
|
156
|
+
const {database, fields} = context;
|
|
157
|
+
const {latitude, longitude, limit, type} = parsePostOptions(options);
|
|
158
|
+
const {objects: selectObjects, queries: selectQueries} = getPostOptional(fields);
|
|
159
|
+
const sortBy: string[] = [];
|
|
160
|
+
|
|
161
|
+
if(latitude !== undefined && longitude !== undefined) {
|
|
162
|
+
const formatLatitude: number = parseNum(latitude);
|
|
163
|
+
const formatLongitude: number = parseNum(longitude);
|
|
164
|
+
selectQueries.push(`LET distance = DISTANCE(
|
|
165
|
+
${formatLatitude},
|
|
166
|
+
${formatLongitude},
|
|
167
|
+
NOT_NULL(p.latitude, 0),
|
|
168
|
+
NOT_NULL(p.longitude, 0))
|
|
169
|
+
`);
|
|
170
|
+
selectObjects.push('distance:distance');
|
|
171
|
+
sortBy.push('distance');
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
sortBy.push('p.added');
|
|
113
175
|
|
|
114
176
|
return Promise.all(
|
|
115
177
|
tagNames.map((tagName: string) => {
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
${limit.aql}
|
|
127
|
-
SORT p.added
|
|
128
|
-
RETURN DISTINCT MERGE(p, {user:u, reactions:reactions})`;
|
|
129
|
-
|
|
178
|
+
const aqlQry: string = `FOR targetTag IN tags
|
|
179
|
+
FILTER targetTag.name == "${tagName}"
|
|
180
|
+
FOR p, e IN OUTBOUND targetTag._id isTagged
|
|
181
|
+
${selectQueries.join('\n')}
|
|
182
|
+
FILTER p.type = "${type}" && p.privacy == "public" && e.type == 'posts'
|
|
183
|
+
${limit.aql}
|
|
184
|
+
SORT ${sortBy.join(', ')}
|
|
185
|
+
RETURN DISTINCT MERGE(p, {${selectObjects.join(', ')}})`;
|
|
186
|
+
|
|
187
|
+
console.log(aqlQry);
|
|
130
188
|
return useDb(database).query(aqlQry)
|
|
131
189
|
.then((cursor: ArrayCursor) => cursor.all())
|
|
132
|
-
.catch((
|
|
133
|
-
throw error;
|
|
134
|
-
});
|
|
190
|
+
.catch(() => []);
|
|
135
191
|
}))
|
|
136
192
|
.then((results) => uniqBy(flatten(results), '_key'))
|
|
137
193
|
.catch((error: Error) => {
|
|
@@ -139,23 +195,52 @@ export const getPostListByTags = (context: ApiContext, tagNames: string[], from?
|
|
|
139
195
|
});
|
|
140
196
|
};
|
|
141
197
|
|
|
142
|
-
export const getPostListByUser = (context: ApiContext, userId: string,
|
|
198
|
+
export const getPostListByUser = (context: ApiContext, userId: string, options?: PostOptions): Promise<PostType[]> => {
|
|
143
199
|
// const action: string = 'getListByUser';
|
|
144
|
-
const {database} = context;
|
|
200
|
+
const {database, fields} = context;
|
|
201
|
+
const {limit, type} = parsePostOptions(options);
|
|
145
202
|
const formatUserId: string = parseId(userId);
|
|
146
|
-
const
|
|
203
|
+
const {objects: selectObjects, queries: selectQueries} = getPostOptional(fields);
|
|
204
|
+
const aqlQry: string = `FOR p IN posts
|
|
205
|
+
FILTER p.userId == "${formatUserId}" && p.type == "${type}" && p.privacy == "public" && p.parent == null
|
|
206
|
+
${selectQueries.join('\n')}
|
|
207
|
+
${limit.aql}
|
|
208
|
+
SORT p.added
|
|
209
|
+
RETURN DISTINCT MERGE(p, {${selectObjects.join(', ')}})`;
|
|
210
|
+
|
|
211
|
+
return useDb(database).query(aqlQry)
|
|
212
|
+
.then((cursor: ArrayCursor) => cursor.all())
|
|
213
|
+
.catch((error: Error) => {
|
|
214
|
+
throw error;
|
|
215
|
+
});
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
export const getPostListByArea = (
|
|
219
|
+
context: ApiContext,
|
|
220
|
+
latitude: number,
|
|
221
|
+
longitude: number,
|
|
222
|
+
options?: PostOptions
|
|
223
|
+
): Promise<PostType[]> => {
|
|
224
|
+
// const action: string = 'getListByUser';
|
|
225
|
+
const {database, fields} = context;
|
|
226
|
+
const {limit, type} = parsePostOptions(options);
|
|
227
|
+
const formatLatitude: number = parseNum(latitude);
|
|
228
|
+
const formatLongitude: number = parseNum(longitude);
|
|
229
|
+
const {objects: selectObjects, queries: selectQueries} = getPostOptional(fields);
|
|
230
|
+
selectQueries.push(`LET distance = DISTANCE(
|
|
231
|
+
${formatLatitude},
|
|
232
|
+
${formatLongitude},
|
|
233
|
+
NOT_NULL(p.latitude, 0),
|
|
234
|
+
NOT_NULL(p.longitude, 0))
|
|
235
|
+
`);
|
|
236
|
+
selectObjects.push('distance:distance');
|
|
237
|
+
|
|
147
238
|
const aqlQry: string = `FOR p IN posts
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
)
|
|
154
|
-
FOR u IN users
|
|
155
|
-
FILTER p.userId == u._key
|
|
156
|
-
${limit.aql}
|
|
157
|
-
SORT p.added
|
|
158
|
-
RETURN DISTINCT MERGE(p, {user:u, reactions:reactions})`;
|
|
239
|
+
${selectQueries.join('\n')}
|
|
240
|
+
FILTER p.type == "${type}" && p.privacy == "public" && p.parentId == null
|
|
241
|
+
${limit.aql}
|
|
242
|
+
SORT distance, p.added
|
|
243
|
+
RETURN DISTINCT MERGE(p, {${selectObjects.join(', ')}})`;
|
|
159
244
|
|
|
160
245
|
return useDb(database).query(aqlQry)
|
|
161
246
|
.then((cursor: ArrayCursor) => cursor.all())
|
|
@@ -166,13 +251,14 @@ export const getPostListByUser = (context: ApiContext, userId: string, from: num
|
|
|
166
251
|
|
|
167
252
|
export const getPost = (context: ApiContext, itemId: string): Promise<PostType> => {
|
|
168
253
|
// const action: string = 'getItem';
|
|
169
|
-
const {database, userId: sessionId} = context;
|
|
254
|
+
const {database, fields, userId: sessionId} = context;
|
|
170
255
|
const formatItemId: string = parseId(itemId);
|
|
171
256
|
const db = useDb(database);
|
|
257
|
+
const {objects: selectObjects, queries: selectQueries} = getPostOptional(fields);
|
|
172
258
|
const aqlQry: AqlQuery = aql`FOR p IN posts
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
259
|
+
FILTER p._key == ${formatItemId}
|
|
260
|
+
LIMIT 1
|
|
261
|
+
RETURN p`;
|
|
176
262
|
|
|
177
263
|
return db.query(aqlQry)
|
|
178
264
|
.then((cursor: ArrayCursor) => cursor.next())
|
|
@@ -184,34 +270,24 @@ export const getPost = (context: ApiContext, itemId: string): Promise<PostType>
|
|
|
184
270
|
}: PostType = post;
|
|
185
271
|
|
|
186
272
|
// Query based on privacy level
|
|
187
|
-
let privacyAqlQry:
|
|
273
|
+
let privacyAqlQry: string;
|
|
188
274
|
|
|
189
275
|
if(groupId && privacy === 'group') {
|
|
190
|
-
privacyAqlQry =
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
LET reactions = (
|
|
194
|
-
FOR post, r IN INBOUND p._id reactions
|
|
195
|
-
COLLECT reactionName = r.value INTO reactionItems
|
|
196
|
-
RETURN {name: reactionName, count: LENGTH(reactionItems[*].r.value)}
|
|
197
|
-
)
|
|
276
|
+
privacyAqlQry = `FOR p IN posts
|
|
277
|
+
FILTER p._key == "${_key}"
|
|
278
|
+
${selectQueries.join('\n')}
|
|
198
279
|
FOR group IN groups
|
|
199
280
|
FILTER group._key == p.groupId
|
|
200
281
|
FOR u, e IN OUTBOUND group._id isGrouped
|
|
201
282
|
FILTER u._key == ${sessionId}
|
|
202
283
|
LIMIT 1
|
|
203
|
-
RETURN MERGE(p, {
|
|
284
|
+
RETURN MERGE(p, {${selectObjects.join(', ')}})`;
|
|
204
285
|
} else if(privacy === 'public') {
|
|
205
|
-
privacyAqlQry =
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
LET reactions = (
|
|
209
|
-
FOR post, r IN INBOUND p._id reactions
|
|
210
|
-
COLLECT reactionName = r.value INTO reactionItems
|
|
211
|
-
RETURN {name: reactionName, count: LENGTH(reactionItems[*].r.value)}
|
|
212
|
-
)
|
|
286
|
+
privacyAqlQry = `FOR p IN posts
|
|
287
|
+
FILTER p._key == "${_key}"
|
|
288
|
+
${selectQueries.join('\n')}
|
|
213
289
|
LIMIT 1
|
|
214
|
-
RETURN MERGE(p, {
|
|
290
|
+
RETURN MERGE(p, {${selectObjects.join(', ')}})`;
|
|
215
291
|
}
|
|
216
292
|
|
|
217
293
|
if(privacyAqlQry) {
|
|
@@ -230,17 +306,18 @@ export const getPost = (context: ApiContext, itemId: string): Promise<PostType>
|
|
|
230
306
|
});
|
|
231
307
|
};
|
|
232
308
|
|
|
233
|
-
export const getPostComments = (context: ApiContext, itemId: string,
|
|
309
|
+
export const getPostComments = (context: ApiContext, itemId: string, options?: PostOptions): Promise<PostType[]> => {
|
|
234
310
|
// const action: string = 'getComments';
|
|
235
311
|
const {database, userId: sessionId} = context;
|
|
312
|
+
const {limit, type} = parsePostOptions(options);
|
|
236
313
|
const formatItemId: string = parseId(itemId);
|
|
237
314
|
|
|
238
315
|
// Get the parent post to get restrictions
|
|
239
316
|
const db = useDb(database);
|
|
240
317
|
const aqlQry: AqlQuery = aql`FOR p IN posts
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
318
|
+
FILTER p.type == ${type} && p._key == ${formatItemId}
|
|
319
|
+
LIMIT 1
|
|
320
|
+
RETURN p`;
|
|
244
321
|
|
|
245
322
|
return db.query(aqlQry)
|
|
246
323
|
.then((cursor: ArrayCursor) => cursor.next())
|
|
@@ -253,36 +330,35 @@ export const getPostComments = (context: ApiContext, itemId: string, from: numbe
|
|
|
253
330
|
|
|
254
331
|
// Query based on privacy level
|
|
255
332
|
let privacyAqlQry: string;
|
|
256
|
-
const limit = getLimit(from, to);
|
|
257
333
|
|
|
258
334
|
if(groupId && privacy === 'group') {
|
|
259
335
|
privacyAqlQry = `FOR p IN posts
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
336
|
+
FOR user IN users
|
|
337
|
+
FILTER p.parent == "${_key}" && user._key == p.userId
|
|
338
|
+
LET reactions = (
|
|
339
|
+
FOR post, r IN INBOUND p._id reactions
|
|
340
|
+
COLLECT reactionName = r.value INTO reactionItems
|
|
341
|
+
RETURN {name: reactionName, count: LENGTH(reactionItems[*].r.value)}
|
|
342
|
+
)
|
|
343
|
+
FOR group IN groups
|
|
344
|
+
FILTER group._key == p.groupId
|
|
345
|
+
FOR u, e IN OUTBOUND group._id isGrouped
|
|
346
|
+
FILTER u._key == "${sessionId}"
|
|
347
|
+
SORT p.added
|
|
348
|
+
${limit.aql}
|
|
349
|
+
RETURN MERGE(p, {user: user, reactions: reactions})`;
|
|
274
350
|
} else if(privacy === 'public') {
|
|
275
351
|
privacyAqlQry = `FOR p IN posts
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
352
|
+
FOR user IN users
|
|
353
|
+
FILTER p.parent == "${_key}" && user._key == p.userId
|
|
354
|
+
LET reactions = (
|
|
355
|
+
FOR post, r IN INBOUND p._id reactions
|
|
356
|
+
COLLECT reactionName = r.value INTO reactionItems
|
|
357
|
+
RETURN {name: reactionName, count: LENGTH(reactionItems[*].r.value)}
|
|
358
|
+
)
|
|
359
|
+
SORT p.added
|
|
360
|
+
${limit.aql}
|
|
361
|
+
RETURN MERGE(p, {user: user, reactions: reactions})`;
|
|
286
362
|
}
|
|
287
363
|
|
|
288
364
|
if(privacyAqlQry) {
|
|
@@ -305,12 +381,15 @@ export const addPost = (context: ApiContext, item: PostType): Promise<PostType>
|
|
|
305
381
|
const {database, userId: sessionId} = context;
|
|
306
382
|
|
|
307
383
|
const {
|
|
384
|
+
content = '',
|
|
308
385
|
groupId = '',
|
|
386
|
+
location,
|
|
387
|
+
latitude,
|
|
388
|
+
longitude,
|
|
309
389
|
name = '',
|
|
310
|
-
parentId =
|
|
390
|
+
parentId = null,
|
|
311
391
|
privacy = 'public',
|
|
312
|
-
|
|
313
|
-
title = ''
|
|
392
|
+
type = 'default'
|
|
314
393
|
}: PostType = item;
|
|
315
394
|
|
|
316
395
|
const now: number = Date.now();
|
|
@@ -318,15 +397,19 @@ export const addPost = (context: ApiContext, item: PostType): Promise<PostType>
|
|
|
318
397
|
const insert: PostType = {
|
|
319
398
|
_key: createHash(`post-${sessionId}`),
|
|
320
399
|
added: now,
|
|
321
|
-
|
|
400
|
+
content: parseString(content, MAX_CONTENT_LENGTH),
|
|
401
|
+
groupId: groupId ? parseId(groupId) : undefined,
|
|
402
|
+
latitude: latitude !== undefined ? parseNum(latitude) : undefined,
|
|
403
|
+
location: location ? parseString(location, 160) : undefined,
|
|
404
|
+
longitude: longitude !== undefined ? parseNum(longitude) : undefined,
|
|
322
405
|
modified: now,
|
|
323
406
|
name: parseString(name, 160),
|
|
324
|
-
parentId: parseId(parentId),
|
|
325
|
-
privacy: parseVarChar(privacy, 16),
|
|
326
|
-
|
|
327
|
-
title: parseString(title, 160),
|
|
407
|
+
parentId: parentId ? parseId(parentId) : undefined,
|
|
408
|
+
privacy: privacy ? parseVarChar(privacy, 16) : undefined,
|
|
409
|
+
type: parseChar(type, 32),
|
|
328
410
|
userId: sessionId
|
|
329
411
|
};
|
|
412
|
+
|
|
330
413
|
const db: Database = useDb(database);
|
|
331
414
|
const aqlQry: AqlQuery = aql`INSERT ${insert} IN posts RETURN NEW`;
|
|
332
415
|
|
|
@@ -336,7 +419,7 @@ export const addPost = (context: ApiContext, item: PostType): Promise<PostType>
|
|
|
336
419
|
const {_key: postKey} = post;
|
|
337
420
|
|
|
338
421
|
// Update linked tags within posts
|
|
339
|
-
return extractTags(db, 'posts', postKey, insert.
|
|
422
|
+
return extractTags(db, 'posts', postKey, insert.content)
|
|
340
423
|
.then((tagList: TagType[]) => {
|
|
341
424
|
post.tags = tagList;
|
|
342
425
|
return post;
|
|
@@ -352,36 +435,25 @@ export const updatePost = (context: ApiContext, item: PostType): Promise<PostTyp
|
|
|
352
435
|
const {database, userId: sessionId} = context;
|
|
353
436
|
const now: number = Date.now();
|
|
354
437
|
const {
|
|
438
|
+
content,
|
|
355
439
|
groupId,
|
|
356
|
-
id,
|
|
357
440
|
name,
|
|
358
441
|
parentId,
|
|
442
|
+
postId,
|
|
359
443
|
privacy,
|
|
360
|
-
|
|
444
|
+
type
|
|
361
445
|
}: PostType = item;
|
|
362
446
|
|
|
363
|
-
const
|
|
364
|
-
|
|
447
|
+
const update: PostType = {
|
|
448
|
+
content: content ? parseString(content, MAX_CONTENT_LENGTH) : undefined,
|
|
449
|
+
modified: now,
|
|
450
|
+
name: name ? parseString(name, 160) : undefined,
|
|
451
|
+
parentId: parentId ? parseString(parentId, 160) : undefined,
|
|
452
|
+
privacy: privacy ? parseVarChar(privacy, 16) : undefined,
|
|
453
|
+
type: type !== undefined ? parseChar(type, 16) : undefined
|
|
365
454
|
};
|
|
366
455
|
|
|
367
|
-
|
|
368
|
-
updatedPost.name = parseString(name, 160);
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
if(text) {
|
|
372
|
-
updatedPost.text = parseString(text, 640);
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
if(privacy) {
|
|
376
|
-
updatedPost.privacy = parseVarChar(privacy, 16);
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
if(parent) {
|
|
380
|
-
updatedPost.parentId = parseId(parentId);
|
|
381
|
-
}
|
|
382
|
-
const update: any = updatedPost;
|
|
383
|
-
|
|
384
|
-
let formatId: string = parseId(id);
|
|
456
|
+
let formatId: string = parseId(postId);
|
|
385
457
|
formatId = formatId === '' ? createHash(`post-${sessionId}`) : formatId;
|
|
386
458
|
const formatGroupId: string = parseId(groupId);
|
|
387
459
|
const insert: any = {
|
|
@@ -393,10 +465,10 @@ export const updatePost = (context: ApiContext, item: PostType): Promise<PostTyp
|
|
|
393
465
|
userId: sessionId
|
|
394
466
|
};
|
|
395
467
|
const db: Database = useDb(database);
|
|
396
|
-
const aqlQry: AqlQuery = aql`UPSERT {_key: ${
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
468
|
+
const aqlQry: AqlQuery = aql`UPSERT {_key: ${formatId}, userId: ${sessionId}}
|
|
469
|
+
INSERT ${insert}
|
|
470
|
+
UPDATE ${update}
|
|
471
|
+
IN posts RETURN NEW`;
|
|
400
472
|
|
|
401
473
|
return db.query(aqlQry)
|
|
402
474
|
.then((cursor: ArrayCursor) => cursor.next())
|
|
@@ -404,7 +476,7 @@ export const updatePost = (context: ApiContext, item: PostType): Promise<PostTyp
|
|
|
404
476
|
const {_key: updatedPostKey} = updatedPost;
|
|
405
477
|
|
|
406
478
|
// Update linked tags
|
|
407
|
-
return extractTags(db, 'posts', updatedPostKey, update.
|
|
479
|
+
return extractTags(db, 'posts', updatedPostKey, update.content || '')
|
|
408
480
|
.then((tagList = []) => {
|
|
409
481
|
updatedPost.tags = tagList;
|
|
410
482
|
|
|
@@ -412,7 +484,7 @@ export const updatePost = (context: ApiContext, item: PostType): Promise<PostTyp
|
|
|
412
484
|
const files: FileType[] = updatedPost.files || [];
|
|
413
485
|
|
|
414
486
|
if(files.length) {
|
|
415
|
-
return updateFiles(db,
|
|
487
|
+
return updateFiles(db, formatId, files)
|
|
416
488
|
.then((fileList = []) => {
|
|
417
489
|
updatedPost.files = fileList;
|
|
418
490
|
return updatedPost;
|
|
@@ -475,7 +547,7 @@ export const deletePost = (context: ApiContext, itemId: string): Promise<PostTyp
|
|
|
475
547
|
export const cleanPosts = (database: string): Promise<number> => {
|
|
476
548
|
// Remove all messages that are over 60 days and not saved
|
|
477
549
|
const aqlQry: AqlQuery = aql`FOR p IN posts
|
|
478
|
-
FILTER p.added < DATE_TIMESTAMP(DATE_SUBTRACT(DATE_NOW(), 60, 'day')) && p.type ==
|
|
550
|
+
FILTER p.added < DATE_TIMESTAMP(DATE_SUBTRACT(DATE_NOW(), 60, 'day')) && p.type == "default"
|
|
479
551
|
REMOVE p IN posts
|
|
480
552
|
RETURN OLD`;
|
|
481
553
|
|
package/src/data/users.ts
CHANGED
|
@@ -207,13 +207,11 @@ export const getUsersByRelations = (
|
|
|
207
207
|
const formatUserId: string = parseId(userId);
|
|
208
208
|
const formatType: string = parseChar(type, 32);
|
|
209
209
|
const limit = getLimit(from, to);
|
|
210
|
-
console.log('context', context);
|
|
211
210
|
const aqlQry: string = `FOR u, r IN INBOUND "${`users/${formatUserId}`}" hasRelation
|
|
212
211
|
FILTER r.type == "${formatType}"
|
|
213
212
|
${limit.aql}
|
|
214
213
|
RETURN u`;
|
|
215
214
|
|
|
216
|
-
console.log('getUsersByRelations::aqlQry', aqlQry);
|
|
217
215
|
return useDb(database).query(aqlQry)
|
|
218
216
|
.then((cursor: ArrayCursor) => cursor.all())
|
|
219
217
|
.catch((error: Error) => logError({
|
package/src/types/apps.ts
CHANGED
package/src/types/auth.ts
CHANGED
package/src/types/files.ts
CHANGED
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
export interface FileType {
|
|
6
6
|
readonly _key?: string;
|
|
7
7
|
readonly added?: number;
|
|
8
|
-
readonly appId?: string;
|
|
9
8
|
readonly base64?: string;
|
|
10
9
|
readonly buffer?: Buffer;
|
|
11
10
|
readonly description?: string;
|
|
@@ -26,7 +25,6 @@ export interface FileDecodedType {
|
|
|
26
25
|
}
|
|
27
26
|
|
|
28
27
|
export interface FileEdgeType {
|
|
29
|
-
readonly appId?: string;
|
|
30
28
|
readonly imgId?: string;
|
|
31
29
|
readonly itemId?: string;
|
|
32
30
|
readonly itemType?: string;
|
package/src/types/groups.ts
CHANGED
package/src/types/images.ts
CHANGED
|
@@ -23,7 +23,6 @@ export interface ImageIdentifyType {
|
|
|
23
23
|
export type ImageUrlTypes = 'app' | 'events' | 'groups' | 'users';
|
|
24
24
|
|
|
25
25
|
export interface ImageUrlData {
|
|
26
|
-
readonly appId?: string;
|
|
27
26
|
readonly directory?: string;
|
|
28
27
|
readonly imgId?: string;
|
|
29
28
|
readonly imgType?: string;
|
package/src/types/locations.ts
CHANGED