backend-manager 3.2.101 → 3.2.103

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": "backend-manager",
3
- "version": "3.2.101",
3
+ "version": "3.2.103",
4
4
  "description": "Quick tools for developing Firebase functions",
5
5
  "main": "src/manager/index.js",
6
6
  "bin": {
@@ -35,7 +35,7 @@
35
35
  "homepage": "https://itwcreativeworks.com",
36
36
  "dependencies": {
37
37
  "@firebase/rules-unit-testing": "^2.0.7",
38
- "@google-cloud/storage": "^7.9.0",
38
+ "@google-cloud/storage": "^7.10.2",
39
39
  "@octokit/rest": "^19.0.13",
40
40
  "@sendgrid/mail": "^7.7.0",
41
41
  "@sentry/node": "^6.19.7",
@@ -44,7 +44,7 @@
44
44
  "cors": "^2.8.5",
45
45
  "dotenv": "^16.4.5",
46
46
  "firebase-admin": "^11.11.1",
47
- "firebase-functions": "^4.8.2",
47
+ "firebase-functions": "^4.9.0",
48
48
  "fs-jetpack": "^5.1.0",
49
49
  "hcaptcha": "^0.1.1",
50
50
  "inquirer": "^8.2.5",
@@ -68,7 +68,7 @@
68
68
  "uid-generator": "^2.0.0",
69
69
  "ultimate-jekyll-poster": "^1.0.1",
70
70
  "uuid": "^9.0.1",
71
- "wonderful-fetch": "^1.1.4",
71
+ "wonderful-fetch": "^1.1.5",
72
72
  "wonderful-log": "^1.0.5",
73
73
  "yargs": "^17.7.2"
74
74
  }
@@ -0,0 +1,192 @@
1
+ const fetch = require('wonderful-fetch');
2
+ const moment = require('moment');
3
+ const jetpack = require('fs-jetpack');
4
+ const powertools = require('node-powertools');
5
+ const uuidv4 = require('uuid').v4;
6
+
7
+ const POST_TEMPLATE = jetpack.read(`${__dirname}/templates/post.html`);
8
+ const IMAGE_TAG = `{%- include /master/helpers/blog-image.html name="{name}" alt="{alt}" -%}`;
9
+ const IMAGE_PATH_SRC = `./assets/_src/images/blog/posts/post-{id}/`;
10
+ const IMAGE_PATH_REG = `/assets/images/blog/posts/post-{id}/`;
11
+ const AD_TAG = `{% include /master/modules/adunits/adsense-in-article.html index="{index}" %}`;
12
+
13
+ const IMAGE_REGEX = /(?:!\[(.*?)\]\((.*?)\))/img;
14
+ const LINK_REGEX = /(?:\[(.*?)\]\((.*?)\))/img;
15
+
16
+ function Module() {
17
+
18
+ }
19
+
20
+ Module.prototype.main = function () {
21
+ const self = this;
22
+ const Manager = self.Manager;
23
+ const Api = self.Api;
24
+ const assistant = self.assistant;
25
+ const payload = self.payload;
26
+
27
+ return new Promise(async function(resolve, reject) {
28
+ // Perform checks
29
+ if (!payload.user.roles.admin && !payload.user.roles.blogger) {
30
+ return reject(assistant.errorify(`Admin required.`, {code: 401}));
31
+ }
32
+
33
+ // Log payload
34
+ assistant.log(`main(): payload.data`, payload.data);
35
+
36
+ // Set now
37
+ const now = assistant.meta.startTime.timestamp;
38
+ const bemRepo = assistant.parseRepo(Manager?.config?.github?.repo_website);
39
+
40
+ // Check for required values
41
+ if (!payload.data.payload.title) {
42
+ return reject(assistant.errorify(`Missing required parameter: title`, {code: 400}));
43
+ } else if (!payload.data.payload.url) {
44
+ return reject(assistant.errorify(`Missing required parameter: url`, {code: 400}));
45
+ } else if (!payload.data.payload.excerpt) {
46
+ return reject(assistant.errorify(`Missing required parameter: excerpt`, {code: 400}));
47
+ } else if (!payload.data.payload.headerImageURL) {
48
+ return reject(assistant.errorify(`Missing required parameter: headerImageURL`, {code: 400}));
49
+ } else if (!payload.data.payload.body) {
50
+ return reject(assistant.errorify(`Missing required parameter: body`, {code: 400}));
51
+ }
52
+
53
+ // Fix other values
54
+ payload.data.payload.author = payload.data.payload.author || 'alex';
55
+ payload.data.payload.affiliate = payload.data.payload.affiliate || '';
56
+ payload.data.payload.tags = payload.data.payload.tags || '';
57
+ payload.data.payload.categories = payload.data.payload.categories || '';
58
+
59
+ // Fix even more values
60
+ payload.data.payload.layout = payload.data.payload.layout || 'app/blog/post';
61
+ payload.data.payload.date = payload.data.payload.date || moment(now).format('YYYY-MM-DD');
62
+ payload.data.payload.id = payload.data.payload.id || Math.round(new Date(now).getTime() / 1000);
63
+ payload.data.payload.path = payload.data.payload.path || `./_posts/${moment(now).format('YYYY')}/guest`;
64
+ payload.data.payload.githubUser = payload.data.payload.githubUser || bemRepo.user;
65
+ payload.data.payload.githubRepo = payload.data.payload.githubRepo || bemRepo.name;
66
+
67
+ // Log
68
+ assistant.log(`main(): Creating post...`, payload.data.payload);
69
+
70
+ // Extract all images
71
+ await self.extractImages();
72
+
73
+ // Set defaults
74
+ const finalContent = powertools.template(POST_TEMPLATE, payload.data.payload);
75
+
76
+ // Log
77
+ assistant.log(`main(): finalContent`, finalContent);
78
+
79
+ });
80
+
81
+ };
82
+
83
+ // Extract images
84
+ Module.prototype.extractImages = function () {
85
+ const self = this;
86
+ const Manager = self.Manager;
87
+ const Api = self.Api;
88
+ const assistant = self.assistant;
89
+ const payload = self.payload;
90
+
91
+ return new Promise(async function(resolve, reject) {
92
+ // Extract images
93
+ const matches = payload.data.payload.body.matchAll(IMAGE_REGEX);
94
+ const images = Array.from(matches).map(match => ({
95
+ src: match[2] || '',
96
+ alt: match[1] || uuidv4(),
97
+ }));
98
+
99
+ // Log
100
+ assistant.log(`extractImages(): images`, images);
101
+
102
+ if (!images) {
103
+ return resolve();
104
+ }
105
+
106
+ // Loop through images
107
+ for (let index = 0; index < images.length; index++) {
108
+ const image = images[index];
109
+
110
+ // download image
111
+ const download = await self.downloadImage(image.src, image.alt);
112
+
113
+ // Log
114
+ assistant.log(`extractImages(): download`, download);
115
+
116
+ // const src = image.src;
117
+ // const alt = image.alt;
118
+ // const hyphenated = hyphenate(alt);
119
+ // const tag = powertools.template(IMAGE_TAG, {name: hyphenate(alt), alt: alt});
120
+
121
+ // console.log(`Image ${index + 1}: src=${image.src}, alt='${image.alt}'`);
122
+ }
123
+
124
+ // const image = images[i];
125
+ // const src = image.match(LINK_REGEX)[2];
126
+ // const alt = image.match(LINK_REGEX)[1] || uuidv4();
127
+ // const name = hyphenate(alt);
128
+ // const tag = IMAGE_TAG.replace('{name}', name).replace('{alt}', alt);
129
+
130
+ // // Log
131
+ // assistant.log(`extractImages(): original`, image.match(LINK_REGEX));
132
+ // assistant.log(`extractImages(): image`, image);
133
+ // assistant.log(`extractImages(): src`, src);
134
+ // assistant.log(`extractImages(): alt`, alt);
135
+ // assistant.log(`extractImages(): name`, name);
136
+ // assistant.log(`extractImages(): tag`, tag);
137
+
138
+ // // Replace image
139
+ // payload.data.payload.body = payload.data.payload.body
140
+ // .replace(image, tag);
141
+
142
+ // // Save image
143
+ // await self.saveImage(src, id, name);
144
+
145
+ // Resolve
146
+ return resolve();
147
+ });
148
+ };
149
+
150
+ // Downlaod image
151
+ Module.prototype.downloadImage = function (src, alt) {
152
+ const self = this;
153
+ const Manager = self.Manager;
154
+ const Api = self.Api;
155
+ const assistant = self.assistant;
156
+ const payload = self.payload;
157
+
158
+ return new Promise(async function(resolve, reject) {
159
+ // Log
160
+ const hyphenated = hyphenate(alt);
161
+
162
+ assistant.log(`downloadImage(): src=${src}, alt=${alt}, hyphenated=${hyphenated}`);
163
+
164
+ // Get image
165
+ const image = await fetch(src, {
166
+ method: 'GET',
167
+ download: hyphenated,
168
+ })
169
+ .then((r) => {
170
+ // Log
171
+ assistant.log(`downloadImage(): Result`, r);
172
+
173
+ // Save image
174
+ return resolve(r);
175
+ })
176
+ .catch((e) => reject(e));
177
+ });
178
+ };
179
+
180
+ function hyphenate(s) {
181
+ return s
182
+ // Remove everything that is not a letter or a number
183
+ .replace(/[^a-zA-Z0-9]/g, '-')
184
+ // Replace multiple hyphens with a single hyphen
185
+ .replace(/-+/g, '-')
186
+ // Remove leading and trailing hyphens
187
+ .replace(/^-|-$/g, '')
188
+ // Lowercase
189
+ .toLowerCase();
190
+ }
191
+
192
+ module.exports = Module;
@@ -1,17 +1,8 @@
1
- const fetch = require('wonderful-fetch');
2
- const moment = require('moment');
3
- const jetpack = require('fs-jetpack');
4
- const powertools = require('node-powertools');
5
- const uuidv4 = require('uuid').v4;
6
-
7
- const POST_TEMPLATE = jetpack.read(`${__dirname}/templates/post.html`);
8
- const IMAGE_TAG = `{%- include /master/helpers/blog-image.html name="{name}" alt="{alt}" -%}`;
9
- const IMAGE_PATH_SRC = `./assets/_src/images/blog/posts/post-{id}/`;
10
- const IMAGE_PATH_REG = `/assets/images/blog/posts/post-{id}/`;
11
- const AD_TAG = `{% include /master/modules/adunits/adsense-in-article.html index="{index}" %}`;
12
-
13
- const IMAGE_REGEX = /(?:!\[(.*?)\]\((.*?)\))/img;
14
- const LINK_REGEX = /(?:\[(.*?)\]\((.*?)\))/img;
1
+ const fetch = require('node-fetch');
2
+ const wonderfulFetch = require('wonderful-fetch');
3
+ const Poster = require('ultimate-jekyll-poster');
4
+ const pathApi = require('path');
5
+ const { get } = require('lodash');
15
6
 
16
7
  function Module() {
17
8
 
@@ -30,161 +21,195 @@ Module.prototype.main = function () {
30
21
  return reject(assistant.errorify(`Admin required.`, {code: 401}));
31
22
  }
32
23
 
33
- // Log payload
34
- assistant.log(`main(): payload.data`, payload.data);
35
-
36
- // Set now
37
- const now = assistant.meta.startTime.timestamp;
38
- const bemRepo = assistant.parseRepo(Manager?.config?.github?.repo_website);
39
-
40
- // Check for required values
41
- if (!payload.data.payload.title) {
42
- return reject(assistant.errorify(`Missing required parameter: title`, {code: 400}));
43
- } else if (!payload.data.payload.url) {
44
- return reject(assistant.errorify(`Missing required parameter: url`, {code: 400}));
45
- } else if (!payload.data.payload.excerpt) {
46
- return reject(assistant.errorify(`Missing required parameter: excerpt`, {code: 400}));
47
- } else if (!payload.data.payload.headerImageURL) {
48
- return reject(assistant.errorify(`Missing required parameter: headerImageURL`, {code: 400}));
49
- } else if (!payload.data.payload.body) {
50
- return reject(assistant.errorify(`Missing required parameter: body`, {code: 400}));
51
- }
24
+ // Get repo info
25
+ const repoInfo = assistant.parseRepo(get(self.Manager.config, 'github.repo_website'));
26
+ const poster = new Poster();
52
27
 
53
- // Fix other values
54
- payload.data.payload.author = payload.data.payload.author || 'alex';
55
- payload.data.payload.affiliate = payload.data.payload.affiliate || '';
56
- payload.data.payload.tags = payload.data.payload.tags || '';
57
- payload.data.payload.categories = payload.data.payload.categories || '';
58
-
59
- // Fix even more values
60
- payload.data.payload.layout = payload.data.payload.layout || 'app/blog/post';
61
- payload.data.payload.date = payload.data.payload.date || moment(now).format('YYYY-MM-DD');
62
- payload.data.payload.id = payload.data.payload.id || Math.round(new Date(now).getTime() / 1000);
63
- payload.data.payload.path = payload.data.payload.path || `./_posts/${moment(now).format('YYYY')}/guest`;
64
- payload.data.payload.githubUser = payload.data.payload.githubUser || bemRepo.user;
65
- payload.data.payload.githubRepo = payload.data.payload.githubRepo || bemRepo.name;
66
-
67
- // Log
68
- assistant.log(`main(): Creating post...`, payload.data.payload);
69
-
70
- // Extract all images
71
- await self.extractImages();
28
+ assistant.log(`main(): Creating post...`, repoInfo);
72
29
 
73
30
  // Set defaults
74
- const finalContent = powertools.template(POST_TEMPLATE, payload.data.payload);
31
+ const githubUser = get(self.Manager.config, 'github.user');
32
+ const githubKey = get(self.Manager.config, 'github.key');
33
+
34
+ // Save to disk OR commit
35
+ poster.onDownload = function (meta) {
36
+ return new Promise(async function(resolve, reject) {
37
+ const tempPath = meta.tempPath;
38
+ const finalPath = poster.removeDirDot(meta.finalPath);
39
+
40
+ // Log
41
+ assistant.log(`onDownload(): tempPath`, tempPath);
42
+ assistant.log(`onDownload(): finalPath`, finalPath);
43
+
44
+ // Check for missing paths (need to check for meta.finalPath as well because it's not always set)
45
+ if (!tempPath || !finalPath || !meta.finalPath) {
46
+ return reject(new Error(`onDownload(): tempPath or finalPath is missing`));
47
+ }
48
+
49
+ // Save to disk
50
+ poster.readImage(tempPath)
51
+ .then(image => {
52
+ self.createFile(githubUser, repoInfo.user, repoInfo.name, githubKey, finalPath, image)
53
+ .then(() => {resolve()})
54
+ .catch((e) => {reject(e)})
55
+ })
56
+ .catch((e) => {reject(e)})
57
+
58
+ });
59
+ }
75
60
 
76
- // Log
77
- assistant.log(`main(): finalContent`, finalContent);
61
+ // Create post
62
+ const finalPost = await poster.create(payload.data).catch(e => e);
63
+ if (finalPost instanceof Error) {
64
+ return reject(assistant.errorify(`Failed to post: ${finalPost}`, {code: 500}));
65
+ }
66
+
67
+ // Request indexing
68
+ // DEPRECATED
69
+ // try {
70
+ // const url = get(self.Manager.config, 'brand.url');
71
+ // const encoded = encodeURIComponent(`${url}/sitemap.xml`);
72
+
73
+ // wonderfulFetch(`https://www.google.com/ping?sitemap=${encoded}`)
74
+
75
+ // // TODO
76
+ // // https://developers.google.com/search/apis/indexing-api/v3/prereqs
77
+ // // https://developers.google.com/search/apis/indexing-api/v3/using-api#url
78
+ // } catch (e) {
79
+ // assistant.error(`Failed to ping google: ${e}`);
80
+ // }
81
+
82
+ // Set file path and content
83
+ const filePath = poster.removeDirDot(finalPost.path);
84
+ const fileContent = finalPost.content;
85
+
86
+ // Save post OR commit
87
+ await self.createFile(githubUser, repoInfo.user, repoInfo.name, githubKey, filePath, fileContent)
88
+ .then(() => {
89
+ return resolve({data: finalPost});
90
+ })
91
+ .catch((e) => {
92
+ return reject(assistant.errorify(`Failed to post: ${e}`, {code: 500}));
93
+ })
78
94
 
79
95
  });
