Implement takedown system

This commit is contained in:
Cadence Ember 2021-11-20 19:42:34 +13:00
parent 741a1199dd
commit b9f703086f
No known key found for this signature in database
GPG Key ID: BC1C2C61CF521B17
10 changed files with 111 additions and 2 deletions

1
.gitignore vendored
View File

@ -14,3 +14,4 @@ node_modules
# Narration
/html/static/media/cant_think_suricrasia_online.mp3
/html/transparency

10
api/takedown.js Normal file
View File

@ -0,0 +1,10 @@
const constants = require("../utils/constants")
const {render} = require("pinski/plugins")
module.exports = [
{
route: "/takedown", methods: ["GET"], code: async () => {
return render(200, "pug/takedown.pug", {constants})
}
}
]

View File

@ -108,6 +108,12 @@ module.exports = [
const settings = user.getSettingsOrDefaults()
const id = url.searchParams.get("v")
// Check if playback is allowed
const videoTakedownInfo = db.prepare("SELECT id, org, url FROM TakedownVideos WHERE id = ?").get(id)
if (videoTakedownInfo) {
return render(451, "pug/takedown-video.pug", videoTakedownInfo)
}
// Media fragment
const t = url.searchParams.get("t")
let mediaFragment = converters.tToMediaFragment(t)
@ -141,6 +147,15 @@ module.exports = [
if (!video) throw new MessageError("The instance returned null.")
if (video.error) throw new InstanceError(video.error, video.identifier)
// Check if channel playback is allowed
const channelTakedownInfo = db.prepare("SELECT ucid, org, url FROM TakedownChannels WHERE ucid = ?").get(video.authorId)
if (channelTakedownInfo) {
// automatically add the entry to the videos list, so it won't be fetched again
const args = {id, ...channelTakedownInfo}
db.prepare("INSERT INTO TakedownVideos (id, org, url) VALUES (@id, @org, @url)").run(args)
return render(451, "pug/takedown-video.pug", channelTakedownInfo)
}
// process stream list ordering
const formats = sortFormats(video, settings.quality)

View File

@ -34,7 +34,7 @@ html
p Released as AGPL free software.
.footer__cols
div
h3.footer__colhead Source
h3.footer__colhead Source code
ul.footer__list
li: a(href="https://sr.ht/~cadence/tube") Project hub
li: a(href="https://lists.sr.ht/~cadence/tube-announce") Announcements
@ -44,3 +44,5 @@ html
ul.footer__list
li: a(href="/privacy") Privacy policy
li: a(href="/licenses" data-jslicense=1) Licenses
if constants.takedown
li: a(href="/takedown") DMCA

22
pug/takedown-video.pug Normal file
View File

@ -0,0 +1,22 @@
extends includes/layout
include includes/video-list-item
include includes/subscribe-button
block head
title Unavailable for legal reasons - CloudTube
block content
main.video-error-page
h2 Unavailable for legal reasons
p The copyright holders of this video issued a legal notice directly to this website. They demanded that access to this particular video, or the particular channel it's from, should be forbidden.
if org
p The notice was issued by #{org}.
if url
p: a(href=url) More information about the notice is available here.
p Any content not covered by this notice is still available.
p You can still #[a(href=`https://www.youtube.com/watch?v=${id}#cloudtube`) watch the video on YouTube.]
footer.takedown-footer
p: i Let this be a warning of why you shouldn't rely on centralised services!
p: i You will always be able to download the CloudTube source code, or try another instance.
p: i That's all we know.

33
pug/takedown.pug Normal file
View File

@ -0,0 +1,33 @@
extends includes/layout
block head
title Takedown - CloudTube
block content
main.takedown-page
h1 Takedown/DMCA
p If you own the copyright to videos on this website, you can remove access to the videos. But:
section.important-section
h2 Read this first.
ul
li CloudTube is a proxy service for YouTube videos.
li CloudTube does not store any videos. Videos are never saved to these servers.
li CloudTube reproduces data from youtube.com in an interface that looks a little bit different.
li All video data is streamed directly from YouTube. All video metadata is collected directly from YouTube.
h2 And understand this:
p Anybody can watch or download YouTube videos using many freely available tools. This is just one such tool, and attacking this website will solve none of your problems.
h2.new-section “I still want to remove access.”
p In addition to the legally mandated information, if you wish for future videos uploaded on the same channel(s) to be restricted, please provide the channel URLs, and state: "Future videos uploaded to the same YouTube channels should also be restricted."
p When providing URLs, please format them like so:
pre.
https://youtube.example.com/watch?v=AAAAAAAAAAA
https://youtube.example.com/watch?v=BBBBBBBBBBB
p i.e., one URL per line, with no other information on those lines.
section.takedown-contact
if constants.takedown && constants.takedown.contact_url
p: a(href=constants.takedown.contact_url) Contact information is here.
else if constants.takedown && constants.takedown.contact_email
p: a(href=`mailto:${constants.takedown.contact_email}`) Send email to #{constants.takedown.contact_email}
else
p You will need to contact the website owner via their domain or hosting provider.
p Please allow 5 days for a response.

View File

@ -0,0 +1,14 @@
@use "colors.sass" as c
.takedown-page
max-width: 700px
margin: 0 auto
.new-section
margin-top: 200px
.important-section
padding: 4px 20px
border: 1px solid c.$edge-grey
color: c.$fg-bright
background-color: c.$bg-darker

View File

@ -161,6 +161,9 @@
.actor
margin: 4px 0px 10px
.takedown-footer
margin-top: 80px
// Chapter highlights
.timestamp--active

View File

@ -1,5 +1,6 @@
@use "includes/base.sass"
@use "includes/colors.sass" as c
@use "includes/base.sass"
@use "sass:selector"
@use "includes/video-page.sass"
@use "includes/search-page.sass"
@ -11,6 +12,7 @@
@use "includes/privacy-page.sass"
@use "includes/licenses-page.sass"
@use "includes/filters-page.sass"
@use "includes/takedown-page.sass"
@use "includes/forms.sass"
@use "includes/nav.sass"
@use "includes/footer.sass"

View File

@ -63,6 +63,13 @@ const deltas = [
function() {
db.prepare("CREATE INDEX Videos_authorID ON Videos (authorID)")
.run()
},
// 10: +TakedownVideos, +TakedownChannels
function() {
db.prepare("CREATE TABLE TakedownVideos (id TEXT NOT NULL, org TEXT, url TEXT, PRIMARY KEY (id))")
.run()
db.prepare("CREATE TABLE TakedownChannels (ucid TEXT NOT NULL, org TEXT, url TEXT, PRIMARY KEY (ucid))")
.run()
}
]