package api
import "github.com/Moosync/extensions-sdk/wasm-extension-go/pkg/api"
Functions
func AddPlaylist
func AddPlaylist(playlist *songs.Playlist) (string, error) {
cmd := &extensions.MainCommand{
Command: &extensions.MainCommand_AddPlaylist{
AddPlaylist: &extensions.AddPlaylistRequest{Playlist: playlist},
},
}
resp, err := sendMainCommand(cmd)
if err != nil {
return "", err
}
return resp.GetAddPlaylist().GetPlaylistId(), nil
}
func AddSongs
func AddSongs(s []*songs.Song) error {
cmd := &extensions.MainCommand{
Command: &extensions.MainCommand_AddSongs{
AddSongs: &extensions.AddSongsRequest{Songs: s},
},
}
_, err := sendMainCommand(cmd)
return err
}
func AddToPlaylist
func AddToPlaylist(req *extensions.AddToPlaylistRequest) error {
cmd := &extensions.MainCommand{
Command: &extensions.MainCommand_AddToPlaylist{
AddToPlaylist: req,
},
}
_, err := sendMainCommand(cmd)
return err
}
func DurationToProto
// DurationToProto converts a native time.Duration to a protobuf duration.
func DurationToProto(d time.Duration) *durationpb.Duration {
return durationpb.New(d)
}
DurationToProto converts a native time.Duration to a protobuf duration.
func EnableHttp
func EnableHttp() {
http.DefaultTransport = &pdkhttp.HTTPTransport{}
}
func GetCurrentSong
func GetCurrentSong() (*songs.Song, error) {
cmd := &extensions.MainCommand{
Command: &extensions.MainCommand_GetCurrentSong{
GetCurrentSong: &extensions.GetCurrentSongRequest{},
},
}
resp, err := sendMainCommand(cmd)
if err != nil {
return nil, err
}
return resp.GetGetCurrentSong().GetSong(), nil
}
func GetPlayerState
func GetPlayerState() (extensions.PlayerState, error) {
cmd := &extensions.MainCommand{
Command: &extensions.MainCommand_GetPlayerState{
GetPlayerState: &extensions.GetPlayerStateRequest{},
},
}
resp, err := sendMainCommand(cmd)
if err != nil {
return extensions.PlayerState_STOPPED, err
}
return resp.GetGetPlayerState().GetState(), nil
}
func GetPreference
func GetPreference(data *extensions.PreferenceData) (*extensions.PreferenceData, error) {
cmd := &extensions.MainCommand{
Command: &extensions.MainCommand_GetPreference{
GetPreference: &extensions.GetPreferenceRequest{Data: data},
},
}
resp, err := sendMainCommand(cmd)
if err != nil {
return nil, err
}
return resp.GetGetPreference().GetData(), nil
}
func GetQueue
func GetQueue() (any, error) {
cmd := &extensions.MainCommand{
Command: &extensions.MainCommand_GetQueue{
GetQueue: &extensions.GetQueueRequest{},
},
}
resp, err := sendMainCommand(cmd)
if err != nil {
return nil, err
}
return resp.GetGetQueue().GetQueue(), nil
}
func GetSecure
func GetSecure(data *extensions.PreferenceData) (*extensions.PreferenceData, error) {
cmd := &extensions.MainCommand{
Command: &extensions.MainCommand_GetSecure{
GetSecure: &extensions.GetSecureRequest{Data: data},
},
}
resp, err := sendMainCommand(cmd)
if err != nil {
return nil, err
}
return resp.GetGetSecure().GetData(), nil
}
func GetSong
func GetSong(options *songs.GetSongOptions) ([]*songs.Song, error) {
cmd := &extensions.MainCommand{
Command: &extensions.MainCommand_GetSong{
GetSong: &extensions.GetSongRequest{Options: options},
},
}
resp, err := sendMainCommand(cmd)
if err != nil {
return nil, err
}
return resp.GetGetSong().GetSongs(), nil
}
func GetTime
func GetTime() (float64, error) {
cmd := &extensions.MainCommand{
Command: &extensions.MainCommand_GetTime{
GetTime: &extensions.GetTimeRequest{},
},
}
resp, err := sendMainCommand(cmd)
if err != nil {
return 0, err
}
return resp.GetGetTime().GetTime(), nil
}
func GetVolume
func GetVolume() (float64, error) {
cmd := &extensions.MainCommand{
Command: &extensions.MainCommand_GetVolume{
GetVolume: &extensions.GetVolumeRequest{},
},
}
resp, err := sendMainCommand(cmd)
if err != nil {
return 0, err
}
return resp.GetGetVolume().GetVolume(), nil
}
func Hash
func Hash(hashType HashType, data []byte) []byte {
memType := pdk.AllocateString(string(hashType))
memData := pdk.AllocateBytes(data)
rPtr := hash(memType.Offset(), memData.Offset())
rMem := pdk.FindMemory(rPtr)
return rMem.ReadBytes()
}
func LogDebug
func LogDebug(format string, args ...any) {
pdk.Log(pdk.LogDebug, fmt.Sprintf(format, args...))
}
func LogError
func LogError(format string, args ...any) {
pdk.Log(pdk.LogError, fmt.Sprintf(format, args...))
}
func LogInfo
func LogInfo(format string, args ...any) {
pdk.Log(pdk.LogInfo, fmt.Sprintf(format, args...))
}
func LogTrace
func LogTrace(format string, args ...any) {
pdk.Log(pdk.LogTrace, fmt.Sprintf(format, args...))
}
func LogWarn
func LogWarn(format string, args ...any) {
pdk.Log(pdk.LogWarn, fmt.Sprintf(format, args...))
}
func OpenExternalUrl
func OpenExternalUrl(url string) error {
cmd := &extensions.MainCommand{
Command: &extensions.MainCommand_OpenExternalUrl{
OpenExternalUrl: &extensions.OpenExternalUrlRequest{Url: url},
},
}
_, err := sendMainCommand(cmd)
return err
}
func OpenSock
func OpenSock(path string) int64 {
mem := pdk.AllocateString(path)
rPtr := open_clientfd(mem.Offset())
rMem := pdk.FindMemory(rPtr)
return int64(binary.LittleEndian.Uint64(rMem.ReadBytes()))
}
func ReadSock
func ReadSock(sockId int64, readLen uint64) []byte {
rPtr := read_sock(sockId, readLen)
rMem := pdk.FindMemory(rPtr)
return rMem.ReadBytes()
}
func RegisterExtension
func RegisterExtension(newExtension Extension) {
if extension != nil {
pdk.Log(pdk.LogError, "Extension cannot be re-registered")
panic("Extension cannot be re-registered")
}
extension = newExtension
}
func RegisterOAuth
func RegisterOAuth(url string) error {
cmd := &extensions.MainCommand{
Command: &extensions.MainCommand_RegisterOauth{
RegisterOauth: &extensions.RegisterOauthRequest{Url: url},
},
}
_, err := sendMainCommand(cmd)
return err
}
func RegisterUserPreference
func RegisterUserPreference(prefs []*ui.PreferenceUiData) error {
cmd := &extensions.MainCommand{
Command: &extensions.MainCommand_RegisterUserPreference{
RegisterUserPreference: &extensions.RegisterUserPreferenceRequest{Prefs: prefs},
},
}
_, err := sendMainCommand(cmd)
return err
}
func RemoveSong
func RemoveSong(s *songs.Song) error {
cmd := &extensions.MainCommand{
Command: &extensions.MainCommand_RemoveSong{
RemoveSong: &extensions.RemoveSongRequest{Song: s},
},
}
_, err := sendMainCommand(cmd)
return err
}
func SetPreference
func SetPreference(data *extensions.PreferenceData) error {
cmd := &extensions.MainCommand{
Command: &extensions.MainCommand_SetPreference{
SetPreference: &extensions.SetPreferenceRequest{Data: data},
},
}
_, err := sendMainCommand(cmd)
return err
}
func SetSecure
func SetSecure(data *extensions.PreferenceData) error {
cmd := &extensions.MainCommand{
Command: &extensions.MainCommand_SetSecure{
SetSecure: &extensions.SetSecureRequest{Data: data},
},
}
_, err := sendMainCommand(cmd)
return err
}
func SystemTime
func SystemTime() uint64 {
rPtr := system_time()
rMem := pdk.FindMemory(rPtr)
return binary.LittleEndian.Uint64(rMem.ReadBytes())
}
func UnregisterUserPreference
func UnregisterUserPreference(keys []string) error {
cmd := &extensions.MainCommand{
Command: &extensions.MainCommand_UnregisterUserPreference{
UnregisterUserPreference: &extensions.UnregisterUserPreferenceRequest{Keys: keys},
},
}
_, err := sendMainCommand(cmd)
return err
}
func UpdateAccounts
func UpdateAccounts(account *string) error {
cmd := &extensions.MainCommand{
Command: &extensions.MainCommand_UpdateAccounts{
UpdateAccounts: &extensions.UpdateAccountsRequest{Account: account},
},
}
_, err := sendMainCommand(cmd)
return err
}
func UpdateSong
func UpdateSong(s *songs.Song) error {
cmd := &extensions.MainCommand{
Command: &extensions.MainCommand_UpdateSong{
UpdateSong: &extensions.UpdateSongRequest{Song: s},
},
}
_, err := sendMainCommand(cmd)
return err
}
func WriteSock
func WriteSock(sockId int64, buf []byte) int64 {
mem := pdk.AllocateBytes(buf)
rPtr := write_sock(sockId, mem.Offset())
rMem := pdk.FindMemory(rPtr)
return int64(binary.LittleEndian.Uint64(rMem.ReadBytes()))
}
func batch_http_request
//go:wasmimport extism:host/user batch_http_request
func batch_http_request(uint64) uint64
func handle_extension_command
//go:wasmexport handle_extension_command
func handle_extension_command() int32 {
inputBytes := pdk.Input()
cmd := &extensions.ExtensionCommand{}
if err := proto.Unmarshal(inputBytes, cmd); err != nil {
pdk.SetError(err)
return 1
}
resp := &extensions.ExtensionCommandResponse{}
switch e := cmd.Event.(type) {
case *extensions.ExtensionCommand_RequestedPlaylists:
res, err := extension.GetPlaylists(e.RequestedPlaylists)
if err != nil {
pdk.SetError(err)
return 1
}
resp.Response = &extensions.ExtensionCommandResponse_RequestedPlaylists{
RequestedPlaylists: &extensions.RequestedPlaylistsResponse{Playlists: res},
}
case *extensions.ExtensionCommand_RequestedPlaylistSongs:
res, err := extension.GetPlaylistContent(e.RequestedPlaylistSongs)
if err != nil {
pdk.SetError(err)
return 1
}
resp.Response = &extensions.ExtensionCommandResponse_RequestedPlaylistSongs{
RequestedPlaylistSongs: res,
}
case *extensions.ExtensionCommand_OauthCallback:
err := extension.OauthCallback(e.OauthCallback)
if err != nil {
pdk.SetError(err)
return 1
}
resp.Response = &extensions.ExtensionCommandResponse_OauthCallback{
OauthCallback: &extensions.OauthCallbackResponse{},
}
case *extensions.ExtensionCommand_SongQueueChanged:
err := extension.OnQueueChanged(e.SongQueueChanged)
if err != nil {
pdk.SetError(err)
return 1
}
resp.Response = &extensions.ExtensionCommandResponse_SongQueueChanged{
SongQueueChanged: &extensions.SongQueueChangedResponse{},
}
case *extensions.ExtensionCommand_Seeked:
err := extension.OnSeeked(e.Seeked)
if err != nil {
pdk.SetError(err)
return 1
}
resp.Response = &extensions.ExtensionCommandResponse_Seeked{
Seeked: &extensions.SeekedResponse{},
}
case *extensions.ExtensionCommand_VolumeChanged:
err := extension.OnVolumeChanged(e.VolumeChanged)
if err != nil {
pdk.SetError(err)
return 1
}
resp.Response = &extensions.ExtensionCommandResponse_VolumeChanged{
VolumeChanged: &extensions.VolumeChangedResponse{},
}
case *extensions.ExtensionCommand_PlayerStateChanged:
err := extension.OnPlayerStateChanged(e.PlayerStateChanged)
if err != nil {
pdk.SetError(err)
return 1
}
resp.Response = &extensions.ExtensionCommandResponse_PlayerStateChanged{
PlayerStateChanged: &extensions.PlayerStateChangedResponse{},
}
case *extensions.ExtensionCommand_SongChanged:
err := extension.OnSongChanged(e.SongChanged)
if err != nil {
pdk.SetError(err)
return 1
}
resp.Response = &extensions.ExtensionCommandResponse_SongChanged{
SongChanged: &extensions.SongChangedResponse{},
}
case *extensions.ExtensionCommand_PreferenceChanged:
err := extension.OnPreferencesChanged(e.PreferenceChanged)
if err != nil {
pdk.SetError(err)
return 1
}
resp.Response = &extensions.ExtensionCommandResponse_PreferenceChanged{
PreferenceChanged: &extensions.PreferenceChangedResponse{},
}
case *extensions.ExtensionCommand_PlaybackDetailsRequested:
res, err := extension.GetPlaybackDetails(e.PlaybackDetailsRequested)
if err != nil {
pdk.SetError(err)
return 1
}
resp.Response = &extensions.ExtensionCommandResponse_PlaybackDetailsRequested{
PlaybackDetailsRequested: res,
}
case *extensions.ExtensionCommand_CustomRequest:
res, err := extension.HandleCustomRequest(e.CustomRequest)
if err != nil {
pdk.SetError(err)
return 1
}
resp.Response = &extensions.ExtensionCommandResponse_CustomRequest{
CustomRequest: res,
}
case *extensions.ExtensionCommand_RequestedSongFromUrl:
res, err := extension.GetSongFromURL(e.RequestedSongFromUrl)
if err != nil {
pdk.SetError(err)
return 1
}
resp.Response = &extensions.ExtensionCommandResponse_RequestedSongFromUrl{
RequestedSongFromUrl: res,
}
case *extensions.ExtensionCommand_RequestedPlaylistFromUrl:
res, err := extension.GetPlaylistFromURL(e.RequestedPlaylistFromUrl)
if err != nil {
pdk.SetError(err)
return 1
}
resp.Response = &extensions.ExtensionCommandResponse_RequestedPlaylistFromUrl{
RequestedPlaylistFromUrl: res,
}
case *extensions.ExtensionCommand_RequestedSearchResult:
res, err := extension.Search(e.RequestedSearchResult)
if err != nil {
pdk.SetError(err)
return 1
}
resp.Response = &extensions.ExtensionCommandResponse_RequestedSearchResult{
RequestedSearchResult: &extensions.RequestedSearchResultResponse{
Songs: res.Songs,
Playlists: res.Playlists,
Artists: res.Artists,
Albums: res.Albums,
},
}
case *extensions.ExtensionCommand_RequestedRecommendations:
res, err := extension.GetRecommendations(e.RequestedRecommendations)
if err != nil {
pdk.SetError(err)
return 1
}
resp.Response = &extensions.ExtensionCommandResponse_RequestedRecommendations{
RequestedRecommendations: &extensions.RequestedRecommendationsResponse{Songs: res},
}
case *extensions.ExtensionCommand_RequestedLyrics:
res, err := extension.GetLyrics(e.RequestedLyrics)
if err != nil {
pdk.SetError(err)
return 1
}
resp.Response = &extensions.ExtensionCommandResponse_RequestedLyrics{
RequestedLyrics: &extensions.RequestedLyricsResponse{Lyrics: res},
}
case *extensions.ExtensionCommand_RequestedArtistSongs:
res, err := extension.GetArtistSongs(e.RequestedArtistSongs)
if err != nil {
pdk.SetError(err)
return 1
}
resp.Response = &extensions.ExtensionCommandResponse_RequestedArtistSongs{
RequestedArtistSongs: res,
}
case *extensions.ExtensionCommand_RequestedAlbumSongs:
res, err := extension.GetAlbumSongs(e.RequestedAlbumSongs)
if err != nil {
pdk.SetError(err)
return 1
}
resp.Response = &extensions.ExtensionCommandResponse_RequestedAlbumSongs{
RequestedAlbumSongs: res,
}
case *extensions.ExtensionCommand_SongAdded:
err := extension.OnSongAdded(e.SongAdded)
if err != nil {
pdk.SetError(err)
return 1
}
resp.Response = &extensions.ExtensionCommandResponse_SongAdded{
SongAdded: &extensions.SongAddedResponse{},
}
case *extensions.ExtensionCommand_SongRemoved:
err := extension.OnSongRemoved(e.SongRemoved)
if err != nil {
pdk.SetError(err)
return 1
}
resp.Response = &extensions.ExtensionCommandResponse_SongRemoved{
SongRemoved: &extensions.SongRemovedResponse{},
}
case *extensions.ExtensionCommand_PlaylistAdded:
err := extension.OnPlaylistAdded(e.PlaylistAdded)
if err != nil {
pdk.SetError(err)
return 1
}
resp.Response = &extensions.ExtensionCommandResponse_PlaylistAdded{
PlaylistAdded: &extensions.PlaylistAddedResponse{},
}
case *extensions.ExtensionCommand_PlaylistRemoved:
err := extension.OnPlaylistRemoved(e.PlaylistRemoved)
if err != nil {
pdk.SetError(err)
return 1
}
resp.Response = &extensions.ExtensionCommandResponse_PlaylistRemoved{
PlaylistRemoved: &extensions.PlaylistRemovedResponse{},
}
case *extensions.ExtensionCommand_RequestedSongFromId:
res, err := extension.GetSongFromID(e.RequestedSongFromId)
if err != nil {
pdk.SetError(err)
return 1
}
resp.Response = &extensions.ExtensionCommandResponse_RequestedSongFromId{
RequestedSongFromId: res,
}
case *extensions.ExtensionCommand_GetRemoteUrl:
pdk.SetError(fmt.Errorf("GetRemoteUrl not implemented"))
return 1
case *extensions.ExtensionCommand_Scrobble:
err := extension.Scrobble(e.Scrobble)
if err != nil {
pdk.SetError(err)
return 1
}
resp.Response = &extensions.ExtensionCommandResponse_Scrobble{
Scrobble: &extensions.ScrobbleResponse{},
}
case *extensions.ExtensionCommand_RequestedSongContextMenu:
_, err := extension.GetSongContextMenu(e.RequestedSongContextMenu)
if err != nil {
pdk.SetError(err)
return 1
}
pdk.SetError(fmt.Errorf("GetSongContextMenu not fully implemented due to proto ambiguity"))
return 1
case *extensions.ExtensionCommand_RequestedPlaylistContextMenu:
pdk.SetError(fmt.Errorf("GetPlaylistContextMenu not fully implemented"))
return 1
case *extensions.ExtensionCommand_ContextMenuAction:
err := extension.OnContextMenuAction(e.ContextMenuAction)
if err != nil {
pdk.SetError(err)
return 1
}
resp.Response = &extensions.ExtensionCommandResponse_ContextMenuAction{
ContextMenuAction: &extensions.ContextMenuActionResponse{},
}
case *extensions.ExtensionCommand_GetProviderScopes:
res, err := extension.GetProviderScopes()
if err != nil {
pdk.SetError(err)
return 1
}
resp.Response = &extensions.ExtensionCommandResponse_GetProviderScopes{
GetProviderScopes: &extensions.GetProviderScopesResponse{Scopes: res},
}
case *extensions.ExtensionCommand_GetAccounts:
res, err := extension.GetAccounts()
if err != nil {
pdk.SetError(err)
return 1
}
resp.Response = &extensions.ExtensionCommandResponse_GetAccounts{
GetAccounts: &extensions.GetAccountsResponse{Accounts: res},
}
case *extensions.ExtensionCommand_PerformAccountLogin:
res, err := extension.PerformAccountLogin(e.PerformAccountLogin)
if err != nil {
pdk.SetError(err)
return 1
}
resp.Response = &extensions.ExtensionCommandResponse_PerformAccountLogin{
PerformAccountLogin: &extensions.PerformAccountLoginResponse{Status: res},
}
default:
pdk.Log(pdk.LogError, fmt.Sprintf("Unknown event: %T", cmd.Event))
return 1
}
outBytes, err := proto.Marshal(resp)
if err != nil {
pdk.SetError(err)
return 1
}
pdk.Output(outBytes)
return 0
}
func hash
//go:wasmimport extism:host/user hash
func hash(uint64, uint64) uint64
func init
func init() {
_ = handle_extension_command
}
func open_clientfd
//go:wasmimport extism:host/user open_clientfd
func open_clientfd(uint64) uint64
func read_sock
//go:wasmimport extism:host/user read_sock
func read_sock(int64, uint64) uint64
func sendMainCommand
func sendMainCommand(cmd *extensions.MainCommand) (*extensions.MainCommandResponse, error) {
inBytes, err := proto.Marshal(cmd)
if err != nil {
return nil, err
}
mem := pdk.AllocateBytes(inBytes)
defer mem.Free()
rPtr := send_main_command(mem.Offset())
rMem := pdk.FindMemory(rPtr)
respBytes := rMem.ReadBytes()
resp := &extensions.MainCommandResponse{}
err = proto.Unmarshal(respBytes, resp)
if err != nil {
return nil, err
}
if errProto := resp.GetError(); errProto != nil {
return nil, errors.New(errProto.Message)
}
return resp, nil
}
func send_main_command
//go:wasmimport extism:host/user send_main_command
func send_main_command(uint64) uint64
func system_time
//go:wasmimport extism:host/user system_time
func system_time() uint64
func write_sock
//go:wasmimport extism:host/user write_sock
func write_sock(int64, uint64) uint64
Types
type DefaultExtension
type DefaultExtension struct{}
func (DefaultExtension) GetAccounts
func (DefaultExtension) GetAccounts() ([]*extensions.ExtensionAccountDetail, error) {
return nil, errors.New("Not implemented")
}
func (DefaultExtension) GetAlbumSongs
func (DefaultExtension) GetAlbumSongs(req *extensions.RequestedAlbumSongsRequest) (*extensions.RequestedAlbumSongsResponse, error) {
return nil, errors.New("Not implemented")
}
func (DefaultExtension) GetArtistSongs
func (DefaultExtension) GetArtistSongs(req *extensions.RequestedArtistSongsRequest) (*extensions.RequestedArtistSongsResponse, error) {
return nil, errors.New("Not implemented")
}
func (DefaultExtension) GetLyrics
func (DefaultExtension) GetLyrics(req *extensions.RequestedLyricsRequest) (string, error) {
return "", errors.New("Not implemented")
}
func (DefaultExtension) GetPlaybackDetails
func (DefaultExtension) GetPlaybackDetails(req *extensions.PlaybackDetailsRequestedRequest) (*extensions.PlaybackDetailsRequestedResponse, error) {
return nil, errors.New("Not implemented")
}
func (DefaultExtension) GetPlaylistContent
func (DefaultExtension) GetPlaylistContent(req *extensions.RequestedPlaylistSongsRequest) (*extensions.RequestedPlaylistSongsResponse, error) {
return nil, errors.New("Not implemented")
}
func (DefaultExtension) GetPlaylistContextMenu
func (DefaultExtension) GetPlaylistContextMenu(req *extensions.RequestedPlaylistContextMenuRequest) ([]*extensions.ContextMenuReturnType, error) {
return nil, errors.New("Not implemented")
}
func (DefaultExtension) GetPlaylistFromURL
func (DefaultExtension) GetPlaylistFromURL(req *extensions.RequestedPlaylistFromUrlRequest) (*extensions.RequestedPlaylistFromUrlResponse, error) {
return nil, errors.New("Not implemented")
}
func (DefaultExtension) GetPlaylists
func (DefaultExtension) GetPlaylists(req *extensions.RequestedPlaylistsRequest) ([]*songs.Playlist, error) {
return nil, errors.New("Not implemented")
}
func (DefaultExtension) GetProviderScopes
func (DefaultExtension) GetProviderScopes() ([]extensions.ExtensionProviderScope, error) {
return nil, errors.New("Not implemented")
}
func (DefaultExtension) GetRecommendations
func (DefaultExtension) GetRecommendations(req *extensions.RequestedRecommendationsRequest) ([]*songs.Song, error) {
return nil, errors.New("Not implemented")
}
func (DefaultExtension) GetSongContextMenu
func (DefaultExtension) GetSongContextMenu(req *extensions.RequestedSongContextMenuRequest) ([]*extensions.ContextMenuReturnType, error) {
return nil, errors.New("Not implemented")
}
func (DefaultExtension) GetSongFromID
func (DefaultExtension) GetSongFromID(req *extensions.RequestedSongFromIdRequest) (*extensions.RequestedSongFromIdResponse, error) {
return nil, errors.New("Not implemented")
}
func (DefaultExtension) GetSongFromURL
func (DefaultExtension) GetSongFromURL(req *extensions.RequestedSongFromUrlRequest) (*extensions.RequestedSongFromUrlResponse, error) {
return nil, errors.New("Not implemented")
}
func (DefaultExtension) HandleCustomRequest
func (DefaultExtension) HandleCustomRequest(req *extensions.CustomRequest) (*extensions.CustomRequestResponse, error) {
return nil, errors.New("Not implemented")
}
func (DefaultExtension) OauthCallback
func (DefaultExtension) OauthCallback(req *extensions.OauthCallbackRequest) error {
return errors.New("Not implemented")
}
func (DefaultExtension) OnContextMenuAction
func (DefaultExtension) OnContextMenuAction(req *extensions.ContextMenuActionRequest) error {
return errors.New("Not implemented")
}
func (DefaultExtension) OnPlayerStateChanged
func (DefaultExtension) OnPlayerStateChanged(req *extensions.PlayerStateChangedRequest) error {
return errors.New("Not implemented")
}
func (DefaultExtension) OnPlaylistAdded
func (DefaultExtension) OnPlaylistAdded(req *extensions.PlaylistAddedRequest) error {
return errors.New("Not implemented")
}
func (DefaultExtension) OnPlaylistRemoved
func (DefaultExtension) OnPlaylistRemoved(req *extensions.PlaylistRemovedRequest) error {
return errors.New("Not implemented")
}
func (DefaultExtension) OnPreferencesChanged
func (DefaultExtension) OnPreferencesChanged(req *extensions.PreferenceChangedRequest) error {
return errors.New("Not implemented")
}
func (DefaultExtension) OnQueueChanged
func (DefaultExtension) OnQueueChanged(req *extensions.SongQueueChangedRequest) error {
return errors.New("Not implemented")
}
func (DefaultExtension) OnSeeked
func (DefaultExtension) OnSeeked(req *extensions.SeekedRequest) error {
return errors.New("Not implemented")
}
func (DefaultExtension) OnSongAdded
func (DefaultExtension) OnSongAdded(req *extensions.SongAddedRequest) error {
return errors.New("Not implemented")
}
func (DefaultExtension) OnSongChanged
func (DefaultExtension) OnSongChanged(req *extensions.SongChangedRequest) error {
return errors.New("Not implemented")
}
func (DefaultExtension) OnSongRemoved
func (DefaultExtension) OnSongRemoved(req *extensions.SongRemovedRequest) error {
return errors.New("Not implemented")
}
func (DefaultExtension) OnVolumeChanged
func (DefaultExtension) OnVolumeChanged(req *extensions.VolumeChangedRequest) error {
return errors.New("Not implemented")
}
func (DefaultExtension) PerformAccountLogin
func (DefaultExtension) PerformAccountLogin(req *extensions.PerformAccountLoginRequest) (string, error) {
return "", errors.New("Not implemented")
}
func (DefaultExtension) Scrobble
func (DefaultExtension) Scrobble(req *extensions.ScrobbleRequest) error {
return errors.New("Not implemented")
}
func (DefaultExtension) Search
func (DefaultExtension) Search(req *extensions.RequestedSearchResultRequest) (*songs.SearchResult, error) {
return nil, errors.New("Not implemented")
}
type Extension
type Extension interface {
GetAccounts() ([]*extensions.ExtensionAccountDetail, error)
PerformAccountLogin(req *extensions.PerformAccountLoginRequest) (string, error)
OauthCallback(req *extensions.OauthCallbackRequest) error
OnSongAdded(req *extensions.SongAddedRequest) error
OnSongRemoved(req *extensions.SongRemovedRequest) error
OnPlaylistAdded(req *extensions.PlaylistAddedRequest) error
OnPlaylistRemoved(req *extensions.PlaylistRemovedRequest) error
OnPreferencesChanged(req *extensions.PreferenceChangedRequest) error
OnQueueChanged(req *extensions.SongQueueChangedRequest) error
OnVolumeChanged(req *extensions.VolumeChangedRequest) error
OnPlayerStateChanged(req *extensions.PlayerStateChangedRequest) error
OnSongChanged(req *extensions.SongChangedRequest) error
OnSeeked(req *extensions.SeekedRequest) error
GetProviderScopes() ([]extensions.ExtensionProviderScope, error)
GetPlaylists(req *extensions.RequestedPlaylistsRequest) ([]*songs.Playlist, error)
GetPlaylistContent(req *extensions.RequestedPlaylistSongsRequest) (*extensions.RequestedPlaylistSongsResponse, error)
GetPlaylistFromURL(req *extensions.RequestedPlaylistFromUrlRequest) (*extensions.RequestedPlaylistFromUrlResponse, error)
GetPlaybackDetails(req *extensions.PlaybackDetailsRequestedRequest) (*extensions.PlaybackDetailsRequestedResponse, error)
Search(req *extensions.RequestedSearchResultRequest) (*songs.SearchResult, error)
GetRecommendations(req *extensions.RequestedRecommendationsRequest) ([]*songs.Song, error)
GetSongFromURL(req *extensions.RequestedSongFromUrlRequest) (*extensions.RequestedSongFromUrlResponse, error)
HandleCustomRequest(req *extensions.CustomRequest) (*extensions.CustomRequestResponse, error)
GetArtistSongs(req *extensions.RequestedArtistSongsRequest) (*extensions.RequestedArtistSongsResponse, error)
GetAlbumSongs(req *extensions.RequestedAlbumSongsRequest) (*extensions.RequestedAlbumSongsResponse, error)
GetSongFromID(req *extensions.RequestedSongFromIdRequest) (*extensions.RequestedSongFromIdResponse, error)
Scrobble(req *extensions.ScrobbleRequest) error
GetLyrics(req *extensions.RequestedLyricsRequest) (string, error)
GetSongContextMenu(req *extensions.RequestedSongContextMenuRequest) ([]*extensions.ContextMenuReturnType, error)
GetPlaylistContextMenu(req *extensions.RequestedPlaylistContextMenuRequest) ([]*extensions.ContextMenuReturnType, error)
OnContextMenuAction(req *extensions.ContextMenuActionRequest) error
}
type HashType
type HashType string
type HttpRequest
type HttpRequest struct {
URL string
Method string
Headers map[string]string
Body []byte
TimeoutMs uint64
}
type HttpResponse
type HttpResponse struct {
StatusCode uint32
StatusText string
Headers map[string]string
Body []byte
}
func BatchHttpGet
func BatchHttpGet(urls []string, headers map[string]string) ([]HttpResponse, []error) {
reqs := make([]HttpRequest, len(urls))
for i, u := range urls {
reqs[i] = HttpRequest{
URL: u,
Method: "GET",
Headers: headers,
}
}
return BatchHttpRequest(reqs)
}
func BatchHttpRequest
func BatchHttpRequest(requests []HttpRequest) ([]HttpResponse, []error) {
if len(requests) == 0 {
return nil, nil
}
protoReqs := make([]*extensions.HttpRequest, len(requests))
for i, r := range requests {
method := r.Method
if method == "" {
method = "GET"
}
var timeout *uint64
if r.TimeoutMs > 0 {
timeout = &r.TimeoutMs
}
protoReqs[i] = &extensions.HttpRequest{
Url: r.URL,
Method: method,
Headers: r.Headers,
Body: r.Body,
TimeoutMs: timeout,
}
}
batch := &extensions.BatchHttpRequest{
Requests: protoReqs,
}
batchBytes, err := proto.Marshal(batch)
if err != nil {
return nil, []error{err}
}
mem := pdk.AllocateBytes(batchBytes)
rPtr := batch_http_request(mem.Offset())
rMem := pdk.FindMemory(rPtr)
rBytes := rMem.ReadBytes()
respBatch := &extensions.BatchHttpResponse{}
if err := proto.Unmarshal(rBytes, respBatch); err != nil {
return nil, []error{err}
}
if respBatch.Error != nil && *respBatch.Error != "" {
return nil, []error{errors.New(*respBatch.Error)}
}
responses := make([]HttpResponse, 0, len(respBatch.Responses))
var errs []error
for i, res := range respBatch.Responses {
switch r := res.Result.(type) {
case *extensions.HttpResult_Response:
if r.Response != nil {
responses = append(responses, HttpResponse{
StatusCode: r.Response.StatusCode,
StatusText: r.Response.StatusText,
Headers: r.Response.Headers,
Body: r.Response.Body,
})
}
case *extensions.HttpResult_Error:
errs = append(errs, fmt.Errorf("request #%d failed: %s", i, r.Error))
default:
errs = append(errs, fmt.Errorf("request #%d returned empty result", i))
}
}
if len(errs) > 0 {
return responses, errs
}
return responses, nil
}
func HttpGet
func HttpGet(url string, headers map[string]string) (HttpResponse, error) {
return SendHttpRequest(HttpRequest{
URL: url,
Method: "GET",
Headers: headers,
})
}
func SendHttpRequest
func SendHttpRequest(req HttpRequest) (HttpResponse, error) {
resps, errs := BatchHttpRequest([]HttpRequest{req})
if len(errs) > 0 {
return HttpResponse{}, errs[0]
}
if len(resps) == 0 {
return HttpResponse{}, errors.New("host runner returned empty response")
}
return resps[0], nil
}
func (*HttpResponse) JSON
func (r *HttpResponse) JSON(v any) error {
return json.Unmarshal(r.Body, v)
}
func (*HttpResponse) OK
func (r *HttpResponse) OK() bool {
return r.StatusCode >= 200 && r.StatusCode < 300
}
func (*HttpResponse) Text
func (r *HttpResponse) Text() string {
return string(r.Body)
}