Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

License

NotificationsYou must be signed in to change notification settings

Castcloud/castcloud-documentation

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 

Repository files navigation

Introduction

Castcloud is a RESTful API specifying how podcast clients can communicate a user’s podcast library to each other via a server.

Features

The server side of the API provides centralized metadata storage for making personal podcast libraries available to multiple clients. The metadata of the library includes subscriptions, episodes, playback status and settings. The server side takes care of feed crawling so that clients don't have to individually crawl all the users feeds. This improves speed and simplifies some of the clients work.

Reference implementations

We have made reference implementations of both the server and the client. The reference server implementation has all server side functionality and the reference client uses a synchronizing model as far as possible for modern browsers (offline media storage is currently problematic), and falling back to streaming when synchronizing is impossible.

License

All code is GPLv3 with some included utilities and libraries being Apache 2.0 and MIT License. This means you are free to make commercial software or solutions with our code, and in fact we encourage it!

In the spirit of making something really useful for all users of podcasting software, we hope that all developers can come together and make this a common standard and improve upon it instead of creating incompatibilities.

Who we are

We are 3 bachelor computer science students from Narvik University College in Norway. We are working on this project as our bachelor thesis. We hope to have a specification ready for implementation in time for our graduation in the beginning of June 2014. We hope this API specification will help solve an issue that in our opinion has plagued and hampered further growth and user adoption of podcasts.

Terminology

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.

Clients

A client in this documentation is a piece of software run by a user on any compatible platform. A client is identified by itsname, regardless of developer or platform. Different instances of a client is identified to the server by itsUUID ortoken, and by its clientname anddecription to users.

There are 2 client models intended for use with the API. Hybrid models are also possible. Both streaming and synchronizing are equal in functionality, however it is recommended to implement as much synchronizing functionality as possible on the clients platform. Synchronizing improves the user experience as the client has a local copy of the library state. This increases the clients speed and enables offline functionality.

Synchronizing

The primary part of a synchronizing client is making sure it hasepisodes,casts,events,labels andsettings stored locally. The fetching ofevents andepisodes can be accelerated using asince timestamp and correct filtering. Clients will have to removeepisodes from its library when it gets deleteevents or acast gets removed (unsubscribed to).

To be fully offline capable, the client needs to manage the related media files locally.

Streaming

Streaming clients fetch information as required. The first part consists ofcasts (andlabels if the client implements folders and sorting). After letting the user select acast orlabel, the client then fetch the relatedepisodes.

Server

A server in this documentation is a piece of software running on a network capable device. It responds to REST requests as specified by this documentation. It handles permanent storage of information and information gathering from podcast feeds.

Most of the data processing is moved server side to simplify client implementation. This documentation will attempt to explain some of the required data processing to ease implementation. The explanation is located under the heading "Server logic" for each of the different calls.

Crawling

It is essential that the server implements crawling correctly. All clients using the server rely on it to have fetched the required feed infomation. If this were to stop all clients would stop working. The server should be a responsible crawler, throttling and properly identifying itself witha useragent. It should implement optimizations like PubSubHubbub to be as fast as possible. It needs to identify content and give it anepisode id without causing duplication. Using theitemsGUID might mostly work, but writing a good crawler isa never ending saga.

The server will need to store allchannel information in the feed for/library/cast and all data inside eachitem for theepisodes related calls. When storing newepisodes after having crawled a feed, the servers time (API server, not the database server) should be included for when it was stored. This will be used when clients use thesince filter in the/library/newepisodes call.

Calls

This document will attempt to explain proper usage of the API. All functions are explained in an interactive documentation called swagger. This can be viewed athttp://api.castcloud.org/utils/swagger-ui/ or run on your own server instance after having compiled the swagger documentation.

To compile the swagger documentation:

cd /your/castcloud/directory//usr/bin/php utils/swagger-php/swagger.phar api/ -o api-docs/ --default-base-path http://your.domain.name/api

XML to JSON conversion

Some data returned from the server has been converted from XML to JSON. This is mostly straight forward with one exception being tags having both attributes and content inside themselves. In these cases the content inside the tag gets put in a field named “_”.

Example:

