Skip to content

Age ratings

Every movie and series can say how old it is rated for. It’s what a profile can be limited by (the content levels), and it’s shown with a title’s details.

TMDB has a certification for each country that rates a title: PG-13 and R in the United States, 12A and 18 in Great Britain, TV-MA for American television, 16 in Germany. The metadata stage keeps all of them (movie_certifications, series_certifications) when it fetches a title, so changing the country needs no fetching.

Which country’s is used is a server setting (contentCountry, on the Server page). Without one it’s the country of the metadata language: en-GB is Great Britain. When TMDB has nothing for that country, the United States’ is used, then Great Britain’s, and the title says so (fallback). One that TMDB has none of at all is unrated.

A rating can be chosen by hand for a movie or series (certification when editing it). It’s in the server’s country, it’s used over TMDB’s, and it’s kept when the details are fetched again. Setting it back to nothing goes back to TMDB’s.

Countries rate differently, so each certification is turned into the youngest age it is for, which compares between them. The table is in library/certification.rs. This is a judgement, and it’s here to be argued with:

Age United States Great Britain Canada Australia
0 G, TV-Y, TV-G U, UC G, C, TV-Y, TV-G G, P, C
7–8 PG, TV-Y7, TV-PG PG PG, C8, TV-Y7, TV-PG PG
12–14 PG-13, TV-14 12, 12A 14A, TV-14
15–16 15 M, MA15+
17–18 R, TV-MA, NC-17 18, R18 18A, R, A, TV-MA R18+, X18+

Others are listed in the code (Ireland, New Zealand, Japan and some more), and a certification that is a number, with or without a + or an A (16, 12+, 14A), is that age whatever the country, which covers most of Europe and South America.

A certification that isn’t known (NR, Not Rated, anything else) has no age, and the title counts as unrated. They are listed in Manage (GET /certifications/unrated) so a rating can be set by hand.

A series’ episodes take the series’ rating.

What a profile may see by age rating is its content level. A level is a set of rating bands and whether a title with no known age is allowed. A band is named by the youngest age in it: Everyone (0), 7+, 12+, 15+, 17+ and 18+. A title is in the band of the greatest of these that isn’t over its age, so PG (8) is in 7+, PG-13 (13) and TV-14 (14) are in 12+, a 15 or an MA15+ is in 15+, R and TV-MA (17) are in 17+, and an 18 is in 18+. GET /content-levels says which certifications of the server’s country are in each band. A device that has given the server’s login can read it too, as the profile picker shows each profile’s level.

Four come with the server, and can be edited and put back (POST /content-levels/{id}/reset) but not deleted:

Level Allows Unrated
Little kids Everyone no
Kids Everyone, 7+ (up to PG) no
Teens Everyone, 7+, 12+, 15+ (up to PG-13, 12, TV-14, 15) no
Adults Everything yes

The admin can make more, and a profile has one, chosen when it’s made or edited by the admin. A profile cannot change its own, and an admin’s profile is always Adults: it cannot be limited, so the server cannot be locked out of. Profiles that were there before levels existed are Adults.

A title a profile’s level doesn’t allow is not there for it:

  • Lists leave it out, and so do their counts, letters and genres: movies and series, search of every kind, the home page and its rows (including continue watching, next up, the watchlist and favourites), “more like this”, box sets (one with fewer than two movies to see isn’t one), people (someone only in what a profile can’t see isn’t found), and what is on a playlist.
  • By ID every route answers 404 for it, as if there were no such thing, so its existence isn’t given away: details, seasons and episodes, playback, the stream, a conversion session and its files, subtitles, seek-bar pictures, segments, images and trailers, progress, favourites and the watchlist, and putting it on a playlist. A movie, series, season, episode, collection or file are all held to the movie or series they belong to. This is done once, for every route that takes an ID (api::auth::hide_what_is_not_allowed).
  • A link for a cast device (/files/{id}/cast) is refused for it, and one made before the profile was given a narrower level stops working.

The admin is always shown everything, and so is a profile whose level allows every band and unrated titles. A title that has no metadata yet has no age, so counts as unrated.

How it is kept to: each movie and series has its age in minimum_age in its metadata (made from the certifications when they are fetched, a rating is set by hand, or the country changes, and when the server starts), and a list’s query asks for what the level allows (Allowed::condition). tests/it/restricted.rs tries every route a profile can reach as a Kids profile, and fails for a route that is added without being tried, so a new route can’t be left open by forgetting.

accounts::levels::Level::allows is the one rule for whether a level lets a title be seen, given the youngest age it is rated for (or none).