javascript-ampache
Version:
A JS library for the Ampache API
846 lines (798 loc) • 27.1 kB
text/typescript
import qs from "querystringify";
import { SongResponse, SongsResponse } from "../songs/types";
import { ArtistResponse, ArtistsResponse } from "../artists/types";
import {
Base,
BinaryBoolean,
ExtendedPagination,
Pagination,
Success,
UID,
} from "../base";
import { AlbumResponse, AlbumsResponse } from "../albums/types";
import { VideoResponse, VideosResponse } from "../videos/types";
import { PlaylistResponse, PlaylistsResponse } from "../playlists/types";
import {
PodcastsResponse,
PodcastEpisodesResponse,
PodcastResponse,
PodcastEpisodeResponse,
} from "../podcasts/types";
import { LiveStreamsResponse } from "../live-streams/types";
import { LabelResponse, LabelsResponse } from "../labels/types";
import { GenreResponse, GenresResponse } from "../genres/types";
import { UserResponse, UsersResponse } from "../users/types";
import { IndexEntry, NowPlayingResponse } from "./types";
export class System extends Base {
/**
* Check Ampache for updates and run the update if there is one.
* @remarks MINIMUM_API_VERSION=5.0.0
* @see {@link https://ampache.org/api/api-json-methods#system_update}
*/
systemUpdate() {
let query = "system_update";
return this.request<Success>(query);
}
/**
* This takes a collection of inputs and returns ID + name for the object type
* @remarks MINIMUM_API_VERSION=400001
* @param params.type type of object to find
* @param [params.filter] search the name of the object_type
* @param [params.add] ISO 8601 Date Format (2020-09-16) Find objects with an 'add' date newer than the specified date
* @param [params.update] ISO 8601 Date Format (2020-09-16) Find objects with an 'update' time newer than the specified date
* @param [params.include] 0, 1 (include songs in a playlist or episodes in a podcast)
* @param [params.hide_search] 0, 1 (if true do not include searches/smartlists in the result)
* @param [params.offset]
* @param [params.limit]
* @param [params.cond]
* @param [params.sort]
* @see {@link https://ampache.org/api/api-json-methods#get_indexes}
* @deprecated Being removed in 7.0.0. Use `list` instead.
*/
getIndexes(
params: {
type:
| "song"
| "album"
| "artist"
| "album_artist"
| "playlist"
| "podcast"
| "podcast_episode"
| "live_stream"
| "catalog"
| "song_artist";
filter?: string;
add?: Date;
update?: Date;
include?: BinaryBoolean;
hide_search?: BinaryBoolean;
} & ExtendedPagination,
) {
let query = "get_indexes";
query += qs.stringify(params, "&");
let data;
switch (params.type) {
case "song":
data = this.request<SongsResponse>(query);
break;
case "album":
data = this.request<AlbumsResponse>(query);
break;
case "artist":
case "album_artist":
data = this.request<ArtistsResponse>(query);
break;
case "playlist":
data = this.request<PlaylistsResponse>(query);
break;
case "podcast":
data = this.request<PodcastsResponse>(query);
break;
case "podcast_episode":
data = this.request<PodcastEpisodesResponse>(query);
break;
case "live_stream":
data = this.request<LiveStreamsResponse>(query);
break;
default:
return false;
}
return data;
}
/**
* This takes a named array of objects and returning `id`, `name`, `prefix` and `basename`
* @remarks MINIMUM_API_VERSION=6.0.0
* @param params.type type of object to find
* @param [params.filter] Value is Alpha Match for returned results, may be more than one letter/number
* @param [params.add] ISO 8601 Date Format (2020-09-16) Find objects with an 'add' date newer than the specified date
* @param [params.update] ISO 8601 Date Format (2020-09-16) Find objects with an 'update' time newer than the specified date
* @param [params.hide_search] 0, 1 (if true do not include searches/smartlists in the result)
* @param [params.offset]
* @param [params.limit]
* @param [params.cond]
* @param [params.sort]
* @see {@link https://ampache.org/api/api-json-methods#list}
*/
list(
params: {
type:
| "song"
| "album"
| "artist"
| "album_artist"
| "playlist"
| "podcast"
| "podcast_episode"
| "live_stream"
| "catalog"
| "song_artist";
filter?: string;
add?: Date;
update?: Date;
hide_search?: BinaryBoolean;
} & ExtendedPagination,
) {
let query = "list";
query += qs.stringify(params, "&");
return this.request<{ list: IndexEntry[] }>(query);
}
/**
* This takes a collection of inputs and return ID's for the object type.
* @remarks MINIMUM_API_VERSION=6.3.0
* @param params.type type of object to find
* @param [params.filter] Value is Alpha Match for returned results, may be more than one letter/number
* @param [params.exact] 0, 1 (if true filter is exact = rather than fuzzy LIKE)
* @param [params.add] ISO 8601 Date Format (2020-09-16) Find objects with an 'add' date newer than the specified date
* @param [params.update] ISO 8601 Date Format (2020-09-16) Find objects with an 'update' time newer than the specified date
* @param [params.include] 0, 1, (include child objects)
* @param [params.hide_search] 0, 1 (if true do not include searches/smartlists in the result)
* @param [params.offset]
* @param [params.limit]
* @param [params.cond]
* @param [params.sort]
* @see {@link https://ampache.org/api/api-json-methods#index}
*/
index(
params: {
type:
| "catalog"
| "song"
| "album"
| "artist"
| "album_artist"
| "song_artist"
| "playlist"
| "podcast"
| "podcast_episode"
| "share"
| "video"
| "live_stream";
filter?: string;
exact?: BinaryBoolean;
add?: Date;
update?: Date;
include?: BinaryBoolean;
hide_search?: BinaryBoolean;
} & ExtendedPagination,
) {
let query = "index";
query += qs.stringify(params, "&");
return this.request<{ index: [] }>(query);
}
/**
* Return children of a parent object in a folder traversal/browse style
* If you don't send any parameters you'll get a catalog list (the 'root' path)
* @remarks MINIMUM_API_VERSION=6.0.0
* @param [params.filter] object_id
* @param [params.type] type of object to find
* @param [params.catalog] catalog ID you are browsing (required on 'artist', 'album', 'podcast')
* @param [params.add] ISO 8601 Date Format (2020-09-16) Find objects with an 'add' date newer than the specified date
* @param [params.update] ISO 8601 Date Format (2020-09-16) Find objects with an 'update' time newer than the specified date
* @param [params.offset]
* @param [params.limit]
* @param [params.cond]
* @param [params.sort]
* @see {@link https://ampache.org/api/api-json-methods#browse}
*/
browse(
params: {
filter?: UID;
type?: "root" | "catalog" | "artist" | "album" | "podcast";
catalog?: number;
add?: Date;
update?: Date;
} & ExtendedPagination,
) {
let query = "browse";
query += qs.stringify(params, "&");
return this.request<{ browse: IndexEntry[] }>(query);
}
/**
* Return similar artist IDs or similar song IDs compared to the input filter
* @remarks MINIMUM_API_VERSION=420000
* @param params.type type of object to check against
* @param params.filter UID to find
* @param [params.offset]
* @param [params.limit]
* @see {@link https://ampache.org/api/api-json-methods#get_similar}
*/
getSimilar(
params: {
type: "song" | "artist";
filter: UID;
} & Pagination,
) {
let query = "get_similar";
query += qs.stringify(params, "&");
let data;
switch (params.type) {
case "song":
data = this.request<SongsResponse>(query);
break;
case "artist":
data = this.request<ArtistsResponse>(query);
break;
default:
return false;
}
return data;
}
/**
* Get some items based on some simple search types and filters. (Random by default)
* @remarks MINIMUM_API_VERSION=380001; CHANGED_IN_API_VERSION=400001
* @param params.type Object type
* @param [params.filter] newest, highest, frequent, recent, forgotten, flagged, random
* @param [params.user_id] Filter results to a certain user by UID
* @param [params.username] Filter results to a certain user by username
* @param [params.offset]
* @param [params.limit]
* @see {@link https://ampache.org/api/api-json-methods#stats}
*/
stats(
params: {
type:
| "song"
| "album"
| "artist"
| "video"
| "playlist"
| "podcast"
| "podcast_episode";
filter?:
| "newest"
| "highest"
| "frequent"
| "recent"
| "forgotten"
| "flagged"
| "random";
user_id?: number;
username?: string;
} & Pagination,
) {
let query = "stats";
query += qs.stringify(params, "&");
let data;
switch (params.type) {
case "song":
data = this.request<SongsResponse>(query);
break;
case "album":
data = this.request<AlbumsResponse>(query);
break;
case "artist":
data = this.request<ArtistsResponse>(query);
break;
case "video":
data = this.request<VideosResponse>(query);
break;
case "playlist":
data = this.request<PlaylistsResponse>(query);
break;
case "podcast":
data = this.request<PodcastsResponse>(query);
break;
case "podcast_episode":
data = this.request<PodcastEpisodesResponse>(query);
break;
default:
return false;
}
return data;
}
/**
* This rates a library item
* @remarks MINIMUM_API_VERSION=380001
* @param params.type Object type
* @param params.id UID to find
* @param params.rating Rating to apply
* @see {@link https://ampache.org/api/api-json-methods#rate}
*/
rate(params: {
type:
| "song"
| "album"
| "artist"
| "playlist"
| "podcast"
| "podcast_episode"
| "video"
| "tvshow"
| "tvshow_season";
id: UID;
rating: 0 | 1 | 2 | 3 | 4 | 5;
}) {
let query = "rate";
query += qs.stringify(params, "&");
return this.request<Success>(query);
}
/**
* This flags a library item as a favorite
* @remarks MINIMUM_API_VERSION=400001
* @param params.type Object type
* @param params.id UID to find
* @param params.flag 0, 1
* @param [params.date] UNIXTIME
* @see {@link https://ampache.org/api/api-json-methods#flag}
*/
flag(params: {
type:
| "song"
| "album"
| "artist"
| "playlist"
| "podcast"
| "podcast_episode"
| "video"
| "tvshow"
| "tvshow_season";
id: UID;
flag: BinaryBoolean;
date?: number;
}) {
let query = "flag";
query += qs.stringify(params, "&");
return this.request<Success>(query);
}
/**
* Take a song_id and update the object_count and user_activity table with a play. This allows other sources to record play history to Ampache.
* If you don't supply a user id (optional) then just fall back to you.
* ACCESS REQUIRED: 100 (Admin) permission to change another user's play history
* @remarks MINIMUM_API_VERSION=400001
* @param params.id UID of song
* @param [params.user] UID of user
* @param [params.client] Client string
* @param [params.date] UNIXTIME
* @see {@link https://ampache.org/api/api-json-methods#record_play}
*/
recordPlay(params: { id: UID; user?: UID; client?: string; date?: number }) {
let query = "record_play";
query += qs.stringify(params, "&");
return this.request<Success>(query);
}
/**
* Search for a song using text info and then record a play if found. This allows other sources to record play history to ampache
* @remarks MINIMUM_API_VERSION=400001
* @param params.song HTML encoded string
* @param params.artist HTML encoded string
* @param params.album HTML encoded string
* @param [params.songmbid] Song MBID
* @param [params.artistmbid] Artist MBID
* @param [params.albummbid] Album MBID
* @param [params.song_mbid] Alias of songmbid
* @param [params.artist_mbid] Alias of artistmbid
* @param [params.album_mbid] Alias of albummbid
* @param [params.date] UNIXTIME
* @param [params.client] Client string
* @see {@link https://ampache.org/api/api-json-methods#scrobble}
*/
scrobble(params: {
song: string;
artist: string;
album: string;
songmbid?: string;
artistmbid?: string;
albummbid?: string;
song_mbid?: string;
artist_mbid?: string;
album_mbid?: string;
date?: number;
client?: string;
}) {
let query = "scrobble";
query += qs.stringify(params, "&");
return this.request<Success>(query);
}
/**
* Update a single album, artist, song from the tag data
* @remarks MINIMUM_API_VERSION=400001
* @param params.type Object type
* @param params.id UID to find
* @see {@link https://ampache.org/api/api-json-methods#update_from_tags}
*/
updateFromTags(params: { type: "song" | "artist" | "album"; id: UID }) {
let query = "update_from_tags";
query += qs.stringify(params, "&");
return this.request<Success>(query);
}
/**
* Update artist information and fetch similar artists from last.fm
* Make sure lastfm_API_key is set in your configuration file
* ACCESS REQUIRED: 75 (Catalog Manager)
* @remarks MINIMUM_API_VERSION=400001
* @param params.id UID to find
* @see {@link https://ampache.org/api/api-json-methods#update_artist_info}
*/
updateArtistInfo(params: { id: UID }) {
let query = "update_artist_info";
query += qs.stringify(params, "&");
return this.request<Success>(query);
}
/**
* Updates a single album, artist, song running the gather_art process.
* Doesn't overwrite existing art by default.
* ACCESS REQUIRED: 75 (Catalog Manager)
* @remarks MINIMUM_API_VERSION=400001
* @param params.id UID to update
* @param params.type Object type
* @param [params.overwrite]
* @see {@link https://ampache.org/api/api-json-methods#update_art}
*/
updateArt(params: {
id: UID;
type: "artist" | "album" | "song";
overwrite?: BinaryBoolean;
}) {
let query = "update_art";
query += qs.stringify(params, "&");
return this.request<Success>(query);
}
/**
* Streams a given media file. Takes the file id in parameter with optional max bit rate, file format, time offset,
* size and estimate content length option.
* NOTE search and playlist will only stream a random object from the list.
* @remarks MINIMUM_API_VERSION=400001
* @param params.id UID to find
* @param params.type Object type
* @param [params.bitrate] Max bitrate for transcoding
* @param [params.format] mp3, ogg, raw, etc. (raw returns the original format)
* @param [params.offset] Time offset
* @param [params.length] 0, 1 (estimate content length)
* @param [params.stats] 0, 1 (if false disable stat recording when playing the object; default: 1)
* @see {@link https://ampache.org/api/api-json-methods#stream}
*/
stream(params: {
id: UID;
type: "song" | "podcast_episode" | "search" | "playlist";
bitrate?: number;
format?: string;
offset?: number;
length?: BinaryBoolean;
stats?: BinaryBoolean;
}) {
let query = "stream";
query += qs.stringify(params, "&");
return this.binary(query);
}
/**
* Downloads a given media file. set format=raw to download the full file
* NOTE search and playlist will only download a random object from the list
* @remarks MINIMUM_API_VERSION=400001
* @param params.id UID to find
* @param params.type Object type
* @param [params.format] mp3, ogg, raw, etc. (raw returns the original format)
* @param [params.bitrate] max bitrate for transcoding in bytes (e.g 192000=192Kb)
* @param [params.stats] 0, 1 (if false disable stat recording when playing the object; default: 1)
* @see {@link https://ampache.org/api/api-json-methods#download}
*/
download(params: {
id: UID;
type: "song" | "podcast_episode" | "search" | "playlist";
format?: string;
bitrate?: number;
stats?: BinaryBoolean;
}) {
let query = "download";
query += qs.stringify(params, "&");
return this.binary(query);
}
/**
* Get an art image file.
* @remarks MINIMUM_API_VERSION=400001
* @param params.id UID to find
* @param params.type Object type
* @param [params.size] width x height (e.g. '640x480')
* @see {@link https://ampache.org/api/api-json-methods#get_art}
*/
getArt(params: {
id: UID;
type: "song" | "artist" | "album" | "playlist" | "search" | "podcast";
size?: string;
}) {
let query = "get_art";
query += qs.stringify(params, "&");
return this.binary(query);
}
/**
* This is for controlling localplay
* @param params.command The command to send to the localplay controller
* @param [params.oid] Object UID
* @param [params.type] Object type
* @param [params.clear] 0, 1 (Clear the current playlist before adding)
* @remarks MINIMUM_API_VERSION=380001; CHANGED_IN_API_VERSION=5.0.0
* @see {@link https://ampache.org/api/api-json-methods#localplay}
*/
localplay(params: {
command:
| "next"
| "prev"
| "stop"
| "play"
| "pause"
| "add"
| "volume_up"
| "volume_down"
| "volume_mute"
| "delete_all"
| "skip"
| "status";
oid?: number;
type?:
| "song"
| "video"
| "podcast_episode"
| "channel"
| "broadcast"
| "democratic"
| "live_stream";
clear?: BinaryBoolean;
}) {
let query = "localplay";
query += qs.stringify(params, "&");
return this.request(query);
}
/**
* Get the list of songs in your localplay playlist
* @remarks MINIMUM_API_VERSION=5.0.0
* @see {@link https://ampache.org/api/api-json-methods#localplay_songs}
*/
localplaySongs() {
let query = "localplay_songs";
return this.request(query);
}
/**
* This is for controlling democratic play (Songs only). VOTE: +1 vote for the oid. DEVOTE: -1 vote for the oid.
* PLAYLIST: Return an array of song items with an additional VOTE COUNT element.
* PLAY: Returns the URL for playing democratic play.
* @remarks MINIMUM_API_VERSION=380001
* @param params.oid UID of song
* @param params.method vote, devote, playlist, play
* @see {@link https://ampache.org/api/api-json-methods#democratic}
*/
democratic(params: {
oid: UID;
method: "vote" | "devote" | "playlist" | "play";
}) {
let query = "democratic";
query += qs.stringify(params, "&");
return this.request(query);
}
/**
* Get what is currently being played by all users.
* @remarks MINIMUM_API_VERSION=6.3.1
* @see {@link https://ampache.org/api/api-json-methods#now_playing}
*/
nowPlaying() {
let query = "now_playing";
return this.request<{ now_playing: NowPlayingResponse[] }>(query);
}
/**
* Inform the server about the state of your client. (Song you are playing, Play/Pause state, etc.)
* @remarks MINIMUM_API_VERSION=6.4.0
* @param params.filter $object_id currently playing/stopping
* @param [params.type] song, video, podcast_episode (Default: song)
* @param [params.state] play, stop (Default: play)
* @param [params.time] current play time in whole seconds (Default: 0)
* @param [params.client] agent/client name
* @see {@link https://ampache.org/api/api-json-methods#player}
*/
player(params: {
filter: UID;
type?: "song" | "video" | "podcast_episode";
state?: "play" | "stop";
time?: number;
client?: string;
}) {
let query = "player";
query += qs.stringify(params, "&");
return this.request<{ now_playing: NowPlayingResponse[] }>(query);
}
/**
* Perform an advanced search given passed rules.
* You'll want to consult the docs for this.
* @remarks MINIMUM_API_VERSION=380001
* @param params.operator and, or (whether to match one rule or all)
* @param params.type Object type to return
* @param params.rules An array of rules
* @param [params.random] 0, 1 (random order of results; default to 0)
* @param [params.offset]
* @param [params.limit]
* @see {@link https://ampache.org/api/api-json-methods#advanced_search}
*/
advancedSearch(
params: {
operator: "and" | "or";
type:
| "song"
| "album"
| "album_disk"
| "artist"
| "album_artist"
| "song_artist"
| "label"
| "playlist"
| "podcast"
| "podcast_episode"
| "genre"
| "user"
| "video";
rules: Array<Array<string>>;
random?: BinaryBoolean;
} & Pagination,
) {
let query = "advanced_search";
for (let i = 0; i < params.rules.length; i++) {
const thisRule = params.rules[i];
const ruleNumber = i + 1;
params["rule_" + ruleNumber] = thisRule[0];
params["rule_" + ruleNumber + "_operator"] = thisRule[1];
params["rule_" + ruleNumber + "_input"] = thisRule[2];
if (thisRule[0] === "metadata") {
params["rule_" + ruleNumber + "_subtype"] = thisRule[3];
}
}
// drop the initial 'rules' as it was split into its parts
delete params.rules;
query += qs.stringify(params, "&");
let data;
switch (params.type) {
case "song":
data = this.request<SongsResponse>(query);
break;
case "album":
data = this.request<AlbumsResponse>(query);
break;
case "artist":
case "album_artist":
case "song_artist":
data = this.request<ArtistsResponse>(query);
break;
case "label":
data = this.request<LabelsResponse>(query);
break;
case "playlist":
data = this.request<PlaylistsResponse>(query);
break;
case "podcast":
data = this.request<PodcastsResponse>(query);
break;
case "podcast_episode":
data = this.request<PodcastEpisodesResponse>(query);
break;
case "genre":
data = this.request<GenresResponse>(query);
break;
case "user":
data = this.request<UsersResponse>(query);
break;
case "video":
data = this.request<VideosResponse>(query);
break;
default:
return false;
}
return data;
}
// alias of advanced_search
search = this.advancedSearch;
/**
* Perform a search given passed rules and return matching objects in a group.
* If the rules do not exist for the object type or would return the entire table they will not return objects
* You'll want to consult the docs for this.
* @remarks MINIMUM_API_VERSION=6.3.0
* @param params.operator and, or (whether to match one rule or all)
* @param params.rules An array of rules
* @param [params.type] Object type to return (all, music, song_artist, album_artist, podcast, video; all by default)
* @param [params.random] 0, 1 (random order of results; default to 0)
* @param [params.offset]
* @param [params.limit]
* @see {@link https://ampache.org/api/api-json-methods#search_group}
*/
searchGroup(
params: {
operator: "and" | "or";
rules: Array<Array<string>>;
type?:
| "all"
| "music"
| "song_artist"
| "album_artist"
| "podcast"
| "video";
random?: BinaryBoolean;
} & Pagination,
) {
let query = "search_group";
for (let i = 0; i < params.rules.length; i++) {
const thisRule = params.rules[i];
const ruleNumber = i + 1;
params["rule_" + ruleNumber] = thisRule[0];
params["rule_" + ruleNumber + "_operator"] = thisRule[1];
params["rule_" + ruleNumber + "_input"] = thisRule[2];
if (thisRule[0] === "metadata") {
params["rule_" + ruleNumber + "_subtype"] = thisRule[3];
}
}
// drop the initial 'rules' as it was split into its parts
delete params.rules;
query += qs.stringify(params, "&");
let data;
switch (params.type) {
case "music":
data = this.request<{ search: {
song: SongResponse[];
album: AlbumResponse[];
artist: ArtistResponse[];
}
}>(query);
break;
case "song_artist":
data = this.request<{ search: {
song: SongResponse[];
album: AlbumResponse[];
song_artist: ArtistResponse[];
}
}>(query);
break;
case "album_artist":
data = this.request<{ search: {
song: SongResponse[];
album: AlbumResponse[];
album_artist: ArtistResponse[];
}
}>(query);
break;
case "podcast":
data = this.request<{ search: {
podcast: PodcastResponse[];
podcast_episode: PodcastEpisodeResponse[];
}
}>(query);
break;
case "video":
data = this.request<{ search: {
video: VideoResponse[];
}
}>(query);
break;
case "all":
default:
data = this.request<{ search: {
song: SongResponse[];
album: AlbumResponse[];
artist: ArtistResponse[];
song_artist: ArtistResponse[];
album_artist: ArtistResponse[];
label: LabelResponse[];
playlist: PlaylistResponse[];
podcast: PodcastResponse[];
podcast_episode: PodcastEpisodeResponse[];
genre: GenreResponse[];
user: UserResponse[];
}
}>(query);
}
return data;
}
}