<guidisPermaLink="false">5B4B1B2C-F9C6-4DC2-B09F-B6DE889A9E25</guid>

becomes

"guid":{"_" :"5B4B1B2C-F9C6-4DC2-B09F-B6DE889A9E25","isPermaLink" :"false"}

Account/Login

Post: Account/Login
ParameterRequiredDescription
usernametrueUsers username
passwordtrueUsers password
clientnametrueClient name
clientdescriptiontrueClient Description. e.g. Sallys iPad
clientversionfalseClient Version

This call registers the user's client and returns the client authorization token. The authorization token is used for all other requests.UUID,name anddescription fields are important as these are used actively.

Example:

curl https:// UrlPath /api/account/login -d username=user -d password=*** -d clientname=Superclient -d clientdescription="Bob's iPhone" -d uuid=1234567890
<script src="https://gist.github.com/basso/0b84947441aeac8c8c2e.js?file=account-login"></script>

UUID

TheUUID is a string used to identify the client instance even if thetoken is expired. TheUUID is used to reduce the number of duplicate client registrations on the server. The client can acquire aUUID string from its platform, or just generate a random string and permanently write it to storage. The string should be at least 8 characters, preferably 256 bit / 32 characters. The string should be unique for every device, but the same for the duration of the deployment on the device.

TheUUID is the only thing that is intended to be kept after a user explicitly signs out.

Name and description

Thename anddescription information is used to identify the user's client. Thename should be hard coded into the client and not change with versioning or platforms (unless features vary).description can be something less rigidly defined. It can describe the device it is running on “iPad” or “Windows 7 (x64)”, but the bestdescription would be something that relates to the user, for example “Livingroom media center” or “Bedroom iPad”.

Server logic

When a user logs in through the API, the client calling the server provides a lot of information.clientname,clientdescription anduuid are intended to simplify backend management.clientname andclientdescription are exposed through the API.clientversion andapikey are intended for future use with a possible client developer backend. TheUUID is intended to prevent duplicate client registrations. If a user has an activetoken for a client with a matchingUUID andname,clientdescription must be updated.

Account/Ping

This can be used to check if the token is valid.

Example:

curl http:// UrlPath /api/account/ping -H"Authorization:1337EGAh10qpLDq7xDTXG41r6T//ONLRvF5hd\/M3AX9I="
<script src="https://gist.github.com/basso/0b84947441aeac8c8c2e.js?file=account-ping"></script>

Server logic

Check if the token is valid.

Account/Settings

Clients are able to store the userssettings server side. This makes the synchronizing experience more seamless. By default allsettings are global for all clients, but clients can createclientspecific overrides.clientspecific overrides will apply for all clients with the same clientname. Global settings are intended for commonsettings with commonvalues. If a client uses uncommon settingsvalues or doesn't understand the current settingvalue, the client must override thesetting to avoid conflicts. A user might use one client differently than their other clients, and might want to configure this client separately from the rest. In these cases clients should offer the ability for users to toggle overrides of settings so that they don't propagate to other clients. When a user untoggles a setting override the client must ask if the user wants to keep thevalue from the override or the globalsetting.

The client has to implement its own set of supportedsettings andvalues with appropriate defaultvalues. If asetting does not exist, the client should set and use the default values. A client should not overwrite the users global settings with its defaults, unless the user asks for it. If a current settingsvalue is not understood by the client, the client should set its default as an override and use the override. The server side does not change its behaviour depending on settings, it only stores them. It is up to the client to implement the settings functionality.

Clients are not required to show any UI for configuring a setting. If some information about the clients state is required to save,settings withclientspecific overrides might be a good place to put it.

Changes tosettings should be sent to the server as fast as possible. It is recommended that clients keep an output buffer of these changes as they occur, then retry sending them until they successfully gets sent.

We hope that developers can come together and create a common list ofsetting keys andvalues. Therefore we suggest using these keys andvalues when implementing settings for related functionality in clients:

