mirror of https://git.sr.ht/~cadence/cloudtube
Implement takedown system
This commit is contained in:
parent
741a1199dd
commit
b9f703086f
|
@ -14,3 +14,4 @@ node_modules
|
||||||
|
|
||||||
# Narration
|
# Narration
|
||||||
/html/static/media/cant_think_suricrasia_online.mp3
|
/html/static/media/cant_think_suricrasia_online.mp3
|
||||||
|
/html/transparency
|
||||||
|
|
|
@ -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})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
15
api/video.js
15
api/video.js
|
@ -108,6 +108,12 @@ module.exports = [
|
||||||
const settings = user.getSettingsOrDefaults()
|
const settings = user.getSettingsOrDefaults()
|
||||||
const id = url.searchParams.get("v")
|
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
|
// Media fragment
|
||||||
const t = url.searchParams.get("t")
|
const t = url.searchParams.get("t")
|
||||||
let mediaFragment = converters.tToMediaFragment(t)
|
let mediaFragment = converters.tToMediaFragment(t)
|
||||||
|
@ -141,6 +147,15 @@ module.exports = [
|
||||||
if (!video) throw new MessageError("The instance returned null.")
|
if (!video) throw new MessageError("The instance returned null.")
|
||||||
if (video.error) throw new InstanceError(video.error, video.identifier)
|
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
|
// process stream list ordering
|
||||||
const formats = sortFormats(video, settings.quality)
|
const formats = sortFormats(video, settings.quality)
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ html
|
||||||
p Released as AGPL free software.
|
p Released as AGPL free software.
|
||||||
.footer__cols
|
.footer__cols
|
||||||
div
|
div
|
||||||
h3.footer__colhead Source
|
h3.footer__colhead Source code
|
||||||
ul.footer__list
|
ul.footer__list
|
||||||
li: a(href="https://sr.ht/~cadence/tube") Project hub
|
li: a(href="https://sr.ht/~cadence/tube") Project hub
|
||||||
li: a(href="https://lists.sr.ht/~cadence/tube-announce") Announcements
|
li: a(href="https://lists.sr.ht/~cadence/tube-announce") Announcements
|
||||||
|
@ -44,3 +44,5 @@ html
|
||||||
ul.footer__list
|
ul.footer__list
|
||||||
li: a(href="/privacy") Privacy policy
|
li: a(href="/privacy") Privacy policy
|
||||||
li: a(href="/licenses" data-jslicense=1) Licenses
|
li: a(href="/licenses" data-jslicense=1) Licenses
|
||||||
|
if constants.takedown
|
||||||
|
li: a(href="/takedown") DMCA
|
||||||
|
|
|
@ -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.
|
|
@ -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.
|
|
@ -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
|
|
@ -161,6 +161,9 @@
|
||||||
.actor
|
.actor
|
||||||
margin: 4px 0px 10px
|
margin: 4px 0px 10px
|
||||||
|
|
||||||
|
.takedown-footer
|
||||||
|
margin-top: 80px
|
||||||
|
|
||||||
// Chapter highlights
|
// Chapter highlights
|
||||||
|
|
||||||
.timestamp--active
|
.timestamp--active
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
@use "includes/base.sass"
|
|
||||||
@use "includes/colors.sass" as c
|
@use "includes/colors.sass" as c
|
||||||
|
|
||||||
|
@use "includes/base.sass"
|
||||||
@use "sass:selector"
|
@use "sass:selector"
|
||||||
@use "includes/video-page.sass"
|
@use "includes/video-page.sass"
|
||||||
@use "includes/search-page.sass"
|
@use "includes/search-page.sass"
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
@use "includes/privacy-page.sass"
|
@use "includes/privacy-page.sass"
|
||||||
@use "includes/licenses-page.sass"
|
@use "includes/licenses-page.sass"
|
||||||
@use "includes/filters-page.sass"
|
@use "includes/filters-page.sass"
|
||||||
|
@use "includes/takedown-page.sass"
|
||||||
@use "includes/forms.sass"
|
@use "includes/forms.sass"
|
||||||
@use "includes/nav.sass"
|
@use "includes/nav.sass"
|
||||||
@use "includes/footer.sass"
|
@use "includes/footer.sass"
|
||||||
|
|
|
@ -63,6 +63,13 @@ const deltas = [
|
||||||
function() {
|
function() {
|
||||||
db.prepare("CREATE INDEX Videos_authorID ON Videos (authorID)")
|
db.prepare("CREATE INDEX Videos_authorID ON Videos (authorID)")
|
||||||
.run()
|
.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()
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue