mirror of
https://github.com/janishutz/MusicPlayerV2.git
synced 2025-11-25 13:04:23 +00:00
some progress, interrupted because MusicKit bugs
This commit is contained in:
@@ -5,6 +5,8 @@
|
|||||||
<link rel="icon" href="/favicon.ico">
|
<link rel="icon" href="/favicon.ico">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200">
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200">
|
||||||
|
<!-- TODO: Update URL -->
|
||||||
|
<script src="/musickit.js"></script>
|
||||||
<title>MusicPlayer</title>
|
<title>MusicPlayer</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
7
MusicPlayerV2-GUI/package-lock.json
generated
7
MusicPlayerV2-GUI/package-lock.json
generated
@@ -8,6 +8,7 @@
|
|||||||
"name": "musicplayerv2-gui",
|
"name": "musicplayerv2-gui",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"musickit-typescript": "^1.2.4",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
"vue": "^3.4.15",
|
"vue": "^3.4.15",
|
||||||
"vue-router": "^4.2.5"
|
"vue-router": "^4.2.5"
|
||||||
@@ -2387,6 +2388,12 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/musickit-typescript": {
|
||||||
|
"version": "1.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/musickit-typescript/-/musickit-typescript-1.2.4.tgz",
|
||||||
|
"integrity": "sha512-3+/20Pi2zOVAHfUFf631LU2NwaC/qEHBBksM+YQzQ/fff4tIMPX5WJ6We/WXmwTHkAkHIOEitJW4cRPnvVAq+A==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/nanoid": {
|
"node_modules/nanoid": {
|
||||||
"version": "3.3.7",
|
"version": "3.3.7",
|
||||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
|
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"musickit-typescript": "^1.2.4",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
"vue": "^3.4.15",
|
"vue": "^3.4.15",
|
||||||
"vue-router": "^4.2.5"
|
"vue-router": "^4.2.5"
|
||||||
|
|||||||
28
MusicPlayerV2-GUI/public/musickit.js
Normal file
28
MusicPlayerV2-GUI/public/musickit.js
Normal file
File diff suppressed because one or more lines are too long
@@ -11,7 +11,7 @@
|
|||||||
<div class="controls-wrapper">
|
<div class="controls-wrapper">
|
||||||
<span class="material-symbols-outlined controls next-previous" @click="control( 'previous' )" id="previous">skip_previous</span>
|
<span class="material-symbols-outlined controls next-previous" @click="control( 'previous' )" id="previous">skip_previous</span>
|
||||||
<span class="material-symbols-outlined controls forward-back" @click="control( 'back' )" :style="'rotate: -' + 360 * clickCountBack + 'deg;'">replay_10</span>
|
<span class="material-symbols-outlined controls forward-back" @click="control( 'back' )" :style="'rotate: -' + 360 * clickCountBack + 'deg;'">replay_10</span>
|
||||||
<span class="material-symbols-outlined controls" v-if="!isPlaying" @click="playPause()" id="play-pause">pause</span>
|
<span class="material-symbols-outlined controls" v-if="isPlaying" @click="playPause()" id="play-pause">pause</span>
|
||||||
<span class="material-symbols-outlined controls" v-else @click="playPause()" id="play-pause">play_arrow</span>
|
<span class="material-symbols-outlined controls" v-else @click="playPause()" id="play-pause">play_arrow</span>
|
||||||
<span class="material-symbols-outlined controls forward-back" @click="control( 'forward' )" :style="'rotate: ' + 360 * clickCountForward + 'deg;'">forward_10</span>
|
<span class="material-symbols-outlined controls forward-back" @click="control( 'forward' )" :style="'rotate: ' + 360 * clickCountForward + 'deg;'">forward_10</span>
|
||||||
<span class="material-symbols-outlined controls next-previous" @click="control( 'next' )" id="next">skip_next</span>
|
<span class="material-symbols-outlined controls next-previous" @click="control( 'next' )" id="next">skip_next</span>
|
||||||
@@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import playlistView from '@/components/playlistView.vue';
|
import playlistView from '@/components/playlistView.vue';
|
||||||
|
import MusicKitJSWrapper from '@/scripts/player';
|
||||||
|
|
||||||
const isPlaying = ref( false );
|
const isPlaying = ref( false );
|
||||||
const repeatMode = ref( '' );
|
const repeatMode = ref( '' );
|
||||||
@@ -37,12 +38,18 @@
|
|||||||
const clickCountForward = ref( 0 );
|
const clickCountForward = ref( 0 );
|
||||||
const clickCountBack = ref( 0 );
|
const clickCountBack = ref( 0 );
|
||||||
const isShowingFullScreenPlayer = ref( false );
|
const isShowingFullScreenPlayer = ref( false );
|
||||||
|
const player = new MusicKitJSWrapper();
|
||||||
|
|
||||||
const emits = defineEmits( [ 'playerStateChange' ] );
|
const emits = defineEmits( [ 'playerStateChange' ] );
|
||||||
|
|
||||||
const playPause = () => {
|
const playPause = () => {
|
||||||
isPlaying.value = !isPlaying.value;
|
isPlaying.value = !isPlaying.value;
|
||||||
// TODO: Execute function on player
|
// TODO: Execute function on player
|
||||||
|
if ( isPlaying.value ) {
|
||||||
|
player.play();
|
||||||
|
} else {
|
||||||
|
player.pause();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const control = ( action: string ) => {
|
const control = ( action: string ) => {
|
||||||
@@ -176,6 +183,11 @@
|
|||||||
font-size: 2.5rem;
|
font-size: 2.5rem;
|
||||||
color: var( --primary-color );
|
color: var( --primary-color );
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
transition: all 0.5s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-fullscreen:hover {
|
||||||
|
transform: scale( 1.25 );
|
||||||
}
|
}
|
||||||
|
|
||||||
.hidden .close-fullscreen {
|
.hidden .close-fullscreen {
|
||||||
|
|||||||
@@ -9,4 +9,6 @@ const app = createApp(App)
|
|||||||
app.use(createPinia())
|
app.use(createPinia())
|
||||||
app.use(router)
|
app.use(router)
|
||||||
|
|
||||||
|
localStorage.setItem( 'url', 'http://localhost:8081' );
|
||||||
|
|
||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
|
|||||||
0
MusicPlayerV2-GUI/src/scripts/bizualizer.ts
Normal file
0
MusicPlayerV2-GUI/src/scripts/bizualizer.ts
Normal file
7
MusicPlayerV2-GUI/src/scripts/notificationHandler.ts
Normal file
7
MusicPlayerV2-GUI/src/scripts/notificationHandler.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
const subscribe = ( handler: ( data: any ) => {} ): string => {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsubscribe = ( id: string ) => {
|
||||||
|
|
||||||
|
}
|
||||||
294
MusicPlayerV2-GUI/src/scripts/player.ts
Normal file
294
MusicPlayerV2-GUI/src/scripts/player.ts
Normal file
@@ -0,0 +1,294 @@
|
|||||||
|
interface Song {
|
||||||
|
/**
|
||||||
|
* The ID. Either the apple music ID, or if from local disk, an ID starting in local_
|
||||||
|
*/
|
||||||
|
id: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The cover image as a URL
|
||||||
|
*/
|
||||||
|
cover: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The artist of the song
|
||||||
|
*/
|
||||||
|
artist: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the song
|
||||||
|
*/
|
||||||
|
title: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Duration of the song in milliseconds
|
||||||
|
*/
|
||||||
|
duration: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (OPTIONAL) The genres this song belongs to. Can be displayed on the showcase screen, but requires settings there
|
||||||
|
*/
|
||||||
|
genres?: string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (OPTIONAL) This will be displayed in brackets on the showcase screens
|
||||||
|
*/
|
||||||
|
additionalInfo?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Config {
|
||||||
|
devToken: string;
|
||||||
|
userToken: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class MusicKitJSWrapper {
|
||||||
|
playingSongID: number;
|
||||||
|
playlist: Song[];
|
||||||
|
queue: number[];
|
||||||
|
config: Config;
|
||||||
|
musicKit: any;
|
||||||
|
isLoggedIn: boolean;
|
||||||
|
|
||||||
|
constructor () {
|
||||||
|
this.playingSongID = 0;
|
||||||
|
this.playlist = [];
|
||||||
|
this.queue = [];
|
||||||
|
this.config = {
|
||||||
|
devToken: '',
|
||||||
|
userToken: '',
|
||||||
|
};
|
||||||
|
this.isLoggedIn = false;
|
||||||
|
|
||||||
|
const self = this;
|
||||||
|
|
||||||
|
if ( !window.MusicKit ) {
|
||||||
|
document.addEventListener( 'musickitloaded', () => {
|
||||||
|
self.init();
|
||||||
|
} );
|
||||||
|
} else {
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logIn () {
|
||||||
|
if ( !this.musicKit.isAuthorized ) {
|
||||||
|
this.musicKit.authorize().then( () => {
|
||||||
|
this.isLoggedIn = true;
|
||||||
|
this.init();
|
||||||
|
} );
|
||||||
|
} else {
|
||||||
|
this.musicKit.authorize().then( () => {
|
||||||
|
this.isLoggedIn = true;
|
||||||
|
this.init();
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init () {
|
||||||
|
fetch( localStorage.getItem( 'url' ) + '/getAppleMusicDevToken', { credentials: 'include' } ).then( res => {
|
||||||
|
if ( res.status === 200 ) {
|
||||||
|
res.text().then( token => {
|
||||||
|
// MusicKit global is now defined
|
||||||
|
MusicKit.configure( {
|
||||||
|
developerToken: token,
|
||||||
|
app: {
|
||||||
|
name: 'MusicPlayer',
|
||||||
|
build: '2'
|
||||||
|
},
|
||||||
|
storefrontId: 'CH',
|
||||||
|
} ).then( () => {
|
||||||
|
this.config.devToken = token;
|
||||||
|
this.musicKit = MusicKit.getInstance();
|
||||||
|
if ( this.musicKit.isAuthorized ) {
|
||||||
|
this.isLoggedIn = true;
|
||||||
|
this.config.userToken = this.musicKit.musicUserToken;
|
||||||
|
}
|
||||||
|
this.musicKit.shuffleMode = MusicKit.PlayerShuffleMode.off;
|
||||||
|
this.apiGetRequest( 'https://api.music.apple.com/v1/me/library/playlists', this.handleAPIReturns );
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
handleAPIReturns ( data: object ) {
|
||||||
|
console.log( data );
|
||||||
|
}
|
||||||
|
|
||||||
|
getUserPlaylists () {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
apiGetRequest ( url: string, callback: ( data: object ) => void ) {
|
||||||
|
if ( this.config.devToken != '' && this.config.userToken != '' ) {
|
||||||
|
fetch( url, {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Authorization': `Bearer ${ this.config.devToken }`,
|
||||||
|
'Music-User-Token': this.config.userToken
|
||||||
|
}
|
||||||
|
} ).then( res => {
|
||||||
|
if ( res.status === 200 ) {
|
||||||
|
res.json().then( json => {
|
||||||
|
try {
|
||||||
|
callback( { 'status': 'ok', 'data': json } );
|
||||||
|
} catch( err ) { /* empty */}
|
||||||
|
} );
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
callback( { 'status': 'error', 'error': res.status } );
|
||||||
|
} catch( err ) { /* empty */}
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
} else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start playing the song at the current songID.
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
play (): void {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start playing the current song
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
pause (): void {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Skip to the next song
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
skip (): void {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return to start of song, or if within four seconds of start of the song, go to previous song.
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
previous (): void {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Go to a specific position in the song. If position > song duration, go to next song
|
||||||
|
* @param {number} pos The position in milliseconds since start of the song
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
goToPos ( pos: number ): void {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: think about queue handling
|
||||||
|
/**
|
||||||
|
* Set, if the queue should be shuffled
|
||||||
|
* @param {boolean} enable True to enable shuffle, false to disable
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
shuffle ( enable: boolean ): void {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the repeat mode
|
||||||
|
* @param {string} repeatType The repeat type. Can be '', '_on' or '_one_on'
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
repeat ( repeatType: string ): void {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the playlist to play.
|
||||||
|
* @param {Song[]} pl Playlist to play. An array of songs
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
setPlaylist ( pl: Song[] ): void {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set which song (by Song-ID) to play.
|
||||||
|
* @param {string} id The song ID (apple music ID or internal ID, if from local drive)
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
setCurrentlyPlayingSongID ( id: string ): void {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a song into the currently playing playlist
|
||||||
|
* @param {Song} song A song using the Song object
|
||||||
|
* @param {number} pos Position in the queue to insert it into
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
insertSong ( song: Song, pos: number ): void {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a song from the queue
|
||||||
|
* @param {string} id Song ID to remove.
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
removeSong ( id: string ): void {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the playlist, as it will play
|
||||||
|
* @returns {Song[]}
|
||||||
|
*/
|
||||||
|
getOrderedPlaylist (): Song[] {
|
||||||
|
return this.playlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the playlist, ignoring order specified by the queue.
|
||||||
|
* @returns {Song[]}
|
||||||
|
*/
|
||||||
|
getPlaylist (): Song[] {
|
||||||
|
return this.playlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the position of the playback head. Returns time in ms
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
getPlaybackPos (): number {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the currently playing song object
|
||||||
|
* @returns {Song}
|
||||||
|
*/
|
||||||
|
getPlayingSong (): Song {
|
||||||
|
return this.playlist[ this.playingSongID ];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the ID of the currently playing song
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
getPlayingSongID (): string {
|
||||||
|
return this.playlist[ this.playingSongID ].id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the index in the playlist of the currently playing song
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
getPlayingIndex (): number {
|
||||||
|
return this.playingSongID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MusicKitJSWrapper;
|
||||||
@@ -62,7 +62,7 @@
|
|||||||
bottom: 10px;
|
bottom: 10px;
|
||||||
left: 10px;
|
left: 10px;
|
||||||
background-color: var( --secondary-color );
|
background-color: var( --secondary-color );
|
||||||
transition: all 1s;
|
transition: all 0.75s ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.full-screen-player {
|
.full-screen-player {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"extends": "@vue/tsconfig/tsconfig.dom.json",
|
"extends": "@vue/tsconfig/tsconfig.dom.json",
|
||||||
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
|
"include": ["env.d.ts", "src/**/*", "src/**/*.vue", "public/musickit.js"],
|
||||||
"exclude": ["src/**/__tests__/*"],
|
"exclude": ["src/**/__tests__/*"],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"composite": true,
|
"composite": true,
|
||||||
|
|||||||
5
backend/config/apple-music-api.config.json
Normal file
5
backend/config/apple-music-api.config.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"teamID": "",
|
||||||
|
"keyID": "",
|
||||||
|
"storefront": "us"
|
||||||
|
}
|
||||||
48
backend/dist/app.js
vendored
Normal file
48
backend/dist/app.js
vendored
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
"use strict";
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const express_1 = __importDefault(require("express"));
|
||||||
|
const path_1 = __importDefault(require("path"));
|
||||||
|
const fs_1 = __importDefault(require("fs"));
|
||||||
|
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
||||||
|
const cors_1 = __importDefault(require("cors"));
|
||||||
|
if (typeof (__dirname) === 'undefined') {
|
||||||
|
__dirname = path_1.default.resolve(path_1.default.dirname(''));
|
||||||
|
}
|
||||||
|
const run = () => {
|
||||||
|
let app = (0, express_1.default)();
|
||||||
|
app.use((0, cors_1.default)({
|
||||||
|
credentials: true,
|
||||||
|
origin: true
|
||||||
|
}));
|
||||||
|
app.get('/', (request, response) => {
|
||||||
|
response.send('HELLO WORLD');
|
||||||
|
});
|
||||||
|
app.get('/getAppleMusicDevToken', (req, res) => {
|
||||||
|
// sign dev token
|
||||||
|
const privateKey = fs_1.default.readFileSync(path_1.default.join(__dirname + '/config/apple_private_key.p8')).toString();
|
||||||
|
// TODO: Remove secret
|
||||||
|
const config = JSON.parse('' + fs_1.default.readFileSync(path_1.default.join(__dirname + '/config/apple-music-api.config.json')));
|
||||||
|
const jwtToken = jsonwebtoken_1.default.sign({}, privateKey, {
|
||||||
|
algorithm: "ES256",
|
||||||
|
expiresIn: "180d",
|
||||||
|
issuer: config.teamID,
|
||||||
|
header: {
|
||||||
|
alg: "ES256",
|
||||||
|
kid: config.keyID
|
||||||
|
}
|
||||||
|
});
|
||||||
|
res.send(jwtToken);
|
||||||
|
});
|
||||||
|
app.use((request, response, next) => {
|
||||||
|
response.status(404).send('ERR_NOT_FOUND');
|
||||||
|
// response.sendFile( path.join( __dirname + '' ) )
|
||||||
|
});
|
||||||
|
const PORT = process.env.PORT || 8081;
|
||||||
|
app.listen(PORT);
|
||||||
|
};
|
||||||
|
exports.default = {
|
||||||
|
run
|
||||||
|
};
|
||||||
1
backend/dist/config
vendored
Symbolic link
1
backend/dist/config
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../config/
|
||||||
2
backend/index.js
Normal file
2
backend/index.js
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
const app = require( './dist/app.js' ).default;
|
||||||
|
app.run();
|
||||||
1043
backend/package-lock.json
generated
Normal file
1043
backend/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
32
backend/package.json
Normal file
32
backend/package.json
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"name": "musicplayer-v2-backend",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "The backend for MusicPlayerV2",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/simplePCBuilding/MusicPlayerV2.git"
|
||||||
|
},
|
||||||
|
"author": "Janis Hutz",
|
||||||
|
"license": "GPL-3.0-or-later",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/simplePCBuilding/MusicPlayerV2/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/simplePCBuilding/MusicPlayerV2#readme",
|
||||||
|
"devDependencies": {
|
||||||
|
"typescript": "^5.4.5"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@types/body-parser": "^1.19.5",
|
||||||
|
"@types/cors": "^2.8.17",
|
||||||
|
"@types/express": "^4.17.21",
|
||||||
|
"@types/jsonwebtoken": "^9.0.6",
|
||||||
|
"body-parser": "^1.20.2",
|
||||||
|
"cors": "^2.8.5",
|
||||||
|
"express": "^4.19.2",
|
||||||
|
"jsonwebtoken": "^9.0.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
54
backend/src/app.ts
Normal file
54
backend/src/app.ts
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import express from 'express';
|
||||||
|
import path from 'path';
|
||||||
|
import fs from 'fs';
|
||||||
|
import bodyParser from 'body-parser';
|
||||||
|
import jwt from 'jsonwebtoken';
|
||||||
|
import cors from 'cors';
|
||||||
|
|
||||||
|
declare let __dirname: string | undefined
|
||||||
|
if ( typeof( __dirname ) === 'undefined' ) {
|
||||||
|
__dirname = path.resolve( path.dirname( '' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
const run = () => {
|
||||||
|
let app = express();
|
||||||
|
app.use( cors( {
|
||||||
|
credentials: true,
|
||||||
|
origin: true
|
||||||
|
} ) );
|
||||||
|
|
||||||
|
app.get( '/', ( request, response ) => {
|
||||||
|
response.send( 'HELLO WORLD' );
|
||||||
|
} );
|
||||||
|
|
||||||
|
|
||||||
|
app.get( '/getAppleMusicDevToken', ( req, res ) => {
|
||||||
|
// sign dev token
|
||||||
|
const privateKey = fs.readFileSync( path.join( __dirname + '/config/apple_private_key.p8' ) ).toString();
|
||||||
|
// TODO: Remove secret
|
||||||
|
const config = JSON.parse( '' + fs.readFileSync( path.join( __dirname + '/config/apple-music-api.config.json' ) ) );
|
||||||
|
const jwtToken = jwt.sign( {}, privateKey, {
|
||||||
|
algorithm: "ES256",
|
||||||
|
expiresIn: "180d",
|
||||||
|
issuer: config.teamID,
|
||||||
|
header: {
|
||||||
|
alg: "ES256",
|
||||||
|
kid: config.keyID
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
res.send( jwtToken );
|
||||||
|
} );
|
||||||
|
|
||||||
|
app.use( ( request: express.Request, response: express.Response, next: express.NextFunction ) => {
|
||||||
|
response.status( 404 ).send( 'ERR_NOT_FOUND' );
|
||||||
|
// response.sendFile( path.join( __dirname + '' ) )
|
||||||
|
} );
|
||||||
|
|
||||||
|
|
||||||
|
const PORT = process.env.PORT || 8081;
|
||||||
|
app.listen( PORT );
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
run
|
||||||
|
}
|
||||||
13
backend/tsconfig.json
Normal file
13
backend/tsconfig.json
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "./dist",
|
||||||
|
"allowJs": true,
|
||||||
|
"target": "ES6",
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"types": ["node"],
|
||||||
|
"module": "NodeNext",
|
||||||
|
"moduleResolution": "NodeNext"
|
||||||
|
},
|
||||||
|
"include": [ "./src/**/*" ],
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user