Setting keyValues (String formatted)
playback/forward_skip15s, 10%Integer followed by a unit character. Available unit characters are "s" = seconds, "%" = percentage of the medias total duration.
playback/backward_skip
playback/speed1.0Decimal number describing the default rate of playback. 1 = normal speed. 1.5 = 150% speed
playback/continous_playbacktrueBoolean. Whether playback should continue after end of track
gui/episode_sortorderpublished, reverse published, alfa, reverse alfa
hotkey/playpausespacebar,P,PlayPausecsv keyboard hotkeys
hotkey/forward_skipArrowRight
hotkey/backward_skipArrowLeft
hotkey/nextJ,N,PageDown
hotkey/previousK,P,PageUp
sync/autodeletefalseBoolean. If true clients can auto delete podcasts with EOT events. Default `exclude` parameter for episode and event related calls should be "60,70".
Notice: It is likely this might change from being a boolean to something with more details.

Notice:Setting keys are not a rigid part of the specification, but an attempt to find common ground. This list will be modified as per developer adoption regardless of API versioning to set a common ground.

Server logic

The server should send all the users globalsettings and allsettings withclientspecific overrides for the active client. The server needs to keep track of which client specified theclientspecific override. Theclientspecific override is applicable to all clients with the same client name string, and it is not specific to the clientsUUID ortoken. Several instances of a client can keep theirclientspecificsettings in sync across several devices.

Library/Casts

casts is the the users subscriptions. Eachcast has its own uniquecast id. Adding a cast to the user subscription list only requires anURL of a valid podcast feed. By using thecast id the client can edit and delete a subscription from the library. It is also possible to import and export casts via opml.

Changes tocasts should be sent to the server as fast as possible. It is recommended that clients keep an output buffer of these changes as they occur, then retry sending them until they successfully get sent.

Example:

curl http:// UrlPath /api/library/casts -H"Authorization:SuperSecretToken"
<script src="https://gist.github.com/basso/0b84947441aeac8c8c2e.js?file=library-casts"></script>

Server logic

A subscription should be stored on the server as a reference between the user and the cast. That way, if two users subscribe to the same cast they will both have the samecast id and the episodes will have the sameepisode ids. This will reduce the amount of feeds the server will need to crawl.casts.opml are the only parts of the api that use xml. Make sure you maintain the proper label structure when you export the opml, and validate it with a validation tool. Importing to iTunes can also be a good test. When importing opml's, make sure you maintain proper label stucture. Remember that labels should only be one layer deep, so you might have to flatten it. Importing a large opml from a feedreader like bazqux.com might be a good choice. Do not forget to crawl the imported opmls.

Library/Episodes and Library/Newepisodes

Both these calls return somewhat similar results. What to use depends on the client model.

Example:

curl https:// UrlPath /api/library/episodes/ID -H"Authorization:SuperSecretToken"
curl https:// UrlPath /api/library/newepisodes -H"Authorization:SuperSecretToken"
<script src="https://gist.github.com/basso/0b84947441aeac8c8c2e.js?file=library-episodes"></script>

Synchronizing model (Library/Newepisodes)

If the client is using a synchronizing client model we recommend usingnewepisodes and related calls as you can get episodes for all feeds with one call. In addition you can save a lot of bandwidth by using thesince parameter. When providing asince parameter, please use thetimestamp included with the last result, and not one from the client side as these might differ.

Please note that using a synchronizing model will force you to get events from/library/events as thelastevent included with eachepisode will quickly get outdated. If you see a newevent for anepisode that you don't have locally, this means the user has undeleted theepisode. Retrieve it with/library/episode/{episodeid}.

Streaming model (Library/Episodes)

If you are using a streaming model all you will need to use is/library/episodes. Before it can be fetched, the client will need to have information from/library/casts or/library/labels ascast id orlabel id is a required parameter.

Deleted / hidden episodes

Users would normally keep deleting episodes as they finish listening to them. This means the episodes would disappear from the normal interface. Deletedepisodes are still stored on the server. To get the complete list ofepisodes use the/library/episodes/{castid} with "" asexclude parameter. When a client displays the complete list ofepisodes, the user should have the option to reset the playback status. Clients undeleteepisodes by sending a new start event (type 10). Most synchronizing clients should implement this as an online only feature.

Server logic

/library/episodes,/library/episode and/library/newepisodes all returnepisodes in the same format. The biggest difference are the filters defined in input parameters./library/newepisodes must also include a timestamp of when it was generated. Thefeed in eachepisode is a JSON representation ofitems xml./library/episode only returns one episode at a time, please note that this must be output as an object and not an array.

