2 lines
13 KiB
JavaScript
2 lines
13 KiB
JavaScript
(function(h,E,w,b,l,g,a,d,V,I){"use strict";const s={DEFAULT_APP_NAME:"Music",DEFAULT_TIME_INTERVAL:5,APPLICATION_ID:"1054951789318909972",MIN_UPDATE_INTERVAL:3,MAX_RETRY_ATTEMPTS:3,RETRY_DELAY:5e3,LFM_API_BASE_URL:"https://ws.audioscrobbler.com/2.0",LFM_DEFAULT_COVER_HASHES:["2a96cbd8b46e442fc41c2b86b821562f","c6f59c1e5e7240a4c0d427abd71f3dbb"],DEFAULT_SETTINGS:{username:"",apiKey:"",appName:"Music",timeInterval:5,showTimestamp:!0,listeningTo:!0,ignoreSpotify:!0,verboseLogging:!1},GITHUB_URL:"https://github.com/kmmiio99o/letup",GITHUB_COMMITS_URL:"https://github.com/kmmiio99o/letup/commits/main/"};function L(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function N(e,t){for(var n=0;n<t.length;n++){var c=t[n];c.enumerable=c.enumerable||!1,c.configurable=!0,"value"in c&&(c.writable=!0),Object.defineProperty(e,c.key,c)}}function P(e,t,n){return t&&N(e.prototype,t),n&&N(e,n),e}I.findByProps("SET_ACTIVITY");const G=I.findByProps("getAssetIds"),O=I.findByStoreName("SelfPresenceStore"),k=I.findByStoreName("UserStore");function v(){return U(null)}function U(e){u.pluginStopped&&(M(),e=null),u.lastActivity=e,a.FluxDispatcher.dispatch({type:"LOCAL_ACTIVITY_UPDATE",activity:e,pid:2312,socketId:"Last.fm@Vendetta"})}async function $(e,t=s.APPLICATION_ID){if(!e?.length)return[];try{return await G.fetchAssetIds(t,e)}catch(n){return console.error("[Last.fm] Failed to fetch assets:",n),[]}}const A={};A.componentMountErrors=[],A.componentMountCount=0,A.settingsLoadAttempts=0;function y(e,t){A[e]=t}const D=function(){function e(){L(this,e)}return P(e,[{key:"validateSettings",value:function(){if(!r.username)throw new Error("Last.fm username is not set");if(!r.apiKey)throw new Error("Last.fm API key is not set")}},{key:"handleError",value:async function(t){this.lastError=t.error;const n={2:"Invalid API key",6:"User not found",11:"Service temporarily unavailable",16:"Service temporarily unavailable",29:"Rate limit exceeded"}[t.error]||t.message||"Unknown error";throw g.showToast(`Last.fm Error: ${n}`,l.getAssetIDByName("Small")),new Error(`Last.fm API Error ${t.error}: ${n}`)}},{key:"makeRequest",value:async function(t){const n=new URLSearchParams({...t,api_key:r.apiKey,format:"json"}).toString(),c=await fetch(`${s.LFM_API_BASE_URL}?${n}`),i=await c.json();return(!c.ok||i.error)&&await this.handleError(i),i}},{key:"fetchLatestScrobble",value:async function(){try{this.validateSettings();const t=(await this.makeRequest({method:"user.getrecenttracks",user:r.username,limit:"1",extended:"1"}))?.recenttracks?.track?.[0];if(y("lastAPIResponse",t),!t)throw new Error("No tracks found");return this.retryCount=0,{name:t.name,artist:t.artist.name,album:t.album["#text"],albumArt:await this.handleAlbumCover(t.image?.find(function(n){return n.size==="large"})?.["#text"]),url:t.url,date:t.date?.["#text"]??"now",nowPlaying:!!t["@attr"]?.nowplaying,loved:t.loved==="1"}}catch(t){if(this.retryCount++,this.retryCount>s.MAX_RETRY_ATTEMPTS)throw this.retryCount=0,t;return await new Promise(function(n){return setTimeout(n,s.RETRY_DELAY)}),this.fetchLatestScrobble()}}},{key:"handleAlbumCover",value:async function(t){return!t||s.LFM_DEFAULT_COVER_HASHES.some(function(n){return t.includes(n)})?null:t}},{key:"getLastError",value:function(){return this.lastError}},{key:"resetRetryCount",value:function(){this.retryCount=0}}],[{key:"getInstance",value:function(){return e.instance||(e.instance=new e),e.instance}}]),e}().getInstance();var Y=function(e){return e[e.PLAYING=0]="PLAYING",e[e.STREAMING=1]="STREAMING",e[e.LISTENING=2]="LISTENING",e[e.COMPETING=5]="COMPETING",e}(Y||{});const f=function(...e){return r.verboseLogging&&console.log("[Last.fm]",...e)},C=function(){function e(){L(this,e)}return P(e,[{key:"updateActivity",value:async function(){if(u.pluginStopped){f("Plugin is stopped, skipping update"),this.stopUpdates();return}f("Fetching last track...");try{if(!r.username||!r.apiKey)throw new Error("Username or API key not set");if(r.ignoreSpotify){if(O.findActivity(function(c){return c.sync_id})){f("Spotify is currently playing, clearing activity"),y("isSpotifyIgnored",!0),v();return}y("isSpotifyIgnored",!1)}const t=await D.fetchLatestScrobble();if(y("lastTrack",t),!t.nowPlaying){f("Last track is not currently playing"),v();return}if(u.lastTrackUrl===t.url){f("Track hasn't changed");return}const n={name:r.appName||s.DEFAULT_APP_NAME,flags:0,type:r.listeningTo?2:0,details:t.name,state:t.artist,status_display_type:1,application_id:s.APPLICATION_ID};if(n.name.includes("{{"))for(const c in t)n.name=n.name.replace(`{{${c}}}`,t[c]||"");if(r.showTimestamp&&(n.timestamps={start:Date.now()|0}),t.album){const c=await $([t.albumArt]);c[0]&&(n.assets={large_image:c[0],large_text:t.album})}f("Setting activity:",n),y("lastActivity",n),await U(n),u.lastTrackUrl=t.url,u.lastActivity=n,this.consecutiveFailures=0,f("Activity set successfully!")}catch(t){console.error("[Last.fm] Update error:",t),this.handleError(t)}}},{key:"handleError",value:function(t){this.consecutiveFailures++,y("lastError",t),this.consecutiveFailures>=s.MAX_RETRY_ATTEMPTS&&(f(`Failed ${this.consecutiveFailures} times, initiating reconnection...`),this.startReconnection())}},{key:"startReconnection",value:function(){var t=this;this.isReconnecting||(this.isReconnecting=!0,this.stopUpdates(),f("Starting reconnection process"),this.reconnectTimer=setInterval(function(){f("Attempting to reconnect..."),t.initialize().then(function(){f("Reconnection successful"),t.stopReconnection()}).catch(function(n){f("Reconnection failed:",n)})},s.RETRY_DELAY))}},{key:"stopReconnection",value:function(){this.reconnectTimer&&(clearInterval(this.reconnectTimer),this.reconnectTimer=void 0),this.isReconnecting=!1,this.consecutiveFailures=0}},{key:"stopUpdates",value:function(){this.updateTimer&&(clearInterval(this.updateTimer),this.updateTimer=void 0)}},{key:"initialize",value:async function(){var t=this;if(u.pluginStopped)throw new Error("Plugin is stopped");this.stopUpdates(),await this.updateActivity();const n=Math.max((Number(r.timeInterval)||s.DEFAULT_SETTINGS.timeInterval)*1e3,s.MIN_UPDATE_INTERVAL*1e3);this.updateTimer=setInterval(function(){return t.updateActivity()},n),f(`Update timer started with interval: ${n}ms`)}},{key:"stop",value:function(){u.pluginStopped=!0,this.stopUpdates(),this.stopReconnection(),v()}}],[{key:"getInstance",value:function(){return e.instance||(e.instance=new e),e.instance}}]),e}().getInstance(),F=function(){return C.initialize()},M=function(){return C.stop()},{FormText:x}=w.Forms,u={pluginStopped:!1,lastActivity:void 0,updateInterval:void 0,lastTrackUrl:void 0},B=s.DEFAULT_SETTINGS;for(const e in B)E.plugin.storage[e]=E.plugin.storage[e]??B[e];const r=new Proxy(E.plugin.storage,{get(e,t){return e[t]},set(e,t,n){return e[t]=n,!0}}),K=V.lazy(function(){return Promise.resolve().then(function(){return W}).catch(function(e){return console.error("[Last.fm] Failed to load settings:",e),{default:function(){return a.React.createElement(d.ScrollView,{style:{flex:1},contentContainerStyle:{padding:16}},a.React.createElement(x,{style:{color:"#ED4245"}},"Failed to load Last.fm settings. Please check your connection and reload Discord."))}}})});let _=0;const H=3,z=5e3;async function m(){try{await F(),_=0}catch(e){console.error("[Last.fm] Initialization error:",e),_++,_<H?(g.showToast("Retrying connection...",l.getAssetIDByName("ic_clock")),setTimeout(m,z)):g.showToast("Failed to connect to Last.fm",l.getAssetIDByName("Small"))}}var j={settings:function(){return a.React.createElement(a.React.Suspense,{fallback:a.React.createElement(d.ScrollView,{style:{flex:1},contentContainerStyle:{padding:16}},a.React.createElement(x,null,"Loading Last.fm settings..."))},a.React.createElement(K,null))},onLoad(){if(u.pluginStopped=!1,!r.username||!r.apiKey){g.showToast("Please configure Last.fm username and API key in settings",l.getAssetIDByName("ic_warning"));return}if(k.getCurrentUser())m();else{const e=function(){k.getCurrentUser()&&(m(),a.FluxDispatcher.unsubscribe("CONNECTION_OPEN",e))};a.FluxDispatcher.subscribe("CONNECTION_OPEN",e)}},onUnload(){u.pluginStopped=!0,M()},onSettingsUpdate(e){Object.assign(r,e),m()},onDiscordReconnect(){u.pluginStopped||m()}};const q=[{version:"2.3.0",date:"2025-09-19",changes:["Settings Refactor"]},{version:"2.2.0",date:"2025-09-13",changes:["Remember kids! Do not sniff crack!"]},{version:"2.0.0",date:"2025-09-13",changes:["Fix settings scrolling"]},{version:"1.3.0",date:"2025-09-13",changes:["fix reanimated"]},{version:"1.2.0",date:"2025-09-13",changes:["test"]},{version:"1.1.0",date:"2025-09-12",changes:["fixed reanimated issue??"]}],X="2.2.0",{FormInput:te,FormRow:ne,FormSwitch:ae,FormSection:ie,FormDivider:re,FormText:J}=w.Forms,{TableRowGroup:T,TableSwitchRow:S,TableRow:o,TableInputRow:R}=findByProps("TableSwitchRow","TableRowGroup","TableRow","TableInputRow");function Q(){b.useProxy(r),b.useProxy(u);const[e,t]=a.React.useState(!1),n=function(i,p){r[i]=p,E.plugin.storage[i]=p},c=async function(){if(!r.username||!r.apiKey){g.showToast("Please enter both username and API key",l.getAssetIDByName("Small"));return}t(!0);try{await D.fetchLatestScrobble(),g.showToast("Connection successful!",l.getAssetIDByName("Check")),await F()}catch(i){g.showToast(`Connection failed: ${i.message}`,l.getAssetIDByName("Small"))}finally{t(!1)}};return a.React.createElement(d.ScrollView,{style:{flex:1},contentContainerStyle:{paddingBottom:20},bounces:!1,showsVerticalScrollIndicator:!0},a.React.createElement(T,{title:"Account Settings"},a.React.createElement(R,{title:"Last.fm Username",placeholder:"Enter your Last.fm username",value:r.username,onChange:function(i){return n("username",i)}}),a.React.createElement(R,{title:"API Key",placeholder:"Enter your Last.fm API key",value:r.apiKey,onChange:function(i){return n("apiKey",i)},secureTextEntry:!0}),a.React.createElement(o,{label:"Get API Key",subLabel:"https://www.last.fm/api/account/create",trailing:a.React.createElement(o.Icon,{source:l.getAssetIDByName("ic_link_24px")}),onPress:function(){return d.Linking.openURL("https://www.last.fm/api/account/create")}}),a.React.createElement(o,{label:"Test Connection",leading:a.React.createElement(o.Icon,{source:l.getAssetIDByName("ic_connection_24px")}),trailing:e?a.React.createElement(o.Arrow,{loading:!0}):a.React.createElement(o.Arrow,null),onPress:c,disabled:e})),a.React.createElement(T,{title:"Display Settings"},a.React.createElement(R,{title:"App Name",placeholder:s.DEFAULT_SETTINGS.appName,value:r.appName,onChange:function(i){return n("appName",i)}}),a.React.createElement(R,{title:"Update Interval (seconds)",placeholder:String(s.DEFAULT_SETTINGS.timeInterval),value:String(r.timeInterval),onChange:function(i){const p=Number(i);p>=s.MIN_UPDATE_INTERVAL?n("timeInterval",p):g.showToast(`Minimum interval is ${s.MIN_UPDATE_INTERVAL} seconds`,l.getAssetIDByName("Small"))},keyboardType:"numeric"})),a.React.createElement(T,{title:"Options"},a.React.createElement(S,{label:"Show 'Listening to' instead of 'Playing'",icon:a.React.createElement(o.Icon,{source:l.getAssetIDByName("ic_music_24px")}),value:r.listeningTo??s.DEFAULT_SETTINGS.listeningTo,onValueChange:function(i){return n("listeningTo",i)}}),a.React.createElement(S,{label:"Unix Timestamp",icon:a.React.createElement(o.Icon,{source:l.getAssetIDByName("ic_timeline_24px")}),value:r.showTimestamp??s.DEFAULT_SETTINGS.showTimestamp,onValueChange:function(i){return n("showTimestamp",i)}}),a.React.createElement(S,{label:"Ignore when Spotify is playing",icon:a.React.createElement(o.Icon,{source:l.getAssetIDByName("ic_spotify_24px")}),value:r.ignoreSpotify??s.DEFAULT_SETTINGS.ignoreSpotify,onValueChange:function(i){return n("ignoreSpotify",i)}}),a.React.createElement(S,{label:"Verbose Logging",icon:a.React.createElement(o.Icon,{source:l.getAssetIDByName("ic_message_copy_24px")}),value:r.verboseLogging??s.DEFAULT_SETTINGS.verboseLogging,onValueChange:function(i){return n("verboseLogging",i)}})),a.React.createElement(T,{title:"Plugin Status"},a.React.createElement(o,{label:"Status",subLabel:u.pluginStopped?"Stopped":"Running"}),a.React.createElement(o,{label:"Last Update",subLabel:u.lastTrackUrl?"Success":"No track data"})),a.React.createElement(T,{title:"Changelog"},a.React.createElement(o,{label:"View GitHub Commits",icon:a.React.createElement(o.Icon,{source:l.getAssetIDByName("ic_history_24px")}),trailing:a.React.createElement(o.Arrow,null),onPress:function(){return d.Linking.openURL(s.GITHUB_COMMITS_URL)}}),q.map(function(i,p){return a.React.createElement(o,{key:p,label:`Version ${i.version}`,subLabel:i.date,onPress:function(){showConfirmationAlert({title:`Version ${i.version}`,content:i.changes.join(`
|
|
\u2022 `),confirmText:"OK",onConfirm:function(){},isDismissable:!0})}})})),a.React.createElement(d.View,{style:{padding:16,alignItems:"center"}},a.React.createElement(J,{style:{opacity:.5}},"Version ",X)))}var W=Object.freeze({__proto__:null,default:Q});return h.currentSettings=r,h.default=j,h.pluginState=u,Object.defineProperty(h,"__esModule",{value:!0}),h})({},vendetta,vendetta.ui.components,vendetta.storage,vendetta.ui.assets,vendetta.ui.toasts,vendetta.metro.common,vendetta.metro.common.ReactNative,window.React,vendetta.metro);
|