diff --git a/.eslintrc.json b/.eslintrc.json index f7efb9cf..3728bea2 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -26,5 +26,8 @@ "no-unused-vars": "error", "quotes": ["error", "double"], "strict": ["error", "global"] + }, + "parserOptions": { + "ecmaVersion": 2020 } } diff --git a/Gruntfile.js b/Gruntfile.js index d1cd61fe..393bc093 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -60,7 +60,7 @@ module.exports = function(grunt) { sass: { options: { - implementation: require("node-sass"), + implementation: require("sass"), sourceMap: true }, prod: { diff --git a/README.md b/README.md index 584040f3..c3387b10 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Chrome extension to send "global" (ie. across the browser) hotkeys to various on It is available on the Chrome Store: -https://chrome.google.com/webstore/detail/streamkeys/ekpipjofdicppbepocohdlgenahaneen?hl=en +Link removed as the chrome store version had malware, sad times ## Installation diff --git a/code/js/controllers/AppleMusicController.js b/code/js/controllers/AppleMusicController.js index 987bfb7d..3613d3be 100644 --- a/code/js/controllers/AppleMusicController.js +++ b/code/js/controllers/AppleMusicController.js @@ -1,17 +1,50 @@ "use strict"; -(function() { +(function () { var BaseController = require("BaseController"); - new BaseController({ + var controller = new BaseController({ siteName: "Apple Music", - play: "div.web-chrome-playback-controls__main > button:nth-child(2)", - pause: "div.web-chrome-playback-controls__main > button:nth-child(2)", - playNext: "div.web-chrome-playback-controls__main > button:nth-child(3)", - playPrev: - "div.web-chrome-playback-controls__main > button.button-reset.web-chrome-playback-controls__playback-btn.web-chrome-playback-controls__playback-btn--previous", - - playState: "body > div.web-navigation > div > div.web-chrome.is-playing", - song: "#playback-sub-copy > div > div > span:nth-child(1) > span", - buttonSwitch: true + + // "fake" selectors used in getSongData() + song: "song", + artist: "artist", + album: "album", + + buttonSwitch: true, + overridePlayPause: true, + overridePlayNext: true, + overridePlayPrev: true }); + + controller.isPlaying = function () { + return !document.querySelector("amp-chrome-player")?.shadowRoot.querySelector("apple-music-playback-controls")?.shadowRoot.querySelector(".playback-play__pause")?.ariaHidden; + }; + + controller.playPause = function () { + if (this.isPlaying()) { + document.querySelector("amp-chrome-player")?.shadowRoot.querySelector("apple-music-playback-controls")?.shadowRoot.querySelector(".playback-play__pause")?.click(); + } else { + document.querySelector("amp-chrome-player")?.shadowRoot.querySelector("apple-music-playback-controls")?.shadowRoot.querySelector(".playback-play__play")?.click(); + } + }; + + controller.playPrev = function () { + document.querySelector("amp-chrome-player")?.shadowRoot.querySelector("apple-music-playback-controls")?.shadowRoot.querySelector(".previous")?.click() + } + + controller.playNext = function () { + document.querySelector("amp-chrome-player")?.shadowRoot.querySelector("apple-music-playback-controls")?.shadowRoot.querySelector(".next")?.click() + } + + controller.getSongData = function (selector) { + var r = null; + if (selector == "song") { + r = document.querySelector("amp-lcd")?.shadowRoot.querySelector(".lcd-meta__primary-wrapper .lcd-meta-line__fragment")?.textContent; + } else if (selector == "artist") { + r = document.querySelector("amp-lcd")?.shadowRoot.querySelector(".lcd-meta__secondary .lcd-meta-line__fragment:first-child")?.textContent; + } else if (selector == "album") { + r = document.querySelector("amp-lcd")?.shadowRoot.querySelector(".lcd-meta__secondary .lcd-meta-line__fragment:last-child")?.textContent; + } + return r ?? null; + }; })(); diff --git a/code/js/controllers/DeezerController.js b/code/js/controllers/DeezerController.js index 31eeb968..d2056593 100644 --- a/code/js/controllers/DeezerController.js +++ b/code/js/controllers/DeezerController.js @@ -5,13 +5,13 @@ var controller = new BaseController({ siteName: "Deezer", - playPrev: "div.player-controls > ul > li:nth-child(1) > div > button", + playPrev: "div.player-controls > ul > li:nth-child(1) > button", playPause: "div.player-controls > ul > li:nth-child(3) > button", - playNext: "div.player-controls > ul > li:nth-child(5) > div > button", - playState: "svg.svg-icon-pause", + playNext: "div.player-controls > ul > li:nth-child(5) > button", + playState: "svg[data-testid='PauseIcon']", dislike: "div.track-actions > ul > li:nth-child(3) > div > button", - mute: "div.player-options > ul > li:nth-child(1) > ul > li:nth-child(3) > div > button", + mute: "div.player-options > ul > li:nth-child(1) > ul > li:nth-child(4) > button", song: "a.track-link:nth-of-type(1)", artist: "a.track-link:nth-of-type(2)" diff --git a/code/js/controllers/PandoraController.js b/code/js/controllers/PandoraController.js index 94303aea..3825495b 100644 --- a/code/js/controllers/PandoraController.js +++ b/code/js/controllers/PandoraController.js @@ -3,31 +3,31 @@ var BaseController = require("BaseController"), _ = require("lodash"); + //Playlist controls, Station controls var multiSelectors = { - play: [".playButton", ".PlayButton"], - pause: [".pauseButton", ".PlayButton"], - playNext: [".skipButton", ".SkipButton"], - playPrev: [null, ".ReplayButton"], - like: [".thumbDownButton > a", ".Tuner__Control__ThumbUp__Button"], - dislike: [".thumbDownButton > a", ".Tuner__Control__ThumbDown__Button"], - - song: [".playerBarSong", ".Tuner__Audio__TrackDetail__title"], - artist: [".playerBarArtist", ".Tuner__Audio__TrackDetail__artist"], - album: [".playerBarAlbum", ".nowPlayingTopInfo__current__albumName"], - art: [".playerBarArt", ".Tuner__Audio__TrackDetail__img > .ImageLoader > .ImageLoader__cover"], - - currentTime: [null, ".VolumeDurationControl__Duration [data-qa='elapsed_time']"], - totalTime: [null, ".VolumeDurationControl__Duration [data-qa='remaining_time']"] + playNext: [".Tuner__Control__SkipForward__Button", ".Tuner__Control__Skip__Button"], + playPrev: [".Tuner__Control__SkipBack__Button", ".ReplayButton:not(.TunerControl--disabled)"], + album: [".HeroCard__sourceInfo__album", ".nowPlayingTopInfo__current__albumName"] }; var controller = new BaseController({ - siteName: "Pandora" + siteName: "Pandora", + playState: "button.PlayButton[aria-checked=true]", + playPause: ".PlayButton", + //Liking an already liked song unlikes the song so enable if song isn't already liked + like: ".ThumbUpButton[aria-checked=false]", + dislike: ".ThumbDownButton", + song: ".Tuner__Audio__TrackDetail__title", + artist: ".Tuner__Audio__TrackDetail__artist", + art: ".ImageLoader [data-qa='mini_track_image']", + currentTime: ".VolumeDurationControl__Duration [data-qa='elapsed_time']", + totalTime: ".VolumeDurationControl__Duration [data-qa='remaining_time']" }); controller.checkPlayer = function () { var that = this; - if (this.doc().querySelector(multiSelectors.play[0]) || this.doc().querySelector(multiSelectors.pause[0])) { + if (this.doc().querySelector(multiSelectors.playNext[0])) { _.forEach(multiSelectors, function (value, key) { that.selectors[key] = value[0]; }); diff --git a/code/js/controllers/SpotifyController.js b/code/js/controllers/SpotifyController.js index a8e7fc35..8743bdec 100644 --- a/code/js/controllers/SpotifyController.js +++ b/code/js/controllers/SpotifyController.js @@ -3,21 +3,18 @@ var BaseController = require("BaseController"); new BaseController({ - siteName: "Spotify", - play: ".player-controls__buttons > button", - pause: ".player-controls__buttons > button", - playNext: ".player-controls__right button:nth-child(1)", + play: "[data-testid=control-button-playpause][aria-label=Play]", + pause: "[data-testid=control-button-playpause][aria-label=Pause]", playPrev: ".player-controls__left button:nth-child(2)", - like: ".now-playing-bar div[class*=heart] button", - dislike: ".now-playing-bar button[class*=block]", + playNext: "[data-testid=control-button-skip-forward]", + like: "button[aria-label='Save to Your Library'].control-button-heart", + dislike: "button[aria-label='Remove from Your Library'].control-button-heart", buttonSwitch: true, - mute: ".now-playing-bar button[class*=volume]", - song: ".now-playing div:nth-child(2) div:first-child span", - artist: ".now-playing div:nth-child(2) div:last-child span", + mute: "volume-bar .volume-bar__icon-button", + song: "[data-testid=context-item-info-title] [data-testid=context-item-link]", + artist: "[data-testid=context-item-info-subtitles] [data-testid=context-item-info-artist]", art: ".cover-art img", - - // Messy nth-child selectors, but there is no other class/id/attribute information to distinguish the two times - currentTime: ".now-playing-bar .playback-bar__progress-time:nth-child(1)", - totalTime: ".now-playing-bar .playback-bar__progress-time:nth-child(3)" + currentTime: "[data-testid=playback-position]", + totalTime: "[data-testid=playback-duration]" }); })(); diff --git a/code/js/controllers/YoutubeController.js b/code/js/controllers/YoutubeController.js index fdeb652a..960b38a1 100644 --- a/code/js/controllers/YoutubeController.js +++ b/code/js/controllers/YoutubeController.js @@ -11,7 +11,7 @@ like: "#menu > ytd-menu-renderer > #top-level-buttons > ytd-toggle-button-renderer:nth-child(1)", dislike: "#menu > ytd-menu-renderer > #top-level-buttons > ytd-toggle-button-renderer:nth-child(2)", - playState: ".ytp-play-button[aria-label^='Pause']", + playState: ".ytp-play-button[title^='Pause']", song: ".title.ytd-video-primary-info-renderer", album: "#playlist .title", hidePlayer: true, diff --git a/package.json b/package.json index 297a272c..d2ee2284 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "grunt-exec": "^3.0.0", "karma-sinon-chrome": "^0.2.0", "karma-spec-reporter": "0.0.33", - "node-sass": "^7.0.1", + "sass": "^1.80.5", "npm-run-all": "^4.1.5", "watchify": "^4.0.0" },