ParameterUse
`since``/library/newepisode`The call must only return episodes stored after this time.
`episode id``/library/episode`Required parameter, should show error if not provided. The call must only return the one episode with the specified episode id.
`cast id``/library/episodes`Required parameter, should show error if not provided. The call should only return episodes for the casts with the specified `cast id`.
`label id``/library/episodes/label`Required parameter, should show error if not provided. The call should only return episodes for casts inside the specified label.
`exclude``/library/episodes`
`/library/episodes/label`
`/library/newepisodes`
Parameter is comma separated integers. The call should only return `episodes` where the `episodes` `lastevent` is not one of the listed types. If no exclude parameter is provided must the server use a default filter of “70” (deleted). If the parameter is empty (“”) must no `episodes` be excluded.

Library/Events

events are how clients keeps track of the users playback progression. They relate to common actions performed on the client.

Event typeDescription
10Start. Playback started. Also used to undelete/reset playback status. Almost equal to no event (`positionts` must be 0).
20Pause. Playback paused.
30Play. Playback resumed after a pause
40Sleeptimer start. This indicates where a sleeptimer was initiated. Concurrentorder must be one less than the `concurrentorder` for the Sleeptimer end event.
50Sleeptimer end. This indicates where a sleeptimer is intended to end. Should be sent with Sleeptimer start, the actual end of a sleeptimer is indicated with a pause at the end of the timer. `concurrentorder` must be one more than the `concurrentorder` for the Sleeptimer end event.
60End of track. The playback has reached the end of the file and can be expected to have been listened to completely.
70Delete. The user has explicitly indicated (by action) that the episode should be deleted. Clients no longer needs to maintain data about this episode unless the user explicitly asks for it.

More complexevents are built up of combinations ofevents. If a users skips from one position to another, the client should then send two events with the sameClientTS. The first event should be a pauseevent with aconcurrentorder of 0. The secondevent should be a play event with the newpositionts and aconcurrentorder of 1, seeking should also be implemented this way.

Clients following a streaming model might not need to fetchevents, as the most recentevent is included when getting episodes. Some clients might offer the ability to show a list of the users events. This might better help the user find back to where they last were. Streaming model clients that offer a complete eventlist should use thecast id to speed up the request. A synchronizing model client that does not offer this functionality, do not need to store more than the last event for eachepisode.

events should be sent to the server as fast as possible. It is recommended that clients keep an output buffer ofevents as they occur, then retry sending them until they successfully get sent.

Example:

curl https:// UrlPath /api/library/events -H"Authorization:SuperSecretToken"
<script src="https://gist.github.com/basso/0b84947441aeac8c8c2e.js?file=library-events"></script>

Server logic

Parameter
`since`The call must only return events received/stored since this time.
`episode id`The call must only return `events` for the specified `episode`.
`exclude`The call must only return `events` where the `episodes` last `event` is not one of the listed `types`. If no `exclude` parameter is provided, the server must use a default filter of “70” (deleted). To completely disable the `exclude` filter submit the parameter but leave it empty (“”).

Library/Labels

Labels allow you to group and sort your subscriptions.

Example:

curl https:// UrlPath /api/library/labels -H"Authorization:SuperSecretToken"
<script src="https://gist.github.com/basso/0b84947441aeac8c8c2e.js?file=library-labels"></script>

Server logic

The most important part of this call is making sure the output is clean and valid. Therefore the output should be validated every time before it gets sent to a client. Clients should not have to change thelabels when they unsubscribe from a podcast or subscribe to a new one. By default allcasts andlabels should be added to the rootlabel. Acast does not have to be in root when it is inside anotherlabel. You might be interested in the functionclean_labels() insideapi/db.php if you are trying to ensure cleanlabels.

<style>.gist-data { max-height: 400px; overflow: auto; } .gist .line, .gist .line-number { font-size:14px !important; line-height:25px !important; }.gist table { margin-bottom: 0 !important;}</style>

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors3

  •  
  •  
  •  

Languages


[8]ページ先頭

©2009-2025 Movatter.jp