Unlike the other migrations, this one uses a bare table name to specify the table. This means it looks in the default search path. Unfortunately, the out of box search path is:
1. Schema with the same name as the user
2. Public
Because of this, if a schema exists with the same name as the DB user, the playlist_videos table will get created in _that_ schema, rather than the public schema, and then the grant statement will fail with an error like below if check_table is enabled as it keeps trying to create the table but failing on the grant statement:
```
2022-01-22 02:27:42 UTC [info] check_table: check_table: CREATE TABLE playlist_videos
Unhandled exception: relation "public.playlist_videos" does not exist (PQ::PQError)
from /usr/share/crystal/src/primitives.cr:266:3 in 'handle_error'
from lib/pg/src/pq/connection.cr:184:9 in 'handle_async_frames'
from lib/pg/src/pq/connection.cr:162:7 in 'read'
from lib/pg/src/pq/query.cr:53:14 in 'exec_all'
from lib/db/src/db/database.cr:126:9 in '__crystal_main'
from /usr/share/crystal/src/crystal/main.cr:110:5 in 'main'
from src/env/__libc_start_main.c:94:2 in 'libc_start_main_stage2'
2022-01-22 02:27:43 UTC [info] check_table: check_table: CREATE TABLE playlist_videos
Unhandled exception: relation "public.playlist_videos" does not exist (PQ::PQError)
from /usr/share/crystal/src/primitives.cr:266:3 in 'handle_error'
from lib/pg/src/pq/connection.cr:184:9 in 'handle_async_frames'
from lib/pg/src/pq/connection.cr:162:7 in 'read'
from lib/pg/src/pq/query.cr:53:14 in 'exec_all'
from lib/db/src/db/database.cr:126:9 in '__crystal_main'
from /usr/share/crystal/src/crystal/main.cr:110:5 in 'main'
from src/env/__libc_start_main.c:94:2 in 'libc_start_main_stage2'
```
Usually, next steps are after the error message.
Here, we want the same options to be right above the stack trace,
so users are less likely to report duplicates.
* Ask to read the FAQ and search for existing issues on Github
* Include links to FAQ and directly to a new github issue
* Github issue title is automatically based on exception name
* Improved HTML
* Minor languages changes
The channel/<ucid>/playlists page was vulnerable to Cross Site Scripting
(XSS), because the different URL parameters were inserted as-is in the URL
meant for instance switching.
This vulnerability could allow an attacker to inject malicious Javascript
in the page by tricking the user to click on a crafted link.
Bug introduced in commit 66e7285108
("Only use /redirect when automatically redirecting").
Thanks to Jack (@testa:cthd.icu on Matrix, @cysea on github) for responsibly
reporting this issue!
'.to_i64?' instead of '.to_i64' returns nil rather than raising
an exception when it's done on an empty string.
In some rare cases, rating can be equal to 5. In this case, the
value of player_response[videoDetails][averageRating] is an
Int and not a Float.
* on watch page and video cards (search results, playlists, etc...)
* on /feed/playlists
* in search filters (not normalized in order to avoid collisions with
an existing PR that reworks the search filters)
given the variables available in this function's context, 'author' and 'ucid'
provide the same data 'self.author' and 'self.ucid', respectively.
Given that fact, the variable `auto_generated` has no impact on the logic of
this function, and hence can be safely removed. this greatly simplifies the
code and makes it perfectly compatible with crystal's calling convention for
'#to_xml' methods.
Changes in the aforementioned PR lead to change the behavior
of some old code.
The data type of the parameters aren't explicit enough, which
makes the compiler use the wrong method because of type infering.
* Fix for #2488 - parse contents of search results of type=Category (returned on first page for universal (type=all) queries instead of returning an error.
* Moved content array walker to Category#to_json
As requested by reviewer this change moves the content array walker from the API endpoint to the Category class.
* Update src/invidious/helpers/serialized_yt_data.cr
Co-authored-by: syeopite <70992037+syeopite@users.noreply.github.com>
* Add debug/trace logging to extract_items
* Handle invalid timestamps for livestreams extraction
* Make use of author_fallback in playlist extractor
* Don't use extract_text for video length extraction
The extract_text function attempts to extract from both the simpleText and
the runs route. This is typically what we'd want for text extraction as
it could appear in both locations. However, while this still holds true,
the thumbnailOverlayTimeStatusRenderer writes a numerical length (when
present on the video) to the simpleText route and uses runs for a
text overlay like "LIVE" or "PREMIERE".
Therefore, when a video has a text overlay instead of a numerical one,
Invidious still passes it onto decode_length_seconds, which obviously
raises since it cannot be converted into integers.
In the future, if more routes requires one text route over the other, we
should go ahead and add an argument to extract_text itself. Though for
now, this is sufficient.
* Handle unsupported "special" categories
- Add extract_text to simplify extraction of InnerTube texts
- Add helper extractor methods to reduce repetition in parsing InnerTube
- Change [] more than 2 blocks long to use #dig or #dig?
- Remove useless ?.try blocks for items that always exists
- Add (some) documentation to VideoRendererParser
This is a squash of a bunch of commits
cherry-picked commits
Fix category parse error on search
(cherry picked from commit cc02fed4e6)
Fix category items not being extracted in search
(cherry picked from commit 2605b9c609)
Make search not include category items for now
(cherry picked from commit ca4afd59f4)
Change behavior of categories in search results
(cherry picked from commit cc10675610)
Fix missing search results in extraction
(cherry picked from commit abda6840d5)
Fix miscount of search results
(cherry picked from commit 491e33450e)
This commit adds a new parser for YT's shelfRenderers which are
typically used to denote different categories.The code for featured
channels parsing has also been moved to use the new parser but some
additional refactoring are needed there.
The ContinuationExtractor has also been improved and is now capable of
extraction continuation data that is packaged under
"appendContinuationItemsAction"
In additional this commit adds some useful helper functions to extract
the current selected tab the continuation token. This is to mainly
reduce code size and repetition.
--
This cherry-picked commit also removes the code for parsing featured
channels present on the original.
(cherry picked from commit 8000d538db)
This commit completely rewrites the extract_item and extract_items
function. Before this commit these two function were an unreadable
mess. The extract_item function was a lengthy if-elsif chain
while the extract_items function contained an incomprehensible
mess of .try, else and ||.
With this commit both of these functions have been pulled into a
separate file with the internal logic being moved to a few classes.
This significantly reduces the size of these two methods, enhances
readability and makes adding new extraction/parse rules much simpler.
See diff for details.
--
This cherry-picked commit also removes the code for parsing featured
channels present on the original.
(cherry picked from commit a027fbf7af)
Upstream requires at least two additional sources. Whereas Invidious needs it to be
able to display a single additional source for normal (dashless)
qualites. Aka medium and hd720.
Clone scripts folder to docker container
Copy videojs-dependencies.yml to docker container
Copy assets folder eariler in build process
Copy assets folder from builder
Video mimetype may contain code information between double quotes.
If not properly escaped, it breaks the browser's parser. E.g:
```
type="video/mp4; codecs=" avc1.64001f,="" mp4a.40.2""=""
```
Thank Robin for catching this!
* Extract feed routes from invidious.cr
* Removes the deprecated route for /feed/top
* Deprecate /view_all_playlist & use /feed/playlists
* Move feed views into their own directory
* Add haltf method to halt current route context
* Change status_code + return blocks to use haltf
* Set appropriate response headers for RSS routes
- Auth (excluding notifications*) APIs
- Mixes
*Notifications currently require the "connection_channel" channel
for talking with the notifications job. Unfortunately, we cannot
access that within the route modules yet.
* Fix "fatal role postgres doesn't exist"
Fix a frequent error with recent postgres docker images:
`FATAL: role "postgres" does not exist`
* Use $$VAR so it's expanded by the shell, not docker
* use the new youtube api for comments
* remove PG_DB & action parameter + allow force region
* support new comments data with onResponseReceivedEndpoints
* Add nightly crystal to a spec matrix
This project is very large and serves as a great test bed for breakages
in nightly builds of crystal
* Order crystal version in CI matrix
* Add daily CI runs
* Extract primary channel routes from invidious.cr
Also removes timedtext_video stub since all it does is redirect to the
homepage. However, Invidious's 404 handler already does this.
--
As the template for the channel about page doesn't exist yet, the
behavior for the /channel/:ucid/about endpoint has been changed to be
the same as what's currently present on Invidious
(cherry picked from commit 8fad19d805)
* Manually extract brand_redirect from 1b569bbc99
This commit manually extracts the brand_redirect function from the
commit mentioned.
However, the redirect to the `.../about` endpoint is removed due to the
fact that it doesn't exist yet.
This commit is also mainly just a bridge for the next few cherry picks from
\#2215
* Update brand_redirect to use youtubei resolve_url
(cherry picked from commit 53335fe7cf)
* Add additional channel endpoints to brand_redirect
(cherry picked from commit 8fc6f3add6)
* Add separate handler for /profile endpoint
* Add /channel/:ucid/home route
* Document all channel brand_urls
* Move Crystal stdlib classes overrides to a separate file
* Document known crystal overrides
* Update crystal overrides for HTTP::Client socket
* Update shard.yml to restrict crystal versions
* Fix compilation error in Crystal 1.1.x (See
https://github.com/crystal-lang/crystal/issues/10965
for more details about this issue).
The private `_post_json` method of the YoutubeAPI requires a ClientConfig
as the third parameter. This was passed in all Youtube API methods except the
`#resolve_url` method.
* Put youtube API functions under the YoutubeAPI namespace
* Implement the following endpoints:
- `next`
- `player`
- `resolve_url`
* Allow a ClientConfig to be passed to YoutubeAPI endpoint handlers.
* Add constants for many new clients
* Fix documentation of YoutubeAPI.browse(): Comments and search
result aren't returned by the browse() endpoint but by the next()
and search() endpoints, respectively.
* Accept gzip compressed data, to help save on bandwidth
* Add debug/trace logging
* Other minor fixes
Major README.md cleaning
Additions:
* Add the invidious logo
* Add Quickstart section
* Add relevant links (instance list, documentation, contribute, donate) directly in the header
Badges:
* Add badges for open issues and PRs
* Add "Awesome Humane Tech" badge, as we're listed there
* Move CI passed/translated badges to the top
* Replace the "license feature" with a proper badge
Major section changes:
* Reword titles
* Rewrite features list
* Promote the screenshots sections. People like screenshots!
* Move "donate" to the end, there is a link at the top anyway
* Move section "made with invidious" after all the other invidious related sections + rename it to "Projects using Invidious"
Other fixes:
* Remove useless HTML in the screenshots table
* Remove extra columns in H2 titles
* Remove all useless lines between sections
* Use markdown for git commands + add the staging step
* Promote invidious redirect in "Extensions"
* Update preference screenshots
Fixes:
* Sanitize user-provided content in HTML (Fixes#2193)
* Fix encoding of search query in prev/next pages (Fixes#2229)
* Fix some issues introduced with #2196:
- Fix alignment of all <h3> elements (Move the inline style from the parent to the <h3> element)
- Add missing comma on 'dir' HTML attribute (Typo introduced by PR #2196)
Code cleaning:
* Remove unnecessary 'each_sclice' + 'each' double loop in ECR files
* Clean the player's <source> list generation code (in player.ecr)
Related to #1416, it doesn't really fix the real error, but instead mutes the exception message.
Like explained in #1416, this "exception Error" while flushing the client data doesn't harm the client-server connection. However, this exception message continuously spams the logs and makes debugging and error finding really difficult.
Cherry picked from ui overhaul branch with a few modifications:
- channel folder is renamed to channels
- parsing for channel home and featured channels are removed due to
lack of infrastructure from other commits
(cherry picked from commit 44d18b8e14)
i was injecting custom css into the site that made the avatars round, and noticed comment avatars looked a little odd
i opened dev tools and siffed through the html, and noticed that the image was being padded,
when it would look nicer if the element used margin instead of padding
with padding:
https://imgur.com/c0pB37e
with proposed changes (margin instead of padding):
https://imgur.com/iKmBzEi
The behavior was as follow: on Right-To-Left text (e.g Arabic) that is wrapped
(because it's too long to fit on one line), the second row and following rows
may or may not be right aligned (as RTL text should be). Opening the devtools
fixes that alignement, as consistently as closing the devtool breaks it.
This problem seems to arrive only in the following configurations (link nested
in a paragraph, both of which may or may not have the dir= attribute):
* `<p><a href="some_link">RTL_TEXT</a></p>`
* `<p><a href="some_link" dir="auto">RTL_TEXT</a></p>`
* `<p dir="auto"><a href="some_link">RTL_TEXT</a></p>`
with the following CSS:
```
p {
unicode-bidi: plaintext;
text-align: start;
}
```
Changing the HTML to the following configuration (a paragraph with the dir=
attribute, nested in a link) seems to fix it:
`<a href="some_link"><p dir="auto">RTL_TEXT</p></a>`
This will prevent, on large pages, the LTR and RTL text to be
far away, on each side of the page. This could happen on channel
and playlists descriptions, when the page is displayed on a large
screen.
Adding these styles is the easiest way to add bidi (bidirectional text) support without or with least side effect. I have tested it by adding it manually on yewtu.be instance and so far it works very well.
* Remove percent-encoding of the search query when calling youtube API, as it
breaks UTF-8
* Empty search redirects to /search, not /
* Show the fullscreen search "home page" (from #1977) at /search
* Allow 'region=' parameter to be passed to /search
* Other minor fixes
Add documentation
Bump web client version string
Add charset=UTF-8 to the 'content-type' header
Parse JSON and return it as a Hash
Handle API error messages
When having a `umask` of `xx7` (e.g. `027`) on the host machine then the directories `assets`, `config` and `locales` don't become readable to the `invidious` user inside the Docker container since the `COPY` commands result in files owned by `root` with the same file permissions like on the host (`640` in my case).
By adding `--chown=invidious` to the `COPY` command we ensure the `invidious` user can read these files.
* Also includes minor fixes when I could (french, italian, icelandic)
* Added a new line at the end of en-US translation.
Updated ar.json (Arabic)
Updated el.json (Greek)
Updated fa.json (Persian)
Updated fr.json (French)
Updated is.json (Icelandic)
Updated it.json (Italian)
Updated tr.json (Turkish)
Updated zh-TW.json (Chinese, Taiwan)
Simple routes have been moved into a single `Misc` file.
Embed routes have been moved into a single `Embed` file.
The preferences route has been renamed to be more consistent with other parts
of the codebase.
Fixes audio mode duration doubled in iPhone iOS browsers. The player will stop after reaching the real duration.
iOS() checks both iOS and iPadOS.
Only tested on iPhone iOS browsers. Testers needed for behavior of iPadOS and MacOS.
The config file can now be specified with `INVIDIOUS_CONFIG_FILE`.
A YAML formatted string can still be passed with `INVIDIOUS_CONFIG`, replacing
the config file.
Additionally all options can now be specified as environment variables.
The syntax for variable names is `INVIDIOUS_` followed by the option name in
upper case. The values are parsed as YAML.
These new env vars only update the provided main configuration, but it is
possible to point the config file at the example config and then use env vars
for all config options:
```
INVIDIOUS_CONFIG_FILE=./config/config.example.yml \
INVIDIOUS_CHANNEL_THREADS=10 \
./invidious
```
The default log level has been changed from `debug` to `info`.
The `debug` log level is now more verbose. `debug` now gives a general overview
of what is happening (where implemented) while `trace` gives all available
details.
The crystal http client maintains a keepalive connection to the other
server which stays alive for some time. This should be closed if the
client instance is not used again to avoid hogging resources
This is similar to the removed `top-enabled` option but for the Popular feed.
The instance needs to be restarted if the feed was enabled.
Editing admin options on the preferences page is also fixed.
The handling of the feed pages now only happens in a single place.
Instead of redirecting:
- The Top feed now displays a message that it was removed from Invidious.
- The Popular feed now displays a message that it was disabled if it was.
Traces can be enabled with `-l trace`.
The problem with subscriptions is that sometimes requests to YouTube never
finish. As soon as that happens `channel-threads` times subscriptions stop
being refreshed. This is most likely a problem with the lsquick bindings.
Everything that gets logged now has a log level associated with it.
The log level can be set with the new `-l` or `--log-level` arguments.
The defaul log level is `debug` for now. There aren't many things that get
logged but if the logs get spammed in the future it can be set down to `info`.
The Top feed used to be a feed based on YouTube ratings. Once YouTube removed
publicly available ratings the Top feed was removed from Invidious but the
option to display a link to it remained.
Besides `auto`, `best` and `worst` it is now possible to select a target height.
If the target height is not available the closest lower height is selected.
* Untrack config.yml
`config/config.yml` has been untracked and moved to `config/config.example.yml`.
The Dockerfile has been updated to copy all `config/config.*` files and to try
to move `config/config.example.yml` to `config/config.yml`. If a user supplied
`config/config.yml` exists it is not overwritten.
* Update Dockerfile to use `shard.lock`
* Fix tests
* Update the cryptocurrency address with newly created one
* Replace the icon used for the donation address and link
* Replace the word Monero with the word XMR
* Replace the Liberapay placeholder with a link to the documentation
The YouTube headers are now always added for requests to YouTube.
Previously they were only added for requests going through QUIC.
The session token is now JSON decoded to unescape escaped Unicode characters.
The comment continuation protobuf has been updated and the request now goes
through the YouTube `pbj` JSON API.
Redirect channels may use JS to redirect now, instead of only a response header
as it used to be. This fix reads the channel to redirect to from `ytInitialData`.
The `ytInitialPlayerResponse` regex can now handle `var` and `window`
assignments.
The video streams can now be extracted from `player_response` and
`initial_data`.
This fixes the descriptions on videos and videos themselves. Videos are
technically broken right now, but work becasue of a fallback that goes through
embeds.
Travis CI is slow, builds are first queued up forever and then the builds
themselves are slow, too.
GitHub Actions run pretty much immediately and are fast. Also separate jobs run
at the same time unlike on Travis CI.
Electric Boogaloo
The long backtrace has been moved into a `<details>` HTML element, as suggested
by @B0pol. To make the error still visible it has been added to the top under
`Title:`. This also encourages informative issue titles.
Since no new tags are created for releases the version has been frozen for some
time, with only the commit hash changing.
Versions based on the latest commit date make it much easier to identify them.
Error handling has been reworked to always go through the new `error_template`,
`error_json` and `error_atom` macros.
They all accept a status code followed by a string message or an exception
object. `error_json` accepts a hash with additional fields as third argument.
If the second argument is an exception a backtrace will be printed, if it is a
string only the string is printed. Since up till now only the exception message
was printed a new `InfoException` class was added for situations where no
backtrace is intended but a string cannot be used.
`error_template` with a string message automatically localizes the message.
Missing error translations have been collected in https://github.com/iv-org/invidious/issues/1497
`error_json` with a string message does not localize the message. This is the
same as previous behavior. If translations are desired for `error_json` they
can be added easily but those error messages have not been collected yet.
Uncaught exceptions previously only printed a generic message ("Looks like
you've found a bug in Invidious. [...]"). They still print that message
but now also include a backtrace.
Using sudo with `echo ... | tee /path/to/file` doesn't make sense, as the command requiring the superuser privileges is the `tee` command and not the echo.
Now that themes are controlled with a class instead of setting
media="none" on the stylesheet link and both themes already being
duplicated in default.css for the automatic themeing it makes sense
to have all theme related CSS in the same place.
This commit also fixes the missing dark theme on embeds.
Themes are now controlled with a class on the body element.
If a preference is set the body element will have either "dark-theme"
or "light-theme" class. If no preference is set or the preference is
empty the class will be "no-theme".
"dark-theme" and "light-theme" are handled by darktheme.css and
lighttheme.css respectively.
"no-theme" is handled by default.css where depending on the value of
"prefers-color-scheme" the styles corresponding to "dark-theme" or
"light-theme" are applied.
Unfortunately this means that both themes are duplicated, once in the
theme .css and once in default.css.
The index was set to index - 1, causing the first video to be shifted in fetch_playlist_videos
(because of its index being -1 lower than it should) and thus not displayed on playlist page.
Using the player on latest Safari, the tooltip appears and stays stuck for long even when switching to fullscreen which is annoying. You need to explicitly click anywhere to dismiss that stuck tooltip.
This doesn't seem to happen in Firefox so I am not sure whether this is a browser bug, but in any case I don't see any value in keeping this tooltip so maybe we can just remove it?
In practice with the patch I usually see backoff to 2 hours when blocked, so it should improve recovery time. The lim_thread is to work with multi-threading, not sure if it's the best way to do it.
* Use new API to fetch videos from channels
This mirrors the process used by subscriptions.gir.st. The old API is
tried first, and if it fails then the new one is used.
* Use the new API whenever getting videos from a channel
I created the get_channel_videos_response function because now instead
of just getting a single url, there are extra steps involved in getting
the API response for channel videos, and these steps don't need to be
repeated throughout the code.
The only remaining exception is the bypass_captcha function, which still
only makes a request to the old API. I don't know whether this code
needs to be updated to use the new API for captcha bypassing to work
correctly.
* Correctly determine video length with new api
* Remove unnecessary line
On the URL specified it says: "Project 'Ealhad/peertubeify' was moved to 'Cha_deL/peertubeify'. Please update any links and bookmarks that may still have the old path."
* More consistent IDs for info section
More consistent IDs for info section: watch-on-youtube, annotations and download
* Consistent IDs: channel-name
* Consistent IDs: published-date
The term "published" can also be found in the answer for the following YouTube API request: https://developers.google.com/youtube/v3/docs/videos/list
Invidious gained support to read its configuration from an env var
instead of config file in e3c10d779d.
Unfortunately, Docker doesn't allow newline characters in env var
values (see [0]) which means we can only provide a proper YAML config
by using the inlined configuration in docker-compose.yml which,
unfortunately, is tracked by Git. Once support for multiline env var
values has been added to Docker, we should migrate and read the config
from a .env file instead (which is not tracked by Git).
[0]: https://github.com/docker/compose/issues/3527
* Verify token signature in constant time
To prevent timing side channel attacks
* Run cheap checks first in token validation process
Expensive checks such as the nonce lookup on the database or the
signature check can be run after cheap/fast checks.
* docker: do not require password for PostgreSQL superuser
A password is now required by the postgres Docker image which makes
initial setup (and our CI build) fail with the following error:
postgres_1 | Error: Database is uninitialized and superuser password is not specified.
postgres_1 | You must specify POSTGRES_PASSWORD for the superuser. Use
postgres_1 | "-e POSTGRES_PASSWORD=password" to set it in "docker run".
postgres_1 |
postgres_1 | You may also use POSTGRES_HOST_AUTH_METHOD=trust to allow all connections
postgres_1 | without a password. This is *not* recommended. See PostgreSQL
postgres_1 | documentation about "trust":
postgres_1 | https://www.postgresql.org/docs/current/auth-trust.html
See https://github.com/docker-library/postgres/issues/681.
* docker,kubernetes: create PostgreSQL "privacy" type before using it
Fixes the following error when setting up the database:
postgres_1 | 2020-02-21 01:01:22.371 UTC [172] ERROR: type "privacy" does not exist at character 200
postgres_1 | 2020-02-21 01:01:22.371 UTC [172] STATEMENT: CREATE TABLE public.playlists
postgres_1 | (
postgres_1 | title text,
postgres_1 | id text primary key,
postgres_1 | author text,
postgres_1 | description text,
postgres_1 | video_count integer,
postgres_1 | created timestamptz,
postgres_1 | updated timestamptz,
postgres_1 | privacy privacy,
postgres_1 | index int8[]
postgres_1 | );
postgres_1 | ERROR: type "privacy" does not exist
postgres_1 | LINE 10: privacy privacy,
* travis: do not run "docker-compose up" in detached mode
Rather, allow database to finish its setup procedure and grant
Invidious time to launch.
Try to read app config from the "INVIDIOUS_CONFIG" environment variable.
If the variable is undefined, read config from config.yml file as before.
Required by https://github.com/omarroth/invidious/pull/1015 et al.
days-before-pr-stale:45# PRs should be active. Anything that hasn't had activity in more than 45 days should be considered abandoned.
days-before-close:30
exempt-pr-labels:blocked
stale-issue-message:'This issue has been automatically marked as stale and will be closed in 30 days because it has not had recent activity and is much likely outdated. If you think this issue is still relevant and applicable, you just have to post a comment and it will be unmarked.'
stale-pr-message:'This pull request has been automatically marked as stale and will be closed in 30 days because it has not had recent activity and is much likely abandoned or outdated. If you think this pull request is still relevant and applicable, you just have to post a comment and it will be unmarked.'
# Note: This is no longer updated and links to omarroths repo, which doesn't exist anymore.
# 0.20.0 (2019-011-06)
# Version 0.20.0: Custom Playlists
@@ -400,7 +402,7 @@ An `/api/v1/stats` endpoint has been added with [#356](https://github.com/omarro
## For Developers
`/api/v1/channels/:ucid` now provides an `autoGenerated` tag, which returns true for [topic channels](https://www.youtube.com/channel/UCE80FOXpJydkkMo-BYoJdEg), and larger [genre channels](https://www.youtube.com/channel/UC-9-kyTW8ZkZNDHQJ6FgpwQ) generated by YouTube. These channels don't have any videos of their own, so `latestVideos` will be empty. It is recommended instead to display a list of playlists generated by YouTube.
`/api/v1/channels/:ucid` now provides an `autoGenerated` tag, which returns true for topic channels, and larger genre channels generated by YouTube. These channels don't have any videos of their own, so `latestVideos` will be empty. It is recommended instead to display a list of playlists generated by YouTube.
You can now pull a list of playlists from a channel with `/api/v1/channels/playlists/:ucid`. Supported options are documented in the [wiki](https://github.com/omarroth/invidious/wiki/API#get-apiv1channelsplaylistsucid-apiv1channelsucidplaylists). Pagination is handled with a `continuation` token, which is generated on each call. Of note is that auto-generated channels currently have one page of results, and subsequent calls will be empty.
[Documentation](https://github.com/omarroth/invidious/wiki) can be found in the wiki.
The full documentation can be accessed online at https://docs.invidious.io/
## Extensions
The documentation's source code is available in this repository:
https://github.com/iv-org/documentation
[Extensions](https://github.com/omarroth/invidious/wiki/Extensions) can be found in the wiki, as well as documentation for integrating it into other projects.
### Extensions
## Made with Invidious
We highly recommend the use of [Privacy Redirect](https://github.com/SimonBrazell/privacy-redirect#get),
a browser extension that automatically redirects Youtube URLs to any Invidious instance and replaces
embedded youtube videos on other websites with invidious.
- [FreeTube](https://github.com/FreeTubeApp/FreeTube): An Open Source YouTube app for privacy.
- [CloudTube](https://cadence.moe/cloudtube/subscriptions): A JS-rich alternate YouTube player
- [PeerTubeify](https://gitlab.com/Ealhad/peertubeify): On YouTube, displays a link to the same video on PeerTube, if it exists.
- [MusicPiped](https://github.com/deep-gaurav/MusicPiped): A materialistic music player that streams music from YouTube.
The documentation contains a list of browser extensions that we recommended to use along with Invidious.
## Contributing
You can read more here: https://docs.invidious.io/Extensions.md
1. Fork it ( https://github.com/omarroth/invidious/fork )
2. Create your feature branch (git checkout -b my-new-feature)
3. Commit your changes (git commit -am 'Add some feature')
4. Push to the branch (git push origin my-new-feature)
5. Create a new Pull Request
## Contact
## Contribute
Feel free to send an email to omarroth@protonmail.com or join our [Matrix Server](https://riot.im/app/#/room/#invidious:matrix.org), or #invidious on Freenode.
### Code
You can also view release notes on the [releases](https://github.com/omarroth/invidious/releases) page or in the CHANGELOG.md included in the repository.
1. Fork it ( https://github.com/iv-org/invidious/fork ).
1. Create your feature branch (`git checkout -b my-new-feature`).
1. Stage your files (`git add .`).
1. Commit your changes (`git commit -am 'Add some feature'`).
1. Push to the branch (`git push origin my-new-feature`).
1. Create a new pull request ( https://github.com/iv-org/invidious/compare ).
!function(e,t){"object"==typeofexports&&"undefined"!=typeofmodule?module.exports=t(require("video.js"),require("global/document")):"function"==typeofdefine&&define.amd?define(["video.js","global/document"],t):e.videojsContribQualityLevels=t(e.videojs,e.document)}(this,function(e,t){"use strict";functionn(e){if(void0===e)thrownewReferenceError("this hasn't been initialised - super() hasn't been called");returne}e=e&&e.hasOwnProperty("default")?e.default:e,t=t&&t.hasOwnProperty("default")?t.default:t;varr=function(r){vari,l;functiono(){vari,l=n(n(i=r.call(this)||this));if(e.browser.IS_IE8)for(varsinl=t.createElement("custom"),o.prototype)"constructor"!==s&&(l[s]=o.prototype[s]);returnl.levels_=[],l.selectedIndex_=-1,Object.defineProperty(l,"selectedIndex",{get:function(){returnl.selectedIndex_}}),Object.defineProperty(l,"length",{get:function(){returnl.levels_.length}}),l||n(i)}l=r,(i=o).prototype=Object.create(l.prototype),i.prototype.constructor=i,i.__proto__=l;vars=o.prototype;returns.addQualityLevel=function(n){varr=this.getQualityLevelById(n.id);if(r)returnr;vari=this.levels_.length;returnr=newfunctionn(r){vari=this;if(e.browser.IS_IE8)for(varlini=t.createElement("custom"),n.prototype)"constructor"!==l&&(i[l]=n.prototype[l]);returni.id=r.id,i.label=i.id,i.width=r.width,i.height=r.height,i.bitrate=r.bandwidth,i.enabled_=r.enabled,Object.defineProperty(i,"enabled",{get:function(){returni.enabled_()},set:function(e){i.enabled_(e)}}),i}(n),""+iinthis||Object.defineProperty(this,i,{get:function(){returnthis.levels_[i]}}),this.levels_.push(r),this.trigger({qualityLevel:r,type:"addqualitylevel"}),r},s.removeQualityLevel=function(e){for(vart=null,n=0,r=this.length;n<r;n++)if(this[n]===e){t=this.levels_.splice(n,1)[0],this.selectedIndex_===n?this.selectedIndex_=-1:this.selectedIndex_>n&&this.selectedIndex_--;break}returnt&&this.trigger({qualityLevel:e,type:"removequalitylevel"}),t},s.getQualityLevelById=function(e){for(vart=0,n=this.length;t<n;t++){varr=this[t];if(r.id===e)returnr}returnnull},s.dispose=function(){this.selectedIndex_=-1,this.levels_.length=0},o}(e.EventTarget);for(variinr.prototype.allowedEvents_={change:"change",addqualitylevel:"addqualitylevel",removequalitylevel:"removequalitylevel"},r.prototype.allowedEvents_)r.prototype["on"+i]=null;varl=function(t){returnn=this,e.mergeOptions({},t),i=n.qualityLevels,l=newr,n.on("dispose",functione(){l.dispose(),n.qualityLevels=i,n.off("dispose",e)}),n.qualityLevels=function(){returnl},n.qualityLevels.VERSION="2.0.9",l;varn,i,l};return(e.registerPlugin||e.plugin)("qualityLevels",l),l.VERSION="2.0.9",l});
!function(t,e){"object"==typeofexports&&"undefined"!=typeofmodule?module.exports=e(require("video.js"),require("global/window")):"function"==typeofdefine&&define.amd?define(["video.js","global/window"],e):t.videojsOverlay=e(t.videojs,t.window)}(this,function(t,e){"use strict";functionn(t){if(void0===t)thrownewReferenceError("this hasn't been initialised - super() hasn't been called");returnt}t=t&&t.hasOwnProperty("default")?t.default:t,e=e&&e.hasOwnProperty("default")?e.default:e;varr={align:"top-left",class:"",content:"This overlay will show up while the video is playing",debug:!1,showBackground:!0,attachToControlBar:!1,overlays:[{start:"playing",end:"paused"}]},i=t.getComponent("Component"),o=t.dom||t,s=t.registerPlugin||t.plugin,a=function(t){return"number"==typeoft&&t==t},h=function(t){return"string"==typeoft&&/^\S+$/.test(t)},d=function(r){vari,s;functiond(t,e){vari;returni=r.call(this,t,e)||this,["start","end"].forEach(function(t){vare=i.options_[t];if(a(e))i[t+"Event_"]="timeupdate";elseif(h(e))i[t+"Event_"]=e;elseif("start"===t)thrownewError('invalid "start" option; expected number or string')}),["endListener_","rewindListener_","startListener_"].forEach(function(t){i[t]=function(e){returnd.prototype[t].call(n(n(i)),e)}}),"timeupdate"===i.startEvent_&&i.on(t,"timeupdate",i.rewindListener_),i.debug('created, listening to "'+i.startEvent_+'" for "start" and "'+(i.endEvent_||"nothing")+'" for "end"'),i.hide(),i}s=r,(i=d).prototype=Object.create(s.prototype),i.prototype.constructor=i,i.__proto__=s;varl=d.prototype;returnl.createEl=function(){vart=this.options_,n=t.content,r=t.showBackground?"vjs-overlay-background":"vjs-overlay-no-background",i=o.createEl("div",{className:"\n vjs-overlay\n vjs-overlay-"+t.align+"\n "+t.class+"\n "+r+"\n vjs-hidden\n "});return"string"==typeofn?i.innerHTML=n:ninstanceofe.DocumentFragment?i.appendChild(n):o.appendContent(i,n),i},l.debug=function(){if(this.options_.debug){for(vare=t.log,n=e,r=arguments.length,i=newArray(r),o=0;o<r;o++)i[o]=arguments[o];e.hasOwnProperty(i[0])&&"function"==typeofe[i[0]]&&(n=e[i.shift()]),n.apply(void0,["overlay#"+this.id()+": "].concat(i))}},l.hide=function(){returnr.prototype.hide.call(this),this.debug("hidden"),this.debug('bound `startListener_` to "'+this.startEvent_+'"'),this.endEvent_&&(this.debug('unbound `endListener_` from "'+this.endEvent_+'"'),this.off(this.player(),this.endEvent_,this.endListener_)),this.on(this.player(),this.startEvent_,this.startListener_),this},l.shouldHide_=function(t,e){varn=this.options_.end;returna(n)?t>=n:n===e},l.show=function(){returnr.prototype.show.call(this),this.off(this.player(),this.startEvent_,this.startListener_),this.debug("shown"),this.debug('unbound `startListener_` from "'+this.startEvent_+'"'),this.endEvent_&&(this.debug('bound `endListener_` to "'+this.endEvent_+'"'),this.on(this.player(),this.endEvent_,this.endListener_)),this},l.shouldShow_=function(t,e){varn=this.options_.start,r=this.options_.end;returna(n)?a(r)?t>=n&&t<r:this.hasShownSinceSeek_?Math.floor(t)===n:(this.hasShownSinceSeek_=!0,t>=n):n===e},l.startListener_=function(t){vare=this.player().currentTime();this.shouldShow_(e,t.type)&&this.show()},l.endListener_=function(t){vare=this.player().currentTime();this.shouldHide_(e,t.type)&&this.hide()},l.rewindListener_=function(t){vare=this.player().currentTime(),n=this.previousTime_,r=this.options_.start,i=this.options_.end;e<n&&(this.debug("rewind detected"),a(i)&&!this.shouldShow_(e)?(this.debug("hiding; "+i+" is an integer and overlay should not show at this time"),this.hasShownSinceSeek_=!1,this.hide()):h(i)&&e<r&&(this.debug("hiding; show point ("+r+") is before now ("+e+") and end point ("+i+") is an event"),this.hasShownSinceSeek_=!1,this.hide())),this.previousTime_=e},d}(i);t.registerComponent("Overlay",d);varl=function(e){varn=this,i=t.mergeOptions(r,e);Array.isArray(this.overlays_)&&this.overlays_.forEach(function(t){n.removeChild(t),n.controlBar&&n.controlBar.removeChild(t),t.dispose()});varo=i.overlays;deletei.overlays,this.overlays_=o.map(function(e){varr=t.mergeOptions(i,e),o="string"==typeofr.attachToControlBar||!0===r.attachToControlBar;if(!n.controls()||!n.controlBar)returnn.addChild("overlay",r);if(o&&-1!==r.align.indexOf("bottom")){vars=n.controlBar.children()[0];if(void0!==n.controlBar.getChild(r.attachToControlBar)&&(s=n.controlBar.getChild(r.attachToControlBar)),s){vara=n.controlBar.addChild("overlay",r);returnn.controlBar.el().insertBefore(a.el(),s.el()),a}}varh=n.addChild("overlay",r);returnn.el().insertBefore(h.el(),n.controlBar.el()),h})};returnl.VERSION="2.1.4",s("overlay",l),l});
"Broken? Try another Invidious Instance":"معطل؟ جرب مثيل Invidious آخر",
"Hide annotations":"إخفاء الملاحظات في الفيديو",
"Show annotations":"عرض الملاحظات في الفيديو",
"Genre: ":"النوع: ",
"License: ":"التراخيص: ",
"Family friendly? ":"محتوى عائلى? ",
"Family friendly? ":"محتوى عائلي؟ ",
"Wilson score: ":"درجة ويلسون: ",
"Engagement: ":"نسبة المشاركة (عدد المشاهدات\\عدد الإعجابات): ",
"Engagement: ":"نسبة المشاركة: ",
"Whitelisted regions: ":"الدول المسموح فيها هذا الفيديو: ",
"Blacklisted regions: ":"الدول الحظور فيها هذا الفيديو: ",
"Blacklisted regions: ":"الدول المحظور فيها هذا الفيديو: ",
"Shared `x`":"شارك منذ `x`",
"`x` views":"`x` مشاهدات",
"Premieres in `x`":"يعرض فى `x`",
"Premieres `x`":"يعرض `x`",
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.":"اهلا! يبدو ان الجافاسكريبت معطلة. اضغط هنا لعرض التعليقات, ضع فى إعتبارك انها ستأخذ وقتاطول للعرض.",
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.":"أهلًا! يبدو أن جافاسكريبت معطلٌ لديك. اضغط هنا لعرض التعليقات، وَضَع في اعتبارك أنها ستأخذ وقتًا أطول للتحميل.",
"View YouTube comments":"عرض تعليقات اليوتيوب",
"View more comments on Reddit":"عرض المزيد من التعليقات على\\من موقع Reddit",
"Quota exceeded, try again in a few hours":"تم تجاوز عدد المرات المسموح بها, حاول مرة اخرى بعد عدة ساعات",
"Unable to log in, make sure two-factor authentication (Authenticator or SMS) is turned on.":"غير قادر على تسجيل الدخول, تأكد من تشغيل المصادقة الثنائية 2FA.",
"Incorrect password":"كلمة السر غير صحيحة",
"Quota exceeded, try again in a few hours":"تم تجاوز عدد المرات المسموح بها، حاول مجددًا بعد بضع ساعات",
"Unable to log in, make sure two-factor authentication (Authenticator or SMS) is turned on.":"غير قادر على تسجيل الدخول، تأكد من تشغيل المصادقة الثنائية 2FA.",
"Invalid TFA code":"كود مصادقة ثنائية 2FA غير صحيح",
"Login failed. This may be because two-factor authentication is not turned on for your account.":"لم يتم تسجيل الدخول. هذا ربما بسبب ان المصادقة الثنائية 2FA معطلة فى حسابك.",
"Login failed. This may be because two-factor authentication is not turned on for your account.":"فشل تسجيل الدخول. قد يكون هذا بسبب أن المصادقة الثنائية 2FA معطلة في حسابك.",
"Wrong answer":"إجابة خاطئة",
"Erroneous CAPTCHA":"الكابتشا CAPTCHA غير صاحلة",
"CAPTCHA is a required field":"مكان الكابتشا CAPTCHA مطلوب",
"User ID is a required field":"مكان إسم المستخدم مطلوب",
"Password is a required field":"مكان الرقم السرى مطلوب",
"Wrong username or password":"إسم المستخدم او الرقم السرى غير صحيح",
"User ID is a required field":"مكان اسم المستخدم مطلوب",
"Password is a required field":"مكان كلمة السر مطلوب",
"Wrong username or password":"اسم المستخدم او كلمة السر غير صحيح",
"Please sign in using 'Log in with Google'":"الرجاء تسجيل الدخول 'تسجيل الدخول بواسطة جوجل'",
"Password cannot be empty":"الرقم السرى لايمكن ان يكون فارغ",
"Password cannot be longer than 55 characters":"الرقم السرى لا يتعدى 55 حرف",
"Password cannot be empty":"لايمكن أن تكون كلمة السر فارغة",
"Password cannot be longer than 55 characters":"يجب أن لا تتعدى كلمة السر 55 حرفًا",
"Please log in":"الرجاء تسجيل الدخول",
"Invidious Private Feed for `x`":"صفحة Invidious للمشتركين الخاصة\\مخفية لـ `x`",
"Invidious Private Feed for `x`":"تغذية Invidious خاصة ل 'x'",
"channel:`x`":"قناة:`x`",
"Deleted or invalid channel":"قناة ممسوحة او غير صالحة",
"This channel does not exist.":"القناة غير موجودة.",
"This channel does not exist.":"هذه القناة غير موجودة.",
"Could not get channel info.":"لم يستطع الحصول على معلومات القناة.",
"Could not fetch comments":"لم يتمكن من إحضار التعليقات",
"View `x` replies":"عرض `x` ردود",
"`x` ago":"`x` منذ",
"Load more":"عرض المزيد",
"`x` points":"`x` نقاط",
"Could not create mix.":"لم يستطع عمل خلط.",
"Empty playlist":"قائمة التشغيل فارغة",
"Not a playlist.":"قائمة التشغيل غير صالحة.",
"Playlist does not exist.":"قائمة التشغيل غير موجودة.",
"Could not pull trending pages.":"لم يستطع عرض الصفحات الراجئة.",
"Hidden field \"challenge\" is a required field":"مكان مخفى \"تحدى\" مكان مطلوب",
"Hidden field \"token\" is a required field":"مكان مخفى \"رمز\" مكان مطلوب",
"Erroneous challenge":"تحدى غير صالح",
"Hidden field \"challenge\" is a required field":"مكان مخفي \"تحدي\" مكان مطلوب",
"Hidden field \"token\" is a required field":"مكان مخفي \"رمز\" مكان مطلوب",
"Erroneous challenge":"تحدي غير صالح",
"Erroneous token":"روز غير صالح",
"No such user":"مستخدم غير صالح",
"Token is expired, please try again":"الرمز منتهى الصلاحية , الرجاء المحاولة مرة اخرى",
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.":"Hej! Det ser ud til at du har JavaScript slået fra. Klik her for at se kommentarer, vær opmærksom på at de kan tage længere om at indlæse.",
"Quota exceeded, try again in a few hours":"Kvota overskredet, prøv igen om et par timer",
"Unable to log in, make sure two-factor authentication (Authenticator or SMS) is turned on.":"Login fejlet, tjek at totrinsbekræftelse (Authenticator eller SMS) er slået til.",
"Invalid TFA code":"Ugyldig TFA kode",
"Login failed. This may be because two-factor authentication is not turned on for your account.":"Login fejlede. Dette kan skyldes, at to-faktor autentificering ikke er aktiveret for din konto.",
"Wrong answer":"Forkert svar",
"Erroneous CAPTCHA":"Fejlagtig CAPTCHA",
"CAPTCHA is a required field":"CAPTCHA er et obligatorisk felt",
"User ID is a required field":"Bruger ID er et krævet felt",
"Password is a required field":"Adgangskode er et obligatorisk felt",
"Wrong username or password":"Forkert brugernavn eller adgangskode",
"Please sign in using 'Log in with Google'":"Log ind via 'Log ind med Google'",
"Password cannot be empty":"Adgangskoden må ikke være tom",
"Password cannot be longer than 55 characters":"Adgangskoden må ikke være længere end 55 tegn",
"Please log in":"Venligst log ind",
"channel:`x`":"kanal: 'x'",
"Deleted or invalid channel":"Slettet eller invalid kanal",
"This channel does not exist.":"Denne kanal eksisterer ikke.",
"Could not get channel info.":"Kunne ikke hente kanal info.",
"Could not fetch comments":"Kunne ikke hente kommentarer",
"`x` ago":"'x' siden",
"Load more":"Hent flere",
"Could not create mix.":"Kunne ikke skabe blanding.",
"Empty playlist":"Tom playliste",
"Not a playlist.":"Ikke en playliste.",
"Playlist does not exist.":"Playlist eksisterer ikke.",
"Esperanto":"Esperanto",
"Czech":"Tjekkisk",
"Danish":"Dansk",
"Community":"Samfund",
"Afrikaans":"Afrikansk",
"Portuguese":"Portugisisk",
"Ukrainian":"Ukrainsk",
"Fallback comments: ":"Fallback kommentarer: ",
"Popular":"Populær",
"footer_donate_page":"Doner",
"Gujarati":"Gujarati",
"Punjabi":"Punjabi",
"Sundanese":"Sundanesisk",
"Urdu":"Urdu",
"preferences_region_label":"Indhold land: ",
"Hidden field \"challenge\" is a required field":"Det skjulte felt \"challenge\" er et påkrævet felt",
"Albanian":"Albansk",
"preferences_quality_dash_label":"Fortrukket DASH video kvalitet: ",
"live":"Direkte",
"Lao":"Lao-tse",
"Filipino":"Filippinsk",
"Greek":"Græsk",
"Kurdish":"Kurdisk",
"Malay":"Malaysisk",
"Romanian":"Rumænsk",
"Somali":"Somalisk",
"preferences_locale_label":"Sprog: ",
"News":"Nyheder",
"permalink":"permalink",
"date":"Upload dato",
"features":"Funktioner",
"filter":"Filter",
"Khmer":"Khmer",
"Finnish":"Finsk",
"week":"Denne uge",
"Korean":"Koreansk",
"Telugu":"Telugu",
"Malayalam":"Malayalam",
"View as playlist":"Se som spilleliste",
"Hungarian":"Ungarsk",
"Welsh":"Walisisk",
"subtitles":"Undertekster/CC",
"Bosnian":"Bosnisk",
"Yiddish":"Jiddisch",
"Belarusian":"Belarussisk",
"today":"I dag",
"Shona":"Shona",
"Slovenian":"Slovensk",
"Gaming":"Gaming",
"Bangla":"Bengali",
"Swahili":"Swahili",
"`x` marked it with a ❤":"`x`markeret med et ❤",
"Kyrgyz":"Kirgisisk",
"Turkish":"Tyrkisk",
"adminprefs_modified_source_code_url_label":"URL-adresse til modificeret kildekodelager",
"Broken? Try another Invidious Instance":"Funktioniert nicht? Probiere eine andere Invidious Instanz aus",
"Hide annotations":"Anmerkungen ausblenden",
"Show annotations":"Anmerkungen anzeigen",
"Genre: ":"Genre: ",
@@ -149,28 +152,30 @@
"Whitelisted regions: ":"Erlaubte Regionen: ",
"Blacklisted regions: ":"Unerlaubte Regionen: ",
"Shared `x`":"Geteilt `x`",
"`x` views":"`x` Aufrufe",
"Premieres in `x`":"Zuerst gesehen in `x`",
"Premieres `x`":"Erster Start `x`",
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.":"Hallo! Anscheinend haben Sie JavaScript deaktiviert. Klicken Sie hier um Kommentare anzuzeigen, beachten sie dass es etwas länger dauern kann um sie zu laden.",
"Quota exceeded, try again in a few hours":"Kontingent überschritten, versuche es in ein paar Stunden erneut",
"Unable to log in, make sure two-factor authentication (Authenticator or SMS) is turned on.":"Login nicht möglich, stellen Sie sicher dass two-factorAuthentifikation (Authentifizierung oder SMS) aktiviert ist.",
"Unable to log in, make sure two-factor authentication (Authenticator or SMS) is turned on.":"Anmeldung nicht möglich, stellen Sie sicher, dass die Zwei-Faktor-Authentisierung (Authenticator oder SMS) aktiviert ist.",
"Invalid TFA code":"Ungültiger TFA Code",
"Login failed. This may be because two-factor authentication is not turned on for your account.":"Login fehlgeschlagen. Das kann daran liegen dass two-factorAuthentifizierung in ihrem Account nicht aktiviert ist.",
"Login failed. This may be because two-factor authentication is not turned on for your account.":"Die Anmeldung ist fehlgeschlagen. Dies kann daran liegen, dass die Zwei-Faktor-Authentisierung für Ihr Konto nicht aktiviert ist.",
"Wrong answer":"Ungültige Antwort",
"Erroneous CAPTCHA":"Ungültiges CAPTCHA",
"CAPTCHA is a required field":"CAPTCHA ist eine erforderliche Eingabe",
"User ID is a required field":"Benutzer ID ist eine erforderliche Eingabe",
"Password is a required field":"Passwort ist eine erforderliche Eingabe",
"Wrong username or password":"Ungültiger Benutzername oder Passwort",
"Please sign in using 'Log in with Google'":"Bitte melden sie sich mit 'Mit Google anmelden' an",
"Please sign in using 'Log in with Google'":"Bitte melden Sie sich mit „Mit Google anmelden“ an",
"Password cannot be empty":"Passwort darf nicht leer sein",
"Password cannot be longer than 55 characters":"Passwort darf nicht länger als 55 Zeichen sein",
"Please log in":"Bitte anmelden",
@@ -180,17 +185,15 @@
"This channel does not exist.":"Dieser Kanal existiert nicht.",
"Could not get channel info.":"Kanalinformationen konnten nicht geladen werden.",
"Could not fetch comments":"Kommentare konnten nicht geladen werden",
"View `x` replies":"Zeige `x` Antworten",
"`x` ago":"vor `x`",
"Load more":"Mehr laden",
"`x` points":"`x` Punkte",
"Could not create mix.":"Mix konnte nicht erstellt werden.",
"Empty playlist":"Playlist ist leer",
"Not a playlist.":"Ungültige Playlist.",
"Playlist does not exist.":"Playlist existiert nicht.",
"Could not pull trending pages.":"Trending Seiten konnten nicht geladen werden.",
"Hidden field \"challenge\" is a required field":"Verstecktes Feld \"challenge\" ist eine erforderliche Eingabe",
"Hidden field \"token\" is a required field":"Verstecktes Feld \"token\" ist eine erforderliche Eingabe",
"Empty playlist":"Wiedergabeliste ist leer",
"Not a playlist.":"Ungültige Wiedergabeliste.",
"Playlist does not exist.":"Wiedergabeliste existiert nicht.",
"Could not pull trending pages.":"Trendenz-Seiten konnten nicht geladen werden.",
"Hidden field \"challenge\" is a required field":"Verstecktes Feld „challenge“ ist eine erforderliche Eingabe",
"Hidden field \"token\" is a required field":"Verstecktes Feld „token“ ist eine erforderliche Eingabe",
"Erroneous challenge":"Ungültiger Test",
"Erroneous token":"Ungültiger Token",
"No such user":"Ungültiger Benutzer",
@@ -301,19 +304,13 @@
"Yiddish":"Jiddisch",
"Yoruba":"Joruba",
"Zulu":"Zulu",
"`x` years":"`x` Jahre",
"`x` months":"`x` Monate",
"`x` weeks":"`x` Wochen",
"`x` days":"`x` Tage",
"`x` hours":"`x` Stunden",
"`x` minutes":"`x` Minuten",
"`x` seconds":"`x` Sekunden",
"Fallback comments: ":"Alternative Kommentare: ",
"Popular":"Populär",
"Search":"Suchen",
"Top":"Top",
"About":"Über",
"Rating: ":"Bewertung: ",
"Language: ":"Sprache: ",
"preferences_locale_label":"Sprache: ",
"View as playlist":"Als Wiedergabeliste anzeigen",
"Premieres `x`":"Επίσημη πρώτη παράσταση του `x`",
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.":"Γεια! Φαίνεται πως έχετε απενεργοποιήσει το JavaScript. Πατήστε εδώ για προβολή σχολίων, αλλά έχετε υπ'όψιν σας πως ίσως φορτώσουν πιο αργά.",
"View YouTube comments":"Προβολή σχολίων από το YouTube",
"View more comments on Reddit":"Προβολή περισσότερων σχολίων στο Reddit",
"crash_page_report_issue":"Εάν κανένα από τα παραπάνω δεν βοήθησε, παρακαλούμε <a href=\"`x`\">ανοίξτε ένα νέο θέμα στο GitHub</a> (κατά προτίμηση στα αγγλικά) και συμπεριλάβετε το ακόλουθο κείμενο στο μήνυμά σας (ΜΗΝ μεταφράζετε αυτό το κείμενο):",
"Broken? Try another Invidious Instance":"Broken? Try another Invidious Instance",
"Hide annotations":"Hide annotations",
"Show annotations":"Show annotations",
"Genre: ":"Genre: ",
@@ -167,17 +187,13 @@
"Whitelisted regions: ":"Whitelisted regions: ",
"Blacklisted regions: ":"Blacklisted regions: ",
"Shared `x`":"Shared `x`",
"`x` views":{
"([^.,0-9]|^)1([^.,0-9]|$)":"`x` view",
"":"`x` views"
},
"Premieres in `x`":"Premieres in `x`",
"Premieres `x`":"Premieres `x`",
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.":"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.",
"View YouTube comments":"View YouTube comments",
"View more comments on Reddit":"View more comments on Reddit",
"View `x` comments":{
"(\\D|^)1(\\D|$)":"View `x` comment",
"([^.,0-9]|^)1([^.,0-9]|$)":"View `x` comment",
"":"View `x` comments"
},
"View Reddit comments":"View Reddit comments",
@@ -204,16 +220,12 @@
"This channel does not exist.":"This channel does not exist.",
"Could not get channel info.":"Could not get channel info.",
"Could not fetch comments":"Could not fetch comments",
"crash_page_you_found_a_bug":"It looks like you found a bug in Invidious!",
"crash_page_before_reporting":"Before reporting a bug, make sure that you have:",
"crash_page_refresh":"tried to <a href=\"`x`\">refresh the page</a>",
"crash_page_switch_instance":"tried to <a href=\"`x`\">use another instance</a>",
"crash_page_read_the_faq":"read the <a href=\"`x`\">Frenquently Asked Questions (FAQ)</a>",
"crash_page_search_issue":"searched for <a href=\"`x`\">existing issues on Github</a>",
"crash_page_report_issue":"If none of the above helped, please <a href=\"`x`\">open a new issue on GitHub</a> (preferably in English) and include the following text in your message (do NOT translate that text):"
"Switch Invidious Instance":"Ŝanĝi instalaĵon de Indivious",
"Broken? Try another Invidious Instance":"Ĉu misfunkcio? Provu alian instalaĵon de Indivious",
"Hide annotations":"Kaŝi prinotojn",
"Show annotations":"Montri prinotojn",
"Genre: ":"Ĝenro: ",
@@ -149,13 +152,15 @@
"Whitelisted regions: ":"Regionoj listigitaj en blanka listo: ",
"Blacklisted regions: ":"Regionoj listigitaj en nigra listo: ",
"Shared `x`":"Konigita `x`",
"`x` views":"`x` spektaĵoj",
"Premieres in `x`":"Premieras en `x`",
"Premieres `x`":"Premieras `x`",
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.":"Saluton! Ŝajnas, ke vi havas Ĝavoskripton malebligitan. Klaku ĉi tie por vidi komentojn, memoru, ke la ŝargado povus daŭri iom pli.",
"View YouTube comments":"Vidi komentojn de YouTube",
"View YouTube comments":"Vidi komentojn de JuTubo",
"View more comments on Reddit":"Vidi pli komentoj en Reddit",
"View `x` comments":"Vidi `x` komentojn",
"View `x` comments":{
"([^.,0-9]|^)1([^.,0-9]|$)":"Vidi `x` komentojn",
"":"Vidi `x` komentojn"
},
"View Reddit comments":"Vidi komentojn de Reddit",
"Hide replies":"Kaŝi respondojn",
"Show replies":"Montri respondojn",
@@ -180,10 +185,8 @@
"This channel does not exist.":"Ĉi tiu kanalo ne ekzistas.",
"Could not get channel info.":"Ne povis havigi kanalan informon.",
"Could not fetch comments":"Ne povis venigi komentojn",
"preferences_automatic_instance_redirect_label":"Redirección automática de instancia (segunda opción a redirect.invidious.io): ",
"preferences_category_subscription":"Preferencias de la suscripción",
"preferences_annotations_subscribed_label":"¿Mostrar anotaciones por defecto para los canales suscritos? ",
"Redirect homepage to feed: ":"Redirigir la página de inicio a la fuente: ",
"Number of videos shown in feed: ":"Número de vídeos mostrados en la fuente: ",
"Sort videos by: ":"Ordenar los vídeos por: ",
"preferences_max_results_label":"Número de vídeos mostrados en la fuente: ",
"preferences_sort_label":"Ordenar los vídeos por: ",
"published":"fecha de publicación",
"published - reverse":"fecha de publicación: orden inverso",
"alphabetically":"alfabéticamente",
@@ -88,12 +89,12 @@
"channel name - reverse":"nombre del canal: orden inverso",
"Only show latest video from channel: ":"Mostrar solo el último vídeo del canal: ",
"Only show latest unwatched video from channel: ":"Mostrar solo el último vídeo sin ver del canal: ",
"Only show unwatched: ":"Mostrar solo los no vistos: ",
"Only show notifications (if there are any): ":"Mostrar solo notificaciones (si hay alguna): ",
"Enable web notifications":"",
"`x` uploaded a video":"",
"`x` is live":"",
"Data preferences":"Preferencias de los datos",
"preferences_unseen_only_label":"Mostrar solo los no vistos: ",
"preferences_notifications_only_label":"Mostrar solo notificaciones (si hay alguna): ",
"Enable web notifications":"Habilitar notificaciones web",
"`x` uploaded a video":"`x` subió un video",
"`x` is live":"`x` esta en vivo",
"preferences_category_data":"Preferencias de los datos",
"Clear watch history":"Borrar el historial de reproducción",
"Import/export data":"Importar/Exportar datos",
"Change password":"Cambiar contraseña",
@@ -101,9 +102,10 @@
"Manage tokens":"Gestionar tokens",
"Watch history":"Historial de reproducción",
"Delete account":"Borrar cuenta",
"Administrator preferences":"Preferencias de administrador",
"Defaulthomepage: ":"Página de inicio por defecto: ",
"Feedmenu: ":"Menú de fuentes: ",
"preferences_category_admin":"Preferencias de administrador",
"preferences_default_home_label":"Página de inicio por defecto: ",
"preferences_feed_menu_label":"Menú de fuentes: ",
"preferences_show_nick_label":"Mostrar nombre de usuario arriba: ",
"Top enabled: ":"¿Habilitar los destacados? ",
"CAPTCHA enabled: ":"¿Habilitar los CAPTCHA? ",
"Login enabled: ":"¿Habilitar el inicio de sesión? ",
@@ -113,32 +115,33 @@
"Subscription manager":"Gestor de suscripciones",
"Token manager":"Gestor de tokens",
"Token":"Token",
"`x` subscriptions":"`x` suscripciones",
"`x` tokens":"`x` tokens",
"Import/export":"Importar/Exportar",
"unsubscribe":"Desuscribirse",
"revoke":"revocar",
"Subscriptions":"Suscripciones",
"`x` unseen notifications":"`x` notificaciones sin ver",
"search":"buscar",
"Log out":"Cerrar la sesión",
"Released under the AGPLv3 by Omar Roth.":"Publicado bajo licencia AGPLv3 por Omar Roth.",
"Released under the AGPLv3 on Github.":"Publicado bajo la AGPLv3 en Github.",
"Source available here.":"Código fuente disponible aquí.",
"View JavaScript license information.":"Ver información de licencia de JavaScript.",
"View privacy policy.":"Ver la política de privacidad.",
"Trending":"Tendencias",
"Public":"",
"Public":"Público",
"Unlisted":"No listado",
"Private":"",
"View all playlists":"",
"Updated `x` ago":"",
"Delete playlist `x`?":"",
"Delete playlist":"",
"Create playlist":"",
"Title":"",
"Playlist privacy":"",
"Editing playlist `x`":"",
"Watch on YouTube":"Ver el vídeo en Youtube",
"Private":"Privado",
"View all playlists":"Ver todas las listas de reproducción",
"Updated `x` ago":"Actualizado hace `x`",
"Delete playlist `x`?":"¿Borrar la lista de reproducción `x`?",
"Delete playlist":"Borrar lista de reproducción",
"Create playlist":"Crear lista de reproducción",
"Title":"Título",
"Playlist privacy":"Privacidad de la lista de reproducción",
"Editing playlist `x`":"Editando la lista de reproducción 'x'",
"Show more":"Mostrar más",
"Show less":"Mostrar menos",
"Watch on YouTube":"Ver el vídeo en YouTube",
"Switch Invidious Instance":"Cambiar Instancia de Invidious",
"Broken? Try another Invidious Instance":"¿Algún error? Prueba otra instancia de Invidious",
"Hide annotations":"Ocultar anotaciones",
"Show annotations":"Mostrar anotaciones",
"Genre: ":"Género: ",
@@ -149,13 +152,15 @@
"Whitelisted regions: ":"Regiones permitidas: ",
"Blacklisted regions: ":"Regiones bloqueadas: ",
"Shared `x`":"Compartido `x`",
"`x` views":"`x` visualizaciones",
"Premieres in `x`":"Se estrena en `x`",
"Premieres `x`":"",
"Premieres `x`":"Estrenos `x`",
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.":"¡Hola! Parece que tiene JavaScript desactivado. Haga clic aquí para ver los comentarios, pero tenga en cuenta que pueden tardar un poco más en cargarse.",
"View YouTube comments":"Ver los comentarios de YouTube",
"View more comments on Reddit":"Ver más comentarios en Reddit",
"crash_page_before_reporting":"Antes de notificar un error asegúrate de que has:",
"crash_page_switch_instance":"probado a <a href=\"`x`\">usar otra instancia</a>",
"crash_page_read_the_faq":"leído las <a href=\"`x`\">Preguntas Frecuentes</a>",
"crash_page_search_issue":"buscado <a href=\"`x`\">problemas existentes en Github</a>",
"crash_page_you_found_a_bug":"¡Parece que has encontrado un error en Invidious!",
"crash_page_refresh":"probado a <a href=\"`x`\">recargar la página</a>",
"crash_page_report_issue":"Si nada de lo anterior ha sido de ayuda, por favor, <a href=\"`x`\">abre una nueva incidencia en GitHub</a> (preferiblemente en inglés) e incluye el siguiente texto en tu mensaje (NO traduzcas este texto):",
"Broken? Try another Invidious Instance":"کار نمیکند؟ نمونه دیگری از اینویدیوس را امتحان کنید",
"Hide annotations":"مخفی کردن حاشیه نویسی ها",
"Show annotations":"نمایش حاشیه نویسی ها",
"Genre: ":"ژانر: ",
"License: ":"مجوز: ",
"Family friendly? ":"خانواده دوستانه؟ ",
"Wilson score: ":"امتیاز ویلسون: ",
"Engagement: ":"نامزدی: ",
"Whitelisted regions: ":"مناطق لیست سفید: ",
"Blacklisted regions: ":"مناطق لیست سیاه: ",
"Shared `x`":"به اشتراک گذاشته شده `x`",
"Premieres in `x`":"برای اولین بار در `x`",
"Premieres `x`":"برای اولین بار `x`",
"Hi! Looks like you have JavaScript turned off. Click here to view comments, keep in mind they may take a bit longer to load.":"سلام! مثل اینکه تو جاوا اسکریپت رو خاموش کرده ای. اینجا کلیک کن تا نظرات را ببینی، این رو یادت باشه که ممکنه بارگذاری اونها کمی طول بکشه.",
"View YouTube comments":"نمایش نظرات یوتیوب",
"View more comments on Reddit":"نمایش نظرات بیشتر در ردیت",
"View `x` comments":{
"([^.,0-9]|^)1([^.,0-9]|$)":"نمایش `x` نظرات",
"":"نمایش `x` نظرات"
},
"View Reddit comments":"نمایش نظرات ردیت",
"Hide replies":"مخفی کردن پاسخ ها",
"Show replies":"نمایش پاسخ ها",
"Incorrect password":"گذرواژه نا درست",
"Quota exceeded, try again in a few hours":"سهمیه بیشتر شده است، چند ساعت بعد دوباره تلاش کنید",
"Unable to log in, make sure two-factor authentication (Authenticator or SMS) is turned on.":"قادر به ورود نیستید، مطمئن شوید احراز تایید-دومرحله (Authenticator یا پیامکوتاه) خاموش باشد.",
"Invalid TFA code":"کد TFA نادرست است",
"Login failed. This may be because two-factor authentication is not turned on for your account.":"ورود با خطا مواجه شد. این ممکن است به خاطر احراز تایید-دومرحله باشد که برای حساب کاربری شما فعال نشده است.",
"Wrong answer":"پاسخ غلط",
"Erroneous CAPTCHA":"CAPTCHA نا درست",
"CAPTCHA is a required field":"CAPTCHA یک فیلد ضروری است",
"User ID is a required field":"شناسه کاربری یک فیلد ضروری است",
"Password is a required field":"گذرواژه یک فیلد ضروری است",
"Wrong username or password":"نام کاربری یا گذرواژه غلط است",
"Please sign in using 'Log in with Google'":"لطفا با استفاده از 'ورود توسط گوگل' وارد شوید",
"Password cannot be empty":"گذرواژه نمیتواند خالی باشد",
"Password cannot be longer than 55 characters":"گذر واژه نمیتواند از ۵۵ کاراکتر بیشتر باشد",
"Please log in":"لطفا وارد شوید",
"Invidious Private Feed for `x`":"خوراک خصوصی زشت برای `x`",
"channel:`x`":"کانال: `x`",
"Deleted or invalid channel":"کانال نا معتبر یا پاک شده است",
"This channel does not exist.":"این کانال وجود ندارد.",
"Could not get channel info.":"نمیتوان اطلاعات کانال را دریافت کرد.",
"Could not fetch comments":"نمیتوان نظرات را دریافت کرد",
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.