parent
a689613a45
commit
dff4acab25
12 changed files with 276 additions and 13 deletions
@ -0,0 +1,6 @@ |
||||
[submodule "client/submodules/youtube-music-api"] |
||||
path = client/submodules/youtube-music-api |
||||
url = https://github.com/SanderVocke/youtube-music-api.git |
||||
[submodule "client/src/submodules/youtube-music-api"] |
||||
path = client/src/submodules/youtube-music-api |
||||
url = https://github.com/SanderVocke/youtube-music-api.git |
After Width: | Height: | Size: 944 B |
@ -0,0 +1,12 @@ |
||||
import React from 'react'; |
||||
import Integration from '../../integrations/Integration'; |
||||
|
||||
export default function IntegrationsWidget(props: { |
||||
integrations: Integration[] |
||||
}) { |
||||
return <> |
||||
{props.integrations.map((integration: Integration) => { |
||||
return integration.getIcon({ style: { height: '30px', width: '30px' } }); |
||||
})} |
||||
</> |
||||
} |
@ -0,0 +1,52 @@ |
||||
import React, { ReactFragment } from 'react'; |
||||
|
||||
export interface IntegrationAlbum { |
||||
name?: string, |
||||
storeLink?: string, |
||||
} |
||||
|
||||
export interface IntegrationArtist { |
||||
name?: string, |
||||
storeLink?: string, |
||||
} |
||||
|
||||
export interface IntegrationSong { |
||||
title?: string, |
||||
album?: IntegrationAlbum, |
||||
artist?: IntegrationArtist, |
||||
storeLink?: string, |
||||
} |
||||
|
||||
export enum IntegrationFeature { |
||||
// Used to get a bucket of songs (typically: the whole library)
|
||||
GetSongs = 0, |
||||
|
||||
// Used to search songs and get some amount of candidate results.
|
||||
SearchSong, |
||||
|
||||
// If included, the integration is required to be connected to work.
|
||||
// Methods connect() and isConnected() have to be used for this.
|
||||
UsesConnection, |
||||
} |
||||
|
||||
export interface IntegrationDescriptor { |
||||
supports: IntegrationFeature[], |
||||
} |
||||
|
||||
export default class Integration { |
||||
constructor() { } |
||||
|
||||
// Common
|
||||
getFeatures(): IntegrationFeature[] { return []; } |
||||
getIcon(props: any): ReactFragment { return <></> } |
||||
|
||||
// Feature: UsesConnection
|
||||
async connect(connectParams: any) { } |
||||
isConnected(): boolean { return false; } |
||||
|
||||
// Feature: GetSongs
|
||||
async getSongs(getSongsParams: any): Promise<IntegrationSong[]> { return []; } |
||||
|
||||
// Feature: SearchSongs
|
||||
async searchSong(songProps: IntegrationSong): Promise<IntegrationSong | null> { return null; } |
||||
} |
@ -0,0 +1,55 @@ |
||||
|
||||
import React from 'react'; |
||||
import Integration, { IntegrationFeature, IntegrationSong } from "../Integration"; |
||||
import StoreLinkIcon, { ExternalStore } from "../../components/common/StoreLinkIcon"; |
||||
const YoutubeMusicApi = require('../../submodules/youtube-music-api'); |
||||
|
||||
export interface YoutubeMusicConnectionParams {} |
||||
|
||||
export default class YoutubeMusicIntegration extends Integration { |
||||
lastConnected: Date | null = null; |
||||
connectionIntervalMs: number = 1000 * 60 * 2; // 2 minutes
|
||||
connectionParams: YoutubeMusicConnectionParams | null = null; |
||||
api: any = null; |
||||
|
||||
getFeatures() : IntegrationFeature[] { |
||||
return [ |
||||
IntegrationFeature.SearchSong, |
||||
IntegrationFeature.UsesConnection, |
||||
] |
||||
} |
||||
|
||||
getIcon(props: any) { |
||||
return <StoreLinkIcon whichStore={ExternalStore.YoutubeMusic} {...props}/> |
||||
} |
||||
|
||||
async connect(connectionParams: YoutubeMusicConnectionParams) { |
||||
const newApi = new YoutubeMusicApi(); |
||||
await newApi.initalize(); |
||||
this.api = newApi; |
||||
this.lastConnected = new Date(); |
||||
|
||||
// TODO start keepalive service worker?
|
||||
} |
||||
|
||||
isConnected() { |
||||
if(!this.connectionParams || !this.lastConnected) { |
||||
return false; |
||||
} |
||||
|
||||
// Last successful connection must be less than 2 minutes ago.
|
||||
return ((new Date().valueOf()) - this.lastConnected.valueOf()) < this.connectionIntervalMs; |
||||
} |
||||
|
||||
async searchSong(songProps: IntegrationSong) { |
||||
var query: string = ""; |
||||
if(songProps.title) { query += " " + songProps.title } |
||||
if(songProps.artist && songProps.artist.name) { query += " " + songProps.artist.name } |
||||
|
||||
const result = await this.api.search(query.trim(), "song"); |
||||
|
||||
console.log("Search result: ", result) |
||||
|
||||
return null; |
||||
} |
||||
} |
@ -0,0 +1,18 @@ |
||||
const { createProxyMiddleware } = require('http-proxy-middleware'); |
||||
|
||||
module.exports = function(app) { |
||||
app.use( |
||||
'/api', |
||||
createProxyMiddleware({ |
||||
target: 'http://localhost:5000', |
||||
changeOrigin: true, |
||||
}) |
||||
); |
||||
app.use( |
||||
'/integrations/ytm', |
||||
createProxyMiddleware({ |
||||
target: 'https://music.youtube.com', |
||||
changeOrigin: true, |
||||
}) |
||||
); |
||||
}; |
@ -0,0 +1 @@ |
||||
Subproject commit 0184b80d4b36f92b2874a0aece6e01d92af0c92c |
Loading…
Reference in new issue