Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Media Source API #298

Open
6 tasks
goto-bus-stop opened this issue Oct 9, 2018 · 2 comments · May be fixed by #436
Open
6 tasks

Media Source API #298

goto-bus-stop opened this issue Oct 9, 2018 · 2 comments · May be fixed by #436
Milestone

Comments

@goto-bus-stop
Copy link
Member

goto-bus-stop commented Oct 9, 2018

Currently, media sources have three API methods:

  • search
  • get
  • import

search and get are quite clear and good now, but import is basically a wildcard and requires custom client support. This issue is intended to scope out the features that would be required in a more restrictive API.

Feature Checklist

  • Flagging support for the below features
    Probably just assign each a name. It could be implicit on the implementer end, so Core would determine it based on which methods are available.
  • Import a playlist from a URL
    Like the current YouTube source, on the web client this should open a panel that lists all the media in a playlist, and that has an "import all" button that can be used to import the entire thing into a new üWave playlist.
    • One feature that would be good to have that does not exist right now is pagination; this may be quite difficult though because not all third parties support the type of pagination that üWave needs.
  • Optionally, view playlists belonging to a user account / [other similar concept].
  • Optionally, view playlists of the current user (if account is connected).
    • How to do the account connection stuff?
  • ...
interface MediaSource {
  api?: number;
  name: string;

  get(context: SourceContext, sourceIDs: string[]): Promise<MediaItem[]>;
  search(context: SourceContext, query: string, pagination?: any): Promise<MediaItem[]>;

  // Get media items in a playlist. sourceID may be ID or a playlist URL or etc
  getPlaylistItems(context: SourceContext, sourceID: string): Promise<MediaItem[]>;
  // Get playlists owned by the user [throw error if user has no connected account]
  getSelfPlaylists(context: SourceContext): Promise<PlaylistMeta[]>;
  // Get (public) playlists owned by some other user or similar concept.
  getUserPlaylists(context: SourceContext, userID: string): Promise<PlaylistMeta[]>;
  // maybe?
  searchPlaylists(context: SourceContext, query: string): Promise<PlaylistMeta[]>;
}
@goto-bus-stop goto-bus-stop added this to the v1 milestone Aug 5, 2020
@goto-bus-stop
Copy link
Member Author

We're going to need an API rework to support runtime configuration. It's kind of possible already because media sources have access to the uw object, but it's unergonomic. You can't use the options parameter that uw.source() gives you because that is static.

For runtime configuration, sources should be managed more strictly by üWave Core. Maybe an API could look like this:

interface MediaItem {
  ...
}

interface PlaylistMeta {
  ...
}

// Maybe a generic parameter for the options object?
// Maybe a generic parameter for the SourceData?
abstract class MediaSource {
  static api: number = 3;
  static name: string;

  // This schema would automatically be merged with an `{ enabled: { type: boolean } }` schema using `allOf`
  static schema: JSONSchema;
  
  constructor(options: object /* or maybe a generic type */);

  get(context: SourceContext, sourceIDs: string[]): Promise<MediaItem[]>;
  search(context: SourceContext, query: string, pagination?: any): Promise<MediaItem[]>;

  // Get media items in a playlist. sourceID may be ID or a playlist URL or etc
  // optional
  getPlaylistItems(context: SourceContext, sourceID: string): Promise<MediaItem[]>;
  // Get playlists owned by the user [throw error if user has no connected account]
  // optional
  getSelfPlaylists(context: SourceContext): Promise<PlaylistMeta[]>;
  // Get (public) playlists owned by some other user or similar concept.
  // optional
  getUserPlaylists(context: SourceContext, userID: string): Promise<PlaylistMeta[]>;
  // maybe?
  // optional
  searchPlaylists(context: SourceContext, query: string): Promise<PlaylistMeta[]>;  

  // optional
  close(): Promise<void> | void {}
}

@goto-bus-stop
Copy link
Member Author

Turns out static abstract members are not a thing. That was the reason for using an abstract class in the sketch above instead of an interface.

Perhaps it could be an interface and a @u-wave/media-source function that wraps it:

import { createMediaSource, MediaSource } = require('@u-wave/media-source');

class YouTubeSource implements MediaSource {
  // ...
}

export = createMediaSource(YouTubeSource, {
  name: 'youtube',
  schema: {
    // ...
  },
})

@goto-bus-stop goto-bus-stop linked a pull request Mar 10, 2021 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant