osdb

package module
v0.0.0-...-441b04b Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 14, 2022 License: BSD-2-Clause Imports: 16 Imported by: 0

README

Build Status Coverage Status Donate using Liberapay

A Go client for OpenSubtitles.

This project allows you to search and download subtitles from OpenSubtitles. It comes both as a command-line program, and a library that you can use from other programs.

If you need to search or download subtitles, then you should find what you need from the latest releases, otherwise the TODO section highlights what remains to be done regarding API coverage.

Installation

If you want to compile the CLI interface for OpenSubtitles, then install the latest Go release, and run:

go get github.com/oz/osdb && go install github.com/oz/osdb/cmd/osdb

Provided that you setup your Go environment correctly, you now have a basic osdb command to interact with OpenSubtitles' API.

$ osdb help
Search and download subtitles from the command-line.

Usage:
  osdb
  osdb [command]

Available Commands:
  get         Get subtitles for a file
  hash        Shows OSDB hash for file.
  help        Help about any command
  imdb        Search IMDB
  put         Upload subtitles for a file
  version     Print the version number of osdb

Use "osdb [command] --help" for more information about a command.

Hence, to download French subtitles for a sample file:

$ osdb get -l fra sample.avi
- Getting fra subtitles for file: sample.avi
- No subtitles found!
- Getting eng subtitles for file: sample.avi
- Downloading to: sample.srt

Hack...

The generated documentation for this package is available at: http://godoc.org/github.com/oz/osdb

To get started...

  • Install with go get -d github.com/oz/osdb,
  • and import "github.com/oz/osdb" in your Go code,
  • or try some of the examples in the README.

To access the OpenSubtitles' XML-RPC server you first need to allocate a client, and then use it to login (even anonymously) in order to receive a session token. With that, you are finally be allowed to talk. Here is a short example:

package main

import "github.com/oz/osdb"

func main() {
	c, err := osdb.NewClient()
	if err != nil {
		// ...
	}

	// Anonymous login will set c.Token when successful
	if err = c.LogIn("", "", ""); err != nil {
		// ...
	}

	// etc.
}

Basic examples

Getting a user session token

Although this library tries to be simple, to use OpenSubtitles' API you need to login first so as to receive a session token: without it you will not be able to call any API method.

c, err := osdb.NewClient()
if err != nil {
	// ...
}

if err = c.LogIn("user", "password", "language"); err != nil {
	// ...
}
// c.Token is now set, and subsequent API calls will not be refused.

However, you do not need to register a user. To login anonymously, just leave the user and password parameters blank:

c.LogIn("", "", "")

Searching subtitles

Subtitle search can be done in a number of ways: using special file-hashes, IMDB movie IDs, or even using full-text queries. Hash-based search will generally yield the best results, so this is what is demoed next. However, in order to search with this method, you must have a movie file to hash.

path := "/path/to/movie.avi"
languages := []string{"eng"}

// Hash movie file, and search...
res, err := client.FileSearch(path, languages)
if err != nil {
	// ...
}

for _, sub := range res {
	fmt.Printf("Found %s subtitles file \"%s\" at %s\n",
		sub.LanguageName, sub.SubFileName, sub.ZipDownloadLink)
}

Downloading subtitles

Let's say you have just made a search, for example using FileSearch(), and as the API provided a few results, you decide to pick one for download:

subs, err := c.FileSearch(...)

// Download subtitle file, and write to disk using subs[0].SubFileName
if err := c.Download(&subs[0]); err != nil {
	// ...
}

// Alternatively, use the filename of your choice:
if err := c.DownloadTo(&subs[0], "safer-name.srt"); err != nil {
	// ...
}

Checking if a subtitle exists

Before trying to upload an allegedly "new" subtitles file to OSDB, you should always check whether they already have it.

As some movies fit on more than one "CD" (remember those?), you will need to use the Subtitles type (note the s?), one per subtitle file:

subs := osdb.Subtitles{
		{
			SubHash:       subHash,       // md5 hash of subtitle file
			SubFileName:   subFileName,
			MovieHash:     movieHash,     // see osdb.Hash()
			MovieByteSize: movieByteSize, // careful, it's a string...
			MovieFileName: movieFileName,
		},
}

Then simply feed that to HasSubtitles, and you will be done.

found, err := c.HasSubtitles(subs)
if err != nil {
	// ...
}

Hashing a file

OSDB uses a custom checksum-hash to identify movie files. If you ever need these:

hash, err := osdb.Hash("somefile.avi")
if err != nil {
	// ...
}
fmt.Println("hash: %x\n", hash)

On user agents...

If you have read OSDB's developer documentation, you should notice that you need to register an "official" user agent in order to use their API.

By default this library will present itself with the "osdb-go" agent, which is fine for me. However, if you need to change this, simply set the client's UserAgent with:

c, err := osdb.NewClient()
if err != nil {
	// ...
}
c.UserAgent = "My custom user agent"

TODO

  • Move docs from README to godoc.org
  • Full API coverage:
  • LogIn
  • LogOut
  • NoOperation
  • SearchSubtitles by hash
  • SearchSubtitles by IMDB IDs
  • SearchToMail
  • DownloadSubtitles
  • TryUploadSubtitles
  • UploadSubtitles
  • SearchMoviesOnIMDB
  • GetIMDBMovieDetails
  • InsertMovie
  • ServerInfo
  • ReportWrongMovieHash
  • SubtitlesVote
  • AddComment
  • GetSubLanguages
  • DetectLanguage
  • GetAvailableTranslations
  • GetTranslation
  • AutoUpdate
  • CheckMovieHash
  • CheckSubHash

License

BSD, see the LICENSE file.

Documentation

Overview

Package osdb is an API client for opensubtitles.org

This is a client for the OSDb protocol. Currently the package only allows movie identification, subtitles search, and download.

Index

Constants

View Source
const (
	// DefaultOSDBServer is OSDB's API base URL.
	DefaultOSDBServer = "https://api.opensubtitles.org:443/xml-rpc"

	// DefaultUserAgent is the current version of this lib.
	DefaultUserAgent = "osdb-go 0.2"

	// SearchLimit = nax hits per search
	SearchLimit = 100

	// StatusSuccess is the successful response status for API calls.
	StatusSuccess = "200 OK"
)
View Source
const (
	// ChunkSize = 64k
	ChunkSize = 65536
)

Variables

This section is empty.

Functions

func Hash

func Hash(path string) (uint64, error)

Hash generates an OSDB hash for a file.

func HashFile

func HashFile(file *os.File) (hash uint64, err error)

HashFile generates an OSDB hash for an *os.File.

Types

type ByDownloads

type ByDownloads Subtitles

ByDownloads implements sort interface for Subtitles, by download count.

func (ByDownloads) Len

func (s ByDownloads) Len() int

func (ByDownloads) Less

func (s ByDownloads) Less(i, j int) bool

func (ByDownloads) Swap

func (s ByDownloads) Swap(i, j int)

type Client

type Client struct {
	UserAgent string
	Token     string
	Login     string
	Password  string
	Language  string
	*xmlrpc.Client
}

Client wraps an XML-RPC client to connect to OSDB.

func NewClient

func NewClient() (*Client, error)

NewClient allocates a new OSDB client.

func (*Client) BestMoviesByHashes

func (c *Client) BestMoviesByHashes(hashes []uint64) ([]*Movie, error)

BestMoviesByHashes searches for the best matching movies for each of the hashes (only for <200). This returns incomplete Movies, with the following fields only: ID, Title and Year.

func (*Client) Download

func (c *Client) Download(s *Subtitle) error

Download saves a subtitle file to disk, using the OSDB specified name.

func (*Client) DownloadSubtitles

func (c *Client) DownloadSubtitles(subtitles Subtitles) ([]SubtitleFile, error)

DownloadSubtitles downloads subtitles in bulk.

func (*Client) DownloadSubtitlesByIds

func (c *Client) DownloadSubtitlesByIds(ids []int) ([]SubtitleFile, error)

DownloadSubtitlesByIds downloads subtitles by ID.

func (*Client) DownloadTo

func (c *Client) DownloadTo(s *Subtitle, path string) (err error)

DownloadTo saves a subtitle file to the specified path.

func (*Client) FileSearch

func (c *Client) FileSearch(path string, langs []string) (Subtitles, error)

FileSearch searches subtitles for a file and list of languages.

func (*Client) GetIMDBMovieDetails

