nodebb-plugin-tenor-gif 2.0.0 → 2.2.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/.eslintrc +1 -137
- package/library.js +63 -59
- package/package.json +9 -7
- package/static/lib/.eslintrc +3 -0
- package/static/lib/admin.js +1 -6
- package/static/lib/main.js +9 -8
- package/static/templates/admin/plugins/tenor-gif.tpl +13 -0
- package/websockets.js +5 -3
package/.eslintrc
CHANGED
|
@@ -1,139 +1,3 @@
|
|
|
1
1
|
{
|
|
2
|
-
"extends": "
|
|
3
|
-
"parserOptions": {
|
|
4
|
-
"sourceType": "script"
|
|
5
|
-
},
|
|
6
|
-
|
|
7
|
-
"rules": {
|
|
8
|
-
// Customized
|
|
9
|
-
"handle-callback-err": [ "error","^(e$|(e|(.*(_e|E)))rr)" ],
|
|
10
|
-
"comma-dangle": ["error", {
|
|
11
|
-
"arrays": "always-multiline",
|
|
12
|
-
"objects": "always-multiline",
|
|
13
|
-
"imports": "always-multiline",
|
|
14
|
-
"exports": "always-multiline",
|
|
15
|
-
"functions": "never"
|
|
16
|
-
}],
|
|
17
|
-
"no-return-await": "off",
|
|
18
|
-
"no-constant-condition": "off",
|
|
19
|
-
"no-empty": ["error", { "allowEmptyCatch": true }],
|
|
20
|
-
"no-underscore-dangle": "off",
|
|
21
|
-
"no-console": "off",
|
|
22
|
-
"no-mixed-operators": ["error", { "allowSamePrecedence": true }],
|
|
23
|
-
"strict": ["error", "global"],
|
|
24
|
-
"consistent-return": "off",
|
|
25
|
-
"func-names": "off",
|
|
26
|
-
"no-tabs": "off",
|
|
27
|
-
"indent": ["error", "tab"],
|
|
28
|
-
"no-eq-null": "off",
|
|
29
|
-
"camelcase": "off",
|
|
30
|
-
"no-new": "off",
|
|
31
|
-
"no-shadow": "off",
|
|
32
|
-
"no-use-before-define": ["error", "nofunc"],
|
|
33
|
-
"no-prototype-builtins": "off",
|
|
34
|
-
"new-cap": "off",
|
|
35
|
-
"no-plusplus": ["error", { "allowForLoopAfterthoughts": true }],
|
|
36
|
-
"object-curly-newline": "off",
|
|
37
|
-
"no-restricted-globals": "off",
|
|
38
|
-
"function-paren-newline": "off",
|
|
39
|
-
"import/no-unresolved": "error",
|
|
40
|
-
"quotes": ["error", "single", {
|
|
41
|
-
"avoidEscape": true,
|
|
42
|
-
"allowTemplateLiterals": true
|
|
43
|
-
}],
|
|
44
|
-
"no-else-return": [ "error", { "allowElseIf": true } ],
|
|
45
|
-
"operator-linebreak": [ "error", "after" ],
|
|
46
|
-
|
|
47
|
-
// ES6
|
|
48
|
-
"prefer-rest-params": "off",
|
|
49
|
-
"prefer-spread": "off",
|
|
50
|
-
"prefer-arrow-callback": "off",
|
|
51
|
-
"prefer-template": "off",
|
|
52
|
-
"no-var": "off",
|
|
53
|
-
"object-shorthand": "off",
|
|
54
|
-
"vars-on-top": "off",
|
|
55
|
-
"prefer-destructuring": "off",
|
|
56
|
-
|
|
57
|
-
// TODO
|
|
58
|
-
"import/no-extraneous-dependencies": "off",
|
|
59
|
-
"import/no-dynamic-require": "off",
|
|
60
|
-
"import/newline-after-import": "off",
|
|
61
|
-
"no-bitwise": "off",
|
|
62
|
-
"global-require": "off",
|
|
63
|
-
"max-len": "off",
|
|
64
|
-
"no-param-reassign": "off",
|
|
65
|
-
"no-restricted-syntax": "off",
|
|
66
|
-
"no-script-url": "off",
|
|
67
|
-
"default-case": "off",
|
|
68
|
-
"linebreak-style": "off",
|
|
69
|
-
|
|
70
|
-
// "no-multi-assign": "off",
|
|
71
|
-
// "one-var": "off",
|
|
72
|
-
// "no-undef": "off",
|
|
73
|
-
// "max-nested-callbacks": "off",
|
|
74
|
-
// "no-mixed-requires": "off",
|
|
75
|
-
// "brace-style": "off",
|
|
76
|
-
// "max-statements-per-line": "off",
|
|
77
|
-
// "no-unused-vars": "off",
|
|
78
|
-
// "no-mixed-spaces-and-tabs": "off",
|
|
79
|
-
// "no-useless-concat": "off",
|
|
80
|
-
// "require-jsdoc": "off",
|
|
81
|
-
// "eqeqeq": "off",
|
|
82
|
-
// "no-negated-condition": "off",
|
|
83
|
-
// "one-var-declaration-per-line": "off",
|
|
84
|
-
// "no-lonely-if": "off",
|
|
85
|
-
// "radix": "off",
|
|
86
|
-
// "no-else-return": "off",
|
|
87
|
-
// "no-useless-escape": "off",
|
|
88
|
-
// "block-scoped-var": "off",
|
|
89
|
-
// "operator-assignment": "off",
|
|
90
|
-
// "yoda": "off",
|
|
91
|
-
// "no-loop-func": "off",
|
|
92
|
-
// "no-void": "off",
|
|
93
|
-
// "valid-jsdoc": "off",
|
|
94
|
-
// "no-cond-assign": "off",
|
|
95
|
-
// "no-redeclare": "off",
|
|
96
|
-
// "no-unreachable": "off",
|
|
97
|
-
// "no-nested-ternary": "off",
|
|
98
|
-
// "operator-linebreak": "off",
|
|
99
|
-
// "guard-for-in": "off",
|
|
100
|
-
// "no-unneeded-ternary": "off",
|
|
101
|
-
// "no-sequences": "off",
|
|
102
|
-
// "no-extend-native": "off",
|
|
103
|
-
// "no-shadow-restricted-names": "off",
|
|
104
|
-
// "no-extra-boolean-cast": "off",
|
|
105
|
-
// "no-path-concat": "off",
|
|
106
|
-
// "no-unused-expressions": "off",
|
|
107
|
-
// "no-return-assign": "off",
|
|
108
|
-
// "no-restricted-modules": "off",
|
|
109
|
-
// "object-curly-spacing": "off",
|
|
110
|
-
// "indent": "off",
|
|
111
|
-
// "padded-blocks": "off",
|
|
112
|
-
// "eol-last": "off",
|
|
113
|
-
// "lines-around-directive": "off",
|
|
114
|
-
// "strict": "off",
|
|
115
|
-
// "comma-dangle": "off",
|
|
116
|
-
// "no-multi-spaces": "off",
|
|
117
|
-
// "quotes": "off",
|
|
118
|
-
// "keyword-spacing": "off",
|
|
119
|
-
// "no-mixed-operators": "off",
|
|
120
|
-
// "comma-spacing": "off",
|
|
121
|
-
// "no-trailing-spaces": "off",
|
|
122
|
-
// "key-spacing": "off",
|
|
123
|
-
// "no-multiple-empty-lines": "off",
|
|
124
|
-
// "spaced-comment": "off",
|
|
125
|
-
// "space-in-parens": "off",
|
|
126
|
-
// "block-spacing": "off",
|
|
127
|
-
// "quote-props": "off",
|
|
128
|
-
// "space-unary-ops": "off",
|
|
129
|
-
// "no-empty": "off",
|
|
130
|
-
// "dot-notation": "off",
|
|
131
|
-
// "func-call-spacing": "off",
|
|
132
|
-
// "array-bracket-spacing": "off",
|
|
133
|
-
// "object-property-newline": "off",
|
|
134
|
-
// "no-continue": "off",
|
|
135
|
-
// "no-extra-semi": "off",
|
|
136
|
-
// "no-spaced-func": "off",
|
|
137
|
-
// "no-useless-return": "off"
|
|
138
|
-
}
|
|
2
|
+
"extends": "nodebb"
|
|
139
3
|
}
|
package/library.js
CHANGED
|
@@ -1,39 +1,30 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
var websockets = require('./websockets');
|
|
5
|
-
var meta = require.main.require('./src/meta');
|
|
6
|
-
var winston = require.main.require('winston');
|
|
3
|
+
const request = require('request-promise-native');
|
|
7
4
|
|
|
8
|
-
|
|
5
|
+
const controllers = require('./lib/controllers');
|
|
6
|
+
const websockets = require('./websockets');
|
|
9
7
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
const nconf = require.main.require('nconf');
|
|
9
|
+
const meta = require.main.require('./src/meta');
|
|
10
|
+
const slugify = require.main.require('./src/slugify');
|
|
11
|
+
const ttlCache = require.main.require('./src/cache/ttl');
|
|
12
|
+
|
|
13
|
+
const plugin = module.exports;
|
|
14
|
+
|
|
15
|
+
plugin._cache = ttlCache({
|
|
16
|
+
name: 'tenor-gif',
|
|
17
|
+
ttl: 1000 * 60 * 60, // 1 hour
|
|
18
|
+
});
|
|
15
19
|
|
|
16
|
-
plugin.init =
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
plugin.init = async (params) => {
|
|
21
|
+
const { router } = params;
|
|
22
|
+
const hostMiddleware = params.middleware;
|
|
19
23
|
|
|
20
24
|
router.get('/admin/plugins/tenor-gif', hostMiddleware.admin.buildHeader, controllers.renderAdminPage);
|
|
21
25
|
router.get('/api/admin/plugins/tenor-gif', controllers.renderAdminPage);
|
|
22
26
|
|
|
23
27
|
websockets.init();
|
|
24
|
-
plugin.refreshSettings(callback);
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
plugin.refreshSettings = function (callback) {
|
|
28
|
-
meta.settings.get('tenor-gif', function (err, settings) {
|
|
29
|
-
Object.assign(plugin._settings, settings);
|
|
30
|
-
|
|
31
|
-
if (!settings.key || !settings.key.length) {
|
|
32
|
-
winston.warn('[plugin/tenor-gif] Invalid or missing API Key, plugin disabled');
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
callback(err);
|
|
36
|
-
});
|
|
37
28
|
};
|
|
38
29
|
|
|
39
30
|
plugin.addAdminNavigation = function (header, callback) {
|
|
@@ -46,45 +37,58 @@ plugin.addAdminNavigation = function (header, callback) {
|
|
|
46
37
|
callback(null, header);
|
|
47
38
|
};
|
|
48
39
|
|
|
49
|
-
plugin.registerFormatting =
|
|
50
|
-
|
|
40
|
+
plugin.registerFormatting = async (payload) => {
|
|
41
|
+
const { key } = await meta.settings.get('tenor-gif');
|
|
42
|
+
if (key) {
|
|
51
43
|
payload.options.push({ name: 'gif', className: 'fa fa-tenor-gif', title: 'Insert GIF' });
|
|
52
44
|
}
|
|
53
45
|
|
|
54
|
-
|
|
46
|
+
return payload;
|
|
55
47
|
};
|
|
56
48
|
|
|
57
|
-
plugin.query =
|
|
58
|
-
|
|
59
|
-
|
|
49
|
+
plugin.query = async (query) => {
|
|
50
|
+
let { contentFilter, key, limit } = await meta.settings.get('tenor-gif');
|
|
51
|
+
if (!limit || limit < 1 || limit > 50) {
|
|
52
|
+
limit = 10;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
query = String(query).trim();
|
|
56
|
+
const commonArgs = `&limit=${limit}&contentfilter=${contentFilter || 'medium'}&key=${key}&client_key=nodebb-${slugify(nconf.get('url'))}`;
|
|
57
|
+
let url = `https://tenor.googleapis.com/v2/featured?type=featured${commonArgs}`;
|
|
58
|
+
if (query) {
|
|
59
|
+
url = `https://tenor.googleapis.com/v2/search?q=${query}${commonArgs}`;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
let gifs = plugin._cache.get(query);
|
|
63
|
+
if (gifs) {
|
|
64
|
+
return gifs;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const body = await request({
|
|
68
|
+
url,
|
|
60
69
|
method: 'get',
|
|
61
70
|
json: true,
|
|
62
|
-
}, function (err, res, body) {
|
|
63
|
-
if (!plugin._settings.key || (body && body.hasOwnProperty('error'))) {
|
|
64
|
-
err = new Error('[[error:invalid-login-credentials]]');
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Malformed return handling
|
|
68
|
-
if (!body || !body.results) {
|
|
69
|
-
return callback(new Error('[[error:invalid-data]]'));
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if (err) {
|
|
73
|
-
return callback(err);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Collapse results down to array of images
|
|
77
|
-
var gifs = body.results.reduce(function (memo, cur) {
|
|
78
|
-
memo.push({
|
|
79
|
-
url: cur.media_formats.gif.url,
|
|
80
|
-
thumb: cur.media_formats.tinygif.url,
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
return memo;
|
|
84
|
-
}, []);
|
|
85
|
-
|
|
86
|
-
callback(null, gifs);
|
|
87
71
|
});
|
|
88
|
-
};
|
|
89
72
|
|
|
90
|
-
|
|
73
|
+
if (!key || (body && body.hasOwnProperty('error'))) {
|
|
74
|
+
throw new Error('[[error:invalid-login-credentials]]');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Malformed return handling
|
|
78
|
+
if (!body.results) {
|
|
79
|
+
throw new Error('[[error:invalid-data]]');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Collapse results down to array of images
|
|
83
|
+
gifs = body.results.reduce((memo, cur) => {
|
|
84
|
+
memo.push({
|
|
85
|
+
url: cur.media_formats.gif.url,
|
|
86
|
+
thumb: cur.media_formats.tinygif.url,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
return memo;
|
|
90
|
+
}, []);
|
|
91
|
+
|
|
92
|
+
plugin._cache.set(query, gifs);
|
|
93
|
+
return gifs;
|
|
94
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nodebb-plugin-tenor-gif",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "library.js",
|
|
6
6
|
"repository": {
|
|
@@ -21,20 +21,22 @@
|
|
|
21
21
|
},
|
|
22
22
|
"readmeFilename": "README.md",
|
|
23
23
|
"nbbpm": {
|
|
24
|
-
"compatibility": "^
|
|
24
|
+
"compatibility": "^2.4.0"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@commitlint/cli": "^9.1.2",
|
|
28
|
-
"eslint": "
|
|
29
|
-
"lint-staged": "^
|
|
30
|
-
"request": "^2.88.
|
|
28
|
+
"eslint": "8.x",
|
|
29
|
+
"lint-staged": "^13.0.3",
|
|
30
|
+
"request": "^2.88.2",
|
|
31
|
+
"request-promise-native": "^1.0.9"
|
|
31
32
|
},
|
|
32
33
|
"devDependencies": {
|
|
33
34
|
"@commitlint/cli": "^9.1.2",
|
|
34
35
|
"@commitlint/config-angular": "^7.1.2",
|
|
35
36
|
"eslint": "^7.7.0",
|
|
36
|
-
"eslint-config-airbnb-base": "^
|
|
37
|
-
"eslint-
|
|
37
|
+
"eslint-config-airbnb-base": "^15.0.0",
|
|
38
|
+
"eslint-config-nodebb": "0.1.1",
|
|
39
|
+
"eslint-plugin-import": "2.x",
|
|
38
40
|
"husky": "^2.4.0",
|
|
39
41
|
"lint-staged": "^10.0.9"
|
|
40
42
|
}
|
package/static/lib/admin.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
/* globals $, app, socket */
|
|
4
|
-
|
|
5
3
|
define('admin/plugins/tenor-gif', ['settings'], function (Settings) {
|
|
6
4
|
var ACP = {};
|
|
7
5
|
|
|
@@ -14,10 +12,7 @@ define('admin/plugins/tenor-gif', ['settings'], function (Settings) {
|
|
|
14
12
|
type: 'success',
|
|
15
13
|
alert_id: 'tenor-gif-saved',
|
|
16
14
|
title: 'Settings Saved',
|
|
17
|
-
|
|
18
|
-
clickfn: function () {
|
|
19
|
-
socket.emit('admin.reload');
|
|
20
|
-
},
|
|
15
|
+
timeout: 5000,
|
|
21
16
|
});
|
|
22
17
|
});
|
|
23
18
|
});
|
package/static/lib/main.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
/* globals $, document, window, socket, bootbox */
|
|
4
|
-
|
|
5
3
|
$(document).ready(function () {
|
|
6
4
|
var Tenor = {};
|
|
7
5
|
|
|
@@ -85,10 +83,6 @@ $(document).ready(function () {
|
|
|
85
83
|
});
|
|
86
84
|
|
|
87
85
|
queryEl.on('keyup', function () {
|
|
88
|
-
if (!queryEl.val().length) {
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
86
|
if (queryTimeout) {
|
|
93
87
|
clearTimeout(queryTimeout);
|
|
94
88
|
}
|
|
@@ -112,6 +106,9 @@ $(document).ready(function () {
|
|
|
112
106
|
callback(this.getAttribute('data-url'), queryEl.val());
|
|
113
107
|
modal.modal('hide');
|
|
114
108
|
});
|
|
109
|
+
|
|
110
|
+
// Start with empty query
|
|
111
|
+
queryEl.trigger('keyup');
|
|
115
112
|
});
|
|
116
113
|
});
|
|
117
114
|
};
|
|
@@ -123,10 +120,14 @@ $(document).ready(function () {
|
|
|
123
120
|
], function (formatting, controls) {
|
|
124
121
|
if (selectionStart === selectionEnd) {
|
|
125
122
|
controls.insertIntoTextarea(textarea, '');
|
|
126
|
-
controls.updateTextareaSelection(
|
|
123
|
+
controls.updateTextareaSelection(
|
|
124
|
+
textarea, selectionStart + query.length + 4, selectionEnd + query.length + url.length + 4
|
|
125
|
+
);
|
|
127
126
|
} else {
|
|
128
127
|
var wrapDelta = controls.wrapSelectionInTextareaWith(textarea, '');
|
|
129
|
-
controls.updateTextareaSelection(
|
|
128
|
+
controls.updateTextareaSelection(
|
|
129
|
+
textarea, selectionEnd + 4 - wrapDelta[1], selectionEnd + url.length + 4 - wrapDelta[1]
|
|
130
|
+
);
|
|
130
131
|
}
|
|
131
132
|
});
|
|
132
133
|
};
|
|
@@ -12,6 +12,19 @@
|
|
|
12
12
|
<label for="key">API Key</label>
|
|
13
13
|
<input type="text" id="key" name="key" title="API Key" class="form-control" placeholder="API Key">
|
|
14
14
|
</div>
|
|
15
|
+
<div class="form-group">
|
|
16
|
+
<label for="contentFilter">Content Filter</label>
|
|
17
|
+
<select class="form-control" id="contentFilter" name="contentFilter">
|
|
18
|
+
<option value="off">Off</option>
|
|
19
|
+
<option value="low">Low</option>
|
|
20
|
+
<option value="medium" selected>Medium (default)</option>
|
|
21
|
+
<option value="high">High</option>
|
|
22
|
+
</select>
|
|
23
|
+
</div>
|
|
24
|
+
<div class="form-group">
|
|
25
|
+
<label for="limit">Limit results</label>
|
|
26
|
+
<input class="form-control" type="number" min="1" max="50" id="limit" placeholder="10" name="limit" />
|
|
27
|
+
</div>
|
|
15
28
|
</div>
|
|
16
29
|
</div>
|
|
17
30
|
</form>
|
package/websockets.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
const SocketPlugins = require.main.require('./src/socket.io/plugins');
|
|
4
4
|
SocketPlugins['tenor-gif'] = {};
|
|
5
5
|
|
|
6
6
|
module.exports.init = function () {
|
|
7
|
-
|
|
7
|
+
const main = module.parent.exports;
|
|
8
8
|
|
|
9
9
|
SocketPlugins['tenor-gif'].query = function (socket, data, callback) {
|
|
10
|
-
main.query(data.query
|
|
10
|
+
main.query(data.query).then((gifs) => {
|
|
11
|
+
callback(null, gifs);
|
|
12
|
+
}).catch(callback);
|
|
11
13
|
};
|
|
12
14
|
};
|
|
13
15
|
|