2020-07-19 16:59:08 +02:00
//META{"name":"SpotifyControls","authorId":"278543574059057154","invite":"Jx3TjNS","donate":"https://www.paypal.me/MircoWittrien","patreon":"https://www.patreon.com/MircoWittrien","website":"https://github.com/mwittrien/BetterDiscordAddons/tree/master/Plugins/SpotifyControls","source":"https://raw.githubusercontent.com/mwittrien/BetterDiscordAddons/master/Plugins/SpotifyControls/SpotifyControls.plugin.js"}*//
var SpotifyControls = ( _ => {
2020-07-19 17:21:45 +02:00
var controls , lastSong , stopTime , updateInterval ;
2020-07-19 16:59:08 +02:00
2020-07-21 15:08:40 +02:00
var settings = { } ;
2020-07-19 16:59:08 +02:00
const SpotifyControlsComponent = class SpotifyControls extends BdApi . React . Component {
componentDidMount ( ) {
controls = this ;
}
request ( socket , device , type , song , data ) {
return new Promise ( callback => {
BDFDB . LibraryRequires . request ( {
url : ` https://api.spotify.com/v1/me/player/ ${ type } ` ,
method : type == "next" || type == "previous" ? "POST" : "PUT" ,
query : { device _id : device . id } ,
headers : {
authorization : ` Bearer ${ socket . accessToken } `
} ,
2020-07-19 17:54:47 +02:00
body : JSON . stringify ( Object . assign ( { } , data ) )
2020-07-19 16:59:08 +02:00
} , ( error , response , result ) => {
2020-07-19 17:58:17 +02:00
if ( response . statusCode == 401 ) {
2020-07-19 16:59:08 +02:00
BDFDB . LibraryModules . SpotifyUtils . getAccessToken ( socket . accountId ) . then ( promiseResult => {
let newSocketDevice = BDFDB . LibraryModules . SpotifyTrackUtils . getActiveSocketAndDevice ( ) ;
this . request ( newSocketDevice . socket , newSocketDevice . device , type , song , data ) . then ( _ => {
callback ( error , response , result ) ;
} ) ;
} ) ;
}
else callback ( error , response , result ) ;
} ) ;
} ) ;
}
render ( ) {
let socketDevice = BDFDB . LibraryModules . SpotifyTrackUtils . getActiveSocketAndDevice ( ) ;
2020-07-19 17:21:45 +02:00
if ( this . props . song ) {
lastSong = this . props . song ;
stopTime = null ;
}
else if ( ! stopTime && lastSong ) stopTime = new Date ( ) ;
2020-07-19 16:59:08 +02:00
return ! socketDevice || ! lastSong ? null : BDFDB . ReactUtils . createElement ( "div" , {
2020-07-21 15:08:40 +02:00
className : BDFDB . DOMUtils . formatClassName ( BDFDB . disCN . _spotifycontrolscontainer , settings . addTimeline && BDFDB . disCN . _spotifycontrolscontainerwithtimeline ) ,
2020-07-19 16:59:08 +02:00
children : [
BDFDB . ReactUtils . createElement ( "div" , {
className : BDFDB . disCN . _spotifycontrolscontainerinner ,
children : [
BDFDB . ReactUtils . createElement ( "img" , {
className : BDFDB . disCN . _spotifycontrolscover ,
src : BDFDB . LibraryModules . AssetUtils . getAssetImage ( lastSong . application _id , lastSong . assets . large _image , [ 128 , 128 ] )
} ) ,
BDFDB . ReactUtils . createElement ( "div" , {
className : BDFDB . disCN . _spotifycontrolsdetails ,
children : [
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . TextElement , {
className : BDFDB . disCN . _spotifycontrolssong ,
children : BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . TextScroller , {
children : lastSong . details
} )
} ) ,
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . TextElement , {
className : BDFDB . disCNS . subtext + BDFDB . disCN . _spotifycontrolsinterpret ,
color : BDFDB . LibraryComponents . TextElement . Colors . CUSTOM ,
size : BDFDB . LibraryComponents . TextElement . Sizes . SIZE _12 ,
children : BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . TextScroller , {
children : BDFDB . LanguageUtils . LanguageStringsFormat ( "USER_ACTIVITY_LISTENING_ARTISTS" , lastSong . state )
} )
} )
]
} ) ,
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . TooltipContainer , {
text : socketDevice . device . is _restricted ? "Can not control Spotify while playing on restricted device" : null ,
tooltipConfig : { color : "red" } ,
children : BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . Flex , {
grow : 0 ,
children : [
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . Button , {
className : BDFDB . DOMUtils . formatClassName ( BDFDB . disCN . accountinfobutton , ! socketDevice . device . is _restricted ? BDFDB . disCN . accountinfobuttonenabled : BDFDB . disCN . accountinfobuttondisabled ) ,
style : { fontFamily : "glue1-spoticon" } ,
look : BDFDB . LibraryComponents . Button . Looks . BLANK ,
size : BDFDB . LibraryComponents . Button . Sizes . NONE ,
children : "" ,
onClick : socketDevice . device . is _restricted ? _ => { } : _ => {
this . request ( socketDevice . socket , socketDevice . device , "previous" ) ;
}
} ) ,
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . Button , {
className : BDFDB . DOMUtils . formatClassName ( BDFDB . disCN . accountinfobutton , ! socketDevice . device . is _restricted ? BDFDB . disCN . accountinfobuttonenabled : BDFDB . disCN . accountinfobuttondisabled ) ,
style : { fontFamily : "glue1-spoticon" } ,
look : BDFDB . LibraryComponents . Button . Looks . BLANK ,
size : BDFDB . LibraryComponents . Button . Sizes . NONE ,
children : this . props . song ? "" : "" ,
onClick : socketDevice . device . is _restricted ? _ => { } : _ => {
if ( this . props . song ) this . request ( socketDevice . socket , socketDevice . device , "pause" ) ;
else this . request ( socketDevice . socket , socketDevice . device , "play" , lastSong ) ;
}
} ) ,
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . Button , {
className : BDFDB . DOMUtils . formatClassName ( BDFDB . disCN . accountinfobutton , ! socketDevice . device . is _restricted ? BDFDB . disCN . accountinfobuttonenabled : BDFDB . disCN . accountinfobuttondisabled ) ,
style : { fontFamily : "glue1-spoticon" } ,
look : BDFDB . LibraryComponents . Button . Looks . BLANK ,
size : BDFDB . LibraryComponents . Button . Sizes . NONE ,
children : "" ,
onClick : socketDevice . device . is _restricted ? _ => { } : _ => {
this . request ( socketDevice . socket , socketDevice . device , "next" ) ;
}
} )
]
} )
} )
]
} ) ,
2020-07-21 15:08:40 +02:00
settings . addTimeline && BDFDB . ReactUtils . createElement ( SpotifyControlsTimelineComponent , {
2020-07-19 17:14:41 +02:00
song : lastSong ,
running : ! ! this . props . song
2020-07-19 16:59:08 +02:00
} )
2020-07-21 15:08:40 +02:00
] . filter ( n => n )
2020-07-19 16:59:08 +02:00
} ) ;
}
} ;
const SpotifyControlsTimelineComponent = class SpotifyControlsTimeline extends BdApi . React . Component {
componentDidMount ( ) {
BDFDB . TimeUtils . clear ( updateInterval ) ;
updateInterval = BDFDB . TimeUtils . interval ( _ => {
if ( ! this . updater || typeof this . updater . isMounted != "function" || ! this . updater . isMounted ( this ) ) BDFDB . TimeUtils . clear ( updateInterval ) ;
2020-07-19 17:14:41 +02:00
else if ( this . props . running ) {
2020-07-21 15:12:43 +02:00
let song = BDFDB . LibraryModules . SpotifyTrackUtils . getActivity ( false ) ;
2020-07-19 17:10:13 +02:00
if ( ! song ) BDFDB . ReactUtils . forceUpdate ( controls ) ;
2020-07-19 17:14:41 +02:00
else if ( this . props . running ) BDFDB . ReactUtils . forceUpdate ( this ) ;
2020-07-19 17:10:13 +02:00
}
2020-07-19 16:59:08 +02:00
} , 1000 ) ;
}
formatTime ( time ) {
let seconds = Math . floor ( ( time / 1000 ) % 60 ) ;
let minutes = Math . floor ( ( time / ( 1000 * 60 ) ) % 60 ) ;
let hours = Math . floor ( ( time / ( 1000 * 60 * 60 ) ) % 24 ) ;
return ` ${ hours > 0 ? hours + ":" : "" } ${ hours > 0 && minutes < 10 ? "0" + minutes : minutes } : ${ seconds < 10 ? "0" + seconds : seconds } `
}
render ( ) {
let maxTime = this . props . song . timestamps . end - this . props . song . timestamps . start ;
2020-07-19 17:21:45 +02:00
let currentTime = ( ! this . props . running && stopTime ? stopTime : new Date ( ) ) - this . props . song . timestamps . start ;
2020-07-19 17:10:13 +02:00
currentTime = currentTime > maxTime ? maxTime : currentTime ;
2020-07-19 16:59:08 +02:00
return BDFDB . ReactUtils . createElement ( "div" , {
2020-07-21 15:15:26 +02:00
className : BDFDB . disCN . _spotifycontrolstimeline ,
2020-07-19 16:59:08 +02:00
children : [
BDFDB . ReactUtils . createElement ( "div" , {
className : BDFDB . disCN . _spotifycontrolsbar ,
children : BDFDB . ReactUtils . createElement ( "div" , {
className : BDFDB . disCN . _spotifycontrolsbarfill ,
style : { width : ` ${ currentTime / maxTime * 100 } % ` }
} )
} ) ,
BDFDB . ReactUtils . createElement ( "div" , {
className : BDFDB . disCN . _spotifycontrolsbartext ,
children : [
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . TextElement , {
className : BDFDB . disCN . height12 ,
size : BDFDB . LibraryComponents . TextElement . Sizes . SIZE _12 ,
children : this . formatTime ( currentTime )
} ) ,
BDFDB . ReactUtils . createElement ( BDFDB . LibraryComponents . TextElement , {
className : BDFDB . disCN . height12 ,
size : BDFDB . LibraryComponents . TextElement . Sizes . SIZE _12 ,
children : this . formatTime ( maxTime )
} )
]
} )
]
} ) ;
}
} ;
return class SpotifyControls {
getName ( ) { return "SpotifyControls" ; }
2020-07-19 17:58:17 +02:00
getVersion ( ) { return "1.0.4" ; }
2020-07-19 16:59:08 +02:00
getAuthor ( ) { return "DevilBro" ; }
getDescription ( ) { return "Adds a control panel to discord when listening to spotify." ; }
constructor ( ) {
2020-07-19 17:54:47 +02:00
this . changelog = {
2020-07-19 17:58:17 +02:00
"fixed" : [ [ "Controls" , "Fixed an issue where the controls would stop working after some time" ] , [ "Resume" , "Playlists should no longer restart, when you resume a song" ] ]
2020-07-19 17:54:47 +02:00
} ;
2020-07-19 16:59:08 +02:00
this . patchedModules = {
after : {
AnalyticsContext : "render"
}
} ;
2020-07-19 17:26:50 +02:00
}
initConstructor ( ) {
2020-07-21 15:08:40 +02:00
this . defaults = {
settings : {
addTimeline : { value : true , description : "Show the song timeline in the controls" }
}
} ;
2020-07-19 16:59:08 +02:00
this . css = `
@ font - face {
font - family : glue1 - spoticon ;
src : url ( "https://mwittrien.github.io/BetterDiscordAddons/Plugins/SpotifyControls/res/spoticon.ttf" ) format ( "truetype" ) ;
font - weight : 400 ;
font - style : normal
}
$ { BDFDB . dotCN . _spotifycontrolscontainer } {
2020-07-21 15:08:40 +02:00
display : flex ;
flex - direction : column ;
justify - content : center ;
min - height : 52 px ;
2020-07-19 16:59:08 +02:00
margin - bottom : 1 px ;
border - bottom : 1 px solid var ( -- background - modifier - accent ) ;
2020-07-21 15:08:40 +02:00
padding : 0 8 px ;
box - sizing : border - box ;
}
$ { BDFDB . dotCN . _spotifycontrolscontainer + BDFDB . dotCN . _spotifycontrolscontainerwithtimeline } {
padding - top : 8 px ;
2020-07-19 16:59:08 +02:00
}
$ { BDFDB . dotCN . _spotifycontrolscontainerinner } {
display : flex ;
align - items : center ;
font - size : 14 px ;
}
2020-07-21 15:15:26 +02:00
$ { BDFDB . dotCN . _spotifycontrolstimeline } {
2020-07-19 16:59:08 +02:00
margin : 4 px 0 ;
}
$ { BDFDB . dotCN . _spotifycontrolsbar } {
border - radius : 2 px ;
background - color : rgba ( 79 , 84 , 92 , 0.16 ) ;
height : 4 px ;
margin - bottom : 4 px ;
}
$ { BDFDB . dotCN . _spotifycontrolsbarfill } {
border - radius : 2 px ;
height : 100 % ;
min - width : 4 px ;
border - radius : 2 px ;
background : var ( -- header - primary ) ;
}
$ { BDFDB . dotCN . _spotifycontrolsbartext } {
display : flex ;
align - items : center ;
justify - content : space - between ;
}
$ { BDFDB . dotCN . _spotifycontrolscover } {
display : block ;
width : 32 px ;
height : 32 px ;
margin - right : 8 px ;
border - radius : 4 px ;
object - fit : cover ;
}
$ { BDFDB . dotCN . _spotifycontrolsdetails } {
user - select : text ;
flex - grow : 1 ;
margin - right : 4 px ;
min - width : 0 ;
}
$ { BDFDB . dotCN . _spotifycontrolssong } {
font - weight : 500 ;
}
$ { BDFDB . dotCN . _spotifycontrolsinterpret } {
font - weight : 300 ;
}
$ { BDFDB . dotCNS . _spotifycontrolscontainer + BDFDB . dotCN . accountinfobuttondisabled } {
2020-07-19 17:30:37 +02:00
cursor : no - drop ;
2020-07-19 16:59:08 +02:00
}
` ;
}
// Legacy
load ( ) { }
start ( ) {
if ( ! window . BDFDB ) window . BDFDB = { myPlugins : { } } ;
if ( window . BDFDB && window . BDFDB . myPlugins && typeof window . BDFDB . myPlugins == "object" ) window . BDFDB . myPlugins [ this . getName ( ) ] = this ;
let libraryScript = document . querySelector ( "head script#BDFDBLibraryScript" ) ;
if ( ! libraryScript || ( performance . now ( ) - libraryScript . getAttribute ( "date" ) ) > 600000 ) {
if ( libraryScript ) libraryScript . remove ( ) ;
libraryScript = document . createElement ( "script" ) ;
libraryScript . setAttribute ( "id" , "BDFDBLibraryScript" ) ;
libraryScript . setAttribute ( "type" , "text/javascript" ) ;
libraryScript . setAttribute ( "src" , "https://mwittrien.github.io/BetterDiscordAddons/Plugins/BDFDB.min.js" ) ;
libraryScript . setAttribute ( "date" , performance . now ( ) ) ;
libraryScript . addEventListener ( "load" , _ => { this . initialize ( ) ; } ) ;
document . head . appendChild ( libraryScript ) ;
}
else if ( window . BDFDB && typeof BDFDB === "object" && BDFDB . loaded ) this . initialize ( ) ;
this . startTimeout = setTimeout ( _ => {
try { return this . initialize ( ) ; }
catch ( err ) { console . error ( ` %c[ ${ this . getName ( ) } ]%c ` , "color: #3a71c1; font-weight: 700;" , "" , "Fatal Error: Could not initiate plugin! " + err ) ; }
} , 30000 ) ;
}
initialize ( ) {
if ( window . BDFDB && typeof BDFDB === "object" && BDFDB . loaded ) {
if ( this . started ) return ;
BDFDB . PluginUtils . init ( this ) ;
BDFDB . ModuleUtils . patch ( this , BDFDB . LibraryModules . SpotifyTrackUtils , "getActivity" , { after : e => {
2020-07-21 15:12:43 +02:00
if ( e . methodArguments [ 0 ] !== false ) {
if ( e . returnValue && e . returnValue . name == "Spotify" ) this . updatePlayer ( e . returnValue ) ;
else if ( ! e . returnValue ) this . updatePlayer ( null ) ;
}
2020-07-19 16:59:08 +02:00
} } ) ;
BDFDB . ModuleUtils . patch ( this , BDFDB . LibraryModules . SpotifyTrackUtils , "wasAutoPaused" , { instead : e => {
return false ;
} } ) ;
BDFDB . ModuleUtils . patch ( this , BDFDB . LibraryModules . SpotifyUtils , "pause" , { instead : e => {
return false ;
} } ) ;
2020-07-21 15:08:40 +02:00
this . forceUpdateAll ( ) ;
2020-07-19 16:59:08 +02:00
}
else {
console . error ( ` %c[ ${ this . getName ( ) } ]%c ` , 'color: #3a71c1; font-weight: 700;' , '' , 'Fatal Error: Could not load BD functions!' ) ;
}
}
stop ( ) {
if ( window . BDFDB && typeof BDFDB === "object" && BDFDB . loaded ) {
this . stopping = true ;
2020-07-21 15:08:40 +02:00
this . forceUpdateAll ( ) ;
2020-07-19 16:59:08 +02:00
BDFDB . PluginUtils . clear ( this ) ;
}
}
// Begin of own functions
2020-07-21 15:08:40 +02:00
onSettingsClosed ( ) {
if ( this . SettingsUpdated ) {
delete this . SettingsUpdated ;
this . forceUpdateAll ( ) ;
}
}
2020-07-19 16:59:08 +02:00
processAnalyticsContext ( e ) {
if ( typeof e . returnvalue . props . children == "function" && e . instance . props . section == BDFDB . DiscordConstants . AnalyticsSections . ACCOUNT _PANEL ) {
let renderChildren = e . returnvalue . props . children ;
e . returnvalue . props . children = ( ... args ) => {
return [
BDFDB . ReactUtils . createElement ( SpotifyControlsComponent , {
song : BDFDB . LibraryModules . SpotifyTrackUtils . getActivity ( )
} ) ,
renderChildren ( ... args )
] ;
} ;
}
}
updatePlayer ( song ) {
if ( controls ) {
controls . props . song = song ;
BDFDB . ReactUtils . forceUpdate ( controls ) ;
}
}
2020-07-21 15:08:40 +02:00
forceUpdateAll ( ) {
settings = BDFDB . DataUtils . get ( this , "settings" ) ;
BDFDB . ModuleUtils . forceAllUpdates ( this ) ;
}
2020-07-19 16:59:08 +02:00
}
} ) ( ) ;