Skip to content

Commit 442629d

Browse files
added metascraper, added youtube preview images when not other specefied
1 parent c521663 commit 442629d

File tree

7 files changed

+559
-16
lines changed

7 files changed

+559
-16
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,12 @@
8181
"feathers-socketio": "~2.0.1",
8282
"fs-blob-store": "~5.2.1",
8383
"fs-extra": "~4.0.2",
84+
"got": "~8.3.0",
8485
"handlebars": "~4.0.11",
8586
"handlebars-layouts": "~3.1.4",
8687
"helmet": "~3.10.0",
8788
"html-excerpt": "~0.1.0",
89+
"metascraper": "~3.9.2",
8890
"mime": "^2.2.0",
8991
"mongoose": "~4.13.2",
9092
"multer": "~1.3.0",

server/.metascraperrc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
rules:
2+
- metascraper-author
3+
- metascraper-date
4+
- metascraper-description
5+
- metascraper-image
6+
- metascraper-lang
7+
- metascraper-logo
8+
- metascraper-publisher
9+
- metascraper-title
10+
- metascraper-url
11+
- metascraper-youtube

server/hooks/create-excerpt.js

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,28 @@ module.exports = function (options = {}) { // eslint-disable-line no-unused-vars
99
if(!hook.data || !hook.data.content) {
1010
return hook;
1111
}
12-
/* eslint no-use-before-define: 0 */ // --> OFF
13-
const content = hook.data.content
12+
13+
try {
14+
/* eslint no-use-before-define: 0 */ // --> OFF
15+
const content = hook.data.content
1416
.replace(/\<br\>|\<\/br\>|\<\/ br\>|\<br\>|\<br\\\>|\<p\>|\<\/p\>/ig, "\n")
1517
.replace(/\<(strong|b|i|blockquote|pre|em|u|h[1-6])>|\<\/(strong|b|i|blockquote|pre|em|u|h[1-6])>/ig, '')
1618
.replace(/\<p\>\<br\>\<\/p\>/ig, ' ')
1719
.replace(/(\ )[2,]/ig, ' ')
1820
.trim();
19-
hook.data.contentExcerpt = trunc(content, 120, {
20-
ignoreTags: ['img', 'script']
21-
}).html;
22-
21+
hook.data.contentExcerpt = trunc(content, 120, {
22+
ignoreTags: ['img', 'script']
23+
}).html;
24+
} catch (err) {
25+
if (hook.data.teaserImg) {
26+
hook.data.contentExcerpt = '-----';
27+
} else {
28+
throw new Error('Content Needed!');
29+
}
30+
}
2331
hook.data.content = hook.data.content
2432
.replace(/(\ )[2,]/ig, ' ')
33+
2534
return Promise.resolve(hook);
2635
};
27-
};
36+
};

server/models/contributions.model.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ module.exports = function (app) {
2828
teaserImg: { type: String },
2929
language: { type: String, required: true },
3030
shoutCount: { type: Number, default: 0 },
31+
meta: {
32+
type: Object,
33+
default: {
34+
hasVideo: false
35+
}
36+
},
3137
visibility: {
3238
type: String,
3339
enum: ['public', 'friends', 'private'],

server/services/contributions/contributions.hooks.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const isModerator = require('../../hooks/is-moderator-boolean');
1515
const excludeDisabled = require('../../hooks/exclude-disabled');
1616
const getAssociatedCanDos = require('./hooks/get-associated-can-dos');
1717
const createMentionNotifications = require('./hooks/create-mention-notifications');
18+
const metascraper = require('./hooks/metascraper');
1819
const isSingleItem = require('../../hooks/is-single-item');
1920

2021
const userSchema = {
@@ -91,6 +92,7 @@ module.exports = {
9192
),
9293
associateCurrentUser(),
9394
createSlug({ field: 'title' }),
95+
metascraper(),
9496
saveRemoteImages(['teaserImg']),
9597
createExcerpt()
9698
],
@@ -103,6 +105,7 @@ module.exports = {
103105
excludeDisabled(),
104106
restrictToOwner()
105107
),
108+
metascraper(),
106109
saveRemoteImages(['teaserImg']),
107110
createExcerpt()
108111
],
@@ -115,6 +118,7 @@ module.exports = {
115118
excludeDisabled(),
116119
restrictToOwner()
117120
),
121+
metascraper(),
118122
saveRemoteImages(['teaserImg']),
119123
createExcerpt()
120124
],
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// get link metadata
2+
// TODO: add more services and use the metascraper to fill some metadata on the article
3+
4+
// const metascraper = require('metascraper');
5+
// const got = require('got');
6+
7+
module.exports = function () {
8+
return function (hook) {
9+
return new Promise(async (resolve, reject) => {
10+
11+
if (hook.data === undefined) {
12+
return reject(new Error('No data found for metascraper.'));
13+
}
14+
15+
// Check required fields
16+
if (!hook.data || !hook.data.content) {
17+
return resolve(hook);
18+
}
19+
20+
try {
21+
// find links
22+
const youtubeRegex = new RegExp(/(?:(?:https?:)?\/\/)?(?:www\.)?youtu(?:be\.com\/(?:watch\?(?:.*?&(?:amp;)?)*v=|v\/|embed\/)|\.be\/)([\w\-]+)(?:(?:&(?:amp;)?|\?)[\w\?=]*)*/, 'ig');
23+
const youtubeLinks = youtubeRegex.exec(hook.data.content);
24+
25+
// here you could scrape the url for metadata
26+
// hook.app.debug('#6');
27+
// const { body: html, url } = await got(youtubeLinks[0]);
28+
// const metadata = await metascraper({html, url});
29+
// hook.app.debug('metadata');
30+
// hook.app.debug(metadata);
31+
32+
if (youtubeLinks.length >= 2) {
33+
hook.data.teaserImg = `https://img.youtube.com/vi/${youtubeLinks[1]}/maxresdefault.jpg`;
34+
hook.data.meta = Object.assign(hook.data.meta || {}, { hasVideo: true });
35+
}
36+
} catch (err) {}
37+
38+
return resolve(hook);
39+
});
40+
};
41+
};

0 commit comments

Comments
 (0)