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)
}