nodebb-plugin-audio-embed 2.0.1 → 3.0.0
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/eslint.config.mjs +10 -0
- package/lib/controllers.js +57 -15
- package/library.js +66 -97
- package/package.json +10 -5
- package/static/lib/admin.js +7 -8
- package/static/lib/main.js +12 -13
package/lib/controllers.js
CHANGED
|
@@ -1,25 +1,67 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const fs = require('fs').promises;
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
const nconf = nodebb.require('nconf');
|
|
7
|
+
const db = nodebb.require('./src/database');
|
|
8
|
+
|
|
3
9
|
const Controllers = module.exports;
|
|
4
10
|
|
|
5
|
-
Controllers.renderAdminPage = function (req, res
|
|
11
|
+
Controllers.renderAdminPage = function (req, res) {
|
|
6
12
|
res.render('admin/plugins/audio-embed', {
|
|
7
13
|
title: 'Audio Embed',
|
|
8
14
|
});
|
|
9
15
|
};
|
|
10
16
|
|
|
11
|
-
Controllers.upload = function(req, res
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
}
|
|
17
|
+
Controllers.upload = async function (req, res) {
|
|
18
|
+
try {
|
|
19
|
+
const payload = await processUpload(req.files[0]);
|
|
20
|
+
res.json([{
|
|
21
|
+
url: payload.id,
|
|
22
|
+
}]);
|
|
23
|
+
} catch (err) {
|
|
24
|
+
res.status(400);
|
|
25
|
+
res.json({
|
|
26
|
+
error: err.message === 'invalid-file-type' ?
|
|
27
|
+
'Invalid File Type Uploaded. Please check the file format or extension to ensure it is an audio file.' :
|
|
28
|
+
err.message,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
25
31
|
};
|
|
32
|
+
|
|
33
|
+
async function processUpload(payload) {
|
|
34
|
+
if (!payload || !payload.path || !payload.name || !payload.size) {
|
|
35
|
+
throw new Error('invalid-file');
|
|
36
|
+
}
|
|
37
|
+
if (!payload.type.startsWith('audio/')) {
|
|
38
|
+
throw new Error('invalid-file-type');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const id = path.basename(payload.path);
|
|
42
|
+
const uploadPath = path.join(nconf.get('upload_path'), 'audio-embed', id);
|
|
43
|
+
|
|
44
|
+
await move(payload.path, uploadPath);
|
|
45
|
+
await db.setObject('audio-embed:id:' + id, {
|
|
46
|
+
name: payload.name,
|
|
47
|
+
size: payload.size,
|
|
48
|
+
});
|
|
49
|
+
await db.sortedSetAdd('audio-embed:date', +new Date(), id);
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
id: id,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function move(path, uploadPath) {
|
|
57
|
+
try {
|
|
58
|
+
await fs.rename(path, uploadPath);
|
|
59
|
+
} catch (err) {
|
|
60
|
+
if (err.code !== 'EXDEV') {
|
|
61
|
+
throw err;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
await fs.copyFile(path, uploadPath);
|
|
65
|
+
await fs.unlink(path);
|
|
66
|
+
}
|
|
67
|
+
}
|
package/library.js
CHANGED
|
@@ -1,121 +1,90 @@
|
|
|
1
|
-
|
|
2
|
-
/* globals require, module */
|
|
1
|
+
'use strict';
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
mkdirp = require('mkdirp'),
|
|
7
|
-
mv = require('mv'),
|
|
8
|
-
async = require('async'),
|
|
9
|
-
nconf = require.main.require('nconf');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const { mkdirp } = require('mkdirp');
|
|
10
5
|
|
|
11
|
-
|
|
6
|
+
const nconf = nodebb.require('nconf');
|
|
12
7
|
|
|
13
|
-
|
|
8
|
+
const db = nodebb.require('./src/database');
|
|
9
|
+
const routeHelpers = nodebb.require('./src/routes/helpers');
|
|
14
10
|
|
|
15
|
-
|
|
16
|
-
embedRegex: /\[audio\/([\w\-_.]+)\]/g
|
|
17
|
-
},
|
|
18
|
-
app;
|
|
11
|
+
const controllers = require('./lib/controllers');
|
|
19
12
|
|
|
20
|
-
plugin
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
13
|
+
const plugin = {
|
|
14
|
+
embedRegex: /\[audio\/([\w\-_.]+)\]/g,
|
|
15
|
+
};
|
|
16
|
+
let app;
|
|
24
17
|
|
|
25
|
-
|
|
18
|
+
plugin.init = async function (params) {
|
|
19
|
+
const { router, middleware } = params;
|
|
26
20
|
|
|
27
|
-
|
|
28
|
-
router.get('/api/admin/plugins/audio-embed', controllers.renderAdminPage);
|
|
29
|
-
router.post('/plugins/nodebb-plugin-audio-embed/upload', multiparty, hostMiddleware.validateFiles, hostMiddleware.applyCSRF, controllers.upload);
|
|
21
|
+
app = params.app;
|
|
30
22
|
|
|
31
|
-
|
|
32
|
-
};
|
|
23
|
+
routeHelpers.setupAdminPageRoute(router, '/admin/plugins/audio-embed', controllers.renderAdminPage);
|
|
33
24
|
|
|
34
|
-
|
|
35
|
-
header.plugins.push({
|
|
36
|
-
route: '/plugins/audio-embed',
|
|
37
|
-
icon: 'fa-volume-up',
|
|
38
|
-
name: 'Audio Embed'
|
|
39
|
-
});
|
|
25
|
+
const upload = nodebb.require('./src/middleware/multer');
|
|
40
26
|
|
|
41
|
-
|
|
42
|
-
};
|
|
27
|
+
router.post('/plugins/nodebb-plugin-audio-embed/upload', upload.any(), middleware.validateFiles, middleware.applyCSRF, routeHelpers.tryRoute(controllers.upload));
|
|
43
28
|
|
|
44
|
-
|
|
45
|
-
payload.options.push({ name: 'audio-embed', className: 'fa fa-file-audio-o' });
|
|
46
|
-
callback(null, payload);
|
|
29
|
+
await mkdirp(path.join(nconf.get('upload_path'), 'audio-embed'));
|
|
47
30
|
};
|
|
48
31
|
|
|
49
|
-
plugin.
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
async.apply(db.setObject, 'audio-embed:id:' + id, {
|
|
57
|
-
name: payload.name,
|
|
58
|
-
size: payload.size
|
|
59
|
-
}),
|
|
60
|
-
async.apply(db.sortedSetAdd, 'audio-embed:date', +new Date(), id)
|
|
61
|
-
], function(err) {
|
|
62
|
-
if (err) {
|
|
63
|
-
return callback(err);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
callback(null, {
|
|
67
|
-
id: id
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
} else {
|
|
71
|
-
callback(new Error('invalid-file-type'));
|
|
72
|
-
}
|
|
32
|
+
plugin.addAdminNavigation = function (header) {
|
|
33
|
+
header.plugins.push({
|
|
34
|
+
route: '/plugins/audio-embed',
|
|
35
|
+
icon: 'fa-volume-up',
|
|
36
|
+
name: 'Audio Embed',
|
|
37
|
+
});
|
|
38
|
+
return header;
|
|
73
39
|
};
|
|
74
40
|
|
|
75
|
-
plugin.
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
41
|
+
plugin.registerFormatting = function (payload) {
|
|
42
|
+
payload.options.push({
|
|
43
|
+
name: 'audio-embed',
|
|
44
|
+
className: 'fa fa-file-audio-o',
|
|
45
|
+
title: 'Embed Audio',
|
|
46
|
+
});
|
|
47
|
+
return payload;
|
|
48
|
+
};
|
|
79
49
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
50
|
+
plugin.parsePost = async function (data) {
|
|
51
|
+
if (!data || !data.postData || !data.postData.content) {
|
|
52
|
+
return data;
|
|
53
|
+
}
|
|
84
54
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
});
|
|
55
|
+
data.postData.content = await plugin.parseRaw(data.postData.content);
|
|
56
|
+
return data;
|
|
88
57
|
};
|
|
89
58
|
|
|
90
|
-
plugin.parseRaw = function(content
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
59
|
+
plugin.parseRaw = async function (content) {
|
|
60
|
+
const matches = [...new Set(content.match(plugin.embedRegex) || [])]
|
|
61
|
+
.map(match => match.slice(7, -1));
|
|
62
|
+
|
|
63
|
+
if (!matches.length) {
|
|
64
|
+
return content;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const existence = await db.isSortedSetMembers('audio-embed:date', matches);
|
|
68
|
+
const ids = matches.filter((id, index) => existence[index]);
|
|
69
|
+
|
|
70
|
+
let parsedContent = content;
|
|
71
|
+
const renderedEmbeds = await Promise.all(ids.map(async id => ({
|
|
72
|
+
id,
|
|
73
|
+
html: await app.renderAsync('partials/audio-embed', {
|
|
74
|
+
id,
|
|
75
|
+
path: path.join(nconf.get('relative_path'), '/uploads/audio-embed', id),
|
|
76
|
+
}),
|
|
77
|
+
})));
|
|
78
|
+
|
|
79
|
+
for (const { id, html } of renderedEmbeds) {
|
|
80
|
+
parsedContent = parsedContent.replace(`[audio/${id}]`, html);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return parsedContent;
|
|
115
84
|
};
|
|
116
85
|
|
|
117
|
-
plugin.exists = function(id
|
|
118
|
-
|
|
86
|
+
plugin.exists = async function (id) {
|
|
87
|
+
return await db.isSortedSetMember('audio-embed:date', id);
|
|
119
88
|
};
|
|
120
89
|
|
|
121
90
|
module.exports = plugin;
|
package/package.json
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nodebb-plugin-audio-embed",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "library.js",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "https://github.com/julianlam/nodebb-plugin-audio-embed"
|
|
9
9
|
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"lint": "eslint ."
|
|
12
|
+
},
|
|
10
13
|
"keywords": [
|
|
11
14
|
"nodebb",
|
|
12
15
|
"plugin"
|
|
@@ -21,11 +24,13 @@
|
|
|
21
24
|
},
|
|
22
25
|
"readmeFilename": "README.md",
|
|
23
26
|
"nbbpm": {
|
|
24
|
-
"compatibility": "^
|
|
27
|
+
"compatibility": "^4.14.0"
|
|
25
28
|
},
|
|
26
29
|
"dependencies": {
|
|
27
|
-
"
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
"mkdirp": "^3.0.1"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"eslint": "10.6.0",
|
|
34
|
+
"eslint-config-nodebb": "^2.0.3"
|
|
30
35
|
}
|
|
31
36
|
}
|
package/static/lib/admin.js
CHANGED
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
/* globals $, app, socket, define */
|
|
3
2
|
|
|
4
|
-
define('admin/plugins/audio-embed', ['settings', 'alerts'], function(Settings, alerts) {
|
|
3
|
+
define('admin/plugins/audio-embed', ['settings', 'alerts'], function (Settings, alerts) {
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
const ACP = {};
|
|
7
6
|
|
|
8
|
-
ACP.init = function() {
|
|
7
|
+
ACP.init = function () {
|
|
9
8
|
Settings.load('audio-embed', $('.audio-embed-settings'));
|
|
10
9
|
|
|
11
|
-
$('#save').on('click', function() {
|
|
12
|
-
Settings.save('audio-embed', $('.audio-embed-settings'), function() {
|
|
10
|
+
$('#save').on('click', function () {
|
|
11
|
+
Settings.save('audio-embed', $('.audio-embed-settings'), function () {
|
|
13
12
|
alerts.alert({
|
|
14
13
|
type: 'success',
|
|
15
14
|
alert_id: 'audio-embed-saved',
|
|
16
15
|
title: 'Settings Saved',
|
|
17
16
|
message: 'Please reload your NodeBB to apply these settings',
|
|
18
|
-
clickfn: function() {
|
|
17
|
+
clickfn: function () {
|
|
19
18
|
socket.emit('admin.reload');
|
|
20
|
-
}
|
|
19
|
+
},
|
|
21
20
|
});
|
|
22
21
|
});
|
|
23
22
|
});
|
package/static/lib/main.js
CHANGED
|
@@ -1,21 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
/* globals $, require */
|
|
1
|
+
'use strict';
|
|
3
2
|
|
|
4
|
-
$(document).ready(function() {
|
|
3
|
+
$(document).ready(function () {
|
|
5
4
|
function upload(callback) {
|
|
6
5
|
require(['uploader'], function (uploader) {
|
|
7
6
|
uploader.show({
|
|
8
7
|
title: 'Upload Audio',
|
|
9
8
|
description: 'Upload an audio file for embedding into your post',
|
|
10
|
-
route: config.relative_path + '/plugins/nodebb-plugin-audio-embed/upload'
|
|
9
|
+
route: config.relative_path + '/plugins/nodebb-plugin-audio-embed/upload',
|
|
11
10
|
}, callback);
|
|
12
11
|
});
|
|
13
12
|
}
|
|
14
13
|
|
|
15
|
-
$(window).on('action:composer.loaded', function (
|
|
16
|
-
require(['composer/formatting', 'composer/controls'], function(formatting, controls) {
|
|
14
|
+
$(window).on('action:composer.loaded', function () {
|
|
15
|
+
require(['composer/formatting', 'composer/controls'], function (formatting, controls) {
|
|
17
16
|
if (formatting && controls) {
|
|
18
|
-
formatting.addButtonDispatch('audio-embed', function(textarea
|
|
17
|
+
formatting.addButtonDispatch('audio-embed', function (textarea) {
|
|
19
18
|
upload(function (id) {
|
|
20
19
|
controls.insertIntoTextarea(textarea, '[audio/' + id + ']');
|
|
21
20
|
controls.updateTextareaSelection(textarea, id.length + 8, id.length + 8);
|
|
@@ -29,33 +28,33 @@ $(document).ready(function() {
|
|
|
29
28
|
}
|
|
30
29
|
});
|
|
31
30
|
|
|
32
|
-
$(window).on('action:redactor.load', function() {
|
|
31
|
+
$(window).on('action:redactor.load', function () {
|
|
33
32
|
$.Redactor.prototype['audio-embed'] = function () {
|
|
34
33
|
return {
|
|
35
34
|
init: function () {
|
|
36
|
-
|
|
35
|
+
const self = this;
|
|
37
36
|
|
|
38
37
|
// require translator as such because it was undefined without it
|
|
39
38
|
require(['translator'], function (translator) {
|
|
40
39
|
translator.translate('Embed Audio', function (translated) {
|
|
41
|
-
|
|
40
|
+
const button = self.button.add('audio-embed', translated);
|
|
42
41
|
self.button.setIcon(button, '<i class="fa fa-file-audio-o"></i>');
|
|
43
42
|
self.button.addCallback(button, self['audio-embed'].onClick);
|
|
44
43
|
});
|
|
45
44
|
});
|
|
46
45
|
},
|
|
47
46
|
onClick: function () {
|
|
48
|
-
|
|
47
|
+
const self = this;
|
|
49
48
|
upload(function (id) {
|
|
50
49
|
require(['benchpress'], (Benchpress) => {
|
|
51
50
|
Benchpress.parse('partials/audio-embed', {
|
|
52
|
-
path: config.relative_path + '/uploads/audio-embed/' + id
|
|
51
|
+
path: config.relative_path + '/uploads/audio-embed/' + id,
|
|
53
52
|
}, function (html) {
|
|
54
53
|
self.insert.html(html);
|
|
55
54
|
});
|
|
56
55
|
});
|
|
57
56
|
});
|
|
58
|
-
}
|
|
57
|
+
},
|
|
59
58
|
};
|
|
60
59
|
};
|
|
61
60
|
});
|