diff --git a/package-lock.json b/package-lock.json index 69e9abef..3d1219e1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "frankerfacez", - "version": "4.17.0", + "version": "4.17.10", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1481,39 +1481,6 @@ "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", "dev": true }, - "cacache": { - "version": "11.3.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.3.tgz", - "integrity": "sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA==", - "dev": true, - "requires": { - "bluebird": "^3.5.5", - "chownr": "^1.1.1", - "figgy-pudding": "^3.5.1", - "glob": "^7.1.4", - "graceful-fs": "^4.1.15", - "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.3", - "ssri": "^6.0.1", - "unique-filename": "^1.1.1", - "y18n": "^4.0.0" - }, - "dependencies": { - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -1924,12 +1891,12 @@ "dev": true }, "copy-webpack-plugin": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-5.0.4.tgz", - "integrity": "sha512-YBuYGpSzoCHSSDGyHy6VJ7SHojKp6WHT4D7ItcQFNAYx2hrwkMe56e97xfVR0/ovDuMTrMffXUiltvQljtAGeg==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-5.1.1.tgz", + "integrity": "sha512-P15M5ZC8dyCjQHWwd4Ia/dm0SgVvZJMYeykVIVYXbGyqO4dWB5oyPHp9i7wjwo5LhtlhKbiBCdS2NvM07Wlybg==", "dev": true, "requires": { - "cacache": "^11.3.3", + "cacache": "^12.0.3", "find-cache-dir": "^2.1.0", "glob-parent": "^3.1.0", "globby": "^7.1.1", @@ -1937,10 +1904,59 @@ "loader-utils": "^1.2.3", "minimatch": "^3.0.4", "normalize-path": "^3.0.0", - "p-limit": "^2.2.0", + "p-limit": "^2.2.1", "schema-utils": "^1.0.0", - "serialize-javascript": "^1.7.0", + "serialize-javascript": "^2.1.2", "webpack-log": "^2.0.0" + }, + "dependencies": { + "cacache": { + "version": "12.0.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.3.tgz", + "integrity": "sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "p-limit": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", + "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "serialize-javascript": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", + "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==", + "dev": true + } } }, "core-util-is": { @@ -2327,8 +2343,9 @@ } }, "displacejs": { - "version": "github:sirstendec/displace#38306dedc200e980fefe3a9b978700cc6d1f127b", - "from": "github:sirstendec/displace" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/displacejs/-/displacejs-1.4.0.tgz", + "integrity": "sha512-uWe6VmPM95lqH8QWxVb+pQ30laahTgvnzCI+bTIOc/cNhd9zSWECdYW7mpWAIEoGDH+CA3HoQgos2lcOQ7fFjw==" }, "dns-equal": { "version": "1.0.0", @@ -4445,6 +4462,12 @@ "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", "dev": true }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -7175,12 +7198,6 @@ } } }, - "serialize-javascript": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.7.0.tgz", - "integrity": "sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA==", - "dev": true - }, "serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", @@ -7929,48 +7946,87 @@ "inherits": "2" } }, - "terser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.0.0.tgz", - "integrity": "sha512-dOapGTU0hETFl1tCo4t56FN+2jffoKyER9qBGoUFyZ6y7WLoKT0bF+lAYi6B6YsILcGF3q1C2FBh8QcKSCgkgA==", - "dev": true, - "requires": { - "commander": "^2.19.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.10" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, "terser-webpack-plugin": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.3.0.tgz", - "integrity": "sha512-W2YWmxPjjkUcOWa4pBEv4OP4er1aeQJlSo2UhtCFQCuRXEHjOFscO8VyWHj9JLlA0RzQb8Y2/Ta78XZvT54uGg==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz", + "integrity": "sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA==", "dev": true, "requires": { - "cacache": "^11.3.2", - "find-cache-dir": "^2.0.0", + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", "is-wsl": "^1.1.0", - "loader-utils": "^1.2.3", "schema-utils": "^1.0.0", - "serialize-javascript": "^1.7.0", + "serialize-javascript": "^2.1.2", "source-map": "^0.6.1", - "terser": "^4.0.0", - "webpack-sources": "^1.3.0", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", "worker-farm": "^1.7.0" }, "dependencies": { + "cacache": { + "version": "12.0.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.3.tgz", + "integrity": "sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "serialize-javascript": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", + "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==", + "dev": true + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true + }, + "terser": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.4.3.tgz", + "integrity": "sha512-0ikKraVtRDKGzHrzkCv5rUNDzqlhmhowOBqC0XqUHFpW+vJ45+20/IFBcebwKfiS2Z9fJin6Eo+F1zLZsxi8RA==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + } + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } } } }, diff --git a/package.json b/package.json index add0bec8..e0c6d439 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "frankerfacez", "author": "Dan Salvato LLC", - "version": "4.17.10", + "version": "4.17.11", "description": "FrankerFaceZ is a Twitch enhancement suite.", "license": "Apache-2.0", "scripts": { @@ -34,7 +34,7 @@ "babel-eslint": "^10.0.2", "babel-loader": "^8.0.6", "clean-webpack-plugin": "^3.0.0", - "copy-webpack-plugin": "^5.0.4", + "copy-webpack-plugin": "^5.1.1", "cross-env": "^5.2.0", "css-loader": "^3.1.0", "eslint": "^6.1.0", @@ -65,7 +65,7 @@ "@ffz/icu-msgparser": "^1.0.2", "crypto-js": "^3.1.9-1", "dayjs": "^1.8.17", - "displacejs": "github:sirstendec/displace", + "displacejs": "^1.4.0", "emoji-regex": "^8.0.0", "file-saver": "^2.0.1", "graphql": "^14.4.2", diff --git a/src/modules/main_menu/components/filter-editor.vue b/src/modules/main_menu/components/filter-editor.vue index f3309ac7..b6598825 100644 --- a/src/modules/main_menu/components/filter-editor.vue +++ b/src/modules/main_menu/components/filter-editor.vue @@ -204,11 +204,13 @@ export default { if ( ! key ) return; - this.editing.push({ + const out = { id: generateUUID(), type: key, data: maybe_call(type.default, type) - }); + }; + + this.editing.push(out); }, updateRule(id, data) { diff --git a/src/modules/metadata.jsx b/src/modules/metadata.jsx index 360eb7a1..d9bcd748 100644 --- a/src/modules/metadata.jsx +++ b/src/modules/metadata.jsx @@ -111,8 +111,6 @@ export default class Metadata extends Module { subtitle: () => this.i18n.t('metadata.uptime.subtitle', 'Uptime'), tooltip(data) { - console.log('tool-tip'); - if ( ! data.created ) return null; diff --git a/src/settings/components/title.vue b/src/settings/components/title.vue new file mode 100644 index 00000000..ccb073f2 --- /dev/null +++ b/src/settings/components/title.vue @@ -0,0 +1,109 @@ + + + \ No newline at end of file diff --git a/src/settings/filters.js b/src/settings/filters.js index 41a0a257..5f95af4a 100644 --- a/src/settings/filters.js +++ b/src/settings/filters.js @@ -4,8 +4,12 @@ // Profile Filters for Settings // ============================================================================ +import safety from 'safe-regex'; + +import {glob_to_regex, escape_regex} from 'utilities/object'; import {createTester} from 'utilities/filtering'; + // Logical Components export const Invert = { @@ -282,4 +286,44 @@ export const Category = { }), editor: () => import(/* webpackChunkName: 'main-menu' */ './components/category.vue') -} \ No newline at end of file +} + +export const Title = { + createTest(config = {}) { + const mode = config.mode; + let title = config.title; + + if ( ! title || ! mode ) + return () => false; + + if ( mode === 'text' ) + title = escape_regex(title); + else if ( mode === 'glob' ) + title = glob_to_regex(title); + else if ( mode !== 'raw' ) + return () => false; + + if ( ! safety(title) ) + return () => false; + + let regex; + try { + regex = new RegExp(title, `g${config.sensitive ? '' : 'i'}`); + } catch(err) { + return () => false; + } + + return ctx => ctx.title && regex.test(ctx.title) + }, + + title: 'Current Title', + i18n: 'settings.filter.title', + + default: () => ({ + title: '', + mode: 'text', + sensitive: false + }), + + editor: () => import(/* webpackChunkName: 'main-menu' */ './components/title.vue') +}; \ No newline at end of file diff --git a/src/sites/twitch-twilight/modules/channel.js b/src/sites/twitch-twilight/modules/channel.js index b096893a..8b160963 100644 --- a/src/sites/twitch-twilight/modules/channel.js +++ b/src/sites/twitch-twilight/modules/channel.js @@ -127,12 +127,14 @@ export default class Channel extends Module { channelID: null, channelColor: null, category: null, - categoryID: null + categoryID: null, + title: null }); }); this.ChannelPage.on('update', inst => { - const category = get('state.video.game', inst) || get('state.clip.game', inst) || get('state.channel.broadcastSettings.game', inst); + const category = get('state.video.game', inst) || get('state.clip.game', inst) || get('state.channel.stream.game', inst) || get('state.channel.broadcastSettings.game', inst), + title = get('state.video.title', inst) || get('state.clip.title', inst) || get('state.channel.stream.title', inst) || get('state.channel.broadcastSettings.title', inst); const color = get('state.primaryColorHex', inst); this.updateChannelColor(color); @@ -142,7 +144,8 @@ export default class Channel extends Module { channelID: get('state.channel.id', inst), channelColor: color, category: category?.name, - categoryID: category?.id + categoryID: category?.id, + title }); if ( this.settings.get('channel.hosting.enable') || has(inst.state, 'hostMode') || has(inst.state, 'hostedChannel') ) @@ -174,7 +177,8 @@ export default class Channel extends Module { clip = inst.state.clip, video = inst.state.video, - category = video?.game || clip?.game || channel?.stream?.game || channel?.broadcastSettings?.game; + category = video?.game || clip?.game || channel?.stream?.game || channel?.broadcastSettings?.game, + title = video?.title || clip?.title || channel?.stream?.title || channel?.broadcastSettings?.title || null; const color = inst.state?.primaryColorHex; this.updateChannelColor(color); @@ -184,7 +188,8 @@ export default class Channel extends Module { channelID: inst.state.channel?.id, channelColor: color, category: category?.name, - categoryID: category?.id + categoryID: category?.id, + title }); } @@ -195,7 +200,8 @@ export default class Channel extends Module { channelID: null, category: null, categoryID: null, - channelColor: null + channelColor: null, + title: null }); } @@ -203,7 +209,8 @@ export default class Channel extends Module { onChannelMounted(inst) { this.wrapChannelPage(inst); - const category = get('state.video.game', inst) || get('state.clip.game', inst) || get('state.channel.broadcastSettings.game', inst); + const category = get('state.video.game', inst) || get('state.clip.game', inst) || get('state.channel.stream.game', inst) || get('state.channel.broadcastSettings.game', inst), + title = get('state.video.title', inst) || get('state.clip.title', inst) || get('state.channel.stream.title', inst) || get('state.channel.broadcastSettings.title', inst) || null; const color = get('state.primaryColorHex', inst); this.updateChannelColor(color); @@ -213,7 +220,8 @@ export default class Channel extends Module { channelID: get('state.channel.id', inst), channelColor: color, category: category?.name, - categoryID: category?.id + categoryID: category?.id, + title }); } diff --git a/src/sites/twitch-twilight/modules/menu_button.jsx b/src/sites/twitch-twilight/modules/menu_button.jsx index 027d35d4..f2be8470 100644 --- a/src/sites/twitch-twilight/modules/menu_button.jsx +++ b/src/sites/twitch-twilight/modules/menu_button.jsx @@ -145,6 +145,9 @@ export default class MenuButton extends SiteModule { if ( typeof val === 'number' ) return this.i18n.formatNumber(val); + if ( val == null && this.has_new ) + return this.i18n.formatNumber(this._new_settings); + return val; } @@ -300,7 +303,7 @@ export default class MenuButton extends SiteModule { {this.has_update && (
{this.i18n.t('site.menu_button.update-desc', 'There is an update available. Please refresh your page.')}
)} - {this.has_new && (
+ {this._new_settings > 0 && (
{this.i18n.t('site.menu_button.new-desc', 'There {count,plural,one {is one new setting} other {are # new settings}}.', {count: this._new_settings})}
)} {this.has_strings && (
diff --git a/src/sites/twitch-twilight/styles/menu_button.scss b/src/sites/twitch-twilight/styles/menu_button.scss index 226e3724..db8583bf 100644 --- a/src/sites/twitch-twilight/styles/menu_button.scss +++ b/src/sites/twitch-twilight/styles/menu_button.scss @@ -6,6 +6,7 @@ .ffz-menu__pill { top: -.5rem; right: 0; + pointer-events: none; } .ffz-menu__extra-pill { diff --git a/src/utilities/data/poll-archive.gql b/src/utilities/data/poll-archive.gql new file mode 100644 index 00000000..c307aa52 --- /dev/null +++ b/src/utilities/data/poll-archive.gql @@ -0,0 +1,8 @@ +mutation FFZ_ArchivePoll($id: ID!) { + archivePoll(input: {pollID: $id}) { + poll { + id + status + } + } +} \ No newline at end of file diff --git a/src/utilities/data/poll-create.gql b/src/utilities/data/poll-create.gql new file mode 100644 index 00000000..9dd56e8a --- /dev/null +++ b/src/utilities/data/poll-create.gql @@ -0,0 +1,12 @@ +mutation FFZ_CreatePoll($input: CreatePollInput!) { + createPoll(input: $input) { + poll { + id + status + choices { + id + title + } + } + } +} \ No newline at end of file diff --git a/src/utilities/data/poll-get.gql b/src/utilities/data/poll-get.gql new file mode 100644 index 00000000..21e8ca48 --- /dev/null +++ b/src/utilities/data/poll-get.gql @@ -0,0 +1,25 @@ +query FFZ_FetchPoll($id: ID!) { + poll(id: $id) { + id + status + title + ownedBy { + id + login + displayName + } + endedAt + startedAt + totalVoters + choices { + id + title + votes { + id + base + bits + total + } + } + } +} \ No newline at end of file diff --git a/src/utilities/data/poll-terminate.gql b/src/utilities/data/poll-terminate.gql new file mode 100644 index 00000000..b544ba7d --- /dev/null +++ b/src/utilities/data/poll-terminate.gql @@ -0,0 +1,8 @@ +mutation FFZ_TerminatePoll($id: ID!) { + terminatePoll(input: {pollID: $id}) { + poll { + id + status + } + } +} \ No newline at end of file diff --git a/src/utilities/twitch-data.js b/src/utilities/twitch-data.js index eed05e32..e6f37646 100644 --- a/src/utilities/twitch-data.js +++ b/src/utilities/twitch-data.js @@ -89,6 +89,23 @@ export default class TwitchData extends Module { return this.apollo.client.query(thing); } + mutate(mutation, variables, options) { + let thing; + if ( ! variables && ! options && mutation.mutation ) + thing = mutation; + else { + thing = { + mutation, + variables + }; + + if ( options ) + thing = Object.assign(thing, options); + } + + return this.apollo.client.mutate(thing); + } + get languageCode() { const session = this.site.getSession(); return session && session.languageCode || 'en' @@ -130,7 +147,7 @@ export default class TwitchData extends Module { async getMatchingCategories(query) { const data = await this.queryApollo( - require('./data/search-category.gql'), + await import(/* webpackChunkName: 'queries' */ './data/search-category.gql'), { query } ); @@ -143,7 +160,7 @@ export default class TwitchData extends Module { async getCategory(id, name) { const data = await this.queryApollo( - require('./data/category-fetch.gql'), + await import(/* webpackChunkName: 'queries' */ './data/category-fetch.gql'), { id, name } ); @@ -157,7 +174,7 @@ export default class TwitchData extends Module { async getMatchingUsers(query) { const data = await this.queryApollo( - require('./data/search-user.gql'), + await import(/* webpackChunkName: 'queries' */ './data/search-user.gql'), { query } ); @@ -170,7 +187,7 @@ export default class TwitchData extends Module { async getUser(id, login) { const data = await this.queryApollo( - require('./data/user-fetch.gql'), + await import(/* webpackChunkName: 'queries' */ './data/user-fetch.gql'), { id, login } ); @@ -179,7 +196,7 @@ export default class TwitchData extends Module { async getLastBroadcast(id, login) { const data = await this.queryApollo( - require('./data/last-broadcast.gql'), + await import(/* webpackChunkName: 'queries' */ './data/last-broadcast.gql'), { id, login } ); @@ -192,7 +209,7 @@ export default class TwitchData extends Module { async getBroadcastID(id, login) { const data = await this.queryApollo({ - query: require('./data/broadcast-id.gql'), + query: await import(/* webpackChunkName: 'queries' */ './data/broadcast-id.gql'), variables: { id, login @@ -203,6 +220,77 @@ export default class TwitchData extends Module { } + // ======================================================================== + // Polls + // ======================================================================== + + async getPoll(poll_id) { + const data = await this.queryApollo({ + query: await import(/* webpackChunkName: 'queries' */ './data/poll-get.gql'), + variables: { + id: poll_id + } + }); + + return get('data.poll', data); + } + + async createPoll(channel_id, title, choices, options = {}) { + if ( typeof title !== 'string' ) + throw new TypeError('title must be string'); + + if ( ! Array.isArray(choices) || choices.some(x => typeof x !== 'string') ) + throw new TypeError('choices must be array of strings'); + + let bits = options.bits || 0, + duration = options.duration || 60; + if ( typeof bits !== 'number' || bits < 0 ) + bits = 0; + if ( typeof duration !== 'number' || duration < 0 ) + duration = 60; + + const data = await this.mutate({ + mutation: await import(/* webpackChunkName: 'queries' */ './data/poll-create.gql'), + variables: { + input: { + bitsCost: bits, + bitsVoting: bits > 0, + choices: choices.map(x => ({title: x})), + durationSeconds: duration, + ownedBy: `${channel_id}`, + subscriberMultiplier: options.subscriberMultiplier || false, + subscriberOnly: options.subscriberOnly || false, + title + } + } + }); + + return get('data.createPoll.poll', data); + } + + async archivePoll(poll_id) { + const data = await this.mutate({ + mutation: await import(/* webpackChunkName: 'queries' */ './data/poll-archive.gql'), + variables: { + id: poll_id + } + }); + + return get('data.archivePoll.poll', data); + } + + async terminatePoll(poll_id) { + const data = await this.mutate({ + mutation: await import(/* webpackChunkName: 'queries' */ './data/poll-terminate.gql'), + variables: { + id: poll_id + } + }); + + return get('data.terminatePoll.poll', data); + } + + // ======================================================================== // Stream Up-Type (Uptime and Type, for Directory Purposes) // ======================================================================== @@ -242,7 +330,7 @@ export default class TwitchData extends Module { try { const data = await this.queryApollo({ - query: require('./data/stream-fetch.gql'), + query: await import(/* webpackChunkName: 'queries' */ './data/stream-fetch.gql'), variables: { ids: ids.length ? ids : null, logins: logins.length ? logins : null @@ -376,7 +464,7 @@ export default class TwitchData extends Module { try { const data = await this.queryApollo( - require('./data/tags-fetch.gql'), + await import(/* webpackChunkName: 'queries' */ './data/tags-fetch.gql'), { ids } @@ -467,7 +555,7 @@ export default class TwitchData extends Module { async getTopTags(limit = 50) { const data = await this.queryApollo( - require('./data/tags-top.gql'), + await import(/* webpackChunkName: 'queries' */ './data/tags-top.gql'), {limit} );