Compare commits

..

6 Commits

Author SHA1 Message Date
TheFrenchGhosty 4d6f92f036 Various small rewording 2026-06-28 23:52:02 +02:00
TheFrenchGhosty c380ca72e7 Various minor enhancements 2026-06-28 20:53:34 +02:00
TheFrenchGhosty 241938538f Update AI_POLICY.md
Co-authored-by: Émilien (perso) <4016501+unixfox@users.noreply.github.com>
2026-06-28 18:36:36 +02:00
TheFrenchGhosty 86b2c4fb7a Typo 2026-06-28 17:23:33 +02:00
TheFrenchGhosty dba5004daf Add some more 2026-06-28 17:22:34 +02:00
TheFrenchGhosty 98d69d87c7 Create AI_POLICY.md 2026-06-28 17:14:50 +02:00
11 changed files with 58 additions and 57 deletions
+2 -2
View File
@@ -65,7 +65,7 @@ jobs:
crystal: ${{ matrix.crystal }} crystal: ${{ matrix.crystal }}
- name: Cache Shards - name: Cache Shards
uses: actions/cache@v6 uses: actions/cache@v5
with: with:
path: | path: |
./lib ./lib
@@ -137,7 +137,7 @@ jobs:
crystal: latest crystal: latest
- name: Cache Shards - name: Cache Shards
uses: actions/cache@v6 uses: actions/cache@v5
with: with:
path: | path: |
./lib ./lib
+36
View File
@@ -0,0 +1,36 @@
Invidious is and has always been made by human first and foremost. However, things have changed recently with the rise of AI.
This document is going to explain everything that you need to know if you ever contribute in any way to Invidious using any kind of AI.
This document has been fully written, from scratch, by a Human.
# Motivation
Invidious is written in an obscure language: Crystal.
Because it is obscure the number of people knowing it is really low.
Invidious is the biggest Crystal project that exists, bigger than Crystal itself [(yes, seriously)](https://shards.info/).
The problem of being the biggest software in an obscure language is that you're often effectively the first project to encounter a problem and because it's an obscure language, not a lot of libraries exist to make it easier for you, meaning, you usually have to make everything you need yourself.
This makes it so working on Invidious far harder than working on most open source projects because you are effectively not benefiting and not using any external libraries for the vast majority of things. Almost any time you need anything, you have to make it yourself, which overcomplicates everything.
We are aware that some people wont like this change and we might even end up on one of the "bad people" list, but we try to be reasonable. We ask that you, please, do not fork the project out of spite because of this new policy - let's not split the thin list of people able to contribute even thinner. Contributions are welcome and highly preferred to anything made by AI.
This policy comes from a place of *need* not from a place of *choice*.
# Policy
Now that AIs exists and have become *reasonably good*, we will tolerate people using them with reasons and knowledge, as long those rules are respected:
- **Any one using AI to report bugs or submit code MUST properly disclose it, this includes mentioning the name of the EXACT model used and the tools used to interact with it.**
- The Human using AI MUST properly check the output manually in addition to any automated check that may exist or may have been created, **this includes BOTH codes AND bug reports**.
- Any code submitted by a Human, written even partially by AI, is the responsibility of this Human - If it's malicious, broken, destructive or anything bad, the Human is the sole responsible.
- Any new code touching any of the actual functions of Invidious MUST BE thoroughly tested by the Human MANUALLY.
- Team members using AIs are strongly encouraged to wait for the review of another Human before merging anything.
- At any point [Human-in-the-loop](https://en.wikipedia.org/wiki/Human-in-the-loop) applies.
+13 -15
View File
@@ -205,6 +205,7 @@ https_only: false
# path: /tmp/invidious.sock # path: /tmp/invidious.sock
# permissions: 777 # permissions: 777
# ----------------------------- # -----------------------------
# Network (outbound) # Network (outbound)
# ----------------------------- # -----------------------------
@@ -227,6 +228,7 @@ https_only: false
## ##
#pool_size: 100 #pool_size: 100
## ##
## Additional cookies to be sent when requesting the youtube API. ## Additional cookies to be sent when requesting the youtube API.
## ##
@@ -261,6 +263,7 @@ https_only: false
# host: # host:
# port: # port:
## ##
## Use Innertube's transcripts API instead of timedtext for closed captions ## Use Innertube's transcripts API instead of timedtext for closed captions
## ##
@@ -341,6 +344,7 @@ https_only: false
## ##
#statistics_enabled: false #statistics_enabled: false
# ----------------------------- # -----------------------------
# Users and accounts # Users and accounts
# ----------------------------- # -----------------------------
@@ -452,25 +456,12 @@ full_refresh: false
## ##
feed_threads: 1 feed_threads: 1
##
## Setting to disable easy to abuse API endpoints that can
## be spammed and therefore blocking your Invidious instance.
##
## Useful for public instance maintainers.
##
## Notes: The following API endpoints will be disabled:
## - /api/v1/videos
## - /api/v1/clips
## - /api/v1/transcripts
##
## Accepted values: true, false
## Default: false
##
disable_abusable_api: false
jobs: jobs:
## Options for the database cleaning job ## Options for the database cleaning job
clear_expired_items: clear_expired_items:
## Enable/Disable job ## Enable/Disable job
## ##
## Accepted values: true, false ## Accepted values: true, false
@@ -480,6 +471,7 @@ jobs:
## Options for the channels updater job ## Options for the channels updater job
refresh_channels: refresh_channels:
## Enable/Disable job ## Enable/Disable job
## ##
## Accepted values: true, false ## Accepted values: true, false
@@ -489,6 +481,7 @@ jobs:
## Options for the RSS feeds updater job ## Options for the RSS feeds updater job
refresh_feeds: refresh_feeds:
## Enable/Disable job ## Enable/Disable job
## ##
## Accepted values: true, false ## Accepted values: true, false
@@ -496,6 +489,7 @@ jobs:
## ##
enable: true enable: true
# ----------------------------- # -----------------------------
# Miscellaneous # Miscellaneous
# ----------------------------- # -----------------------------
@@ -694,6 +688,7 @@ default_user_preferences:
## ##
#captions: ["", "", ""] #captions: ["", "", ""]
# ----------------------------- # -----------------------------
# Interface # Interface
# ----------------------------- # -----------------------------
@@ -795,6 +790,7 @@ default_user_preferences:
## ##
#related_videos: true #related_videos: true
# ----------------------------- # -----------------------------
# Video player behavior # Video player behavior
# ----------------------------- # -----------------------------
@@ -858,6 +854,7 @@ default_user_preferences:
## ##
#video_loop: false #video_loop: false
# ----------------------------- # -----------------------------
# Video playback settings # Video playback settings
# ----------------------------- # -----------------------------
@@ -969,6 +966,7 @@ default_user_preferences:
## ##
#sort: published #sort: published
# ----------------------------- # -----------------------------
# Miscellaneous # Miscellaneous
# ----------------------------- # -----------------------------
-1
View File
@@ -217,7 +217,6 @@ end
Kemal.config.powered_by_header = false Kemal.config.powered_by_header = false
add_handler FilteredCompressHandler.new add_handler FilteredCompressHandler.new
add_handler APIHandler.new add_handler APIHandler.new
add_handler DisableAbusableAPIHandler.new
add_handler AuthHandler.new add_handler AuthHandler.new
add_handler DenyFrame.new add_handler DenyFrame.new
-3
View File
@@ -183,9 +183,6 @@ class Config
# Playlist length limit # Playlist length limit
property playlist_length_limit : Int32 = 500 property playlist_length_limit : Int32 = 500
# Disable easy to abuse API endpoints
property disable_abusable_api : Bool = false
def disabled?(option) def disabled?(option)
case disabled = CONFIG.disable_proxy case disabled = CONFIG.disable_proxy
when Bool when Bool
+3 -3
View File
@@ -194,13 +194,13 @@ module Invidious::Database::PlaylistVideos
PG_DB.exec(request, args: video_array) PG_DB.exec(request, args: video_array)
end end
def delete(index, plid : String) def delete(index)
request = <<-SQL request = <<-SQL
DELETE FROM playlist_videos * DELETE FROM playlist_videos *
WHERE index = $1 AND plid = $2 WHERE index = $1
SQL SQL
PG_DB.exec(request, index, plid) PG_DB.exec(request, index)
end end
def delete_by_playlist(plid : String) def delete_by_playlist(plid : String)
-20
View File
@@ -133,26 +133,6 @@ class APIHandler < Kemal::Handler
end end
end end
class DisableAbusableAPIHandler < Kemal::Handler
{% for method in %w(GET HEAD) %}
# This endpoints make a video request to Invidious companion.
{% for endpoint in %w(videos clips transcripts) %}
only ["/api/v1/{{ endpoint.id }}/:id"], {{ method }}
{% end %}
{% end %}
def call(env)
return call_next env unless only_match?(env) && CONFIG.disable_abusable_api
env.response.content_type = "application/json"
env.response.status_code = 403
message = {"error" => "This API endpoint has been disabled by the administrator."}.to_json
env.response.print message
env.response.close
return
end
end
class DenyFrame < Kemal::Handler class DenyFrame < Kemal::Handler
exclude ["/embed/*"] exclude ["/embed/*"]
@@ -36,11 +36,6 @@ class Invidious::Jobs::RefreshChannelsJob < Invidious::Jobs::BaseJob
LOGGER.trace("RefreshChannelsJob: #{id} fiber : Updating DB") LOGGER.trace("RefreshChannelsJob: #{id} fiber : Updating DB")
Invidious::Database::Channels.update_author(id, channel.author) Invidious::Database::Channels.update_author(id, channel.author)
if backoff > 2.minutes
backoff /= 2
LOGGER.debug("RefreshChannelsJob: #{id} fiber : decreasing backoff to #{backoff}s")
end
rescue ex rescue ex
LOGGER.error("RefreshChannelsJob: #{id} : #{ex.message}") LOGGER.error("RefreshChannelsJob: #{id} : #{ex.message}")
if ex.message == "Deleted or invalid channel" if ex.message == "Deleted or invalid channel"
+1 -1
View File
@@ -364,7 +364,7 @@ module Invidious::Routes::API::V1::Authenticated
return error_json(404, "Playlist does not contain index") return error_json(404, "Playlist does not contain index")
end end
Invidious::Database::PlaylistVideos.delete(index, plid) Invidious::Database::PlaylistVideos.delete(index)
Invidious::Database::Playlists.update_video_removed(plid, index) Invidious::Database::Playlists.update_video_removed(plid, index)
env.response.status_code = 204 env.response.status_code = 204
+2 -6
View File
@@ -357,12 +357,8 @@ module Invidious::Routes::Playlists
Invidious::Database::PlaylistVideos.insert(playlist_video) Invidious::Database::PlaylistVideos.insert(playlist_video)
Invidious::Database::Playlists.update_video_added(playlist_id, playlist_video.index) Invidious::Database::Playlists.update_video_added(playlist_id, playlist_video.index)
when "remove_video" when "remove_video"
index = env.params.query["set_video_id"].to_i64? index = env.params.query["set_video_id"]
if index.nil? || !playlist.index.includes? index Invidious::Database::PlaylistVideos.delete(index)
return error_json(404, "Playlist does not contain index")
end
Invidious::Database::PlaylistVideos.delete(index, playlist_id)
Invidious::Database::Playlists.update_video_removed(playlist_id, index) Invidious::Database::Playlists.update_video_removed(playlist_id, index)
when "move_video_before" when "move_video_before"
# TODO: Playlist stub # TODO: Playlist stub
+1 -1
View File
@@ -106,7 +106,7 @@ end
def add_yt_headers(request) def add_yt_headers(request)
request.headers.delete("User-Agent") if request.headers["User-Agent"] == "Crystal" request.headers.delete("User-Agent") if request.headers["User-Agent"] == "Crystal"
request.headers["User-Agent"] ||= "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36" request.headers["User-Agent"] ||= "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36"
request.headers["Accept-Charset"] ||= "ISO-8859-1,utf-8;q=0.7,*;q=0.7" request.headers["Accept-Charset"] ||= "ISO-8859-1,utf-8;q=0.7,*;q=0.7"
request.headers["Accept"] ||= "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" request.headers["Accept"] ||= "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"