func (c *Client) GetIMDBMovieDetails(id string) (*Movie, error)

GetIMDBMovieDetails fetches movie details from IMDB by ID.

func (*Client) HasSubtitles

func (c *Client) HasSubtitles(subs Subtitles) (bool, error)

HasSubtitles checks whether subtitles already exists in OSDB. The mandatory fields in the received Subtitle slice are: SubHash, SubFileName, MovieHash, MovieByteSize, and MovieFileName.

func (*Client) HashSearch

func (c *Client) HashSearch(hash uint64, size int64, langs []string) (Subtitles, error)

HashSearch Searches for subtitles that match a specific hash/size/language combination. This function does not require the path of the movie file, just the hash/size values.

func (*Client) IMDBSearch

func (c *Client) IMDBSearch(q string) (Movies, error)

IMDBSearch searches movies on IMDB.

func (*Client) IMDBSearchByID

func (c *Client) IMDBSearchByID(ids []string, langs []string) (Subtitles, error)

IMDBSearchByID searches subtitles that match some IMDB IDs.

func (*Client) IMDBSearchByIDFiltered

func (c *Client) IMDBSearchByIDFiltered(imdbCode string, isMovie bool, season uint, episode uint, lang []string) (Subtitles, error)

IMDBSearchByIDFiltered Searches for a movie or tv episode by IMDB code. Set isMovie to true to ignore the season and episode otherwise the search try to find a subtitle that matches the season and episode supplied. Note: When looking for Episodes by the Series IMDB code, if you don't filter by episode/season - the result might include too many subtitles to return and thus some results will be ommited.

func (*Client) LogIn

func (c *Client) LogIn(user string, pass string, lang string) (err error)

LogIn to the API, and return a session token.

func (*Client) LogOut

func (c *Client) LogOut() (err error)

LogOut ...

func (*Client) Noop

func (c *Client) Noop() (err error)

Noop keeps a session alive.

func (*Client) SearchSubtitles

func (c *Client) SearchSubtitles(params *[]interface{}) (Subtitles, error)

SearchSubtitles searches OSDB with your own parameters.

func (*Client) UploadSubtitles

func (c *Client) UploadSubtitles(subs Subtitles) (string, error)

UploadSubtitles uploads subtitles.

XXX Mandatory fields in the received Subtitle slice are: SubHash, SubFileName, MovieHash, SubLanguageID, MovieByteSize, and MovieFileName.

type Movie

type Movie struct {
	ID             string            `xmlrpc:"id"`
	Title          string            `xmlrpc:"title"`
	Cover          string            `xmlrpc:"cover"`
	Year           string            `xmlrpc:"year"`
	Duration       string            `xmlrpc:"duration"`
	TagLine        string            `xmlrpc:"tagline"`
	Plot           string            `xmlrpc:"plot"`
	Goofs          string            `xmlrpc:"goofs"`
	Trivia         string            `xmlrpc:"trivia"`
	Cast           map[string]string `xmlrpc:"cast"`
	Directors      map[string]string `xmlrpc:"directors"`
	Writers        map[string]string `xmlrpc:"writers"`
	Awards         []string          `xmlrpc:"awards"`
	Genres         []string          `xmlrpc:"genres"`
	Countries      []string          `xmlrpc:"country"`
	Languages      []string          `xmlrpc:"language"`
	Certifications []string          `xmlrpc:"certification"`
}

Movie is a type that stores the information from IMDB searches.

type Movies

type Movies []Movie

Movies is just a slice of movies.

func (Movies) Empty

func (m Movies) Empty() bool

Empty checks whether Movies is empty.

type Subtitle