80
96
 
81
97
  };
82
98
 
83
- // Extract images
84
- Module.prototype.extractImages = function () {
99
+ // HELPERS //
100
+ Module.prototype.createFile = function (user, repoUser, repoName, key, path, contents) {
85
101
  const self = this;
86
102
  const Manager = self.Manager;
87
103
  const Api = self.Api;
88
104
  const assistant = self.assistant;
89
105
  const payload = self.payload;
90
106
 
91
- return new Promise(async function(resolve, reject) {
92
- // Extract images
93
- const matches = payload.data.payload.body.matchAll(IMAGE_REGEX);
94
- const images = Array.from(matches).map(match => ({
95
- src: match[2] || '',
96
- alt: match[1] || uuidv4(),
97
- }));
107
+ return new Promise(async (resolve, reject) => {
108
+ let fileParsed = pathApi.parse(path);
109
+ let base64Data = Buffer.from(contents).toString('base64');
110
+ let sha;
98
111
 
99
112
  // Log
100
- assistant.log(`extractImages(): images`, images);
113
+ assistant.log(`createFile(): Writing file to ${repoUser}/${repoName}/${path}`);
101
114
 
102
- if (!images) {
103
- return resolve();
104
- }
105
-
106
- // Loop through images
107
- for (let index = 0; index < images.length; index++) {
108
- const image = images[index];
109
-
110
- // download image
111
- const download = await self.downloadImage(image.src, image.alt);
115
+ // Try to get sha
116
+ try {
117
+ let branch = repoName === 'ultimate-jekyll' ? 'template' : 'master';
118
+ let pathGet = `https://api.github.com/repos/${repoUser}/${repoName}/git/trees/${branch}:${encodeURIComponent(pathApi.dirname(path))}`;
112
119
 
113
120
  // Log
114
- assistant.log(`extractImages(): download`, download);
115
-
116
- // const src = image.src;
117
- // const alt = image.alt;
118
- // const hyphenated = hyphenate(alt);
119
- // const tag = powertools.template(IMAGE_TAG, {name: hyphenate(alt), alt: alt});
120
-
121
- // console.log(`Image ${index + 1}: src=${image.src}, alt='${image.alt}'`);
121
+ assistant.log(`createFile(): pathGet`, pathGet);
122
+
123
+ // Make request
124
+ await makeRequest({
125
+ method: 'GET',
126
+ url: pathGet,
127
+ body: {
128
+ },
129
+ timeout: 30000,
130
+ json: true,
131
+ headers: {
132
+ 'User-Agent': user,
133
+ // 'Authorization': `Basic ${user}:${key}`,
134
+ 'Authorization': `Basic ${Buffer.from(user + ':' + key).toString('base64')}`,
135
+ }
136
+ })
137
+ .then(function (resp) {
138
+ // sha = resp.sha;
139
+ sha = resp.tree.find(function (element) {
140
+ // console.log('checiing', element.path, fileParsed.base);
141
+ return element.path === fileParsed.base;
142
+ });
143
+ sha = sha.sha;
144
+ });
145
+ } catch (e) {
146
+ sha = null;
147
+ }
148
+
149
+ let pathPut = `https://api.github.com/repos/${repoUser}/${repoName}/contents/${path}`;
150
+ let writeRequest = {
151
+ // url: `https://api.github.com/repos/:owner/:repo/contents/:path`,
152
+ method: 'PUT',
153
+ url: pathPut,
154
+ body: {
155
+ message: `BackendManager Post: ${new Date().toISOString()}`,
156
+ content: base64Data,
157
+ },
158
+ timeout: 30000,
159
+ json: true,
160
+ headers: {
161
+ 'User-Agent': user,
162
+ // 'Authorization': `Basic ${user}:${key}`,
163
+ 'Authorization': `Basic ${Buffer.from(user + ':' + key).toString('base64')}`,
122
164
  }
165
+ }
123
166
 
124
- // const image = images[i];
125
- // const src = image.match(LINK_REGEX)[2];
126
- // const alt = image.match(LINK_REGEX)[1] || uuidv4();
127
- // const name = hyphenate(alt);
128
- // const tag = IMAGE_TAG.replace('{name}', name).replace('{alt}', alt);
129
-
130
- // // Log
131
- // assistant.log(`extractImages(): original`, image.match(LINK_REGEX));
132
- // assistant.log(`extractImages(): image`, image);
133
- // assistant.log(`extractImages(): src`, src);
134
- // assistant.log(`extractImages(): alt`, alt);
135
- // assistant.log(`extractImages(): name`, name);
136
- // assistant.log(`extractImages(): tag`, tag);
137
-
138
- // // Replace image
139
- // payload.data.payload.body = payload.data.payload.body
140
- // .replace(image, tag);
141
-
142
- // // Save image
143
- // await self.saveImage(src, id, name);
144
-
145
- // Resolve
146
- return resolve();
147
- });
148
- };
167
+ // Log
168
+ assistant.log(`createFile(): pathPut`, pathPut);
149
169
 
150
- // Downlaod image
151
- Module.prototype.downloadImage = function (src, alt) {
152
- const self = this;
153
- const Manager = self.Manager;
154
- const Api = self.Api;
155
- const assistant = self.assistant;
156
- const payload = self.payload;
170
+ // Add sha if it exists
171
+ if (sha) {
172
+ writeRequest.body.sha = sha;
173
+ }
157
174
 
158
- return new Promise(async function(resolve, reject) {
159
- // Log
160
- assistant.log(`downloadImage(): src=${src}, alt=${alt}`);
175
+ // Make request
176
+ await makeRequest(writeRequest)
177
+ .then((json) => {
178
+ if (!json || (json.message && (json.message === 'Not Found' || json.message.includes('Invalid request'))) ) {
179
+ return reject(new Error(json.message));
180
+ }
181
+ })
182
+ .catch((e) => {
183
+ return reject(e);
184
+ })
185
+ return resolve(true)
186
+ });
187
+ }
161
188
 
162
- // Get image
163
- const image = await fetch(src, {
164
- method: 'GET',
165
- download: true,
166
- })
167
- .then((r) => {
168
- // Log
169
- assistant.log(`downloadImage(): Result`, r);
189
+ function makeRequest(options) {
190
+ return new Promise(function(resolve, reject) {
191
+ options.headers = options.headers || {};
192
+ options.headers['Content-Type'] = 'application/json';
193
+
194
+ let hasBody = Object.keys(options.body || {}).length > 0
195
+
196
+ fetch(options.url, {
197
+ method: options.method,
198
+ body: hasBody ? JSON.stringify(options.body) : undefined,
199
+ timeout: 30000,
200
+ headers: options.headers,
201
+ auth: options.auth,
202
+ })
203
+ .then(res => res.json())
204
+ .then(json => {
205
+ return resolve(json);
206
+ })
207
+ .catch(e => {
208
+ // console.error('e', e);
209
+ return reject(e);
210
+ })
170
211
 
171
- // Save image
172
- return resolve(r);
173
- })
174
- .catch((e) => reject(e));
175
212
  });
176
- };
177
-
178
- function hyphenate(s) {
179
- return s
180
- // Remove everything that is not a letter or a number
181
- .replace(/[^a-zA-Z0-9]/g, '-')
182
- // Replace multiple hyphens with a single hyphen
183
- .replace(/-+/g, '-')
184
- // Remove leading and trailing hyphens
185
- .replace(/^-|-$/g, '')
186
- // Lowercase
187
- .toLowerCase();
188
213
  }
189
214
 
190
215
  module.exports = Module;
@@ -131,6 +131,7 @@ function Analytics(Manager, options) {
131
131
 
132
132
  // Fix user data
133
133
  // https://developers.google.com/analytics/devguides/collection/ga4/uid-data
134
+ // https://stackoverflow.com/questions/68636233/ga4-measurement-protocol-does-not-display-user-data-location-screen-resolution
134
135
  self.userData = {
135
136
  sha256_email_address: authUser?.auth?.email
136
137
  ? toSHA256(authUser?.auth?.email)
@@ -1,215 +0,0 @@
1
- const fetch = require('node-fetch');
2
- const wonderfulFetch = require('wonderful-fetch');
3
- const Poster = require('ultimate-jekyll-poster');
4
- const pathApi = require('path');
5
- const { get } = require('lodash');
6
-
7
- function Module() {
8
-
9
- }
10
-
11
- Module.prototype.main = function () {
12
- const self = this;
13
- const Manager = self.Manager;
14
- const Api = self.Api;
15
- const assistant = self.assistant;
16
- const payload = self.payload;
17
-
18
- return new Promise(async function(resolve, reject) {
19
- // Perform checks
20
- if (!payload.user.roles.admin && !payload.user.roles.blogger) {
21
- return reject(assistant.errorify(`Admin required.`, {code: 401}));
22
- }
23
-
24
- // Get repo info
25
- const repoInfo = assistant.parseRepo(get(self.Manager.config, 'github.repo_website'));
26
- const poster = new Poster();
27
-
28
- assistant.log(`main(): Creating post...`, repoInfo);
29
-
30
- // Set defaults
31
- const githubUser = get(self.Manager.config, 'github.user');
32
- const githubKey = get(self.Manager.config, 'github.key');
33
-
34
- // Save to disk OR commit
35
- poster.onDownload = function (meta) {
36
- return new Promise(async function(resolve, reject) {
37
- const tempPath = meta.tempPath;
38
- const finalPath = poster.removeDirDot(meta.finalPath);
39
-
40
- // Log
41
- assistant.log(`onDownload(): tempPath`, tempPath);
42
- assistant.log(`onDownload(): finalPath`, finalPath);
43
-
44
- // Check for missing paths (need to check for meta.finalPath as well because it's not always set)
45
- if (!tempPath || !finalPath || !meta.finalPath) {
46
- return reject(new Error(`onDownload(): tempPath or finalPath is missing`));
47
- }
48
-
49
- // Save to disk
50
- poster.readImage(tempPath)
51
- .then(image => {
52
- self.createFile(githubUser, repoInfo.user, repoInfo.name, githubKey, finalPath, image)
53
- .then(() => {resolve()})
54
- .catch((e) => {reject(e)})
55
- })
56
- .catch((e) => {reject(e)})
57
-
58
- });
59
- }
60
-
61
- // Create post
62
- const finalPost = await poster.create(payload.data).catch(e => e);
63
- if (finalPost instanceof Error) {
64
- return reject(assistant.errorify(`Failed to post: ${finalPost}`, {code: 500}));
65
- }
66
-
67
- // Request indexing
68
- // DEPRECATED
69
- // try {
70
- // const url = get(self.Manager.config, 'brand.url');
71
- // const encoded = encodeURIComponent(`${url}/sitemap.xml`);
72
-
73
- // wonderfulFetch(`https://www.google.com/ping?sitemap=${encoded}`)
74
-
75
- // // TODO
76
- // // https://developers.google.com/search/apis/indexing-api/v3/prereqs
77
- // // https://developers.google.com/search/apis/indexing-api/v3/using-api#url
78
- // } catch (e) {
79
- // assistant.error(`Failed to ping google: ${e}`);
80
- // }
81
-
82
- // Set file path and content
83
- const filePath = poster.removeDirDot(finalPost.path);
84
- const fileContent = finalPost.content;
85
-
86
- // Save post OR commit
87
- await self.createFile(githubUser, repoInfo.user, repoInfo.name, githubKey, filePath, fileContent)
88
- .then(() => {
89
- return resolve({data: finalPost});
90
- })
91
- .catch((e) => {
92
- return reject(assistant.errorify(`Failed to post: ${e}`, {code: 500}));
93
- })
94
-
95
- });
96
-
97
- };
98
-
99
- // HELPERS //
100
- Module.prototype.createFile = function (user, repoUser, repoName, key, path, contents) {
101
- const self = this;
102
- const Manager = self.Manager;
103
- const Api = self.Api;
104
- const assistant = self.assistant;
105
- const payload = self.payload;
106
-
107
- return new Promise(async (resolve, reject) => {
108
- let fileParsed = pathApi.parse(path);
109
- let base64Data = Buffer.from(contents).toString('base64');
110
- let sha;
111
-
112
- // Log
113
- assistant.log(`createFile(): Writing file to ${repoUser}/${repoName}/${path}`);
114
-
115
- // Try to get sha
116
- try {
117
- let branch = repoName === 'ultimate-jekyll' ? 'template' : 'master';
118
- let pathGet = `https://api.github.com/repos/${repoUser}/${repoName}/git/trees/${branch}:${encodeURIComponent(pathApi.dirname(path))}`;
119
-
120
- // Log
121
- assistant.log(`createFile(): pathGet`, pathGet);
122
-
123
- // Make request
124
- await makeRequest({
125
- method: 'GET',
126
- url: pathGet,
127
- body: {
128
- },
129
- timeout: 30000,
130
- json: true,
131
- headers: {
132
- 'User-Agent': user,
133
- // 'Authorization': `Basic ${user}:${key}`,
134
- 'Authorization': `Basic ${Buffer.from(user + ':' + key).toString('base64')}`,
135
- }
136
- })
137
- .then(function (resp) {
138
- // sha = resp.sha;
139
- sha = resp.tree.find(function (element) {
140
- // console.log('checiing', element.path, fileParsed.base);
141
- return element.path === fileParsed.base;
142
- });
143
- sha = sha.sha;
144
- });
145
- } catch (e) {
146
- sha = null;
147
- }
148
-
149
- let pathPut = `https://api.github.com/repos/${repoUser}/${repoName}/contents/${path}`;
150
- let writeRequest = {
151
- // url: `https://api.github.com/repos/:owner/:repo/contents/:path`,
152
- method: 'PUT',
153
- url: pathPut,
154
- body: {
155
- message: `BackendManager Post: ${new Date().toISOString()}`,
156
- content: base64Data,
157
- },
158
- timeout: 30000,
159
- json: true,
160
- headers: {
161
- 'User-Agent': user,
162
- // 'Authorization': `Basic ${user}:${key}`,
163
- 'Authorization': `Basic ${Buffer.from(user + ':' + key).toString('base64')}`,
164
- }
165
- }
166
-
167
- // Log
168
- assistant.log(`createFile(): pathPut`, pathPut);
169
-
170
- // Add sha if it exists
171
- if (sha) {
172
- writeRequest.body.sha = sha;
173
- }
174
-
175
- // Make request
176
- await makeRequest(writeRequest)
177
- .then((json) => {
178
- if (!json || (json.message && (json.message === 'Not Found' || json.message.includes('Invalid request'))) ) {
179
- return reject(new Error(json.message));
180
- }
181
- })
182
- .catch((e) => {
183
- return reject(e);
184
- })
185
- return resolve(true)
186
- });
187
- }
188
-
189
- function makeRequest(options) {
190
- return new Promise(function(resolve, reject) {
191
- options.headers = options.headers || {};
192
- options.headers['Content-Type'] = 'application/json';
193
-
194
- let hasBody = Object.keys(options.body || {}).length > 0
195
-
196
- fetch(options.url, {
197
- method: options.method,
198
- body: hasBody ? JSON.stringify(options.body) : undefined,
199
- timeout: 30000,
200
- headers: options.headers,
201
- auth: options.auth,
202
- })
203
- .then(res => res.json())
204
- .then(json => {
205
- return resolve(json);
206
- })
207
- .catch(e => {
208
- // console.error('e', e);
209
- return reject(e);
210
- })
211
-
212
- });
213
- }
214
-
215
- module.exports = Module;