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 CHANGED
@@ -1,139 +1,3 @@
1
1
  {
2
- "extends": "airbnb-base",
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
- var controllers = require('./lib/controllers');
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
- var request = require('request');
5
+ const controllers = require('./lib/controllers');
6
+ const websockets = require('./websockets');
9
7
 
10
- var plugin = {
11
- _settings: {
12
- key: null,
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 = function (params, callback) {
17
- var router = params.router;
18
- var hostMiddleware = params.middleware;
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 = function (payload, callback) {
50
- if (plugin._settings.key) {
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
- callback(null, payload);
46
+ return payload;
55
47
  };
56
48
 
57
- plugin.query = function (query, callback) {
58
- request({
59
- url: 'https://tenor.googleapis.com/v2/search?q=' + query + '&key=' + plugin._settings.key,
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
- module.exports = plugin;
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.0.0",
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": "^1.6.0 || ^2.0.0"
24
+ "compatibility": "^2.4.0"
25
25
  },
26
26
  "dependencies": {
27
27
  "@commitlint/cli": "^9.1.2",
28
- "eslint": "^7.7.0",
29
- "lint-staged": "^10.0.9",
30
- "request": "^2.88.0"
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": "^12.1.0",
37
- "eslint-plugin-import": "^2.8.0",
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
  }
@@ -0,0 +1,3 @@
1
+ {
2
+ "extends": "nodebb/public"
3
+ }
@@ -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
- message: 'Please reload your NodeBB to apply these settings',
18
- clickfn: function () {
19
- socket.emit('admin.reload');
20
- },
15
+ timeout: 5000,
21
16
  });
22
17
  });
23
18
  });
@@ -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, '![' + query + '](' + url + ')');
126
- controls.updateTextareaSelection(textarea, selectionStart + query.length + 4, selectionEnd + query.length + url.length + 4);
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, '![', '](' + url + ')');
129
- controls.updateTextareaSelection(textarea, selectionEnd + 4 - wrapDelta[1], selectionEnd + url.length + 4 - wrapDelta[1]);
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
- var SocketPlugins = require.main.require('./src/socket.io/plugins');
3
+ const SocketPlugins = require.main.require('./src/socket.io/plugins');
4
4
  SocketPlugins['tenor-gif'] = {};
5
5
 
6
6
  module.exports.init = function () {
7
- var main = module.parent.exports;
7
+ const main = module.parent.exports;
8
8
 
9
9
  SocketPlugins['tenor-gif'].query = function (socket, data, callback) {
10
- main.query(data.query, callback);
10
+ main.query(data.query).then((gifs) => {
11
+ callback(null, gifs);
12
+ }).catch(callback);
11
13
  };
12
14
  };
13
15