type Subtitle struct {
	IDMovie             string `xmlrpc:"IDMovie"`
	IDMovieImdb         string `xmlrpc:"IDMovieImdb"`
	IDSubMovieFile      string `xmlrpc:"IDSubMovieFile"`
	IDSubtitle          string `xmlrpc:"IDSubtitle"`
	IDSubtitleFile      string `xmlrpc:"IDSubtitleFile"`
	ISO639              string `xmlrpc:"ISO639"`
	LanguageName        string `xmlrpc:"LanguageName"`
	MatchedBy           string `xmlrpc:"MatchedBy"`
	MovieByteSize       string `xmlrpc:"MovieByteSize"`
	MovieFPS            string `xmlrpc:"MovieFPS"`
	MovieHash           string `xmlrpc:"MovieHash"`
	MovieImdbRating     string `xmlrpc:"MovieImdbRating"`
	MovieKind           string `xmlrpc:"MovieKind"`
	MovieName           string `xmlrpc:"MovieName"`
	MovieNameEng        string `xmlrpc:"MovieNameEng"`
	MovieReleaseName    string `xmlrpc:"MovieReleaseName"`
	MovieTimeMS         string `xmlrpc:"MovieTimeMS"`
	MovieYear           string `xmlrpc:"MovieYear"`
	MovieFileName       string `xmlrpc:"MovieName"`
	QueryNumber         string `xmlrpc:"QueryNumber"`
	SeriesEpisode       string `xmlrpc:"SeriesEpisode"`
	SeriesIMDBParent    string `xmlrpc:"SeriesIMDBParent"`
	SeriesSeason        string `xmlrpc:"SeriesSeason"`
	SubActualCD         string `xmlrpc:"SubActualCD"`
	SubAddDate          string `xmlrpc:"SubAddDate"`
	SubAuthorComment    string `xmlrpc:"SubAuthorComment"`
	SubAutoTranslation  string `xmlrpc:"SubAutoTranslation"`
	SubBad              string `xmlrpc:"SubBad"`
	SubComments         string `xmlrpc:"SubComments"`
	SubDownloadLink     string `xmlrpc:"SubDownloadLink"`
	SubDownloadsCnt     string `xmlrpc:"SubDownloadsCnt"`
	SubFeatured         string `xmlrpc:"SubFeatured"`
	SubFileName         string `xmlrpc:"SubFileName"`
	SubFormat           string `xmlrpc:"SubFormat"`
	SubHash             string `xmlrpc:"SubHash"`
	SubHD               string `xmlrpc:"SubHD"`
	SubHearingImpaired  string `xmlrpc:"SubHearingImpaired"`
	SubLanguageID       string `xmlrpc:"SubLanguageID"`
	SubRating           string `xmlrpc:"SubRating"`
	SubSize             string `xmlrpc:"SubSize"`
	SubSumCD            string `xmlrpc:"SubSumCD"`
	SubEncoding         string `xmlrpc:"SubEncoding"`
	SubForeignPartsOnly string `xmlrpc:"SubForeignPartsOnly"`
	SubFromTrusted      string `xmlrpc:"SubFromTrusted"`
	SubtitlesLink       string `xmlrpc:"SubtitlesLink"`
	UserID              string `xmlrpc:"UserID"`
	UserNickName        string `xmlrpc:"UserNickName"`
	UserRank            string `xmlrpc:"UserRank"`
	ZipDownloadLink     string `xmlrpc:"ZipDownloadLink"`
	// contains filtered or unexported fields
}

A Subtitle with its many OSDB attributes...

func NewSubtitle

func NewSubtitle(moviePath string, subPath string, langID string) (s Subtitle, err error)

NewSubtitle builds a Subtitle struct.

type SubtitleFile

type SubtitleFile struct {
	ID       string `xmlrpc:"idsubtitlefile"`
	Data     string `xmlrpc:"data"`
	Encoding encoding.Encoding
	// contains filtered or unexported fields
}

SubtitleFile contains file data as returned by OSDB's API, that is to say: gzip-ped and base64-encoded text.

func (*SubtitleFile) Reader

func (sf *SubtitleFile) Reader() (r io.ReadCloser, err error)

Reader interface for SubtitleFile. Subtitle's contents are decompressed, and usually encoded to UTF-8: if encoding info is missing, no re-encoding is done.

type Subtitles

type Subtitles []Subtitle

Subtitles is a collection of subtitles.

func NewSubtitles

func NewSubtitles(moviePath string, subPaths []string, langID string) (Subtitles, error)

NewSubtitles builds a Subtitles from a movie path and a slice of subtitles paths. Intended to be used with for osdb.HasSubtitles() and osdb.UploadSubtitles().

func (Subtitles) Best

func (subs Subtitles) Best() *Subtitle

Best finds the best subsitle in a Subtitles collection. Of course "best" is hardly an absolute concept: here, we just take the most downloaded file.

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL